ares-test.cc (41080B)
1 /* MIT License 2 * 3 * Copyright (c) The c-ares project and its contributors 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a copy 6 * of this software and associated documentation files (the "Software"), to deal 7 * in the Software without restriction, including without limitation the rights 8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 * copies of the Software, and to permit persons to whom the Software is 10 * furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice (including the next 13 * paragraph) shall be included in all copies or substantial portions of the 14 * Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 * SOFTWARE. 23 * 24 * SPDX-License-Identifier: MIT 25 */ 26 #include "ares_setup.h" 27 #include "ares.h" 28 #include "ares_nameser.h" 29 #include "ares-test.h" 30 #include "ares-test-ai.h" 31 #include "dns-proto.h" 32 #include "ares_dns.h" 33 34 extern "C" { 35 // Remove command-line defines of package variables for the test project... 36 #undef PACKAGE_NAME 37 #undef PACKAGE_BUGREPORT 38 #undef PACKAGE_STRING 39 #undef PACKAGE_TARNAME 40 // ... so we can include the library's config without symbol redefinitions. 41 #include "ares_setup.h" 42 #include "ares_inet_net_pton.h" 43 #include "ares_data.h" 44 #include "str/ares_strsplit.h" 45 #include "ares_private.h" 46 } 47 48 49 #ifdef HAVE_NETDB_H 50 #include <netdb.h> 51 #endif 52 #ifdef HAVE_NETINET_TCP_H 53 #include <netinet/tcp.h> 54 #endif 55 #include <stdio.h> 56 #include <stdlib.h> 57 #include <string.h> 58 59 #include <functional> 60 #include <sstream> 61 #include <algorithm> 62 #include <chrono> 63 64 #ifdef WIN32 65 #define BYTE_CAST (char *) 66 #define mkdir_(d, p) mkdir(d) 67 #else 68 #define BYTE_CAST 69 #define mkdir_(d, p) mkdir(d, p) 70 #endif 71 72 namespace ares { 73 namespace test { 74 75 bool verbose = false; 76 static constexpr unsigned short dynamic_port = 0; 77 unsigned short mock_port = dynamic_port; 78 79 const std::vector<int> both_families = {AF_INET, AF_INET6}; 80 const std::vector<int> ipv4_family = {AF_INET}; 81 const std::vector<int> ipv6_family = {AF_INET6}; 82 83 const std::vector<std::pair<int, bool>> both_families_both_modes = { 84 std::make_pair<int, bool>(AF_INET, false), 85 std::make_pair<int, bool>(AF_INET, true), 86 std::make_pair<int, bool>(AF_INET6, false), 87 std::make_pair<int, bool>(AF_INET6, true) 88 }; 89 const std::vector<std::pair<int, bool>> ipv4_family_both_modes = { 90 std::make_pair<int, bool>(AF_INET, false), 91 std::make_pair<int, bool>(AF_INET, true) 92 }; 93 const std::vector<std::pair<int, bool>> ipv6_family_both_modes = { 94 std::make_pair<int, bool>(AF_INET6, false), 95 std::make_pair<int, bool>(AF_INET6, true) 96 }; 97 98 99 const std::vector<std::tuple<ares_evsys_t, int, bool>> all_evsys_ipv4_family_both_modes = { 100 #ifdef _WIN32 101 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_WIN32, AF_INET, false), 102 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_WIN32, AF_INET, true), 103 #endif 104 #ifdef HAVE_KQUEUE 105 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_KQUEUE, AF_INET, false), 106 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_KQUEUE, AF_INET, true), 107 #endif 108 #ifdef HAVE_EPOLL 109 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_EPOLL, AF_INET, false), 110 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_EPOLL, AF_INET, true), 111 #endif 112 #ifdef HAVE_POLL 113 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_POLL, AF_INET, false), 114 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_POLL, AF_INET, true), 115 #endif 116 #ifdef HAVE_PIPE 117 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_SELECT, AF_INET, false), 118 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_SELECT, AF_INET, true), 119 #endif 120 }; 121 122 const std::vector<std::tuple<ares_evsys_t, int, bool>> all_evsys_ipv6_family_both_modes = { 123 #ifdef _WIN32 124 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_WIN32, AF_INET6, false), 125 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_WIN32, AF_INET6, true), 126 #endif 127 #ifdef HAVE_KQUEUE 128 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_KQUEUE, AF_INET6, false), 129 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_KQUEUE, AF_INET6, true), 130 #endif 131 #ifdef HAVE_EPOLL 132 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_EPOLL, AF_INET6, false), 133 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_EPOLL, AF_INET6, true), 134 #endif 135 #ifdef HAVE_POLL 136 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_POLL, AF_INET6, false), 137 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_POLL, AF_INET6, true), 138 #endif 139 #ifdef HAVE_PIPE 140 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_SELECT, AF_INET6, false), 141 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_SELECT, AF_INET6, true), 142 #endif 143 }; 144 145 const std::vector<std::tuple<ares_evsys_t, int, bool>> all_evsys_both_families_both_modes = { 146 #ifdef _WIN32 147 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_WIN32, AF_INET, false), 148 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_WIN32, AF_INET, true), 149 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_WIN32, AF_INET6, false), 150 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_WIN32, AF_INET6, true), 151 #endif 152 #ifdef HAVE_KQUEUE 153 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_KQUEUE, AF_INET, false), 154 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_KQUEUE, AF_INET, true), 155 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_KQUEUE, AF_INET6, false), 156 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_KQUEUE, AF_INET6, true), 157 #endif 158 #ifdef HAVE_EPOLL 159 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_EPOLL, AF_INET, false), 160 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_EPOLL, AF_INET, true), 161 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_EPOLL, AF_INET6, false), 162 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_EPOLL, AF_INET6, true), 163 #endif 164 #ifdef HAVE_POLL 165 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_POLL, AF_INET, false), 166 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_POLL, AF_INET, true), 167 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_POLL, AF_INET6, false), 168 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_POLL, AF_INET6, true), 169 #endif 170 #ifdef HAVE_PIPE 171 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_SELECT, AF_INET, false), 172 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_SELECT, AF_INET, true), 173 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_SELECT, AF_INET6, false), 174 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_SELECT, AF_INET6, true), 175 #endif 176 }; 177 178 179 std::vector<std::tuple<ares_evsys_t, int, bool>> evsys_families_modes = all_evsys_both_families_both_modes; 180 181 182 const std::vector<std::tuple<ares_evsys_t, int>> all_evsys_ipv4_family = { 183 #ifdef _WIN32 184 std::make_tuple<ares_evsys_t, int>(ARES_EVSYS_WIN32, AF_INET), 185 #endif 186 #ifdef HAVE_KQUEUE 187 std::make_tuple<ares_evsys_t, int>(ARES_EVSYS_KQUEUE, AF_INET), 188 #endif 189 #ifdef HAVE_EPOLL 190 std::make_tuple<ares_evsys_t, int>(ARES_EVSYS_EPOLL, AF_INET), 191 #endif 192 #ifdef HAVE_POLL 193 std::make_tuple<ares_evsys_t, int>(ARES_EVSYS_POLL, AF_INET), 194 #endif 195 #ifdef HAVE_PIPE 196 std::make_tuple<ares_evsys_t, int>(ARES_EVSYS_SELECT, AF_INET), 197 #endif 198 }; 199 200 const std::vector<std::tuple<ares_evsys_t, int>> all_evsys_ipv6_family = { 201 #ifdef _WIN32 202 std::make_tuple<ares_evsys_t, int>(ARES_EVSYS_WIN32, AF_INET6), 203 #endif 204 #ifdef HAVE_KQUEUE 205 std::make_tuple<ares_evsys_t, int>(ARES_EVSYS_KQUEUE, AF_INET6), 206 #endif 207 #ifdef HAVE_EPOLL 208 std::make_tuple<ares_evsys_t, int>(ARES_EVSYS_EPOLL, AF_INET6), 209 #endif 210 #ifdef HAVE_POLL 211 std::make_tuple<ares_evsys_t, int>(ARES_EVSYS_POLL, AF_INET6), 212 #endif 213 #ifdef HAVE_PIPE 214 std::make_tuple<ares_evsys_t, int>(ARES_EVSYS_SELECT, AF_INET6), 215 #endif 216 }; 217 218 const std::vector<std::tuple<ares_evsys_t, int>> all_evsys_both_families = { 219 #ifdef _WIN32 220 std::make_tuple<ares_evsys_t, int>(ARES_EVSYS_WIN32, AF_INET), 221 std::make_tuple<ares_evsys_t, int>(ARES_EVSYS_WIN32, AF_INET6), 222 #endif 223 #ifdef HAVE_KQUEUE 224 std::make_tuple<ares_evsys_t, int>(ARES_EVSYS_KQUEUE, AF_INET), 225 std::make_tuple<ares_evsys_t, int>(ARES_EVSYS_KQUEUE, AF_INET6), 226 #endif 227 #ifdef HAVE_EPOLL 228 std::make_tuple<ares_evsys_t, int>(ARES_EVSYS_EPOLL, AF_INET), 229 std::make_tuple<ares_evsys_t, int>(ARES_EVSYS_EPOLL, AF_INET6), 230 #endif 231 #ifdef HAVE_POLL 232 std::make_tuple<ares_evsys_t, int>(ARES_EVSYS_POLL, AF_INET), 233 std::make_tuple<ares_evsys_t, int>(ARES_EVSYS_POLL, AF_INET6), 234 #endif 235 #ifdef HAVE_PIPE 236 std::make_tuple<ares_evsys_t, int>(ARES_EVSYS_SELECT, AF_INET), 237 std::make_tuple<ares_evsys_t, int>(ARES_EVSYS_SELECT, AF_INET6), 238 #endif 239 }; 240 241 242 243 std::vector<std::tuple<ares_evsys_t, int>> evsys_families = all_evsys_both_families; 244 245 246 // Which parameters to use in tests 247 std::vector<int> families = both_families; 248 std::vector<std::pair<int, bool>> families_modes = both_families_both_modes; 249 250 unsigned long long LibraryTest::fails_ = 0; 251 std::map<size_t, int> LibraryTest::size_fails_; 252 std::mutex LibraryTest::lock_; 253 bool LibraryTest::failsend_ = false; 254 255 void ares_sleep_time(unsigned int ms) 256 { 257 auto duration = std::chrono::milliseconds(ms); 258 auto start_time = std::chrono::high_resolution_clock::now(); 259 auto wake_time = start_time + duration; 260 std::this_thread::sleep_until(wake_time); 261 auto end_time = std::chrono::high_resolution_clock::now(); 262 if (verbose) std::cerr << "sleep requested " << ms << "ms, slept for " << std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time).count() << "ms" << std::endl; 263 } 264 265 void ProcessWork(ares_channel_t *channel, 266 std::function<std::set<ares_socket_t>()> get_extrafds, 267 std::function<void(ares_socket_t)> process_extra, 268 unsigned int cancel_ms) { 269 int nfds, count; 270 fd_set readers, writers; 271 272 auto tv_begin = std::chrono::high_resolution_clock::now(); 273 auto tv_cancel = tv_begin; 274 275 if (cancel_ms) { 276 if (verbose) std::cerr << "ares_cancel will be called after " << cancel_ms << "ms" << std::endl; 277 tv_cancel += std::chrono::milliseconds(cancel_ms); 278 } 279 280 while (true) { 281 struct timeval tv; 282 struct timeval *tv_select; 283 284 // Retrieve the set of file descriptors that the library wants us to monitor. 285 FD_ZERO(&readers); 286 FD_ZERO(&writers); 287 nfds = ares_fds(channel, &readers, &writers); 288 if (nfds == 0) // no work left to do in the library 289 return; 290 291 // Add in the extra FDs if present. 292 std::set<ares_socket_t> extrafds = get_extrafds(); 293 for (ares_socket_t extrafd : extrafds) { 294 FD_SET(extrafd, &readers); 295 if (extrafd >= (ares_socket_t)nfds) { 296 nfds = (int)extrafd + 1; 297 } 298 } 299 300 /* If ares_timeout returns NULL, it means there are no requests in queue, 301 * so we can break out */ 302 tv_select = ares_timeout(channel, NULL, &tv); 303 if (tv_select == NULL) 304 return; 305 306 if (cancel_ms) { 307 auto tv_now = std::chrono::high_resolution_clock::now(); 308 auto remaining_ms = std::chrono::duration_cast<std::chrono::milliseconds>(tv_cancel - tv_now).count(); 309 310 if (remaining_ms <= 0) { 311 if (verbose) std::cerr << "Issuing ares_cancel()" << std::endl; 312 ares_cancel(channel); 313 cancel_ms = 0; /* Disable issuing cancel again */ 314 } else { 315 struct timeval tv_remaining; 316 317 tv_remaining.tv_sec = remaining_ms / 1000; 318 tv_remaining.tv_usec = (int)(remaining_ms % 1000); 319 320 /* Recalculate proper timeout since we also have a cancel to wait on */ 321 tv_select = ares_timeout(channel, &tv_remaining, &tv); 322 } 323 } 324 325 count = select(nfds, &readers, &writers, nullptr, tv_select); 326 if (count < 0) { 327 fprintf(stderr, "select() failed, errno %d\n", errno); 328 return; 329 } 330 331 // Let the library process any activity. 332 ares_process(channel, &readers, &writers); 333 334 // Let the provided callback process any activity on the extra FD. 335 for (ares_socket_t extrafd : extrafds) { 336 if (FD_ISSET(extrafd, &readers)) { 337 process_extra(extrafd); 338 } 339 } 340 } 341 } 342 343 344 void LibraryTest::SetFailSend() { 345 failsend_ = true; 346 } 347 348 // static 349 ares_ssize_t LibraryTest::ares_sendv_fail(ares_socket_t socket, const struct iovec *vec, int len, void *user_data) 350 { 351 (void)user_data; 352 353 if (failsend_) { 354 #ifdef USE_WINSOCK 355 WSASetLastError(WSAECONNREFUSED); 356 #else 357 errno = ECONNREFUSED; 358 #endif 359 failsend_ = false; 360 return -1; 361 } 362 363 return send(socket, (const char *)vec[0].iov_base, vec[0].iov_len, 0); 364 } 365 366 367 void LibraryTest::SetAllocFail(int nth) { 368 lock_.lock(); 369 assert(nth > 0); 370 assert(nth <= (int)(8 * sizeof(fails_))); 371 fails_ |= (1LL << (nth - 1)); 372 lock_.unlock(); 373 } 374 375 // static 376 void LibraryTest::SetAllocSizeFail(size_t size) { 377 lock_.lock(); 378 size_fails_[size]++; 379 lock_.unlock(); 380 } 381 382 // static 383 void LibraryTest::ClearFails() { 384 lock_.lock(); 385 fails_ = 0; 386 size_fails_.clear(); 387 lock_.unlock(); 388 } 389 390 391 // static 392 bool LibraryTest::ShouldAllocFail(size_t size) { 393 lock_.lock(); 394 bool fail = (fails_ & 0x01); 395 fails_ >>= 1; 396 if (size_fails_[size] > 0) { 397 size_fails_[size]--; 398 fail = true; 399 } 400 lock_.unlock(); 401 return fail; 402 } 403 404 // static 405 void* LibraryTest::amalloc(size_t size) { 406 if (ShouldAllocFail(size) || size == 0) { 407 if (verbose) std::cerr << "Failing malloc(" << size << ") request" << std::endl; 408 return nullptr; 409 } else { 410 return malloc(size); 411 } 412 } 413 414 // static 415 void* LibraryTest::arealloc(void *ptr, size_t size) { 416 if (ShouldAllocFail(size)) { 417 if (verbose) std::cerr << "Failing realloc(" << ptr << ", " << size << ") request" << std::endl; 418 return nullptr; 419 } else { 420 return realloc(ptr, size); 421 } 422 } 423 424 // static 425 void LibraryTest::afree(void *ptr) { 426 free(ptr); 427 } 428 429 std::set<ares_socket_t> NoExtraFDs() { 430 return std::set<ares_socket_t>(); 431 } 432 433 void DefaultChannelTest::Process(unsigned int cancel_ms) { 434 ProcessWork(channel_, NoExtraFDs, nullptr, cancel_ms); 435 } 436 437 void FileChannelTest::Process(unsigned int cancel_ms) { 438 ProcessWork(channel_, NoExtraFDs, nullptr, cancel_ms); 439 } 440 441 void DefaultChannelModeTest::Process(unsigned int cancel_ms) { 442 ProcessWork(channel_, NoExtraFDs, nullptr, cancel_ms); 443 } 444 445 MockServer::MockServer(int family, unsigned short port) 446 : udpport_(port), tcpport_(port), qid_(-1) { 447 reply_ = nullptr; 448 // Create a TCP socket to receive data on. 449 tcp_data_ = NULL; 450 tcp_data_len_ = 0; 451 tcpfd_ = socket(family, SOCK_STREAM, 0); 452 EXPECT_NE(ARES_SOCKET_BAD, tcpfd_); 453 int optval = 1; 454 setsockopt(tcpfd_, SOL_SOCKET, SO_REUSEADDR, 455 BYTE_CAST &optval , sizeof(int)); 456 // Send TCP data right away. 457 setsockopt(tcpfd_, IPPROTO_TCP, TCP_NODELAY, 458 BYTE_CAST &optval , sizeof(int)); 459 #if defined(SO_NOSIGPIPE) 460 setsockopt(tcpfd_, SOL_SOCKET, SO_NOSIGPIPE, (void *)&optval, sizeof(optval)); 461 #endif 462 463 /* Test system enable TCP FastOpen */ 464 #if defined(TCP_FASTOPEN) 465 # ifdef __linux__ 466 int qlen = 32; 467 setsockopt(tcpfd_, IPPROTO_TCP, TCP_FASTOPEN, &qlen, sizeof(qlen)); 468 # else 469 int on = 1; 470 setsockopt(tcpfd_, IPPROTO_TCP, TCP_FASTOPEN, BYTE_CAST &on, sizeof(on)); 471 # endif 472 #endif 473 474 // Create a UDP socket to receive data on. 475 udpfd_ = socket(family, SOCK_DGRAM, 0); 476 EXPECT_NE(ARES_SOCKET_BAD, udpfd_); 477 #if defined(SO_NOSIGPIPE) 478 setsockopt(udpfd_, SOL_SOCKET, SO_NOSIGPIPE, (void *)&optval, sizeof(optval)); 479 #endif 480 481 // Bind the sockets to the given port. 482 if (family == AF_INET) { 483 struct sockaddr_in addr; 484 memset(&addr, 0, sizeof(addr)); 485 addr.sin_family = AF_INET; 486 addr.sin_addr.s_addr = htonl(INADDR_ANY); 487 addr.sin_port = htons(tcpport_); 488 int tcprc = bind(tcpfd_, (struct sockaddr*)&addr, sizeof(addr)); 489 EXPECT_EQ(0, tcprc) << "Failed to bind AF_INET to TCP port " << tcpport_; 490 addr.sin_port = htons(udpport_); 491 int udprc = bind(udpfd_, (struct sockaddr*)&addr, sizeof(addr)); 492 EXPECT_EQ(0, udprc) << "Failed to bind AF_INET to UDP port " << udpport_; 493 // retrieve system-assigned port 494 if (udpport_ == dynamic_port) { 495 ares_socklen_t len = sizeof(addr); 496 auto result = getsockname(udpfd_, (struct sockaddr*)&addr, &len); 497 EXPECT_EQ(0, result); 498 udpport_ = ntohs(addr.sin_port); 499 EXPECT_NE(dynamic_port, udpport_); 500 } 501 if (tcpport_ == dynamic_port) { 502 ares_socklen_t len = sizeof(addr); 503 auto result = getsockname(tcpfd_, (struct sockaddr*)&addr, &len); 504 EXPECT_EQ(0, result); 505 tcpport_ = ntohs(addr.sin_port); 506 EXPECT_NE(dynamic_port, tcpport_); 507 } 508 } else { 509 EXPECT_EQ(AF_INET6, family); 510 struct sockaddr_in6 addr; 511 memset(&addr, 0, sizeof(addr)); 512 addr.sin6_family = AF_INET6; 513 memset(&addr.sin6_addr, 0, sizeof(addr.sin6_addr)); // in6addr_any 514 addr.sin6_port = htons(tcpport_); 515 int tcprc = bind(tcpfd_, (struct sockaddr*)&addr, sizeof(addr)); 516 EXPECT_EQ(0, tcprc) << "Failed to bind AF_INET6 to TCP port " << tcpport_; 517 addr.sin6_port = htons(udpport_); 518 int udprc = bind(udpfd_, (struct sockaddr*)&addr, sizeof(addr)); 519 EXPECT_EQ(0, udprc) << "Failed to bind AF_INET6 to UDP port " << udpport_; 520 // retrieve system-assigned port 521 if (udpport_ == dynamic_port) { 522 ares_socklen_t len = sizeof(addr); 523 auto result = getsockname(udpfd_, (struct sockaddr*)&addr, &len); 524 EXPECT_EQ(0, result); 525 udpport_ = ntohs(addr.sin6_port); 526 EXPECT_NE(dynamic_port, udpport_); 527 } 528 if (tcpport_ == dynamic_port) { 529 ares_socklen_t len = sizeof(addr); 530 auto result = getsockname(tcpfd_, (struct sockaddr*)&addr, &len); 531 EXPECT_EQ(0, result); 532 tcpport_ = ntohs(addr.sin6_port); 533 EXPECT_NE(dynamic_port, tcpport_); 534 } 535 } 536 if (verbose) std::cerr << "Configured " 537 << (family == AF_INET ? "IPv4" : "IPv6") 538 << " mock server with TCP socket " << tcpfd_ 539 << " on port " << tcpport_ 540 << " and UDP socket " << udpfd_ 541 << " on port " << udpport_ << std::endl; 542 543 // For TCP, also need to listen for connections. 544 EXPECT_EQ(0, listen(tcpfd_, 5)) << "Failed to listen for TCP connections"; 545 } 546 547 MockServer::~MockServer() { 548 for (ares_socket_t fd : connfds_) { 549 sclose(fd); 550 } 551 sclose(tcpfd_); 552 sclose(udpfd_); 553 free(tcp_data_); 554 } 555 556 static unsigned short getaddrport(struct sockaddr_storage *addr) 557 { 558 if (addr->ss_family == AF_INET) 559 return ntohs(((struct sockaddr_in *)(void *)addr)->sin_port); 560 if (addr->ss_family == AF_INET6) 561 return ntohs(((struct sockaddr_in6 *)(void *)addr)->sin6_port); 562 563 /* TCP should use getpeername() to get the port, getting this from recvfrom 564 * won't work */ 565 return 0; 566 } 567 568 void MockServer::ProcessPacket(ares_socket_t fd, struct sockaddr_storage *addr, ares_socklen_t addrlen, 569 byte *data, int len) { 570 571 // Assume the packet is a well-formed DNS request and extract the request 572 // details. 573 if (len < NS_HFIXEDSZ) { 574 std::cerr << "Packet too short (" << len << ")" << std::endl; 575 return; 576 } 577 int qid = DNS_HEADER_QID(data); 578 if (DNS_HEADER_QR(data) != 0) { 579 std::cerr << "Not a request" << std::endl; 580 return; 581 } 582 if (DNS_HEADER_OPCODE(data) != O_QUERY) { 583 std::cerr << "Not a query (opcode " << DNS_HEADER_OPCODE(data) 584 << ")" << std::endl; 585 return; 586 } 587 if (DNS_HEADER_QDCOUNT(data) != 1) { 588 std::cerr << "Unexpected question count (" << DNS_HEADER_QDCOUNT(data) 589 << ")" << std::endl; 590 return; 591 } 592 byte* question = data + NS_HFIXEDSZ; 593 int qlen = len - NS_HFIXEDSZ; 594 595 char *name = nullptr; 596 long enclen; 597 ares_expand_name(question, data, len, &name, &enclen); 598 if (!name) { 599 std::cerr << "Failed to retrieve name" << std::endl; 600 return; 601 } 602 if (enclen > qlen) { 603 std::cerr << "(error, encoded name len " << enclen << "bigger than remaining data " << qlen << " bytes)" << std::endl; 604 ares_free_string(name); 605 return; 606 } 607 qlen -= (int)enclen; 608 question += enclen; 609 610 if (qlen < 4) { 611 std::cerr << "Unexpected question size (" << qlen 612 << " bytes after name)" << std::endl; 613 ares_free_string(name); 614 return; 615 } 616 if (DNS_QUESTION_CLASS(question) != C_IN) { 617 std::cerr << "Unexpected question class (" << DNS_QUESTION_CLASS(question) 618 << ")" << std::endl; 619 ares_free_string(name); 620 return; 621 } 622 int rrtype = DNS_QUESTION_TYPE(question); 623 624 std::vector<byte> req(data, data + len); 625 std::string reqstr = PacketToString(req); 626 if (verbose) { 627 std::cerr << "received " << (fd == udpfd_ ? "UDP" : "TCP") << " request " << reqstr 628 << " on port " << (fd == udpfd_ ? udpport_ : tcpport_) 629 << ":" << getaddrport(addr) << std::endl; 630 std::cerr << "ProcessRequest(" << qid << ", '" << name 631 << "', " << RRTypeToString(rrtype) << ")" << std::endl; 632 } 633 ProcessRequest(fd, addr, addrlen, req, reqstr, qid, name, rrtype); 634 ares_free_string(name); 635 } 636 637 void MockServer::ProcessFD(ares_socket_t fd) { 638 if (fd != tcpfd_ && fd != udpfd_ && connfds_.find(fd) == connfds_.end()) { 639 // Not one of our FDs. 640 return; 641 } 642 if (fd == tcpfd_) { 643 ares_socket_t connfd = accept(tcpfd_, NULL, NULL); 644 if (connfd == ARES_SOCKET_BAD) { 645 std::cerr << "Error accepting connection on fd " << fd << std::endl; 646 } else { 647 connfds_.insert(connfd); 648 } 649 return; 650 } 651 652 // Activity on a data-bearing file descriptor. 653 struct sockaddr_storage addr; 654 socklen_t addrlen = sizeof(addr); 655 memset(&addr, 0, sizeof(addr)); 656 byte buffer[2048]; 657 ares_ssize_t len = (ares_ssize_t)recvfrom(fd, BYTE_CAST buffer, sizeof(buffer), 0, 658 (struct sockaddr *)&addr, &addrlen); 659 660 if (fd != udpfd_) { 661 if (len <= 0) { 662 connfds_.erase(std::find(connfds_.begin(), connfds_.end(), fd)); 663 sclose(fd); 664 free(tcp_data_); 665 tcp_data_ = NULL; 666 tcp_data_len_ = 0; 667 return; 668 } 669 tcp_data_ = (unsigned char *)realloc(tcp_data_, tcp_data_len_ + (size_t)len); 670 memcpy(tcp_data_ + tcp_data_len_, buffer, (size_t)len); 671 tcp_data_len_ += (size_t)len; 672 673 /* TCP might aggregate the various requests into a single packet, so we 674 * need to split */ 675 while (tcp_data_len_ > 2) { 676 size_t tcplen = ((size_t)tcp_data_[0] << 8) + (size_t)tcp_data_[1]; 677 if (tcp_data_len_ - 2 < tcplen) 678 break; 679 680 ProcessPacket(fd, &addr, addrlen, tcp_data_ + 2, (int)tcplen); 681 682 /* strip off processed data if connection not terminated */ 683 if (tcp_data_ != NULL) { 684 memmove(tcp_data_, tcp_data_ + tcplen + 2, tcp_data_len_ - 2 - tcplen); 685 tcp_data_len_ -= 2 + tcplen; 686 } 687 } 688 } else { 689 /* UDP is always a single packet */ 690 ProcessPacket(fd, &addr, addrlen, buffer, (int)len); 691 } 692 693 } 694 695 std::set<ares_socket_t> MockServer::fds() const { 696 std::set<ares_socket_t> result = connfds_; 697 result.insert(tcpfd_); 698 result.insert(udpfd_); 699 return result; 700 } 701 702 void MockServer::ProcessRequest(ares_socket_t fd, struct sockaddr_storage* addr, 703 ares_socklen_t addrlen, const std::vector<byte> &req, 704 const std::string &reqstr, 705 int qid, const char *name, int rrtype) { 706 707 /* DNS 0x20 will mix case, do case-insensitive matching of name in request */ 708 char lower_name[256]; 709 int flags = 0; 710 711 arestest_strtolower(lower_name, name, sizeof(lower_name)); 712 713 // Before processing, let gMock know the request is happening. 714 OnRequest(lower_name, rrtype); 715 716 // If we are expecting a specific request then check it matches here. 717 if (expected_request_.length() > 0) { 718 ASSERT_EQ(expected_request_, reqstr); 719 } 720 721 if (reply_ != nullptr) { 722 ares_dns_record_t *dnsrec = NULL; 723 /* We will *attempt* to parse the request string. It may be malformed that 724 * will lead to a parse failure. If so, we just ignore it. We want to 725 * pass this parsed data structure to the reply generator in case it needs 726 * to extract metadata (such as a DNS client cookie) from the original 727 * request. If we can't parse it, oh well, we'll just pass NULL, most 728 * replies don't need anything from the request other than the name which 729 * is passed separately. */ 730 ares_dns_parse(req.data(), req.size(), 0, &dnsrec); 731 exact_reply_ = reply_->data(name, dnsrec); 732 ares_dns_record_destroy(dnsrec); 733 } 734 735 if (exact_reply_.size() == 0) { 736 return; 737 } 738 739 // Make a local copy of the current pending reply. 740 std::vector<byte> reply = exact_reply_; 741 742 if (qid_ >= 0) { 743 // Use the explicitly specified query ID. 744 qid = qid_; 745 } 746 if (reply.size() >= 2) { 747 // Overwrite the query ID if space to do so. 748 reply[0] = (byte)((qid >> 8) & 0xff); 749 reply[1] = (byte)(qid & 0xff); 750 } 751 if (verbose) { 752 std::cerr << "sending reply " << PacketToString(reply) 753 << " on port " << ((fd == udpfd_) ? udpport_ : tcpport_) 754 << ":" << getaddrport(addr) << std::endl; 755 } 756 757 // Prefix with 2-byte length if TCP. 758 if (fd != udpfd_) { 759 int len = (int)reply.size(); 760 std::vector<byte> vlen = {(byte)((len & 0xFF00) >> 8), (byte)(len & 0xFF)}; 761 reply.insert(reply.begin(), vlen.begin(), vlen.end()); 762 // Also, don't bother with the destination address. 763 addr = nullptr; 764 addrlen = 0; 765 } 766 767 #ifdef MSG_NOSIGNAL 768 flags |= MSG_NOSIGNAL; 769 #endif 770 771 ares_ssize_t rc = (ares_ssize_t)sendto(fd, BYTE_CAST reply.data(), (SEND_TYPE_ARG3)reply.size(), flags, 772 (struct sockaddr *)addr, addrlen); 773 if (rc < static_cast<ares_ssize_t>(reply.size())) { 774 std::cerr << "Failed to send full reply, rc=" << rc << std::endl; 775 } 776 777 } 778 779 // static 780 MockChannelOptsTest::NiceMockServers MockChannelOptsTest::BuildServers(int count, int family, unsigned short base_port) { 781 NiceMockServers servers; 782 assert(count > 0); 783 for (unsigned short ii = 0; ii < count; ii++) { 784 unsigned short port = base_port == dynamic_port ? dynamic_port : base_port + ii; 785 std::unique_ptr<NiceMockServer> server(new NiceMockServer(family, port)); 786 servers.push_back(std::move(server)); 787 } 788 return servers; 789 } 790 791 MockChannelOptsTest::MockChannelOptsTest(int count, 792 int family, 793 bool force_tcp, 794 bool honor_sysconfig, 795 struct ares_options* givenopts, 796 int optmask) 797 : servers_(BuildServers(count, family, mock_port)), 798 server_(*servers_[0].get()), channel_(nullptr) { 799 // Set up channel options. 800 const char *domains[3] = {"first.com", "second.org", "third.gov"}; 801 struct ares_options opts; 802 if (givenopts) { 803 memcpy(&opts, givenopts, sizeof(opts)); 804 } else { 805 memset(&opts, 0, sizeof(opts)); 806 } 807 808 /* Honor items from resolv.conf except the dns server itself */ 809 if (!honor_sysconfig) { 810 if (!(optmask & (ARES_OPT_TIMEOUTMS|ARES_OPT_TIMEOUT))) { 811 // Reduce timeouts significantly to shorten test times. 812 opts.timeout = 250; 813 optmask |= ARES_OPT_TIMEOUTMS; 814 } 815 // If not already overridden, set 3 retries. 816 if (!(optmask & ARES_OPT_TRIES)) { 817 opts.tries = 3; 818 optmask |= ARES_OPT_TRIES; 819 } 820 821 // If not already overridden, set search domains. 822 if (!(optmask & ARES_OPT_DOMAINS)) { 823 opts.ndomains = 3; 824 opts.domains = (char**)domains; 825 optmask |= ARES_OPT_DOMAINS; 826 } 827 828 /* Tests expect ndots=1 in general, the system config may not default to this 829 * so we don't want to inherit that. */ 830 if (!(optmask & ARES_OPT_NDOTS)) { 831 opts.ndots = 1; 832 optmask |= ARES_OPT_NDOTS; 833 } 834 } 835 836 if (force_tcp) { 837 opts.flags |= ARES_FLAG_USEVC; 838 optmask |= ARES_OPT_FLAGS; 839 } 840 841 /* Disable the query cache for tests unless explicitly enabled. As of 842 * c-ares 1.31.0, the query cache is enabled by default so we have to set 843 * the option and set the TTL to 0 to effectively disable it. */ 844 if (!(optmask & ARES_OPT_QUERY_CACHE)) { 845 opts.qcache_max_ttl = 0; 846 optmask |= ARES_OPT_QUERY_CACHE; 847 } 848 849 /* Enable DNS0x20 by default. Need to also turn on default flag of EDNS */ 850 if (!(optmask & ARES_OPT_FLAGS)) { 851 optmask |= ARES_OPT_FLAGS; 852 opts.flags = ARES_FLAG_DNS0x20|ARES_FLAG_EDNS; 853 } 854 855 EXPECT_EQ(ARES_SUCCESS, ares_init_options(&channel_, &opts, optmask)); 856 EXPECT_NE(nullptr, channel_); 857 858 // Set up servers after construction so we can set individual ports 859 struct ares_addr_port_node* prev = nullptr; 860 struct ares_addr_port_node* first = nullptr; 861 for (const auto& server : servers_) { 862 struct ares_addr_port_node* node = (struct ares_addr_port_node*)malloc(sizeof(*node)); 863 if (prev) { 864 prev->next = node; 865 } else { 866 first = node; 867 } 868 node->next = nullptr; 869 node->family = family; 870 node->udp_port = server->udpport(); 871 node->tcp_port = server->tcpport(); 872 if (family == AF_INET) { 873 node->addr.addr4.s_addr = htonl(0x7F000001); 874 } else { 875 memset(&node->addr.addr6, 0, sizeof(node->addr.addr6)); 876 node->addr.addr6._S6_un._S6_u8[15] = 1; 877 } 878 prev = node; 879 } 880 EXPECT_EQ(ARES_SUCCESS, ares_set_servers_ports(channel_, first)); 881 882 while (first) { 883 prev = first; 884 first = first->next; 885 free(prev); 886 } 887 if (verbose) { 888 std::cerr << "Configured library with servers:"; 889 std::cerr << GetNameServers(channel_); 890 std::cerr << std::endl; 891 } 892 } 893 894 MockChannelOptsTest::~MockChannelOptsTest() { 895 if (channel_) { 896 ares_destroy(channel_); 897 } 898 channel_ = nullptr; 899 } 900 901 std::set<ares_socket_t> MockChannelOptsTest::fds() const { 902 std::set<ares_socket_t> fds; 903 for (const auto& server : servers_) { 904 std::set<ares_socket_t> serverfds = server->fds(); 905 fds.insert(serverfds.begin(), serverfds.end()); 906 } 907 return fds; 908 } 909 910 void MockChannelOptsTest::ProcessFD(ares_socket_t fd) { 911 for (auto& server : servers_) { 912 server->ProcessFD(fd); 913 } 914 } 915 916 void MockChannelOptsTest::ProcessAltChannel(ares_channel_t *chan, unsigned int cancel_ms) { 917 using namespace std::placeholders; 918 ProcessWork(chan, 919 std::bind(&MockChannelOptsTest::fds, this), 920 std::bind(&MockChannelOptsTest::ProcessFD, this, _1), 921 cancel_ms); 922 } 923 924 void MockChannelOptsTest::Process(unsigned int cancel_ms) { 925 ProcessAltChannel(channel_, cancel_ms); 926 } 927 928 void MockEventThreadOptsTest::Process(unsigned int cancel_ms) { 929 std::set<ares_socket_t> fds; 930 931 auto tv_begin = std::chrono::high_resolution_clock::now(); 932 auto tv_cancel = tv_begin; 933 934 if (cancel_ms) { 935 if (verbose) std::cerr << "ares_cancel will be called after " << cancel_ms << "ms" << std::endl; 936 tv_cancel += std::chrono::milliseconds(cancel_ms); 937 } 938 939 while (ares_queue_active_queries(channel_)) { 940 //if (verbose) std::cerr << "pending queries: " << ares_queue_active_queries(channel_) << std::endl; 941 942 int nfds = 0; 943 fd_set readers; 944 945 struct timeval tv; 946 947 /* c-ares is using its own event thread, so we only need to monitor the 948 * extrafds passed in */ 949 FD_ZERO(&readers); 950 fds = MockEventThreadOptsTest::fds(); 951 for (ares_socket_t fd : fds) { 952 FD_SET(fd, &readers); 953 if (fd >= (ares_socket_t)nfds) { 954 nfds = (int)fd + 1; 955 } 956 } 957 958 /* We just always wait 20ms then recheck if we're done. Not doing any 959 * complex signaling. */ 960 tv.tv_sec = 0; 961 tv.tv_usec = 20000; 962 963 if (cancel_ms) { 964 auto tv_now = std::chrono::high_resolution_clock::now(); 965 auto remaining_ms = std::chrono::duration_cast<std::chrono::milliseconds>(tv_cancel - tv_now).count(); 966 967 if (remaining_ms <= 0) { 968 if (verbose) std::cerr << "Issuing ares_cancel()" << std::endl; 969 ares_cancel(channel_); 970 cancel_ms = 0; /* Disable issuing cancel again */ 971 } else { 972 tv.tv_sec = remaining_ms / 1000; 973 tv.tv_usec = (int)(remaining_ms % 1000); 974 } 975 } 976 977 if (select(nfds, &readers, nullptr, nullptr, &tv) < 0) { 978 fprintf(stderr, "select() failed, errno %d\n", errno); 979 return; 980 } 981 982 // Let the provided callback process any activity on the extra FD. 983 for (ares_socket_t fd : fds) { 984 if (FD_ISSET(fd, &readers)) { 985 ProcessFD(fd); 986 } 987 } 988 } 989 990 //if (verbose) std::cerr << "pending queries at process end: " << ares_queue_active_queries(channel_) << std::endl; 991 } 992 993 std::ostream& operator<<(std::ostream& os, const HostResult& result) { 994 os << '{'; 995 if (result.done_) { 996 os << StatusToString(result.status_); 997 if (result.host_.addrtype_ != -1) { 998 os << " " << result.host_; 999 } else { 1000 os << ", (no hostent)"; 1001 } 1002 } else { 1003 os << "(incomplete)"; 1004 } 1005 os << '}'; 1006 return os; 1007 } 1008 1009 HostEnt::HostEnt(const struct hostent *hostent) : addrtype_(-1) { 1010 if (!hostent) 1011 return; 1012 1013 if (hostent->h_name) { 1014 // DNS 0x20 may mix case, output as all lower for checks as the mixed case 1015 // is really more of an internal thing 1016 char lowername[256]; 1017 arestest_strtolower(lowername, hostent->h_name, sizeof(lowername)); 1018 name_ = lowername; 1019 } 1020 1021 if (hostent->h_aliases) { 1022 char** palias = hostent->h_aliases; 1023 while (*palias != nullptr) { 1024 aliases_.push_back(*palias); 1025 palias++; 1026 } 1027 } 1028 1029 addrtype_ = hostent->h_addrtype; 1030 1031 if (hostent->h_addr_list) { 1032 char** paddr = hostent->h_addr_list; 1033 while (*paddr != nullptr) { 1034 std::string addr = AddressToString(*paddr, hostent->h_length); 1035 addrs_.push_back(addr); 1036 paddr++; 1037 } 1038 } 1039 } 1040 1041 std::ostream& operator<<(std::ostream& os, const HostEnt& host) { 1042 os << "{'"; 1043 if (host.name_.length() > 0) { 1044 os << host.name_; 1045 } 1046 os << "' aliases=["; 1047 for (size_t ii = 0; ii < host.aliases_.size(); ii++) { 1048 if (ii > 0) os << ", "; 1049 os << host.aliases_[ii]; 1050 } 1051 os << "] "; 1052 os << "addrs=["; 1053 for (size_t ii = 0; ii < host.addrs_.size(); ii++) { 1054 if (ii > 0) os << ", "; 1055 os << host.addrs_[ii]; 1056 } 1057 os << "]"; 1058 os << '}'; 1059 return os; 1060 } 1061 1062 void HostCallback(void *data, int status, int timeouts, 1063 struct hostent *hostent) { 1064 EXPECT_NE(nullptr, data); 1065 if (data == nullptr) 1066 return; 1067 1068 HostResult* result = reinterpret_cast<HostResult*>(data); 1069 result->done_ = true; 1070 result->status_ = status; 1071 result->timeouts_ = timeouts; 1072 if (hostent) 1073 result->host_ = HostEnt(hostent); 1074 if (verbose) std::cerr << "HostCallback(" << *result << ")" << std::endl; 1075 } 1076 1077 std::ostream& operator<<(std::ostream& os, const AresDnsRecord& dnsrec) { 1078 os << "{'"; 1079 /* XXX: Todo */ 1080 os << '}'; 1081 return os; 1082 } 1083 1084 std::ostream& operator<<(std::ostream& os, const QueryResult& result) { 1085 os << '{'; 1086 if (result.done_) { 1087 os << StatusToString(result.status_); 1088 if (result.dnsrec_.dnsrec_ != nullptr) { 1089 os << " " << result.dnsrec_; 1090 } else { 1091 os << ", (no dnsrec)"; 1092 } 1093 } else { 1094 os << "(incomplete)"; 1095 } 1096 os << '}'; 1097 return os; 1098 } 1099 1100 void QueryCallback(void *data, ares_status_t status, size_t timeouts, 1101 const ares_dns_record_t *dnsrec) { 1102 EXPECT_NE(nullptr, data); 1103 if (data == nullptr) 1104 return; 1105 1106 QueryResult* result = reinterpret_cast<QueryResult*>(data); 1107 result->done_ = true; 1108 result->status_ = status; 1109 result->timeouts_ = timeouts; 1110 if (dnsrec) 1111 result->dnsrec_.SetDnsRecord(dnsrec); 1112 if (verbose) std::cerr << "QueryCallback(" << *result << ")" << std::endl; 1113 } 1114 1115 std::ostream& operator<<(std::ostream& os, const AddrInfoResult& result) { 1116 os << '{'; 1117 if (result.done_ && result.ai_) { 1118 os << StatusToString(result.status_) << " " << result.ai_; 1119 } else { 1120 os << "(incomplete)"; 1121 } 1122 os << '}'; 1123 return os; 1124 } 1125 1126 std::ostream& operator<<(std::ostream& os, const AddrInfo& ai) { 1127 os << '{'; 1128 if (ai == nullptr) { 1129 os << "nullptr}"; 1130 return os; 1131 } 1132 1133 struct ares_addrinfo_cname *next_cname = ai->cnames; 1134 while(next_cname) { 1135 if(next_cname->alias) { 1136 os << next_cname->alias << "->"; 1137 } 1138 if(next_cname->name) { 1139 os << next_cname->name; 1140 } 1141 1142 next_cname = next_cname->next; 1143 1144 if (next_cname != NULL) 1145 os << ", "; 1146 else 1147 os << " "; 1148 } 1149 1150 struct ares_addrinfo_node *next = ai->nodes; 1151 while(next) { 1152 //if(next->ai_canonname) { 1153 //os << "'" << next->ai_canonname << "' "; 1154 //} 1155 unsigned short port = 0; 1156 os << "addr=["; 1157 if(next->ai_family == AF_INET) { 1158 sockaddr_in* sin = (sockaddr_in *)((void *)next->ai_addr); 1159 port = ntohs(sin->sin_port); 1160 os << AddressToString(&sin->sin_addr, 4); 1161 } 1162 else if (next->ai_family == AF_INET6) { 1163 sockaddr_in6* sin = (sockaddr_in6*)((void *)next->ai_addr); 1164 port = ntohs(sin->sin6_port); 1165 os << "[" << AddressToString(&sin->sin6_addr, 16) << "]"; 1166 } 1167 else 1168 os << "unknown family"; 1169 if(port) { 1170 os << ":" << port; 1171 } 1172 os << "]"; 1173 next = next->ai_next; 1174 if (next != NULL) 1175 os << ", "; 1176 } 1177 os << '}'; 1178 return os; 1179 } 1180 1181 void AddrInfoCallback(void *data, int status, int timeouts, 1182 struct ares_addrinfo *ai) { 1183 EXPECT_NE(nullptr, data); 1184 AddrInfoResult* result = reinterpret_cast<AddrInfoResult*>(data); 1185 result->done_ = true; 1186 result->status_ = status; 1187 result->timeouts_= timeouts; 1188 if (ai) 1189 result->ai_ = AddrInfo(ai); 1190 if (verbose) std::cerr << "AddrInfoCallback(" << *result << ")" << std::endl; 1191 } 1192 1193 std::ostream& operator<<(std::ostream& os, const SearchResult& result) { 1194 os << '{'; 1195 if (result.done_) { 1196 os << StatusToString(result.status_) << " " << PacketToString(result.data_); 1197 } else { 1198 os << "(incomplete)"; 1199 } 1200 os << '}'; 1201 return os; 1202 } 1203 1204 void SearchCallback(void *data, int status, int timeouts, 1205 unsigned char *abuf, int alen) { 1206 EXPECT_NE(nullptr, data); 1207 SearchResult* result = reinterpret_cast<SearchResult*>(data); 1208 result->done_ = true; 1209 result->status_ = status; 1210 result->timeouts_ = timeouts; 1211 result->data_.assign(abuf, abuf + alen); 1212 if (verbose) std::cerr << "SearchCallback(" << *result << ")" << std::endl; 1213 } 1214 1215 void SearchCallbackDnsRec(void *data, ares_status_t status, size_t timeouts, 1216 const ares_dns_record_t *dnsrec) { 1217 EXPECT_NE(nullptr, data); 1218 SearchResult* result = reinterpret_cast<SearchResult*>(data); 1219 unsigned char *abuf = NULL; 1220 size_t alen = 0; 1221 result->done_ = true; 1222 result->status_ = (int)status; 1223 result->timeouts_ = (int)timeouts; 1224 if (dnsrec != NULL) { 1225 ares_dns_write(dnsrec, &abuf, &alen); 1226 } 1227 result->data_.assign(abuf, abuf + alen); 1228 ares_free_string(abuf); 1229 if (verbose) std::cerr << "SearchCallbackDnsRec(" << *result << ")" << std::endl; 1230 } 1231 1232 std::ostream& operator<<(std::ostream& os, const NameInfoResult& result) { 1233 os << '{'; 1234 if (result.done_) { 1235 os << StatusToString(result.status_) << " " << result.node_ << " " << result.service_; 1236 } else { 1237 os << "(incomplete)"; 1238 } 1239 os << '}'; 1240 return os; 1241 } 1242 1243 void NameInfoCallback(void *data, int status, int timeouts, 1244 char *node, char *service) { 1245 EXPECT_NE(nullptr, data); 1246 NameInfoResult* result = reinterpret_cast<NameInfoResult*>(data); 1247 result->done_ = true; 1248 result->status_ = status; 1249 result->timeouts_ = timeouts; 1250 result->node_ = std::string(node ? node : ""); 1251 result->service_ = std::string(service ? service : ""); 1252 if (verbose) std::cerr << "NameInfoCallback(" << *result << ")" << std::endl; 1253 } 1254 1255 std::string GetNameServers(ares_channel_t *channel) { 1256 char *csv = ares_get_servers_csv(channel); 1257 EXPECT_NE((char *)NULL, csv); 1258 1259 std::string servers(csv); 1260 1261 ares_free_string(csv); 1262 return servers; 1263 } 1264 1265 TransientDir::TransientDir(const std::string& dirname) : dirname_(dirname) { 1266 if (mkdir_(dirname_.c_str(), 0755) != 0) { 1267 std::cerr << "Failed to create subdirectory '" << dirname_ << "'" << std::endl; 1268 } 1269 } 1270 1271 TransientDir::~TransientDir() { 1272 rmdir(dirname_.c_str()); 1273 } 1274 1275 TransientFile::TransientFile(const std::string& filename, 1276 const std::string& contents) 1277 : filename_(filename) { 1278 FILE *f = fopen(filename.c_str(), "w"); 1279 if (f == nullptr) { 1280 std::cerr << "Error: failed to create '" << filename << "'" << std::endl; 1281 return; 1282 } 1283 size_t rc = (size_t)fwrite(contents.data(), 1, contents.size(), f); 1284 if (rc != contents.size()) { 1285 std::cerr << "Error: failed to write contents of '" << filename << "'" << std::endl; 1286 } 1287 fclose(f); 1288 } 1289 1290 TransientFile::~TransientFile() { 1291 unlink(filename_.c_str()); 1292 } 1293 1294 std::string TempNam(const char *dir, const char *prefix) { 1295 char *p = tempnam(dir, prefix); 1296 std::string result(p); 1297 free(p); 1298 return result; 1299 } 1300 1301 TempFile::TempFile(const std::string& contents) 1302 : TransientFile(TempNam(nullptr, "ares"), contents) { 1303 1304 } 1305 1306 VirtualizeIO::VirtualizeIO(ares_channel_t *c) 1307 : channel_(c) 1308 { 1309 ares_set_socket_functions(channel_, &default_functions, 0); 1310 } 1311 1312 VirtualizeIO::~VirtualizeIO() { 1313 ares_set_socket_functions(channel_, 0, 0); 1314 } 1315 1316 } // namespace test 1317 } // namespace ares