1// 2// detail/impl/socket_ops.ipp 3// ~~~~~~~~~~~~~~~~~~~~~~~~~~ 4// 5// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com) 6// 7// Distributed under the Boost Software License, Version 1.0. (See accompanying 8// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9// 10 11#ifndef ASIO_DETAIL_SOCKET_OPS_IPP 12#define ASIO_DETAIL_SOCKET_OPS_IPP 13 14#if defined(_MSC_VER) && (_MSC_VER >= 1200) 15# pragma once 16#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 17 18#include "asio/detail/config.hpp" 19 20#include <cctype> 21#include <cstdio> 22#include <cstdlib> 23#include <cstring> 24#include <cerrno> 25#include <new> 26#include "asio/detail/assert.hpp" 27#include "asio/detail/socket_ops.hpp" 28#include "asio/error.hpp" 29 30#if defined(ASIO_WINDOWS_RUNTIME) 31# include <codecvt> 32# include <locale> 33# include <string> 34#endif // defined(ASIO_WINDOWS_RUNTIME) 35 36#if defined(ASIO_WINDOWS) || defined(__CYGWIN__) \ 37 || defined(__MACH__) && defined(__APPLE__) 38# if defined(ASIO_HAS_PTHREADS) 39# include <pthread.h> 40# endif // defined(ASIO_HAS_PTHREADS) 41#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__) 42 // || defined(__MACH__) && defined(__APPLE__) 43 44#include "asio/detail/push_options.hpp" 45 46namespace asio { 47namespace detail { 48namespace socket_ops { 49 50#if !defined(ASIO_WINDOWS_RUNTIME) 51 52#if defined(ASIO_WINDOWS) || defined(__CYGWIN__) 53struct msghdr { int msg_namelen; }; 54#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__) 55 56#if defined(__hpux) 57// HP-UX doesn't declare these functions extern "C", so they are declared again 58// here to avoid linker errors about undefined symbols. 59extern "C" char* if_indextoname(unsigned int, char*); 60extern "C" unsigned int if_nametoindex(const char*); 61#endif // defined(__hpux) 62 63#endif // !defined(ASIO_WINDOWS_RUNTIME) 64 65inline void clear_last_error() 66{ 67#if defined(ASIO_WINDOWS) || defined(__CYGWIN__) 68 WSASetLastError(0); 69#else 70 errno = 0; 71#endif 72} 73 74#if !defined(ASIO_WINDOWS_RUNTIME) 75 76template <typename ReturnType> 77inline ReturnType error_wrapper(ReturnType return_value, 78 asio::error_code& ec) 79{ 80#if defined(ASIO_WINDOWS) || defined(__CYGWIN__) 81 ec = asio::error_code(WSAGetLastError(), 82 asio::error::get_system_category()); 83#else 84 ec = asio::error_code(errno, 85 asio::error::get_system_category()); 86#endif 87 return return_value; 88} 89 90template <typename SockLenType> 91inline socket_type call_accept(SockLenType msghdr::*, 92 socket_type s, socket_addr_type* addr, std::size_t* addrlen) 93{ 94 SockLenType tmp_addrlen = addrlen ? (SockLenType)*addrlen : 0; 95 socket_type result = ::accept(s, addr, addrlen ? &tmp_addrlen : 0); 96 if (addrlen) 97 *addrlen = (std::size_t)tmp_addrlen; 98 return result; 99} 100 101socket_type accept(socket_type s, socket_addr_type* addr, 102 std::size_t* addrlen, asio::error_code& ec) 103{ 104 if (s == invalid_socket) 105 { 106 ec = asio::error::bad_descriptor; 107 return invalid_socket; 108 } 109 110 clear_last_error(); 111 112 socket_type new_s = error_wrapper(call_accept( 113 &msghdr::msg_namelen, s, addr, addrlen), ec); 114 if (new_s == invalid_socket) 115 return new_s; 116 117#if defined(__MACH__) && defined(__APPLE__) || (defined(__FreeBSD__) || defined(__DragonFly__)) 118 int optval = 1; 119 int result = error_wrapper(::setsockopt(new_s, 120 SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)), ec); 121 if (result != 0) 122 { 123 ::close(new_s); 124 return invalid_socket; 125 } 126#endif 127 128 ec = asio::error_code(); 129 return new_s; 130} 131 132socket_type sync_accept(socket_type s, state_type state, 133 socket_addr_type* addr, std::size_t* addrlen, asio::error_code& ec) 134{ 135 // Accept a socket. 136 for (;;) 137 { 138 // Try to complete the operation without blocking. 139 socket_type new_socket = socket_ops::accept(s, addr, addrlen, ec); 140 141 // Check if operation succeeded. 142 if (new_socket != invalid_socket) 143 return new_socket; 144 145 // Operation failed. 146 if (ec == asio::error::would_block 147 || ec == asio::error::try_again) 148 { 149 if (state & user_set_non_blocking) 150 return invalid_socket; 151 // Fall through to retry operation. 152 } 153 else if (ec == asio::error::connection_aborted) 154 { 155 if (state & enable_connection_aborted) 156 return invalid_socket; 157 // Fall through to retry operation. 158 } 159#if defined(EPROTO) 160 else if (ec.value() == EPROTO) 161 { 162 if (state & enable_connection_aborted) 163 return invalid_socket; 164 // Fall through to retry operation. 165 } 166#endif // defined(EPROTO) 167 else 168 return invalid_socket; 169 170 // Wait for socket to become ready. 171 if (socket_ops::poll_read(s, 0, ec) < 0) 172 return invalid_socket; 173 } 174} 175 176#if defined(ASIO_HAS_IOCP) 177 178void complete_iocp_accept(socket_type s, 179 void* output_buffer, DWORD address_length, 180 socket_addr_type* addr, std::size_t* addrlen, 181 socket_type new_socket, asio::error_code& ec) 182{ 183 // Map non-portable errors to their portable counterparts. 184 if (ec.value() == ERROR_NETNAME_DELETED) 185 ec = asio::error::connection_aborted; 186 187 if (!ec) 188 { 189 // Get the address of the peer. 190 if (addr && addrlen) 191 { 192 LPSOCKADDR local_addr = 0; 193 int local_addr_length = 0; 194 LPSOCKADDR remote_addr = 0; 195 int remote_addr_length = 0; 196 GetAcceptExSockaddrs(output_buffer, 0, address_length, 197 address_length, &local_addr, &local_addr_length, 198 &remote_addr, &remote_addr_length); 199 if (static_cast<std::size_t>(remote_addr_length) > *addrlen) 200 { 201 ec = asio::error::invalid_argument; 202 } 203 else 204 { 205 using namespace std; // For memcpy. 206 memcpy(addr, remote_addr, remote_addr_length); 207 *addrlen = static_cast<std::size_t>(remote_addr_length); 208 } 209 } 210 211 // Need to set the SO_UPDATE_ACCEPT_CONTEXT option so that getsockname 212 // and getpeername will work on the accepted socket. 213 SOCKET update_ctx_param = s; 214 socket_ops::state_type state = 0; 215 socket_ops::setsockopt(new_socket, state, 216 SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, 217 &update_ctx_param, sizeof(SOCKET), ec); 218 } 219} 220 221#else // defined(ASIO_HAS_IOCP) 222 223bool non_blocking_accept(socket_type s, 224 state_type state, socket_addr_type* addr, std::size_t* addrlen, 225 asio::error_code& ec, socket_type& new_socket) 226{ 227 for (;;) 228 { 229 // Accept the waiting connection. 230 new_socket = socket_ops::accept(s, addr, addrlen, ec); 231 232 // Check if operation succeeded. 233 if (new_socket != invalid_socket) 234 return true; 235 236 // Retry operation if interrupted by signal. 237 if (ec == asio::error::interrupted) 238 continue; 239 240 // Operation failed. 241 if (ec == asio::error::would_block 242 || ec == asio::error::try_again) 243 { 244 if (state & user_set_non_blocking) 245 return true; 246 // Fall through to retry operation. 247 } 248 else if (ec == asio::error::connection_aborted) 249 { 250 if (state & enable_connection_aborted) 251 return true; 252 // Fall through to retry operation. 253 } 254#if defined(EPROTO) 255 else if (ec.value() == EPROTO) 256 { 257 if (state & enable_connection_aborted) 258 return true; 259 // Fall through to retry operation. 260 } 261#endif // defined(EPROTO) 262 else 263 return true; 264 265 return false; 266 } 267} 268 269#endif // defined(ASIO_HAS_IOCP) 270 271template <typename SockLenType> 272inline int call_bind(SockLenType msghdr::*, 273 socket_type s, const socket_addr_type* addr, std::size_t addrlen) 274{ 275 return ::bind(s, addr, (SockLenType)addrlen); 276} 277 278int bind(socket_type s, const socket_addr_type* addr, 279 std::size_t addrlen, asio::error_code& ec) 280{ 281 if (s == invalid_socket) 282 { 283 ec = asio::error::bad_descriptor; 284 return socket_error_retval; 285 } 286 287 clear_last_error(); 288 int result = error_wrapper(call_bind( 289 &msghdr::msg_namelen, s, addr, addrlen), ec); 290 if (result == 0) 291 ec = asio::error_code(); 292 return result; 293} 294 295int close(socket_type s, state_type& state, 296 bool destruction, asio::error_code& ec) 297{ 298 int result = 0; 299 if (s != invalid_socket) 300 { 301 // We don't want the destructor to block, so set the socket to linger in 302 // the background. If the user doesn't like this behaviour then they need 303 // to explicitly close the socket. 304 if (destruction && (state & user_set_linger)) 305 { 306 ::linger opt; 307 opt.l_onoff = 0; 308 opt.l_linger = 0; 309 asio::error_code ignored_ec; 310 socket_ops::setsockopt(s, state, SOL_SOCKET, 311 SO_LINGER, &opt, sizeof(opt), ignored_ec); 312 } 313 314 clear_last_error(); 315#if defined(ASIO_WINDOWS) || defined(__CYGWIN__) 316 result = error_wrapper(::closesocket(s), ec); 317#else // defined(ASIO_WINDOWS) || defined(__CYGWIN__) 318 result = error_wrapper(::close(s), ec); 319#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__) 320 321 if (result != 0 322 && (ec == asio::error::would_block 323 || ec == asio::error::try_again)) 324 { 325 // According to UNIX Network Programming Vol. 1, it is possible for 326 // close() to fail with EWOULDBLOCK under certain circumstances. What 327 // isn't clear is the state of the descriptor after this error. The one 328 // current OS where this behaviour is seen, Windows, says that the socket 329 // remains open. Therefore we'll put the descriptor back into blocking 330 // mode and have another attempt at closing it. 331#if defined(ASIO_WINDOWS) || defined(__CYGWIN__) 332 ioctl_arg_type arg = 0; 333 ::ioctlsocket(s, FIONBIO, &arg); 334#else // defined(ASIO_WINDOWS) || defined(__CYGWIN__) 335# if defined(__SYMBIAN32__) 336 int flags = ::fcntl(s, F_GETFL, 0); 337 if (flags >= 0) 338 ::fcntl(s, F_SETFL, flags & ~O_NONBLOCK); 339# else // defined(__SYMBIAN32__) 340 ioctl_arg_type arg = 0; 341 ::ioctl(s, FIONBIO, &arg); 342# endif // defined(__SYMBIAN32__) 343#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__) 344 state &= ~non_blocking; 345 346 clear_last_error(); 347#if defined(ASIO_WINDOWS) || defined(__CYGWIN__) 348 result = error_wrapper(::closesocket(s), ec); 349#else // defined(ASIO_WINDOWS) || defined(__CYGWIN__) 350 result = error_wrapper(::close(s), ec); 351#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__) 352 } 353 } 354 355 if (result == 0) 356 ec = asio::error_code(); 357 return result; 358} 359 360bool set_user_non_blocking(socket_type s, 361 state_type& state, bool value, asio::error_code& ec) 362{ 363 if (s == invalid_socket) 364 { 365 ec = asio::error::bad_descriptor; 366 return false; 367 } 368 369 clear_last_error(); 370#if defined(ASIO_WINDOWS) || defined(__CYGWIN__) 371 ioctl_arg_type arg = (value ? 1 : 0); 372 int result = error_wrapper(::ioctlsocket(s, FIONBIO, &arg), ec); 373#elif defined(__SYMBIAN32__) 374 int result = error_wrapper(::fcntl(s, F_GETFL, 0), ec); 375 if (result >= 0) 376 { 377 clear_last_error(); 378 int flag = (value ? (result | O_NONBLOCK) : (result & ~O_NONBLOCK)); 379 result = error_wrapper(::fcntl(s, F_SETFL, flag), ec); 380 } 381#else 382 ioctl_arg_type arg = (value ? 1 : 0); 383 int result = error_wrapper(::ioctl(s, FIONBIO, &arg), ec); 384#endif 385 386 if (result >= 0) 387 { 388 ec = asio::error_code(); 389 if (value) 390 state |= user_set_non_blocking; 391 else 392 { 393 // Clearing the user-set non-blocking mode always overrides any 394 // internally-set non-blocking flag. Any subsequent asynchronous 395 // operations will need to re-enable non-blocking I/O. 396 state &= ~(user_set_non_blocking | internal_non_blocking); 397 } 398 return true; 399 } 400 401 return false; 402} 403 404bool set_internal_non_blocking(socket_type s, 405 state_type& state, bool value, asio::error_code& ec) 406{ 407 if (s == invalid_socket) 408 { 409 ec = asio::error::bad_descriptor; 410 return false; 411 } 412 413 if (!value && (state & user_set_non_blocking)) 414 { 415 // It does not make sense to clear the internal non-blocking flag if the 416 // user still wants non-blocking behaviour. Return an error and let the 417 // caller figure out whether to update the user-set non-blocking flag. 418 ec = asio::error::invalid_argument; 419 return false; 420 } 421 422 clear_last_error(); 423#if defined(ASIO_WINDOWS) || defined(__CYGWIN__) 424 ioctl_arg_type arg = (value ? 1 : 0); 425 int result = error_wrapper(::ioctlsocket(s, FIONBIO, &arg), ec); 426#elif defined(__SYMBIAN32__) 427 int result = error_wrapper(::fcntl(s, F_GETFL, 0), ec); 428 if (result >= 0) 429 { 430 clear_last_error(); 431 int flag = (value ? (result | O_NONBLOCK) : (result & ~O_NONBLOCK)); 432 result = error_wrapper(::fcntl(s, F_SETFL, flag), ec); 433 } 434#else 435 ioctl_arg_type arg = (value ? 1 : 0); 436 int result = error_wrapper(::ioctl(s, FIONBIO, &arg), ec); 437#endif 438 439 if (result >= 0) 440 { 441 ec = asio::error_code(); 442 if (value) 443 state |= internal_non_blocking; 444 else 445 state &= ~internal_non_blocking; 446 return true; 447 } 448 449 return false; 450} 451 452int shutdown(socket_type s, int what, asio::error_code& ec) 453{ 454 if (s == invalid_socket) 455 { 456 ec = asio::error::bad_descriptor; 457 return socket_error_retval; 458 } 459 460 clear_last_error(); 461 int result = error_wrapper(::shutdown(s, what), ec); 462 if (result == 0) 463 ec = asio::error_code(); 464 return result; 465} 466 467template <typename SockLenType> 468inline int call_connect(SockLenType msghdr::*, 469 socket_type s, const socket_addr_type* addr, std::size_t addrlen) 470{ 471 return ::connect(s, addr, (SockLenType)addrlen); 472} 473 474int connect(socket_type s, const socket_addr_type* addr, 475 std::size_t addrlen, asio::error_code& ec) 476{ 477 if (s == invalid_socket) 478 { 479 ec = asio::error::bad_descriptor; 480 return socket_error_retval; 481 } 482 483 clear_last_error(); 484 int result = error_wrapper(call_connect( 485 &msghdr::msg_namelen, s, addr, addrlen), ec); 486 if (result == 0) 487 ec = asio::error_code(); 488#if defined(__linux__) 489 else if (ec == asio::error::try_again) 490 ec = asio::error::no_buffer_space; 491#endif // defined(__linux__) 492 return result; 493} 494 495void sync_connect(socket_type s, const socket_addr_type* addr, 496 std::size_t addrlen, asio::error_code& ec) 497{ 498 // Perform the connect operation. 499 socket_ops::connect(s, addr, addrlen, ec); 500 if (ec != asio::error::in_progress 501 && ec != asio::error::would_block) 502 { 503 // The connect operation finished immediately. 504 return; 505 } 506 507 // Wait for socket to become ready. 508 if (socket_ops::poll_connect(s, ec) < 0) 509 return; 510 511 // Get the error code from the connect operation. 512 int connect_error = 0; 513 size_t connect_error_len = sizeof(connect_error); 514 if (socket_ops::getsockopt(s, 0, SOL_SOCKET, SO_ERROR, 515 &connect_error, &connect_error_len, ec) == socket_error_retval) 516 return; 517 518 // Return the result of the connect operation. 519 ec = asio::error_code(connect_error, 520 asio::error::get_system_category()); 521} 522 523#if defined(ASIO_HAS_IOCP) 524 525void complete_iocp_connect(socket_type s, asio::error_code& ec) 526{ 527 // Map non-portable errors to their portable counterparts. 528 switch (ec.value()) 529 { 530 case ERROR_CONNECTION_REFUSED: 531 ec = asio::error::connection_refused; 532 break; 533 case ERROR_NETWORK_UNREACHABLE: 534 ec = asio::error::network_unreachable; 535 break; 536 case ERROR_HOST_UNREACHABLE: 537 ec = asio::error::host_unreachable; 538 break; 539 case ERROR_SEM_TIMEOUT: 540 ec = asio::error::timed_out; 541 break; 542 default: 543 break; 544 } 545 546 if (!ec) 547 { 548 // Need to set the SO_UPDATE_CONNECT_CONTEXT option so that getsockname 549 // and getpeername will work on the connected socket. 550 socket_ops::state_type state = 0; 551 const int so_update_connect_context = 0x7010; 552 socket_ops::setsockopt(s, state, SOL_SOCKET, 553 so_update_connect_context, 0, 0, ec); 554 } 555} 556 557#endif // defined(ASIO_HAS_IOCP) 558 559bool non_blocking_connect(socket_type s, asio::error_code& ec) 560{ 561 // Check if the connect operation has finished. This is required since we may 562 // get spurious readiness notifications from the reactor. 563#if defined(ASIO_WINDOWS) \ 564 || defined(__CYGWIN__) \ 565 || defined(__SYMBIAN32__) 566 fd_set write_fds; 567 FD_ZERO(&write_fds); 568 FD_SET(s, &write_fds); 569 fd_set except_fds; 570 FD_ZERO(&except_fds); 571 FD_SET(s, &except_fds); 572 timeval zero_timeout; 573 zero_timeout.tv_sec = 0; 574 zero_timeout.tv_usec = 0; 575 int ready = ::select(s + 1, 0, &write_fds, &except_fds, &zero_timeout); 576#else // defined(ASIO_WINDOWS) 577 // || defined(__CYGWIN__) 578 // || defined(__SYMBIAN32__) 579 pollfd fds; 580 fds.fd = s; 581 fds.events = POLLOUT; 582 fds.revents = 0; 583 int ready = ::poll(&fds, 1, 0); 584#endif // defined(ASIO_WINDOWS) 585 // || defined(__CYGWIN__) 586 // || defined(__SYMBIAN32__) 587 if (ready == 0) 588 { 589 // The asynchronous connect operation is still in progress. 590 return false; 591 } 592 593 // Get the error code from the connect operation. 594 int connect_error = 0; 595 size_t connect_error_len = sizeof(connect_error); 596 if (socket_ops::getsockopt(s, 0, SOL_SOCKET, SO_ERROR, 597 &connect_error, &connect_error_len, ec) == 0) 598 { 599 if (connect_error) 600 { 601 ec = asio::error_code(connect_error, 602 asio::error::get_system_category()); 603 } 604 else 605 ec = asio::error_code(); 606 } 607 608 return true; 609} 610 611int socketpair(int af, int type, int protocol, 612 socket_type sv[2], asio::error_code& ec) 613{ 614#if defined(ASIO_WINDOWS) || defined(__CYGWIN__) 615 (void)(af); 616 (void)(type); 617 (void)(protocol); 618 (void)(sv); 619 ec = asio::error::operation_not_supported; 620 return socket_error_retval; 621#else 622 clear_last_error(); 623 int result = error_wrapper(::socketpair(af, type, protocol, sv), ec); 624 if (result == 0) 625 ec = asio::error_code(); 626 return result; 627#endif 628} 629 630bool sockatmark(socket_type s, asio::error_code& ec) 631{ 632 if (s == invalid_socket) 633 { 634 ec = asio::error::bad_descriptor; 635 return false; 636 } 637 638#if defined(SIOCATMARK) 639 ioctl_arg_type value = 0; 640# if defined(ASIO_WINDOWS) || defined(__CYGWIN__) 641 int result = error_wrapper(::ioctlsocket(s, SIOCATMARK, &value), ec); 642# else // defined(ASIO_WINDOWS) || defined(__CYGWIN__) 643 int result = error_wrapper(::ioctl(s, SIOCATMARK, &value), ec); 644# endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__) 645 if (result == 0) 646 ec = asio::error_code(); 647# if defined(ENOTTY) 648 if (ec.value() == ENOTTY) 649 ec = asio::error::not_socket; 650# endif // defined(ENOTTY) 651#else // defined(SIOCATMARK) 652 int value = error_wrapper(::sockatmark(s), ec); 653 if (value != -1) 654 ec = asio::error_code(); 655#endif // defined(SIOCATMARK) 656 657 return ec ? false : value != 0; 658} 659 660size_t available(socket_type s, asio::error_code& ec) 661{ 662 if (s == invalid_socket) 663 { 664 ec = asio::error::bad_descriptor; 665 return 0; 666 } 667 668 ioctl_arg_type value = 0; 669#if defined(ASIO_WINDOWS) || defined(__CYGWIN__) 670 int result = error_wrapper(::ioctlsocket(s, FIONREAD, &value), ec); 671#else // defined(ASIO_WINDOWS) || defined(__CYGWIN__) 672 int result = error_wrapper(::ioctl(s, FIONREAD, &value), ec); 673#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__) 674 if (result == 0) 675 ec = asio::error_code(); 676#if defined(ENOTTY) 677 if (ec.value() == ENOTTY) 678 ec = asio::error::not_socket; 679#endif // defined(ENOTTY) 680 681 return ec ? static_cast<size_t>(0) : static_cast<size_t>(value); 682} 683 684int listen(socket_type s, int backlog, asio::error_code& ec) 685{ 686 if (s == invalid_socket) 687 { 688 ec = asio::error::bad_descriptor; 689 return socket_error_retval; 690 } 691 692 clear_last_error(); 693 int result = error_wrapper(::listen(s, backlog), ec); 694 if (result == 0) 695 ec = asio::error_code(); 696 return result; 697} 698 699inline void init_buf_iov_base(void*& base, void* addr) 700{ 701 base = addr; 702} 703 704template <typename T> 705inline void init_buf_iov_base(T& base, void* addr) 706{ 707 base = static_cast<T>(addr); 708} 709 710#if defined(ASIO_WINDOWS) || defined(__CYGWIN__) 711typedef WSABUF buf; 712#else // defined(ASIO_WINDOWS) || defined(__CYGWIN__) 713typedef iovec buf; 714#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__) 715 716void init_buf(buf& b, void* data, size_t size) 717{ 718#if defined(ASIO_WINDOWS) || defined(__CYGWIN__) 719 b.buf = static_cast<char*>(data); 720 b.len = static_cast<u_long>(size); 721#else // defined(ASIO_WINDOWS) || defined(__CYGWIN__) 722 init_buf_iov_base(b.iov_base, data); 723 b.iov_len = size; 724#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__) 725} 726 727void init_buf(buf& b, const void* data, size_t size) 728{ 729#if defined(ASIO_WINDOWS) || defined(__CYGWIN__) 730 b.buf = static_cast<char*>(const_cast<void*>(data)); 731 b.len = static_cast<u_long>(size); 732#else // defined(ASIO_WINDOWS) || defined(__CYGWIN__) 733 init_buf_iov_base(b.iov_base, const_cast<void*>(data)); 734 b.iov_len = size; 735#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__) 736} 737 738inline void init_msghdr_msg_name(void*& name, socket_addr_type* addr) 739{ 740 name = addr; 741} 742 743inline void init_msghdr_msg_name(void*& name, const socket_addr_type* addr) 744{ 745 name = const_cast<socket_addr_type*>(addr); 746} 747 748template <typename T> 749inline void init_msghdr_msg_name(T& name, socket_addr_type* addr) 750{ 751 name = reinterpret_cast<T>(addr); 752} 753 754template <typename T> 755inline void init_msghdr_msg_name(T& name, const socket_addr_type* addr) 756{ 757 name = reinterpret_cast<T>(const_cast<socket_addr_type*>(addr)); 758} 759 760signed_size_type recv(socket_type s, buf* bufs, size_t count, 761 int flags, asio::error_code& ec) 762{ 763 clear_last_error(); 764#if defined(ASIO_WINDOWS) || defined(__CYGWIN__) 765 // Receive some data. 766 DWORD recv_buf_count = static_cast<DWORD>(count); 767 DWORD bytes_transferred = 0; 768 DWORD recv_flags = flags; 769 int result = error_wrapper(::WSARecv(s, bufs, 770 recv_buf_count, &bytes_transferred, &recv_flags, 0, 0), ec); 771 if (ec.value() == ERROR_NETNAME_DELETED) 772 ec = asio::error::connection_reset; 773 else if (ec.value() == ERROR_PORT_UNREACHABLE) 774 ec = asio::error::connection_refused; 775 if (result != 0) 776 return socket_error_retval; 777 ec = asio::error_code(); 778 return bytes_transferred; 779#else // defined(ASIO_WINDOWS) || defined(__CYGWIN__) 780 msghdr msg = msghdr(); 781 msg.msg_iov = bufs; 782 msg.msg_iovlen = static_cast<int>(count); 783 signed_size_type result = error_wrapper(::recvmsg(s, &msg, flags), ec); 784 if (result >= 0) 785 ec = asio::error_code(); 786 return result; 787#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__) 788} 789 790size_t sync_recv(socket_type s, state_type state, buf* bufs, 791 size_t count, int flags, bool all_empty, asio::error_code& ec) 792{ 793 if (s == invalid_socket) 794 { 795 ec = asio::error::bad_descriptor; 796 return 0; 797 } 798 799 // A request to read 0 bytes on a stream is a no-op. 800 if (all_empty && (state & stream_oriented)) 801 { 802 ec = asio::error_code(); 803 return 0; 804 } 805 806 // Read some data. 807 for (;;) 808 { 809 // Try to complete the operation without blocking. 810 signed_size_type bytes = socket_ops::recv(s, bufs, count, flags, ec); 811 812 // Check if operation succeeded. 813 if (bytes > 0) 814 return bytes; 815 816 // Check for EOF. 817 if ((state & stream_oriented) && bytes == 0) 818 { 819 ec = asio::error::eof; 820 return 0; 821 } 822 823 // Operation failed. 824 if ((state & user_set_non_blocking) 825 || (ec != asio::error::would_block 826 && ec != asio::error::try_again)) 827 return 0; 828 829 // Wait for socket to become ready. 830 if (socket_ops::poll_read(s, 0, ec) < 0) 831 return 0; 832 } 833} 834 835#if defined(ASIO_HAS_IOCP) 836 837void complete_iocp_recv(state_type state, 838 const weak_cancel_token_type& cancel_token, bool all_empty, 839 asio::error_code& ec, size_t bytes_transferred) 840{ 841 // Map non-portable errors to their portable counterparts. 842 if (ec.value() == ERROR_NETNAME_DELETED) 843 { 844 if (cancel_token.expired()) 845 ec = asio::error::operation_aborted; 846 else 847 ec = asio::error::connection_reset; 848 } 849 else if (ec.value() == ERROR_PORT_UNREACHABLE) 850 { 851 ec = asio::error::connection_refused; 852 } 853 854 // Check for connection closed. 855 else if (!ec && bytes_transferred == 0 856 && (state & stream_oriented) != 0 857 && !all_empty) 858 { 859 ec = asio::error::eof; 860 } 861} 862 863#else // defined(ASIO_HAS_IOCP) 864 865bool non_blocking_recv(socket_type s, 866 buf* bufs, size_t count, int flags, bool is_stream, 867 asio::error_code& ec, size_t& bytes_transferred) 868{ 869 for (;;) 870 { 871 // Read some data. 872 signed_size_type bytes = socket_ops::recv(s, bufs, count, flags, ec); 873 874 // Check for end of stream. 875 if (is_stream && bytes == 0) 876 { 877 ec = asio::error::eof; 878 return true; 879 } 880 881 // Retry operation if interrupted by signal. 882 if (ec == asio::error::interrupted) 883 continue; 884 885 // Check if we need to run the operation again. 886 if (ec == asio::error::would_block 887 || ec == asio::error::try_again) 888 return false; 889 890 // Operation is complete. 891 if (bytes >= 0) 892 { 893 ec = asio::error_code(); 894 bytes_transferred = bytes; 895 } 896 else 897 bytes_transferred = 0; 898 899 return true; 900 } 901} 902 903#endif // defined(ASIO_HAS_IOCP) 904 905signed_size_type recvfrom(socket_type s, buf* bufs, size_t count, 906 int flags, socket_addr_type* addr, std::size_t* addrlen, 907 asio::error_code& ec) 908{ 909 clear_last_error(); 910#if defined(ASIO_WINDOWS) || defined(__CYGWIN__) 911 // Receive some data. 912 DWORD recv_buf_count = static_cast<DWORD>(count); 913 DWORD bytes_transferred = 0; 914 DWORD recv_flags = flags; 915 int tmp_addrlen = (int)*addrlen; 916 int result = error_wrapper(::WSARecvFrom(s, bufs, recv_buf_count, 917 &bytes_transferred, &recv_flags, addr, &tmp_addrlen, 0, 0), ec); 918 *addrlen = (std::size_t)tmp_addrlen; 919 if (ec.value() == ERROR_NETNAME_DELETED) 920 ec = asio::error::connection_reset; 921 else if (ec.value() == ERROR_PORT_UNREACHABLE) 922 ec = asio::error::connection_refused; 923 if (result != 0) 924 return socket_error_retval; 925 ec = asio::error_code(); 926 return bytes_transferred; 927#else // defined(ASIO_WINDOWS) || defined(__CYGWIN__) 928 msghdr msg = msghdr(); 929 init_msghdr_msg_name(msg.msg_name, addr); 930 msg.msg_namelen = static_cast<int>(*addrlen); 931 msg.msg_iov = bufs; 932 msg.msg_iovlen = static_cast<int>(count); 933 signed_size_type result = error_wrapper(::recvmsg(s, &msg, flags), ec); 934 *addrlen = msg.msg_namelen; 935 if (result >= 0) 936 ec = asio::error_code(); 937 return result; 938#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__) 939} 940 941size_t sync_recvfrom(socket_type s, state_type state, buf* bufs, 942 size_t count, int flags, socket_addr_type* addr, 943 std::size_t* addrlen, asio::error_code& ec) 944{ 945 if (s == invalid_socket) 946 { 947 ec = asio::error::bad_descriptor; 948 return 0; 949 } 950 951 // Read some data. 952 for (;;) 953 { 954 // Try to complete the operation without blocking. 955 signed_size_type bytes = socket_ops::recvfrom( 956 s, bufs, count, flags, addr, addrlen, ec); 957 958 // Check if operation succeeded. 959 if (bytes >= 0) 960 return bytes; 961 962 // Operation failed. 963 if ((state & user_set_non_blocking) 964 || (ec != asio::error::would_block 965 && ec != asio::error::try_again)) 966 return 0; 967 968 // Wait for socket to become ready. 969 if (socket_ops::poll_read(s, 0, ec) < 0) 970 return 0; 971 } 972} 973 974#if defined(ASIO_HAS_IOCP) 975 976void complete_iocp_recvfrom( 977 const weak_cancel_token_type& cancel_token, 978 asio::error_code& ec) 979{ 980 // Map non-portable errors to their portable counterparts. 981 if (ec.value() == ERROR_NETNAME_DELETED) 982 { 983 if (cancel_token.expired()) 984 ec = asio::error::operation_aborted; 985 else 986 ec = asio::error::connection_reset; 987 } 988 else if (ec.value() == ERROR_PORT_UNREACHABLE) 989 { 990 ec = asio::error::connection_refused; 991 } 992} 993 994#else // defined(ASIO_HAS_IOCP) 995 996bool non_blocking_recvfrom(socket_type s, 997 buf* bufs, size_t count, int flags, 998 socket_addr_type* addr, std::size_t* addrlen, 999 asio::error_code& ec, size_t& bytes_transferred) 1000{ 1001 for (;;) 1002 { 1003 // Read some data. 1004 signed_size_type bytes = socket_ops::recvfrom( 1005 s, bufs, count, flags, addr, addrlen, ec); 1006 1007 // Retry operation if interrupted by signal. 1008 if (ec == asio::error::interrupted) 1009 continue; 1010 1011 // Check if we need to run the operation again. 1012 if (ec == asio::error::would_block 1013 || ec == asio::error::try_again) 1014 return false; 1015 1016 // Operation is complete. 1017 if (bytes >= 0) 1018 { 1019 ec = asio::error_code(); 1020 bytes_transferred = bytes; 1021 } 1022 else 1023 bytes_transferred = 0; 1024 1025 return true; 1026 } 1027} 1028 1029#endif // defined(ASIO_HAS_IOCP) 1030 1031signed_size_type recvmsg(socket_type s, buf* bufs, size_t count, 1032 int in_flags, int& out_flags, asio::error_code& ec) 1033{ 1034 clear_last_error(); 1035#if defined(ASIO_WINDOWS) || defined(__CYGWIN__) 1036 out_flags = 0; 1037 return socket_ops::recv(s, bufs, count, in_flags, ec); 1038#else // defined(ASIO_WINDOWS) || defined(__CYGWIN__) 1039 msghdr msg = msghdr(); 1040 msg.msg_iov = bufs; 1041 msg.msg_iovlen = static_cast<int>(count); 1042 signed_size_type result = error_wrapper(::recvmsg(s, &msg, in_flags), ec); 1043 if (result >= 0) 1044 { 1045 ec = asio::error_code(); 1046 out_flags = msg.msg_flags; 1047 } 1048 else 1049 out_flags = 0; 1050 return result; 1051#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__) 1052} 1053 1054size_t sync_recvmsg(socket_type s, state_type state, 1055 buf* bufs, size_t count, int in_flags, int& out_flags, 1056 asio::error_code& ec) 1057{ 1058 if (s == invalid_socket) 1059 { 1060 ec = asio::error::bad_descriptor; 1061 return 0; 1062 } 1063 1064 // Read some data. 1065 for (;;) 1066 { 1067 // Try to complete the operation without blocking. 1068 signed_size_type bytes = socket_ops::recvmsg( 1069 s, bufs, count, in_flags, out_flags, ec); 1070 1071 // Check if operation succeeded. 1072 if (bytes >= 0) 1073 return bytes; 1074 1075 // Operation failed. 1076 if ((state & user_set_non_blocking) 1077 || (ec != asio::error::would_block 1078 && ec != asio::error::try_again)) 1079 return 0; 1080 1081 // Wait for socket to become ready. 1082 if (socket_ops::poll_read(s, 0, ec) < 0) 1083 return 0; 1084 } 1085} 1086 1087#if defined(ASIO_HAS_IOCP) 1088 1089void complete_iocp_recvmsg( 1090 const weak_cancel_token_type& cancel_token, 1091 asio::error_code& ec) 1092{ 1093 // Map non-portable errors to their portable counterparts. 1094 if (ec.value() == ERROR_NETNAME_DELETED) 1095 { 1096 if (cancel_token.expired()) 1097 ec = asio::error::operation_aborted; 1098 else 1099 ec = asio::error::connection_reset; 1100 } 1101 else if (ec.value() == ERROR_PORT_UNREACHABLE) 1102 { 1103 ec = asio::error::connection_refused; 1104 } 1105} 1106 1107#else // defined(ASIO_HAS_IOCP) 1108 1109bool non_blocking_recvmsg(socket_type s, 1110 buf* bufs, size_t count, int in_flags, int& out_flags, 1111 asio::error_code& ec, size_t& bytes_transferred) 1112{ 1113 for (;;) 1114 { 1115 // Read some data. 1116 signed_size_type bytes = socket_ops::recvmsg( 1117 s, bufs, count, in_flags, out_flags, ec); 1118 1119 // Retry operation if interrupted by signal. 1120 if (ec == asio::error::interrupted) 1121 continue; 1122 1123 // Check if we need to run the operation again. 1124 if (ec == asio::error::would_block 1125 || ec == asio::error::try_again) 1126 return false; 1127 1128 // Operation is complete. 1129 if (bytes >= 0) 1130 { 1131 ec = asio::error_code(); 1132 bytes_transferred = bytes; 1133 } 1134 else 1135 bytes_transferred = 0; 1136 1137 return true; 1138 } 1139} 1140 1141#endif // defined(ASIO_HAS_IOCP) 1142 1143signed_size_type send(socket_type s, const buf* bufs, size_t count, 1144 int flags, asio::error_code& ec) 1145{ 1146 clear_last_error(); 1147#if defined(ASIO_WINDOWS) || defined(__CYGWIN__) 1148 // Send the data. 1149 DWORD send_buf_count = static_cast<DWORD>(count); 1150 DWORD bytes_transferred = 0; 1151 DWORD send_flags = flags; 1152 int result = error_wrapper(::WSASend(s, const_cast<buf*>(bufs), 1153 send_buf_count, &bytes_transferred, send_flags, 0, 0), ec); 1154 if (ec.value() == ERROR_NETNAME_DELETED) 1155 ec = asio::error::connection_reset; 1156 else if (ec.value() == ERROR_PORT_UNREACHABLE) 1157 ec = asio::error::connection_refused; 1158 if (result != 0) 1159 return socket_error_retval; 1160 ec = asio::error_code(); 1161 return bytes_transferred; 1162#else // defined(ASIO_WINDOWS) || defined(__CYGWIN__) 1163 msghdr msg = msghdr(); 1164 msg.msg_iov = const_cast<buf*>(bufs); 1165 msg.msg_iovlen = static_cast<int>(count); 1166#if defined(__linux__) 1167 flags |= MSG_NOSIGNAL; 1168#endif // defined(__linux__) 1169 signed_size_type result = error_wrapper(::sendmsg(s, &msg, flags), ec); 1170 if (result >= 0) 1171 ec = asio::error_code(); 1172 return result; 1173#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__) 1174} 1175 1176size_t sync_send(socket_type s, state_type state, const buf* bufs, 1177 size_t count, int flags, bool all_empty, asio::error_code& ec) 1178{ 1179 if (s == invalid_socket) 1180 { 1181 ec = asio::error::bad_descriptor; 1182 return 0; 1183 } 1184 1185 // A request to write 0 bytes to a stream is a no-op. 1186 if (all_empty && (state & stream_oriented)) 1187 { 1188 ec = asio::error_code(); 1189 return 0; 1190 } 1191 1192 // Read some data. 1193 for (;;) 1194 { 1195 // Try to complete the operation without blocking. 1196 signed_size_type bytes = socket_ops::send(s, bufs, count, flags, ec); 1197 1198 // Check if operation succeeded. 1199 if (bytes >= 0) 1200 return bytes; 1201 1202 // Operation failed. 1203 if ((state & user_set_non_blocking) 1204 || (ec != asio::error::would_block 1205 && ec != asio::error::try_again)) 1206 return 0; 1207 1208 // Wait for socket to become ready. 1209 if (socket_ops::poll_write(s, 0, ec) < 0) 1210 return 0; 1211 } 1212} 1213 1214#if defined(ASIO_HAS_IOCP) 1215 1216void complete_iocp_send( 1217 const weak_cancel_token_type& cancel_token, 1218 asio::error_code& ec) 1219{ 1220 // Map non-portable errors to their portable counterparts. 1221 if (ec.value() == ERROR_NETNAME_DELETED) 1222 { 1223 if (cancel_token.expired()) 1224 ec = asio::error::operation_aborted; 1225 else 1226 ec = asio::error::connection_reset; 1227 } 1228 else if (ec.value() == ERROR_PORT_UNREACHABLE) 1229 { 1230 ec = asio::error::connection_refused; 1231 } 1232} 1233 1234#else // defined(ASIO_HAS_IOCP) 1235 1236bool non_blocking_send(socket_type s, 1237 const buf* bufs, size_t count, int flags, 1238 asio::error_code& ec, size_t& bytes_transferred) 1239{ 1240 for (;;) 1241 { 1242 // Write some data. 1243 signed_size_type bytes = socket_ops::send(s, bufs, count, flags, ec); 1244 1245 // Retry operation if interrupted by signal. 1246 if (ec == asio::error::interrupted) 1247 continue; 1248 1249 // Check if we need to run the operation again. 1250 if (ec == asio::error::would_block 1251 || ec == asio::error::try_again) 1252 return false; 1253 1254 // Operation is complete. 1255 if (bytes >= 0) 1256 { 1257 ec = asio::error_code(); 1258 bytes_transferred = bytes; 1259 } 1260 else 1261 bytes_transferred = 0; 1262 1263 return true; 1264 } 1265} 1266 1267#endif // defined(ASIO_HAS_IOCP) 1268 1269signed_size_type sendto(socket_type s, const buf* bufs, size_t count, 1270 int flags, const socket_addr_type* addr, std::size_t addrlen, 1271 asio::error_code& ec) 1272{ 1273 clear_last_error(); 1274#if defined(ASIO_WINDOWS) || defined(__CYGWIN__) 1275 // Send the data. 1276 DWORD send_buf_count = static_cast<DWORD>(count); 1277 DWORD bytes_transferred = 0; 1278 int result = error_wrapper(::WSASendTo(s, const_cast<buf*>(bufs), 1279 send_buf_count, &bytes_transferred, flags, addr, 1280 static_cast<int>(addrlen), 0, 0), ec); 1281 if (ec.value() == ERROR_NETNAME_DELETED) 1282 ec = asio::error::connection_reset; 1283 else if (ec.value() == ERROR_PORT_UNREACHABLE) 1284 ec = asio::error::connection_refused; 1285 if (result != 0) 1286 return socket_error_retval; 1287 ec = asio::error_code(); 1288 return bytes_transferred; 1289#else // defined(ASIO_WINDOWS) || defined(__CYGWIN__) 1290 msghdr msg = msghdr(); 1291 init_msghdr_msg_name(msg.msg_name, addr); 1292 msg.msg_namelen = static_cast<int>(addrlen); 1293 msg.msg_iov = const_cast<buf*>(bufs); 1294 msg.msg_iovlen = static_cast<int>(count); 1295#if defined(__linux__) 1296 flags |= MSG_NOSIGNAL; 1297#endif // defined(__linux__) 1298 signed_size_type result = error_wrapper(::sendmsg(s, &msg, flags), ec); 1299 if (result >= 0) 1300 ec = asio::error_code(); 1301 return result; 1302#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__) 1303} 1304 1305size_t sync_sendto(socket_type s, state_type state, const buf* bufs, 1306 size_t count, int flags, const socket_addr_type* addr, 1307 std::size_t addrlen, asio::error_code& ec) 1308{ 1309 if (s == invalid_socket) 1310 { 1311 ec = asio::error::bad_descriptor; 1312 return 0; 1313 } 1314 1315 // Write some data. 1316 for (;;) 1317 { 1318 // Try to complete the operation without blocking. 1319 signed_size_type bytes = socket_ops::sendto( 1320 s, bufs, count, flags, addr, addrlen, ec); 1321 1322 // Check if operation succeeded. 1323 if (bytes >= 0) 1324 return bytes; 1325 1326 // Operation failed. 1327 if ((state & user_set_non_blocking) 1328 || (ec != asio::error::would_block 1329 && ec != asio::error::try_again)) 1330 return 0; 1331 1332 // Wait for socket to become ready. 1333 if (socket_ops::poll_write(s, 0, ec) < 0) 1334 return 0; 1335 } 1336} 1337 1338#if !defined(ASIO_HAS_IOCP) 1339 1340bool non_blocking_sendto(socket_type s, 1341 const buf* bufs, size_t count, int flags, 1342 const socket_addr_type* addr, std::size_t addrlen, 1343 asio::error_code& ec, size_t& bytes_transferred) 1344{ 1345 for (;;) 1346 { 1347 // Write some data. 1348 signed_size_type bytes = socket_ops::sendto( 1349 s, bufs, count, flags, addr, addrlen, ec); 1350 1351 // Retry operation if interrupted by signal. 1352 if (ec == asio::error::interrupted) 1353 continue; 1354 1355 // Check if we need to run the operation again. 1356 if (ec == asio::error::would_block 1357 || ec == asio::error::try_again) 1358 return false; 1359 1360 // Operation is complete. 1361 if (bytes >= 0) 1362 { 1363 ec = asio::error_code(); 1364 bytes_transferred = bytes; 1365 } 1366 else 1367 bytes_transferred = 0; 1368 1369 return true; 1370 } 1371} 1372 1373#endif // !defined(ASIO_HAS_IOCP) 1374 1375socket_type socket(int af, int type, int protocol, 1376 asio::error_code& ec) 1377{ 1378 clear_last_error(); 1379#if defined(ASIO_WINDOWS) || defined(__CYGWIN__) 1380 socket_type s = error_wrapper(::WSASocketW(af, type, protocol, 0, 0, 1381 WSA_FLAG_OVERLAPPED), ec); 1382 if (s == invalid_socket) 1383 return s; 1384 1385 if (af == ASIO_OS_DEF(AF_INET6)) 1386 { 1387 // Try to enable the POSIX default behaviour of having IPV6_V6ONLY set to 1388 // false. This will only succeed on Windows Vista and later versions of 1389 // Windows, where a dual-stack IPv4/v6 implementation is available. 1390 DWORD optval = 0; 1391 ::setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, 1392 reinterpret_cast<const char*>(&optval), sizeof(optval)); 1393 } 1394 1395 ec = asio::error_code(); 1396 1397 return s; 1398#elif defined(__MACH__) && defined(__APPLE__) || (defined(__FreeBSD__) || defined(__DragonFly__)) 1399 socket_type s = error_wrapper(::socket(af, type, protocol), ec); 1400 if (s == invalid_socket) 1401 return s; 1402 1403 int optval = 1; 1404 int result = error_wrapper(::setsockopt(s, 1405 SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)), ec); 1406 if (result != 0) 1407 { 1408 ::close(s); 1409 return invalid_socket; 1410 } 1411 1412 return s; 1413#else 1414 int s = error_wrapper(::socket(af, type, protocol), ec); 1415 if (s >= 0) 1416 ec = asio::error_code(); 1417 return s; 1418#endif 1419} 1420 1421template <typename SockLenType> 1422inline int call_setsockopt(SockLenType msghdr::*, 1423 socket_type s, int level, int optname, 1424 const void* optval, std::size_t optlen) 1425{ 1426 return ::setsockopt(s, level, optname, 1427 (const char*)optval, (SockLenType)optlen); 1428} 1429 1430int setsockopt(socket_type s, state_type& state, int level, int optname, 1431 const void* optval, std::size_t optlen, asio::error_code& ec) 1432{ 1433 if (s == invalid_socket) 1434 { 1435 ec = asio::error::bad_descriptor; 1436 return socket_error_retval; 1437 } 1438 1439 if (level == custom_socket_option_level && optname == always_fail_option) 1440 { 1441 ec = asio::error::invalid_argument; 1442 return socket_error_retval; 1443 } 1444 1445 if (level == custom_socket_option_level 1446 && optname == enable_connection_aborted_option) 1447 { 1448 if (optlen != sizeof(int)) 1449 { 1450 ec = asio::error::invalid_argument; 1451 return socket_error_retval; 1452 } 1453 1454 if (*static_cast<const int*>(optval)) 1455 state |= enable_connection_aborted; 1456 else 1457 state &= ~enable_connection_aborted; 1458 ec = asio::error_code(); 1459 return 0; 1460 } 1461 1462 if (level == SOL_SOCKET && optname == SO_LINGER) 1463 state |= user_set_linger; 1464 1465#if defined(__BORLANDC__) 1466 // Mysteriously, using the getsockopt and setsockopt functions directly with 1467 // Borland C++ results in incorrect values being set and read. The bug can be 1468 // worked around by using function addresses resolved with GetProcAddress. 1469 if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32")) 1470 { 1471 typedef int (WSAAPI *sso_t)(SOCKET, int, int, const char*, int); 1472 if (sso_t sso = (sso_t)::GetProcAddress(winsock_module, "setsockopt")) 1473 { 1474 clear_last_error(); 1475 return error_wrapper(sso(s, level, optname, 1476 reinterpret_cast<const char*>(optval), 1477 static_cast<int>(optlen)), ec); 1478 } 1479 } 1480 ec = asio::error::fault; 1481 return socket_error_retval; 1482#else // defined(__BORLANDC__) 1483 clear_last_error(); 1484 int result = error_wrapper(call_setsockopt(&msghdr::msg_namelen, 1485 s, level, optname, optval, optlen), ec); 1486 if (result == 0) 1487 { 1488 ec = asio::error_code(); 1489 1490#if defined(__MACH__) && defined(__APPLE__) \ 1491 || defined(__NetBSD__) || (defined(__FreeBSD__) || defined(__DragonFly__)) || defined(__OpenBSD__) 1492 // To implement portable behaviour for SO_REUSEADDR with UDP sockets we 1493 // need to also set SO_REUSEPORT on BSD-based platforms. 1494 if ((state & datagram_oriented) 1495 && level == SOL_SOCKET && optname == SO_REUSEADDR) 1496 { 1497 call_setsockopt(&msghdr::msg_namelen, s, 1498 SOL_SOCKET, SO_REUSEPORT, optval, optlen); 1499 } 1500#endif 1501 } 1502 1503 return result; 1504#endif // defined(__BORLANDC__) 1505} 1506 1507template <typename SockLenType> 1508inline int call_getsockopt(SockLenType msghdr::*, 1509 socket_type s, int level, int optname, 1510 void* optval, std::size_t* optlen) 1511{ 1512 SockLenType tmp_optlen = (SockLenType)*optlen; 1513 int result = ::getsockopt(s, level, optname, (char*)optval, &tmp_optlen); 1514 *optlen = (std::size_t)tmp_optlen; 1515 return result; 1516} 1517 1518int getsockopt(socket_type s, state_type state, int level, int optname, 1519 void* optval, size_t* optlen, asio::error_code& ec) 1520{ 1521 if (s == invalid_socket) 1522 { 1523 ec = asio::error::bad_descriptor; 1524 return socket_error_retval; 1525 } 1526 1527 if (level == custom_socket_option_level && optname == always_fail_option) 1528 { 1529 ec = asio::error::invalid_argument; 1530 return socket_error_retval; 1531 } 1532 1533 if (level == custom_socket_option_level 1534 && optname == enable_connection_aborted_option) 1535 { 1536 if (*optlen != sizeof(int)) 1537 { 1538 ec = asio::error::invalid_argument; 1539 return socket_error_retval; 1540 } 1541 1542 *static_cast<int*>(optval) = (state & enable_connection_aborted) ? 1 : 0; 1543 ec = asio::error_code(); 1544 return 0; 1545 } 1546 1547#if defined(__BORLANDC__) 1548 // Mysteriously, using the getsockopt and setsockopt functions directly with 1549 // Borland C++ results in incorrect values being set and read. The bug can be 1550 // worked around by using function addresses resolved with GetProcAddress. 1551 if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32")) 1552 { 1553 typedef int (WSAAPI *gso_t)(SOCKET, int, int, char*, int*); 1554 if (gso_t gso = (gso_t)::GetProcAddress(winsock_module, "getsockopt")) 1555 { 1556 clear_last_error(); 1557 int tmp_optlen = static_cast<int>(*optlen); 1558 int result = error_wrapper(gso(s, level, optname, 1559 reinterpret_cast<char*>(optval), &tmp_optlen), ec); 1560 *optlen = static_cast<size_t>(tmp_optlen); 1561 if (result != 0 && level == IPPROTO_IPV6 && optname == IPV6_V6ONLY 1562 && ec.value() == WSAENOPROTOOPT && *optlen == sizeof(DWORD)) 1563 { 1564 // Dual-stack IPv4/v6 sockets, and the IPV6_V6ONLY socket option, are 1565 // only supported on Windows Vista and later. To simplify program logic 1566 // we will fake success of getting this option and specify that the 1567 // value is non-zero (i.e. true). This corresponds to the behavior of 1568 // IPv6 sockets on Windows platforms pre-Vista. 1569 *static_cast<DWORD*>(optval) = 1; 1570 ec = asio::error_code(); 1571 } 1572 return result; 1573 } 1574 } 1575 ec = asio::error::fault; 1576 return socket_error_retval; 1577#elif defined(ASIO_WINDOWS) || defined(__CYGWIN__) 1578 clear_last_error(); 1579 int result = error_wrapper(call_getsockopt(&msghdr::msg_namelen, 1580 s, level, optname, optval, optlen), ec); 1581 if (result != 0 && level == IPPROTO_IPV6 && optname == IPV6_V6ONLY 1582 && ec.value() == WSAENOPROTOOPT && *optlen == sizeof(DWORD)) 1583 { 1584 // Dual-stack IPv4/v6 sockets, and the IPV6_V6ONLY socket option, are only 1585 // supported on Windows Vista and later. To simplify program logic we will 1586 // fake success of getting this option and specify that the value is 1587 // non-zero (i.e. true). This corresponds to the behavior of IPv6 sockets 1588 // on Windows platforms pre-Vista. 1589 *static_cast<DWORD*>(optval) = 1; 1590 ec = asio::error_code(); 1591 } 1592 if (result == 0) 1593 ec = asio::error_code(); 1594 return result; 1595#else // defined(ASIO_WINDOWS) || defined(__CYGWIN__) 1596 clear_last_error(); 1597 int result = error_wrapper(call_getsockopt(&msghdr::msg_namelen, 1598 s, level, optname, optval, optlen), ec); 1599#if defined(__linux__) 1600 if (result == 0 && level == SOL_SOCKET && *optlen == sizeof(int) 1601 && (optname == SO_SNDBUF || optname == SO_RCVBUF)) 1602 { 1603 // On Linux, setting SO_SNDBUF or SO_RCVBUF to N actually causes the kernel 1604 // to set the buffer size to N*2. Linux puts additional stuff into the 1605 // buffers so that only about half is actually available to the application. 1606 // The retrieved value is divided by 2 here to make it appear as though the 1607 // correct value has been set. 1608 *static_cast<int*>(optval) /= 2; 1609 } 1610#endif // defined(__linux__) 1611 if (result == 0) 1612 ec = asio::error_code(); 1613 return result; 1614#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__) 1615} 1616 1617template <typename SockLenType> 1618inline int call_getpeername(SockLenType msghdr::*, 1619 socket_type s, socket_addr_type* addr, std::size_t* addrlen) 1620{ 1621 SockLenType tmp_addrlen = (SockLenType)*addrlen; 1622 int result = ::getpeername(s, addr, &tmp_addrlen); 1623 *addrlen = (std::size_t)tmp_addrlen; 1624 return result; 1625} 1626 1627int getpeername(socket_type s, socket_addr_type* addr, 1628 std::size_t* addrlen, bool cached, asio::error_code& ec) 1629{ 1630 if (s == invalid_socket) 1631 { 1632 ec = asio::error::bad_descriptor; 1633 return socket_error_retval; 1634 } 1635 1636#if defined(ASIO_WINDOWS) && !defined(ASIO_WINDOWS_APP) \ 1637 || defined(__CYGWIN__) 1638 if (cached) 1639 { 1640 // Check if socket is still connected. 1641 DWORD connect_time = 0; 1642 size_t connect_time_len = sizeof(connect_time); 1643 if (socket_ops::getsockopt(s, 0, SOL_SOCKET, SO_CONNECT_TIME, 1644 &connect_time, &connect_time_len, ec) == socket_error_retval) 1645 { 1646 return socket_error_retval; 1647 } 1648 if (connect_time == 0xFFFFFFFF) 1649 { 1650 ec = asio::error::not_connected; 1651 return socket_error_retval; 1652 } 1653 1654 // The cached value is still valid. 1655 ec = asio::error_code(); 1656 return 0; 1657 } 1658#else // defined(ASIO_WINDOWS) && !defined(ASIO_WINDOWS_APP) 1659 // || defined(__CYGWIN__) 1660 (void)cached; 1661#endif // defined(ASIO_WINDOWS) && !defined(ASIO_WINDOWS_APP) 1662 // || defined(__CYGWIN__) 1663 1664 clear_last_error(); 1665 int result = error_wrapper(call_getpeername( 1666 &msghdr::msg_namelen, s, addr, addrlen), ec); 1667 if (result == 0) 1668 ec = asio::error_code(); 1669 return result; 1670} 1671 1672template <typename SockLenType> 1673inline int call_getsockname(SockLenType msghdr::*, 1674 socket_type s, socket_addr_type* addr, std::size_t* addrlen) 1675{ 1676 SockLenType tmp_addrlen = (SockLenType)*addrlen; 1677 int result = ::getsockname(s, addr, &tmp_addrlen); 1678 *addrlen = (std::size_t)tmp_addrlen; 1679 return result; 1680} 1681 1682int getsockname(socket_type s, socket_addr_type* addr, 1683 std::size_t* addrlen, asio::error_code& ec) 1684{ 1685 if (s == invalid_socket) 1686 { 1687 ec = asio::error::bad_descriptor; 1688 return socket_error_retval; 1689 } 1690 1691 clear_last_error(); 1692 int result = error_wrapper(call_getsockname( 1693 &msghdr::msg_namelen, s, addr, addrlen), ec); 1694 if (result == 0) 1695 ec = asio::error_code(); 1696 return result; 1697} 1698 1699int ioctl(socket_type s, state_type& state, int cmd, 1700 ioctl_arg_type* arg, asio::error_code& ec) 1701{ 1702 if (s == invalid_socket) 1703 { 1704 ec = asio::error::bad_descriptor; 1705 return socket_error_retval; 1706 } 1707 1708 clear_last_error(); 1709#if defined(ASIO_WINDOWS) || defined(__CYGWIN__) 1710 int result = error_wrapper(::ioctlsocket(s, cmd, arg), ec); 1711#elif defined(__MACH__) && defined(__APPLE__) \ 1712 || defined(__NetBSD__) || (defined(__FreeBSD__) || defined(__DragonFly__)) || defined(__OpenBSD__) 1713 int result = error_wrapper(::ioctl(s, 1714 static_cast<unsigned int>(cmd), arg), ec); 1715#else 1716 int result = error_wrapper(::ioctl(s, cmd, arg), ec); 1717#endif 1718 if (result >= 0) 1719 { 1720 ec = asio::error_code(); 1721 1722 // When updating the non-blocking mode we always perform the ioctl syscall, 1723 // even if the flags would otherwise indicate that the socket is already in 1724 // the correct state. This ensures that the underlying socket is put into 1725 // the state that has been requested by the user. If the ioctl syscall was 1726 // successful then we need to update the flags to match. 1727 if (cmd == static_cast<int>(FIONBIO)) 1728 { 1729 if (*arg) 1730 { 1731 state |= user_set_non_blocking; 1732 } 1733 else 1734 { 1735 // Clearing the non-blocking mode always overrides any internally-set 1736 // non-blocking flag. Any subsequent asynchronous operations will need 1737 // to re-enable non-blocking I/O. 1738 state &= ~(user_set_non_blocking | internal_non_blocking); 1739 } 1740 } 1741 } 1742 1743 return result; 1744} 1745 1746int select(int nfds, fd_set* readfds, fd_set* writefds, 1747 fd_set* exceptfds, timeval* timeout, asio::error_code& ec) 1748{ 1749 clear_last_error(); 1750#if defined(ASIO_WINDOWS) || defined(__CYGWIN__) 1751 if (!readfds && !writefds && !exceptfds && timeout) 1752 { 1753 DWORD milliseconds = timeout->tv_sec * 1000 + timeout->tv_usec / 1000; 1754 if (milliseconds == 0) 1755 milliseconds = 1; // Force context switch. 1756 ::Sleep(milliseconds); 1757 ec = asio::error_code(); 1758 return 0; 1759 } 1760 1761 // The select() call allows timeout values measured in microseconds, but the 1762 // system clock (as wrapped by boost::posix_time::microsec_clock) typically 1763 // has a resolution of 10 milliseconds. This can lead to a spinning select 1764 // reactor, meaning increased CPU usage, when waiting for the earliest 1765 // scheduled timeout if it's less than 10 milliseconds away. To avoid a tight 1766 // spin we'll use a minimum timeout of 1 millisecond. 1767 if (timeout && timeout->tv_sec == 0 1768 && timeout->tv_usec > 0 && timeout->tv_usec < 1000) 1769 timeout->tv_usec = 1000; 1770#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__) 1771 1772#if defined(__hpux) && defined(__SELECT) 1773 timespec ts; 1774 ts.tv_sec = timeout ? timeout->tv_sec : 0; 1775 ts.tv_nsec = timeout ? timeout->tv_usec * 1000 : 0; 1776 return error_wrapper(::pselect(nfds, readfds, 1777 writefds, exceptfds, timeout ? &ts : 0, 0), ec); 1778#else 1779 int result = error_wrapper(::select(nfds, readfds, 1780 writefds, exceptfds, timeout), ec); 1781 if (result >= 0) 1782 ec = asio::error_code(); 1783 return result; 1784#endif 1785} 1786 1787int poll_read(socket_type s, state_type state, asio::error_code& ec) 1788{ 1789 if (s == invalid_socket) 1790 { 1791 ec = asio::error::bad_descriptor; 1792 return socket_error_retval; 1793 } 1794 1795#if defined(ASIO_WINDOWS) \ 1796 || defined(__CYGWIN__) \ 1797 || defined(__SYMBIAN32__) 1798 fd_set fds; 1799 FD_ZERO(&fds); 1800 FD_SET(s, &fds); 1801 timeval zero_timeout; 1802 zero_timeout.tv_sec = 0; 1803 zero_timeout.tv_usec = 0; 1804 timeval* timeout = (state & user_set_non_blocking) ? &zero_timeout : 0; 1805 clear_last_error(); 1806 int result = error_wrapper(::select(s + 1, &fds, 0, 0, timeout), ec); 1807#else // defined(ASIO_WINDOWS) 1808 // || defined(__CYGWIN__) 1809 // || defined(__SYMBIAN32__) 1810 pollfd fds; 1811 fds.fd = s; 1812 fds.events = POLLIN; 1813 fds.revents = 0; 1814 int timeout = (state & user_set_non_blocking) ? 0 : -1; 1815 clear_last_error(); 1816 int result = error_wrapper(::poll(&fds, 1, timeout), ec); 1817#endif // defined(ASIO_WINDOWS) 1818 // || defined(__CYGWIN__) 1819 // || defined(__SYMBIAN32__) 1820 if (result == 0) 1821 ec = (state & user_set_non_blocking) 1822 ? asio::error::would_block : asio::error_code(); 1823 else if (result > 0) 1824 ec = asio::error_code(); 1825 return result; 1826} 1827 1828int poll_write(socket_type s, state_type state, asio::error_code& ec) 1829{ 1830 if (s == invalid_socket) 1831 { 1832 ec = asio::error::bad_descriptor; 1833 return socket_error_retval; 1834 } 1835 1836#if defined(ASIO_WINDOWS) \ 1837 || defined(__CYGWIN__) \ 1838 || defined(__SYMBIAN32__) 1839 fd_set fds; 1840 FD_ZERO(&fds); 1841 FD_SET(s, &fds); 1842 timeval zero_timeout; 1843 zero_timeout.tv_sec = 0; 1844 zero_timeout.tv_usec = 0; 1845 timeval* timeout = (state & user_set_non_blocking) ? &zero_timeout : 0; 1846 clear_last_error(); 1847 int result = error_wrapper(::select(s + 1, 0, &fds, 0, timeout), ec); 1848#else // defined(ASIO_WINDOWS) 1849 // || defined(__CYGWIN__) 1850 // || defined(__SYMBIAN32__) 1851 pollfd fds; 1852 fds.fd = s; 1853 fds.events = POLLOUT; 1854 fds.revents = 0; 1855 int timeout = (state & user_set_non_blocking) ? 0 : -1; 1856 clear_last_error(); 1857 int result = error_wrapper(::poll(&fds, 1, timeout), ec); 1858#endif // defined(ASIO_WINDOWS) 1859 // || defined(__CYGWIN__) 1860 // || defined(__SYMBIAN32__) 1861 if (result == 0) 1862 ec = (state & user_set_non_blocking) 1863 ? asio::error::would_block : asio::error_code(); 1864 else if (result > 0) 1865 ec = asio::error_code(); 1866 return result; 1867} 1868 1869int poll_connect(socket_type s, asio::error_code& ec) 1870{ 1871 if (s == invalid_socket) 1872 { 1873 ec = asio::error::bad_descriptor; 1874 return socket_error_retval; 1875 } 1876 1877#if defined(ASIO_WINDOWS) \ 1878 || defined(__CYGWIN__) \ 1879 || defined(__SYMBIAN32__) 1880 fd_set write_fds; 1881 FD_ZERO(&write_fds); 1882 FD_SET(s, &write_fds); 1883 fd_set except_fds; 1884 FD_ZERO(&except_fds); 1885 FD_SET(s, &except_fds); 1886 clear_last_error(); 1887 int result = error_wrapper(::select( 1888 s + 1, 0, &write_fds, &except_fds, 0), ec); 1889 if (result >= 0) 1890 ec = asio::error_code(); 1891 return result; 1892#else // defined(ASIO_WINDOWS) 1893 // || defined(__CYGWIN__) 1894 // || defined(__SYMBIAN32__) 1895 pollfd fds; 1896 fds.fd = s; 1897 fds.events = POLLOUT; 1898 fds.revents = 0; 1899 clear_last_error(); 1900 int result = error_wrapper(::poll(&fds, 1, -1), ec); 1901 if (result >= 0) 1902 ec = asio::error_code(); 1903 return result; 1904#endif // defined(ASIO_WINDOWS) 1905 // || defined(__CYGWIN__) 1906 // || defined(__SYMBIAN32__) 1907} 1908 1909#endif // !defined(ASIO_WINDOWS_RUNTIME) 1910 1911const char* inet_ntop(int af, const void* src, char* dest, size_t length, 1912 unsigned long scope_id, asio::error_code& ec) 1913{ 1914 clear_last_error(); 1915#if defined(ASIO_WINDOWS_RUNTIME) 1916 using namespace std; // For sprintf. 1917 const unsigned char* bytes = static_cast<const unsigned char*>(src); 1918 if (af == ASIO_OS_DEF(AF_INET)) 1919 { 1920 sprintf_s(dest, length, "%u.%u.%u.%u", 1921 bytes[0], bytes[1], bytes[2], bytes[3]); 1922 return dest; 1923 } 1924 else if (af == ASIO_OS_DEF(AF_INET6)) 1925 { 1926 size_t n = 0, b = 0, z = 0; 1927 while (n < length && b < 16) 1928 { 1929 if (bytes[b] == 0 && bytes[b + 1] == 0 && z == 0) 1930 { 1931 do b += 2; while (b < 16 && bytes[b] == 0 && bytes[b + 1] == 0); 1932 n += sprintf_s(dest + n, length - n, ":%s", b < 16 ? "" : ":"), ++z; 1933 } 1934 else 1935 { 1936 n += sprintf_s(dest + n, length - n, "%s%x", b ? ":" : "", 1937 (static_cast<u_long_type>(bytes[b]) << 8) | bytes[b + 1]); 1938 b += 2; 1939 } 1940 } 1941 if (scope_id) 1942 n += sprintf_s(dest + n, length - n, "%%%lu", scope_id); 1943 return dest; 1944 } 1945 else 1946 { 1947 ec = asio::error::address_family_not_supported; 1948 return 0; 1949 } 1950#elif defined(ASIO_WINDOWS) || defined(__CYGWIN__) 1951 using namespace std; // For memcpy. 1952 1953 if (af != ASIO_OS_DEF(AF_INET) && af != ASIO_OS_DEF(AF_INET6)) 1954 { 1955 ec = asio::error::address_family_not_supported; 1956 return 0; 1957 } 1958 1959 union 1960 { 1961 socket_addr_type base; 1962 sockaddr_storage_type storage; 1963 sockaddr_in4_type v4; 1964 sockaddr_in6_type v6; 1965 } address; 1966 DWORD address_length; 1967 if (af == ASIO_OS_DEF(AF_INET)) 1968 { 1969 address_length = sizeof(sockaddr_in4_type); 1970 address.v4.sin_family = ASIO_OS_DEF(AF_INET); 1971 address.v4.sin_port = 0; 1972 memcpy(&address.v4.sin_addr, src, sizeof(in4_addr_type)); 1973 } 1974 else // AF_INET6 1975 { 1976 address_length = sizeof(sockaddr_in6_type); 1977 address.v6.sin6_family = ASIO_OS_DEF(AF_INET6); 1978 address.v6.sin6_port = 0; 1979 address.v6.sin6_flowinfo = 0; 1980 address.v6.sin6_scope_id = scope_id; 1981 memcpy(&address.v6.sin6_addr, src, sizeof(in6_addr_type)); 1982 } 1983 1984 DWORD string_length = static_cast<DWORD>(length); 1985#if defined(BOOST_NO_ANSI_APIS) || (defined(_MSC_VER) && (_MSC_VER >= 1800)) 1986 LPWSTR string_buffer = (LPWSTR)_alloca(length * sizeof(WCHAR)); 1987 int result = error_wrapper(::WSAAddressToStringW(&address.base, 1988 address_length, 0, string_buffer, &string_length), ec); 1989 ::WideCharToMultiByte(CP_ACP, 0, string_buffer, -1, 1990 dest, static_cast<int>(length), 0, 0); 1991#else 1992 int result = error_wrapper(::WSAAddressToStringA( 1993 &address.base, address_length, 0, dest, &string_length), ec); 1994#endif 1995 1996 // Windows may set error code on success. 1997 if (result != socket_error_retval) 1998 ec = asio::error_code(); 1999 2000 // Windows may not set an error code on failure. 2001 else if (result == socket_error_retval && !ec) 2002 ec = asio::error::invalid_argument; 2003 2004 return result == socket_error_retval ? 0 : dest; 2005#else // defined(ASIO_WINDOWS) || defined(__CYGWIN__) 2006 const char* result = error_wrapper(::inet_ntop( 2007 af, src, dest, static_cast<int>(length)), ec); 2008 if (result == 0 && !ec) 2009 ec = asio::error::invalid_argument; 2010 if (result != 0 && af == ASIO_OS_DEF(AF_INET6) && scope_id != 0) 2011 { 2012 using namespace std; // For strcat and sprintf. 2013 char if_name[IF_NAMESIZE + 1] = "%"; 2014 const in6_addr_type* ipv6_address = static_cast<const in6_addr_type*>(src); 2015 bool is_link_local = ((ipv6_address->s6_addr[0] == 0xfe) 2016 && ((ipv6_address->s6_addr[1] & 0xc0) == 0x80)); 2017 bool is_multicast_link_local = ((ipv6_address->s6_addr[0] == 0xff) 2018 && ((ipv6_address->s6_addr[1] & 0x0f) == 0x02)); 2019 if ((!is_link_local && !is_multicast_link_local) 2020 || if_indextoname(static_cast<unsigned>(scope_id), if_name + 1) == 0) 2021 sprintf(if_name + 1, "%lu", scope_id); 2022 strcat(dest, if_name); 2023 } 2024 return result; 2025#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__) 2026} 2027 2028int inet_pton(int af, const char* src, void* dest, 2029 unsigned long* scope_id, asio::error_code& ec) 2030{ 2031 clear_last_error(); 2032#if defined(ASIO_WINDOWS_RUNTIME) 2033 using namespace std; // For sscanf. 2034 unsigned char* bytes = static_cast<unsigned char*>(dest); 2035 if (af == ASIO_OS_DEF(AF_INET)) 2036 { 2037 unsigned int b0, b1, b2, b3; 2038 if (sscanf_s(src, "%u.%u.%u.%u", &b0, &b1, &b2, &b3) != 4) 2039 { 2040 ec = asio::error::invalid_argument; 2041 return -1; 2042 } 2043 if (b0 > 255 || b1 > 255 || b2 > 255 || b3 > 255) 2044 { 2045 ec = asio::error::invalid_argument; 2046 return -1; 2047 } 2048 bytes[0] = static_cast<unsigned char>(b0); 2049 bytes[1] = static_cast<unsigned char>(b1); 2050 bytes[2] = static_cast<unsigned char>(b2); 2051 bytes[3] = static_cast<unsigned char>(b3); 2052 ec = asio::error_code(); 2053 return 1; 2054 } 2055 else if (af == ASIO_OS_DEF(AF_INET6)) 2056 { 2057 unsigned char* bytes = static_cast<unsigned char*>(dest); 2058 std::memset(bytes, 0, 16); 2059 unsigned char back_bytes[16] = { 0 }; 2060 int num_front_bytes = 0, num_back_bytes = 0; 2061 const char* p = src; 2062 2063 enum { fword, fcolon, bword, scope, done } state = fword; 2064 unsigned long current_word = 0; 2065 while (state != done) 2066 { 2067 if (current_word > 0xFFFF) 2068 { 2069 ec = asio::error::invalid_argument; 2070 return -1; 2071 } 2072 2073 switch (state) 2074 { 2075 case fword: 2076 if (*p >= '0' && *p <= '9') 2077 current_word = current_word * 16 + *p++ - '0'; 2078 else if (*p >= 'a' && *p <= 'f') 2079 current_word = current_word * 16 + *p++ - 'a' + 10; 2080 else if (*p >= 'A' && *p <= 'F') 2081 current_word = current_word * 16 + *p++ - 'A' + 10; 2082 else 2083 { 2084 if (num_front_bytes == 16) 2085 { 2086 ec = asio::error::invalid_argument; 2087 return -1; 2088 } 2089 2090 bytes[num_front_bytes++] = (current_word >> 8) & 0xFF; 2091 bytes[num_front_bytes++] = current_word & 0xFF; 2092 current_word = 0; 2093 2094 if (*p == ':') 2095 state = fcolon, ++p; 2096 else if (*p == '%') 2097 state = scope, ++p; 2098 else if (*p == 0) 2099 state = done; 2100 else 2101 { 2102 ec = asio::error::invalid_argument; 2103 return -1; 2104 } 2105 } 2106 break; 2107 2108 case fcolon: 2109 if (*p == ':') 2110 state = bword, ++p; 2111 else 2112 state = fword; 2113 break; 2114 2115 case bword: 2116 if (*p >= '0' && *p <= '9') 2117 current_word = current_word * 16 + *p++ - '0'; 2118 else if (*p >= 'a' && *p <= 'f') 2119 current_word = current_word * 16 + *p++ - 'a' + 10; 2120 else if (*p >= 'A' && *p <= 'F') 2121 current_word = current_word * 16 + *p++ - 'A' + 10; 2122 else 2123 { 2124 if (num_front_bytes + num_back_bytes == 16) 2125 { 2126 ec = asio::error::invalid_argument; 2127 return -1; 2128 } 2129 2130 back_bytes[num_back_bytes++] = (current_word >> 8) & 0xFF; 2131 back_bytes[num_back_bytes++] = current_word & 0xFF; 2132 current_word = 0; 2133 2134 if (*p == ':') 2135 state = bword, ++p; 2136 else if (*p == '%') 2137 state = scope, ++p; 2138 else if (*p == 0) 2139 state = done; 2140 else 2141 { 2142 ec = asio::error::invalid_argument; 2143 return -1; 2144 } 2145 } 2146 break; 2147 2148 case scope: 2149 if (*p >= '0' && *p <= '9') 2150 current_word = current_word * 10 + *p++ - '0'; 2151 else if (*p == 0) 2152 *scope_id = current_word, state = done; 2153 else 2154 { 2155 ec = asio::error::invalid_argument; 2156 return -1; 2157 } 2158 break; 2159 2160 default: 2161 break; 2162 } 2163 } 2164 2165 for (int i = 0; i < num_back_bytes; ++i) 2166 bytes[16 - num_back_bytes + i] = back_bytes[i]; 2167 2168 ec = asio::error_code(); 2169 return 1; 2170 } 2171 else 2172 { 2173 ec = asio::error::address_family_not_supported; 2174 return -1; 2175 } 2176#elif defined(ASIO_WINDOWS) || defined(__CYGWIN__) 2177 using namespace std; // For memcpy and strcmp. 2178 2179 if (af != ASIO_OS_DEF(AF_INET) && af != ASIO_OS_DEF(AF_INET6)) 2180 { 2181 ec = asio::error::address_family_not_supported; 2182 return -1; 2183 } 2184 2185 union 2186 { 2187 socket_addr_type base; 2188 sockaddr_storage_type storage; 2189 sockaddr_in4_type v4; 2190 sockaddr_in6_type v6; 2191 } address; 2192 int address_length = sizeof(sockaddr_storage_type); 2193#if defined(BOOST_NO_ANSI_APIS) || (defined(_MSC_VER) && (_MSC_VER >= 1800)) 2194 int num_wide_chars = static_cast<int>(strlen(src)) + 1; 2195 LPWSTR wide_buffer = (LPWSTR)_alloca(num_wide_chars * sizeof(WCHAR)); 2196 ::MultiByteToWideChar(CP_ACP, 0, src, -1, wide_buffer, num_wide_chars); 2197 int result = error_wrapper(::WSAStringToAddressW( 2198 wide_buffer, af, 0, &address.base, &address_length), ec); 2199#else 2200 int result = error_wrapper(::WSAStringToAddressA( 2201 const_cast<char*>(src), af, 0, &address.base, &address_length), ec); 2202#endif 2203 2204 if (af == ASIO_OS_DEF(AF_INET)) 2205 { 2206 if (result != socket_error_retval) 2207 { 2208 memcpy(dest, &address.v4.sin_addr, sizeof(in4_addr_type)); 2209 ec = asio::error_code(); 2210 } 2211 else if (strcmp(src, "255.255.255.255") == 0) 2212 { 2213 static_cast<in4_addr_type*>(dest)->s_addr = INADDR_NONE; 2214 ec = asio::error_code(); 2215 } 2216 } 2217 else // AF_INET6 2218 { 2219 if (result != socket_error_retval) 2220 { 2221 memcpy(dest, &address.v6.sin6_addr, sizeof(in6_addr_type)); 2222 if (scope_id) 2223 *scope_id = address.v6.sin6_scope_id; 2224 ec = asio::error_code(); 2225 } 2226 } 2227 2228 // Windows may not set an error code on failure. 2229 if (result == socket_error_retval && !ec) 2230 ec = asio::error::invalid_argument; 2231 2232 if (result != socket_error_retval) 2233 ec = asio::error_code(); 2234 2235 return result == socket_error_retval ? -1 : 1; 2236#else // defined(ASIO_WINDOWS) || defined(__CYGWIN__) 2237 using namespace std; // For strchr, memcpy and atoi. 2238 2239 // On some platforms, inet_pton fails if an address string contains a scope 2240 // id. Detect and remove the scope id before passing the string to inet_pton. 2241 const bool is_v6 = (af == ASIO_OS_DEF(AF_INET6)); 2242 const char* if_name = is_v6 ? strchr(src, '%') : 0; 2243 char src_buf[max_addr_v6_str_len + 1]; 2244 const char* src_ptr = src; 2245 if (if_name != 0) 2246 { 2247 if (if_name - src > max_addr_v6_str_len) 2248 { 2249 ec = asio::error::invalid_argument; 2250 return 0; 2251 } 2252 memcpy(src_buf, src, if_name - src); 2253 src_buf[if_name - src] = 0; 2254 src_ptr = src_buf; 2255 } 2256 2257 int result = error_wrapper(::inet_pton(af, src_ptr, dest), ec); 2258 if (result <= 0 && !ec) 2259 ec = asio::error::invalid_argument; 2260 if (result > 0 && is_v6 && scope_id) 2261 { 2262 using namespace std; // For strchr and atoi. 2263 *scope_id = 0; 2264 if (if_name != 0) 2265 { 2266 in6_addr_type* ipv6_address = static_cast<in6_addr_type*>(dest); 2267 bool is_link_local = ((ipv6_address->s6_addr[0] == 0xfe) 2268 && ((ipv6_address->s6_addr[1] & 0xc0) == 0x80)); 2269 bool is_multicast_link_local = ((ipv6_address->s6_addr[0] == 0xff) 2270 && ((ipv6_address->s6_addr[1] & 0x0f) == 0x02)); 2271 if (is_link_local || is_multicast_link_local) 2272 *scope_id = if_nametoindex(if_name + 1); 2273 if (*scope_id == 0) 2274 *scope_id = atoi(if_name + 1); 2275 } 2276 } 2277 return result; 2278#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__) 2279} 2280 2281int gethostname(char* name, int namelen, asio::error_code& ec) 2282{ 2283 clear_last_error(); 2284#if defined(ASIO_WINDOWS_RUNTIME) 2285 try 2286 { 2287 using namespace Windows::Foundation::Collections; 2288 using namespace Windows::Networking; 2289 using namespace Windows::Networking::Connectivity; 2290 IVectorView<HostName^>^ hostnames = NetworkInformation::GetHostNames(); 2291 for (unsigned i = 0; i < hostnames->Size; ++i) 2292 { 2293 HostName^ hostname = hostnames->GetAt(i); 2294 if (hostname->Type == HostNameType::DomainName) 2295 { 2296 std::wstring_convert<std::codecvt_utf8<wchar_t>> converter; 2297 std::string raw_name = converter.to_bytes(hostname->RawName->Data()); 2298 if (namelen > 0 && raw_name.size() < static_cast<std::size_t>(namelen)) 2299 { 2300 strcpy_s(name, namelen, raw_name.c_str()); 2301 return 0; 2302 } 2303 } 2304 } 2305 return -1; 2306 } 2307 catch (Platform::Exception^ e) 2308 { 2309 ec = asio::error_code(e->HResult, 2310 asio::system_category()); 2311 return -1; 2312 } 2313#else // defined(ASIO_WINDOWS_RUNTIME) 2314 int result = error_wrapper(::gethostname(name, namelen), ec); 2315# if defined(ASIO_WINDOWS) 2316 if (result == 0) 2317 ec = asio::error_code(); 2318# endif // defined(ASIO_WINDOWS) 2319 return result; 2320#endif // defined(ASIO_WINDOWS_RUNTIME) 2321} 2322 2323#if !defined(ASIO_WINDOWS_RUNTIME) 2324 2325#if !defined(ASIO_HAS_GETADDRINFO) 2326 2327// The following functions are only needed for emulation of getaddrinfo and 2328// getnameinfo. 2329 2330inline asio::error_code translate_netdb_error(int error) 2331{ 2332 switch (error) 2333 { 2334 case 0: 2335 return asio::error_code(); 2336 case HOST_NOT_FOUND: 2337 return asio::error::host_not_found; 2338 case TRY_AGAIN: 2339 return asio::error::host_not_found_try_again; 2340 case NO_RECOVERY: 2341 return asio::error::no_recovery; 2342 case NO_DATA: 2343 return asio::error::no_data; 2344 default: 2345 ASIO_ASSERT(false); 2346 return asio::error::invalid_argument; 2347 } 2348} 2349 2350inline hostent* gethostbyaddr(const char* addr, int length, int af, 2351 hostent* result, char* buffer, int buflength, asio::error_code& ec) 2352{ 2353 clear_last_error(); 2354#if defined(ASIO_WINDOWS) || defined(__CYGWIN__) 2355 (void)(buffer); 2356 (void)(buflength); 2357 hostent* retval = error_wrapper(::gethostbyaddr(addr, length, af), ec); 2358 if (!retval) 2359 return 0; 2360 ec = asio::error_code(); 2361 *result = *retval; 2362 return retval; 2363#elif defined(__sun) || defined(__QNX__) 2364 int error = 0; 2365 hostent* retval = error_wrapper(::gethostbyaddr_r(addr, length, af, result, 2366 buffer, buflength, &error), ec); 2367 if (error) 2368 ec = translate_netdb_error(error); 2369 return retval; 2370#elif defined(__MACH__) && defined(__APPLE__) 2371 (void)(buffer); 2372 (void)(buflength); 2373 int error = 0; 2374 hostent* retval = error_wrapper(::getipnodebyaddr( 2375 addr, length, af, &error), ec); 2376 if (error) 2377 ec = translate_netdb_error(error); 2378 if (!retval) 2379 return 0; 2380 *result = *retval; 2381 return retval; 2382#else 2383 hostent* retval = 0; 2384 int error = 0; 2385 error_wrapper(::gethostbyaddr_r(addr, length, af, result, buffer, 2386 buflength, &retval, &error), ec); 2387 if (error) 2388 ec = translate_netdb_error(error); 2389 return retval; 2390#endif 2391} 2392 2393inline hostent* gethostbyname(const char* name, int af, struct hostent* result, 2394 char* buffer, int buflength, int ai_flags, asio::error_code& ec) 2395{ 2396 clear_last_error(); 2397#if defined(ASIO_WINDOWS) || defined(__CYGWIN__) 2398 (void)(buffer); 2399 (void)(buflength); 2400 (void)(ai_flags); 2401 if (af != ASIO_OS_DEF(AF_INET)) 2402 { 2403 ec = asio::error::address_family_not_supported; 2404 return 0; 2405 } 2406 hostent* retval = error_wrapper(::gethostbyname(name), ec); 2407 if (!retval) 2408 return 0; 2409 ec = asio::error_code(); 2410 *result = *retval; 2411 return result; 2412#elif defined(__sun) || defined(__QNX__) 2413 (void)(ai_flags); 2414 if (af != ASIO_OS_DEF(AF_INET)) 2415 { 2416 ec = asio::error::address_family_not_supported; 2417 return 0; 2418 } 2419 int error = 0; 2420 hostent* retval = error_wrapper(::gethostbyname_r(name, result, buffer, 2421 buflength, &error), ec); 2422 if (error) 2423 ec = translate_netdb_error(error); 2424 return retval; 2425#elif defined(__MACH__) && defined(__APPLE__) 2426 (void)(buffer); 2427 (void)(buflength); 2428 int error = 0; 2429 hostent* retval = error_wrapper(::getipnodebyname( 2430 name, af, ai_flags, &error), ec); 2431 if (error) 2432 ec = translate_netdb_error(error); 2433 if (!retval) 2434 return 0; 2435 *result = *retval; 2436 return retval; 2437#else 2438 (void)(ai_flags); 2439 if (af != ASIO_OS_DEF(AF_INET)) 2440 { 2441 ec = asio::error::address_family_not_supported; 2442 return 0; 2443 } 2444 hostent* retval = 0; 2445 int error = 0; 2446 error_wrapper(::gethostbyname_r(name, result, 2447 buffer, buflength, &retval, &error), ec); 2448 if (error) 2449 ec = translate_netdb_error(error); 2450 return retval; 2451#endif 2452} 2453 2454inline void freehostent(hostent* h) 2455{ 2456#if defined(__MACH__) && defined(__APPLE__) 2457 if (h) 2458 ::freehostent(h); 2459#else 2460 (void)(h); 2461#endif 2462} 2463 2464// Emulation of getaddrinfo based on implementation in: 2465// Stevens, W. R., UNIX Network Programming Vol. 1, 2nd Ed., Prentice-Hall 1998. 2466 2467struct gai_search 2468{ 2469 const char* host; 2470 int family; 2471}; 2472 2473inline int gai_nsearch(const char* host, 2474 const addrinfo_type* hints, gai_search (&search)[2]) 2475{ 2476 int search_count = 0; 2477 if (host == 0 || host[0] == '\0') 2478 { 2479 if (hints->ai_flags & AI_PASSIVE) 2480 { 2481 // No host and AI_PASSIVE implies wildcard bind. 2482 switch (hints->ai_family) 2483 { 2484 case ASIO_OS_DEF(AF_INET): 2485 search[search_count].host = "0.0.0.0"; 2486 search[search_count].family = ASIO_OS_DEF(AF_INET); 2487 ++search_count; 2488 break; 2489 case ASIO_OS_DEF(AF_INET6): 2490 search[search_count].host = "0::0"; 2491 search[search_count].family = ASIO_OS_DEF(AF_INET6); 2492 ++search_count; 2493 break; 2494 case ASIO_OS_DEF(AF_UNSPEC): 2495 search[search_count].host = "0::0"; 2496 search[search_count].family = ASIO_OS_DEF(AF_INET6); 2497 ++search_count; 2498 search[search_count].host = "0.0.0.0"; 2499 search[search_count].family = ASIO_OS_DEF(AF_INET); 2500 ++search_count; 2501 break; 2502 default: 2503 break; 2504 } 2505 } 2506 else 2507 { 2508 // No host and not AI_PASSIVE means connect to local host. 2509 switch (hints->ai_family) 2510 { 2511 case ASIO_OS_DEF(AF_INET): 2512 search[search_count].host = "localhost"; 2513 search[search_count].family = ASIO_OS_DEF(AF_INET); 2514 ++search_count; 2515 break; 2516 case ASIO_OS_DEF(AF_INET6): 2517 search[search_count].host = "localhost"; 2518 search[search_count].family = ASIO_OS_DEF(AF_INET6); 2519 ++search_count; 2520 break; 2521 case ASIO_OS_DEF(AF_UNSPEC): 2522 search[search_count].host = "localhost"; 2523 search[search_count].family = ASIO_OS_DEF(AF_INET6); 2524 ++search_count; 2525 search[search_count].host = "localhost"; 2526 search[search_count].family = ASIO_OS_DEF(AF_INET); 2527 ++search_count; 2528 break; 2529 default: 2530 break; 2531 } 2532 } 2533 } 2534 else 2535 { 2536 // Host is specified. 2537 switch (hints->ai_family) 2538 { 2539 case ASIO_OS_DEF(AF_INET): 2540 search[search_count].host = host; 2541 search[search_count].family = ASIO_OS_DEF(AF_INET); 2542 ++search_count; 2543 break; 2544 case ASIO_OS_DEF(AF_INET6): 2545 search[search_count].host = host; 2546 search[search_count].family = ASIO_OS_DEF(AF_INET6); 2547 ++search_count; 2548 break; 2549 case ASIO_OS_DEF(AF_UNSPEC): 2550 search[search_count].host = host; 2551 search[search_count].family = ASIO_OS_DEF(AF_INET6); 2552 ++search_count; 2553 search[search_count].host = host; 2554 search[search_count].family = ASIO_OS_DEF(AF_INET); 2555 ++search_count; 2556 break; 2557 default: 2558 break; 2559 } 2560 } 2561 return search_count; 2562} 2563 2564template <typename T> 2565inline T* gai_alloc(std::size_t size = sizeof(T)) 2566{ 2567 using namespace std; 2568 T* p = static_cast<T*>(::operator new(size, std::nothrow)); 2569 if (p) 2570 memset(p, 0, size); 2571 return p; 2572} 2573 2574inline void gai_free(void* p) 2575{ 2576 ::operator delete(p); 2577} 2578 2579inline void gai_strcpy(char* target, const char* source, std::size_t max_size) 2580{ 2581 using namespace std; 2582#if defined(ASIO_HAS_SECURE_RTL) 2583 strcpy_s(target, max_size, source); 2584#else // defined(ASIO_HAS_SECURE_RTL) 2585 *target = 0; 2586 if (max_size > 0) 2587 strncat(target, source, max_size - 1); 2588#endif // defined(ASIO_HAS_SECURE_RTL) 2589} 2590 2591enum { gai_clone_flag = 1 << 30 }; 2592 2593inline int gai_aistruct(addrinfo_type*** next, const addrinfo_type* hints, 2594 const void* addr, int family) 2595{ 2596 using namespace std; 2597 2598 addrinfo_type* ai = gai_alloc<addrinfo_type>(); 2599 if (ai == 0) 2600 return EAI_MEMORY; 2601 2602 ai->ai_next = 0; 2603 **next = ai; 2604 *next = &ai->ai_next; 2605 2606 ai->ai_canonname = 0; 2607 ai->ai_socktype = hints->ai_socktype; 2608 if (ai->ai_socktype == 0) 2609 ai->ai_flags |= gai_clone_flag; 2610 ai->ai_protocol = hints->ai_protocol; 2611 ai->ai_family = family; 2612 2613 switch (ai->ai_family) 2614 { 2615 case ASIO_OS_DEF(AF_INET): 2616 { 2617 sockaddr_in4_type* sinptr = gai_alloc<sockaddr_in4_type>(); 2618 if (sinptr == 0) 2619 return EAI_MEMORY; 2620 sinptr->sin_family = ASIO_OS_DEF(AF_INET); 2621 memcpy(&sinptr->sin_addr, addr, sizeof(in4_addr_type)); 2622 ai->ai_addr = reinterpret_cast<sockaddr*>(sinptr); 2623 ai->ai_addrlen = sizeof(sockaddr_in4_type); 2624 break; 2625 } 2626 case ASIO_OS_DEF(AF_INET6): 2627 { 2628 sockaddr_in6_type* sin6ptr = gai_alloc<sockaddr_in6_type>(); 2629 if (sin6ptr == 0) 2630 return EAI_MEMORY; 2631 sin6ptr->sin6_family = ASIO_OS_DEF(AF_INET6); 2632 memcpy(&sin6ptr->sin6_addr, addr, sizeof(in6_addr_type)); 2633 ai->ai_addr = reinterpret_cast<sockaddr*>(sin6ptr); 2634 ai->ai_addrlen = sizeof(sockaddr_in6_type); 2635 break; 2636 } 2637 default: 2638 break; 2639 } 2640 2641 return 0; 2642} 2643 2644inline addrinfo_type* gai_clone(addrinfo_type* ai) 2645{ 2646 using namespace std; 2647 2648 addrinfo_type* new_ai = gai_alloc<addrinfo_type>(); 2649 if (new_ai == 0) 2650 return new_ai; 2651 2652 new_ai->ai_next = ai->ai_next; 2653 ai->ai_next = new_ai; 2654 2655 new_ai->ai_flags = 0; 2656 new_ai->ai_family = ai->ai_family; 2657 new_ai->ai_socktype = ai->ai_socktype; 2658 new_ai->ai_protocol = ai->ai_protocol; 2659 new_ai->ai_canonname = 0; 2660 new_ai->ai_addrlen = ai->ai_addrlen; 2661 new_ai->ai_addr = gai_alloc<sockaddr>(ai->ai_addrlen); 2662 memcpy(new_ai->ai_addr, ai->ai_addr, ai->ai_addrlen); 2663 2664 return new_ai; 2665} 2666 2667inline int gai_port(addrinfo_type* aihead, int port, int socktype) 2668{ 2669 int num_found = 0; 2670 2671 for (addrinfo_type* ai = aihead; ai; ai = ai->ai_next) 2672 { 2673 if (ai->ai_flags & gai_clone_flag) 2674 { 2675 if (ai->ai_socktype != 0) 2676 { 2677 ai = gai_clone(ai); 2678 if (ai == 0) 2679 return -1; 2680 // ai now points to newly cloned entry. 2681 } 2682 } 2683 else if (ai->ai_socktype != socktype) 2684 { 2685 // Ignore if mismatch on socket type. 2686 continue; 2687 } 2688 2689 ai->ai_socktype = socktype; 2690 2691 switch (ai->ai_family) 2692 { 2693 case ASIO_OS_DEF(AF_INET): 2694 { 2695 sockaddr_in4_type* sinptr = 2696 reinterpret_cast<sockaddr_in4_type*>(ai->ai_addr); 2697 sinptr->sin_port = port; 2698 ++num_found; 2699 break; 2700 } 2701 case ASIO_OS_DEF(AF_INET6): 2702 { 2703 sockaddr_in6_type* sin6ptr = 2704 reinterpret_cast<sockaddr_in6_type*>(ai->ai_addr); 2705 sin6ptr->sin6_port = port; 2706 ++num_found; 2707 break; 2708 } 2709 default: 2710 break; 2711 } 2712 } 2713 2714 return num_found; 2715} 2716 2717inline int gai_serv(addrinfo_type* aihead, 2718 const addrinfo_type* hints, const char* serv) 2719{ 2720 using namespace std; 2721 2722 int num_found = 0; 2723 2724 if ( 2725#if defined(AI_NUMERICSERV) 2726 (hints->ai_flags & AI_NUMERICSERV) || 2727#endif 2728 isdigit(static_cast<unsigned char>(serv[0]))) 2729 { 2730 int port = htons(atoi(serv)); 2731 if (hints->ai_socktype) 2732 { 2733 // Caller specifies socket type. 2734 int rc = gai_port(aihead, port, hints->ai_socktype); 2735 if (rc < 0) 2736 return EAI_MEMORY; 2737 num_found += rc; 2738 } 2739 else 2740 { 2741 // Caller does not specify socket type. 2742 int rc = gai_port(aihead, port, SOCK_STREAM); 2743 if (rc < 0) 2744 return EAI_MEMORY; 2745 num_found += rc; 2746 rc = gai_port(aihead, port, SOCK_DGRAM); 2747 if (rc < 0) 2748 return EAI_MEMORY; 2749 num_found += rc; 2750 } 2751 } 2752 else 2753 { 2754 // Try service name with TCP first, then UDP. 2755 if (hints->ai_socktype == 0 || hints->ai_socktype == SOCK_STREAM) 2756 { 2757 servent* sptr = getservbyname(serv, "tcp"); 2758 if (sptr != 0) 2759 { 2760 int rc = gai_port(aihead, sptr->s_port, SOCK_STREAM); 2761 if (rc < 0) 2762 return EAI_MEMORY; 2763 num_found += rc; 2764 } 2765 } 2766 if (hints->ai_socktype == 0 || hints->ai_socktype == SOCK_DGRAM) 2767 { 2768 servent* sptr = getservbyname(serv, "udp"); 2769 if (sptr != 0) 2770 { 2771 int rc = gai_port(aihead, sptr->s_port, SOCK_DGRAM); 2772 if (rc < 0) 2773 return EAI_MEMORY; 2774 num_found += rc; 2775 } 2776 } 2777 } 2778 2779 if (num_found == 0) 2780 { 2781 if (hints->ai_socktype == 0) 2782 { 2783 // All calls to getservbyname() failed. 2784 return EAI_NONAME; 2785 } 2786 else 2787 { 2788 // Service not supported for socket type. 2789 return EAI_SERVICE; 2790 } 2791 } 2792 2793 return 0; 2794} 2795 2796inline int gai_echeck(const char* host, const char* service, 2797 int flags, int family, int socktype, int protocol) 2798{ 2799 (void)(flags); 2800 (void)(protocol); 2801 2802 // Host or service must be specified. 2803 if (host == 0 || host[0] == '\0') 2804 if (service == 0 || service[0] == '\0') 2805 return EAI_NONAME; 2806 2807 // Check combination of family and socket type. 2808 switch (family) 2809 { 2810 case ASIO_OS_DEF(AF_UNSPEC): 2811 break; 2812 case ASIO_OS_DEF(AF_INET): 2813 case ASIO_OS_DEF(AF_INET6): 2814 if (service != 0 && service[0] != '\0') 2815 if (socktype != 0 && socktype != SOCK_STREAM && socktype != SOCK_DGRAM) 2816 return EAI_SOCKTYPE; 2817 break; 2818 default: 2819 return EAI_FAMILY; 2820 } 2821 2822 return 0; 2823} 2824 2825inline void freeaddrinfo_emulation(addrinfo_type* aihead) 2826{ 2827 addrinfo_type* ai = aihead; 2828 while (ai) 2829 { 2830 gai_free(ai->ai_addr); 2831 gai_free(ai->ai_canonname); 2832 addrinfo_type* ainext = ai->ai_next; 2833 gai_free(ai); 2834 ai = ainext; 2835 } 2836} 2837 2838inline int getaddrinfo_emulation(const char* host, const char* service, 2839 const addrinfo_type* hintsp, addrinfo_type** result) 2840{ 2841 // Set up linked list of addrinfo structures. 2842 addrinfo_type* aihead = 0; 2843 addrinfo_type** ainext = &aihead; 2844 char* canon = 0; 2845 2846 // Supply default hints if not specified by caller. 2847 addrinfo_type hints = addrinfo_type(); 2848 hints.ai_family = ASIO_OS_DEF(AF_UNSPEC); 2849 if (hintsp) 2850 hints = *hintsp; 2851 2852 // If the resolution is not specifically for AF_INET6, remove the AI_V4MAPPED 2853 // and AI_ALL flags. 2854#if defined(AI_V4MAPPED) 2855 if (hints.ai_family != ASIO_OS_DEF(AF_INET6)) 2856 hints.ai_flags &= ~AI_V4MAPPED; 2857#endif 2858#if defined(AI_ALL) 2859 if (hints.ai_family != ASIO_OS_DEF(AF_INET6)) 2860 hints.ai_flags &= ~AI_ALL; 2861#endif 2862 2863 // Basic error checking. 2864 int rc = gai_echeck(host, service, hints.ai_flags, hints.ai_family, 2865 hints.ai_socktype, hints.ai_protocol); 2866 if (rc != 0) 2867 { 2868 freeaddrinfo_emulation(aihead); 2869 return rc; 2870 } 2871 2872 gai_search search[2]; 2873 int search_count = gai_nsearch(host, &hints, search); 2874 for (gai_search* sptr = search; sptr < search + search_count; ++sptr) 2875 { 2876 // Check for IPv4 dotted decimal string. 2877 in4_addr_type inaddr; 2878 asio::error_code ec; 2879 if (socket_ops::inet_pton(ASIO_OS_DEF(AF_INET), 2880 sptr->host, &inaddr, 0, ec) == 1) 2881 { 2882 if (hints.ai_family != ASIO_OS_DEF(AF_UNSPEC) 2883 && hints.ai_family != ASIO_OS_DEF(AF_INET)) 2884 { 2885 freeaddrinfo_emulation(aihead); 2886 gai_free(canon); 2887 return EAI_FAMILY; 2888 } 2889 if (sptr->family == ASIO_OS_DEF(AF_INET)) 2890 { 2891 rc = gai_aistruct(&ainext, &hints, &inaddr, ASIO_OS_DEF(AF_INET)); 2892 if (rc != 0) 2893 { 2894 freeaddrinfo_emulation(aihead); 2895 gai_free(canon); 2896 return rc; 2897 } 2898 } 2899 continue; 2900 } 2901 2902 // Check for IPv6 hex string. 2903 in6_addr_type in6addr; 2904 if (socket_ops::inet_pton(ASIO_OS_DEF(AF_INET6), 2905 sptr->host, &in6addr, 0, ec) == 1) 2906 { 2907 if (hints.ai_family != ASIO_OS_DEF(AF_UNSPEC) 2908 && hints.ai_family != ASIO_OS_DEF(AF_INET6)) 2909 { 2910 freeaddrinfo_emulation(aihead); 2911 gai_free(canon); 2912 return EAI_FAMILY; 2913 } 2914 if (sptr->family == ASIO_OS_DEF(AF_INET6)) 2915 { 2916 rc = gai_aistruct(&ainext, &hints, &in6addr, 2917 ASIO_OS_DEF(AF_INET6)); 2918 if (rc != 0) 2919 { 2920 freeaddrinfo_emulation(aihead); 2921 gai_free(canon); 2922 return rc; 2923 } 2924 } 2925 continue; 2926 } 2927 2928 // Look up hostname. 2929 hostent hent; 2930 char hbuf[8192] = ""; 2931 hostent* hptr = socket_ops::gethostbyname(sptr->host, 2932 sptr->family, &hent, hbuf, sizeof(hbuf), hints.ai_flags, ec); 2933 if (hptr == 0) 2934 { 2935 if (search_count == 2) 2936 { 2937 // Failure is OK if there are multiple searches. 2938 continue; 2939 } 2940 freeaddrinfo_emulation(aihead); 2941 gai_free(canon); 2942 if (ec == asio::error::host_not_found) 2943 return EAI_NONAME; 2944 if (ec == asio::error::host_not_found_try_again) 2945 return EAI_AGAIN; 2946 if (ec == asio::error::no_recovery) 2947 return EAI_FAIL; 2948 if (ec == asio::error::no_data) 2949 return EAI_NONAME; 2950 return EAI_NONAME; 2951 } 2952 2953 // Check for address family mismatch if one was specified. 2954 if (hints.ai_family != ASIO_OS_DEF(AF_UNSPEC) 2955 && hints.ai_family != hptr->h_addrtype) 2956 { 2957 freeaddrinfo_emulation(aihead); 2958 gai_free(canon); 2959 socket_ops::freehostent(hptr); 2960 return EAI_FAMILY; 2961 } 2962 2963 // Save canonical name first time. 2964 if (host != 0 && host[0] != '\0' && hptr->h_name && hptr->h_name[0] 2965 && (hints.ai_flags & AI_CANONNAME) && canon == 0) 2966 { 2967 std::size_t canon_len = strlen(hptr->h_name) + 1; 2968 canon = gai_alloc<char>(canon_len); 2969 if (canon == 0) 2970 { 2971 freeaddrinfo_emulation(aihead); 2972 socket_ops::freehostent(hptr); 2973 return EAI_MEMORY; 2974 } 2975 gai_strcpy(canon, hptr->h_name, canon_len); 2976 } 2977 2978 // Create an addrinfo structure for each returned address. 2979 for (char** ap = hptr->h_addr_list; *ap; ++ap) 2980 { 2981 rc = gai_aistruct(&ainext, &hints, *ap, hptr->h_addrtype); 2982 if (rc != 0) 2983 { 2984 freeaddrinfo_emulation(aihead); 2985 gai_free(canon); 2986 socket_ops::freehostent(hptr); 2987 return EAI_FAMILY; 2988 } 2989 } 2990 2991 socket_ops::freehostent(hptr); 2992 } 2993 2994 // Check if we found anything. 2995 if (aihead == 0) 2996 { 2997 gai_free(canon); 2998 return EAI_NONAME; 2999 } 3000 3001 // Return canonical name in first entry. 3002 if (host != 0 && host[0] != '\0' && (hints.ai_flags & AI_CANONNAME)) 3003 { 3004 if (canon) 3005 { 3006 aihead->ai_canonname = canon; 3007 canon = 0; 3008 } 3009 else 3010 { 3011 std::size_t canonname_len = strlen(search[0].host) + 1; 3012 aihead->ai_canonname = gai_alloc<char>(canonname_len); 3013 if (aihead->ai_canonname == 0) 3014 { 3015 freeaddrinfo_emulation(aihead); 3016 return EAI_MEMORY; 3017 } 3018 gai_strcpy(aihead->ai_canonname, search[0].host, canonname_len); 3019 } 3020 } 3021 gai_free(canon); 3022 3023 // Process the service name. 3024 if (service != 0 && service[0] != '\0') 3025 { 3026 rc = gai_serv(aihead, &hints, service); 3027 if (rc != 0) 3028 { 3029 freeaddrinfo_emulation(aihead); 3030 return rc; 3031 } 3032 } 3033 3034 // Return result to caller. 3035 *result = aihead; 3036 return 0; 3037} 3038 3039inline asio::error_code getnameinfo_emulation( 3040 const socket_addr_type* sa, std::size_t salen, char* host, 3041 std::size_t hostlen, char* serv, std::size_t servlen, int flags, 3042 asio::error_code& ec) 3043{ 3044 using namespace std; 3045 3046 const char* addr; 3047 size_t addr_len; 3048 unsigned short port; 3049 switch (sa->sa_family) 3050 { 3051 case ASIO_OS_DEF(AF_INET): 3052 if (salen != sizeof(sockaddr_in4_type)) 3053 { 3054 return ec = asio::error::invalid_argument; 3055 } 3056 addr = reinterpret_cast<const char*>( 3057 &reinterpret_cast<const sockaddr_in4_type*>(sa)->sin_addr); 3058 addr_len = sizeof(in4_addr_type); 3059 port = reinterpret_cast<const sockaddr_in4_type*>(sa)->sin_port; 3060 break; 3061 case ASIO_OS_DEF(AF_INET6): 3062 if (salen != sizeof(sockaddr_in6_type)) 3063 { 3064 return ec = asio::error::invalid_argument; 3065 } 3066 addr = reinterpret_cast<const char*>( 3067 &reinterpret_cast<const sockaddr_in6_type*>(sa)->sin6_addr); 3068 addr_len = sizeof(in6_addr_type); 3069 port = reinterpret_cast<const sockaddr_in6_type*>(sa)->sin6_port; 3070 break; 3071 default: 3072 return ec = asio::error::address_family_not_supported; 3073 } 3074 3075 if (host && hostlen > 0) 3076 { 3077 if (flags & NI_NUMERICHOST) 3078 { 3079 if (socket_ops::inet_ntop(sa->sa_family, addr, host, hostlen, 0, ec) == 0) 3080 { 3081 return ec; 3082 } 3083 } 3084 else 3085 { 3086 hostent hent; 3087 char hbuf[8192] = ""; 3088 hostent* hptr = socket_ops::gethostbyaddr(addr, 3089 static_cast<int>(addr_len), sa->sa_family, 3090 &hent, hbuf, sizeof(hbuf), ec); 3091 if (hptr && hptr->h_name && hptr->h_name[0] != '\0') 3092 { 3093 if (flags & NI_NOFQDN) 3094 { 3095 char* dot = strchr(hptr->h_name, '.'); 3096 if (dot) 3097 { 3098 *dot = 0; 3099 } 3100 } 3101 gai_strcpy(host, hptr->h_name, hostlen); 3102 socket_ops::freehostent(hptr); 3103 } 3104 else 3105 { 3106 socket_ops::freehostent(hptr); 3107 if (flags & NI_NAMEREQD) 3108 { 3109 return ec = asio::error::host_not_found; 3110 } 3111 if (socket_ops::inet_ntop(sa->sa_family, 3112 addr, host, hostlen, 0, ec) == 0) 3113 { 3114 return ec; 3115 } 3116 } 3117 } 3118 } 3119 3120 if (serv && servlen > 0) 3121 { 3122 if (flags & NI_NUMERICSERV) 3123 { 3124 if (servlen < 6) 3125 { 3126 return ec = asio::error::no_buffer_space; 3127 } 3128#if defined(ASIO_HAS_SECURE_RTL) 3129 sprintf_s(serv, servlen, "%u", ntohs(port)); 3130#else // defined(ASIO_HAS_SECURE_RTL) 3131 sprintf(serv, "%u", ntohs(port)); 3132#endif // defined(ASIO_HAS_SECURE_RTL) 3133 } 3134 else 3135 { 3136#if defined(ASIO_HAS_PTHREADS) 3137 static ::pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 3138 ::pthread_mutex_lock(&mutex); 3139#endif // defined(ASIO_HAS_PTHREADS) 3140 servent* sptr = ::getservbyport(port, (flags & NI_DGRAM) ? "udp" : 0); 3141 if (sptr && sptr->s_name && sptr->s_name[0] != '\0') 3142 { 3143 gai_strcpy(serv, sptr->s_name, servlen); 3144 } 3145 else 3146 { 3147 if (servlen < 6) 3148 { 3149 return ec = asio::error::no_buffer_space; 3150 } 3151#if defined(ASIO_HAS_SECURE_RTL) 3152 sprintf_s(serv, servlen, "%u", ntohs(port)); 3153#else // defined(ASIO_HAS_SECURE_RTL) 3154 sprintf(serv, "%u", ntohs(port)); 3155#endif // defined(ASIO_HAS_SECURE_RTL) 3156 } 3157#if defined(ASIO_HAS_PTHREADS) 3158 ::pthread_mutex_unlock(&mutex); 3159#endif // defined(ASIO_HAS_PTHREADS) 3160 } 3161 } 3162 3163 ec = asio::error_code(); 3164 return ec; 3165} 3166 3167#endif // !defined(ASIO_HAS_GETADDRINFO) 3168 3169inline asio::error_code translate_addrinfo_error(int error) 3170{ 3171 switch (error) 3172 { 3173 case 0: 3174 return asio::error_code(); 3175 case EAI_AGAIN: 3176 return asio::error::host_not_found_try_again; 3177 case EAI_BADFLAGS: 3178 return asio::error::invalid_argument; 3179 case EAI_FAIL: 3180 return asio::error::no_recovery; 3181 case EAI_FAMILY: 3182 return asio::error::address_family_not_supported; 3183 case EAI_MEMORY: 3184 return asio::error::no_memory; 3185 case EAI_NONAME: 3186#if defined(EAI_ADDRFAMILY) 3187 case EAI_ADDRFAMILY: 3188#endif 3189#if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME) 3190 case EAI_NODATA: 3191#endif 3192 return asio::error::host_not_found; 3193 case EAI_SERVICE: 3194 return asio::error::service_not_found; 3195 case EAI_SOCKTYPE: 3196 return asio::error::socket_type_not_supported; 3197 default: // Possibly the non-portable EAI_SYSTEM. 3198#if defined(ASIO_WINDOWS) || defined(__CYGWIN__) 3199 return asio::error_code( 3200 WSAGetLastError(), asio::error::get_system_category()); 3201#else 3202 return asio::error_code( 3203 errno, asio::error::get_system_category()); 3204#endif 3205 } 3206} 3207 3208asio::error_code getaddrinfo(const char* host, 3209 const char* service, const addrinfo_type& hints, 3210 addrinfo_type** result, asio::error_code& ec) 3211{ 3212 host = (host && *host) ? host : 0; 3213 service = (service && *service) ? service : 0; 3214 clear_last_error(); 3215#if defined(ASIO_WINDOWS) || defined(__CYGWIN__) 3216# if defined(ASIO_HAS_GETADDRINFO) 3217 // Building for Windows XP, Windows Server 2003, or later. 3218 int error = ::getaddrinfo(host, service, &hints, result); 3219 return ec = translate_addrinfo_error(error); 3220# else 3221 // Building for Windows 2000 or earlier. 3222 typedef int (WSAAPI *gai_t)(const char*, 3223 const char*, const addrinfo_type*, addrinfo_type**); 3224 if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32")) 3225 { 3226 if (gai_t gai = (gai_t)::GetProcAddress(winsock_module, "getaddrinfo")) 3227 { 3228 int error = gai(host, service, &hints, result); 3229 return ec = translate_addrinfo_error(error); 3230 } 3231 } 3232 int error = getaddrinfo_emulation(host, service, &hints, result); 3233 return ec = translate_addrinfo_error(error); 3234# endif 3235#elif !defined(ASIO_HAS_GETADDRINFO) 3236 int error = getaddrinfo_emulation(host, service, &hints, result); 3237 return ec = translate_addrinfo_error(error); 3238#else 3239 int error = ::getaddrinfo(host, service, &hints, result); 3240 return ec = translate_addrinfo_error(error); 3241#endif 3242} 3243 3244asio::error_code background_getaddrinfo( 3245 const weak_cancel_token_type& cancel_token, const char* host, 3246 const char* service, const addrinfo_type& hints, 3247 addrinfo_type** result, asio::error_code& ec) 3248{ 3249 if (cancel_token.expired()) 3250 ec = asio::error::operation_aborted; 3251 else 3252 socket_ops::getaddrinfo(host, service, hints, result, ec); 3253 return ec; 3254} 3255 3256void freeaddrinfo(addrinfo_type* ai) 3257{ 3258#if defined(ASIO_WINDOWS) || defined(__CYGWIN__) 3259# if defined(ASIO_HAS_GETADDRINFO) 3260 // Building for Windows XP, Windows Server 2003, or later. 3261 ::freeaddrinfo(ai); 3262# else 3263 // Building for Windows 2000 or earlier. 3264 typedef int (WSAAPI *fai_t)(addrinfo_type*); 3265 if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32")) 3266 { 3267 if (fai_t fai = (fai_t)::GetProcAddress(winsock_module, "freeaddrinfo")) 3268 { 3269 fai(ai); 3270 return; 3271 } 3272 } 3273 freeaddrinfo_emulation(ai); 3274# endif 3275#elif !defined(ASIO_HAS_GETADDRINFO) 3276 freeaddrinfo_emulation(ai); 3277#else 3278 ::freeaddrinfo(ai); 3279#endif 3280} 3281 3282asio::error_code getnameinfo(const socket_addr_type* addr, 3283 std::size_t addrlen, char* host, std::size_t hostlen, 3284 char* serv, std::size_t servlen, int flags, asio::error_code& ec) 3285{ 3286#if defined(ASIO_WINDOWS) || defined(__CYGWIN__) 3287# if defined(ASIO_HAS_GETADDRINFO) 3288 // Building for Windows XP, Windows Server 2003, or later. 3289 clear_last_error(); 3290 int error = ::getnameinfo(addr, static_cast<socklen_t>(addrlen), 3291 host, static_cast<DWORD>(hostlen), 3292 serv, static_cast<DWORD>(servlen), flags); 3293 return ec = translate_addrinfo_error(error); 3294# else 3295 // Building for Windows 2000 or earlier. 3296 typedef int (WSAAPI *gni_t)(const socket_addr_type*, 3297 int, char*, DWORD, char*, DWORD, int); 3298 if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32")) 3299 { 3300 if (gni_t gni = (gni_t)::GetProcAddress(winsock_module, "getnameinfo")) 3301 { 3302 clear_last_error(); 3303 int error = gni(addr, static_cast<int>(addrlen), 3304 host, static_cast<DWORD>(hostlen), 3305 serv, static_cast<DWORD>(servlen), flags); 3306 return ec = translate_addrinfo_error(error); 3307 } 3308 } 3309 clear_last_error(); 3310 return getnameinfo_emulation(addr, addrlen, 3311 host, hostlen, serv, servlen, flags, ec); 3312# endif 3313#elif !defined(ASIO_HAS_GETADDRINFO) 3314 using namespace std; // For memcpy. 3315 sockaddr_storage_type tmp_addr; 3316 memcpy(&tmp_addr, addr, addrlen); 3317 tmp_addr.ss_len = addrlen; 3318 addr = reinterpret_cast<socket_addr_type*>(&tmp_addr); 3319 clear_last_error(); 3320 return getnameinfo_emulation(addr, addrlen, 3321 host, hostlen, serv, servlen, flags, ec); 3322#else 3323 clear_last_error(); 3324 int error = ::getnameinfo(addr, addrlen, host, hostlen, serv, servlen, flags); 3325 return ec = translate_addrinfo_error(error); 3326#endif 3327} 3328 3329asio::error_code sync_getnameinfo( 3330 const socket_addr_type* addr, std::size_t addrlen, 3331 char* host, std::size_t hostlen, char* serv, 3332 std::size_t servlen, int sock_type, asio::error_code& ec) 3333{ 3334 // First try resolving with the service name. If that fails try resolving 3335 // but allow the service to be returned as a number. 3336 int flags = (sock_type == SOCK_DGRAM) ? NI_DGRAM : 0; 3337 socket_ops::getnameinfo(addr, addrlen, host, 3338 hostlen, serv, servlen, flags, ec); 3339 if (ec) 3340 { 3341 socket_ops::getnameinfo(addr, addrlen, host, hostlen, 3342 serv, servlen, flags | NI_NUMERICSERV, ec); 3343 } 3344 3345 return ec; 3346} 3347 3348asio::error_code background_getnameinfo( 3349 const weak_cancel_token_type& cancel_token, 3350 const socket_addr_type* addr, std::size_t addrlen, 3351 char* host, std::size_t hostlen, char* serv, 3352 std::size_t servlen, int sock_type, asio::error_code& ec) 3353{ 3354 if (cancel_token.expired()) 3355 { 3356 ec = asio::error::operation_aborted; 3357 } 3358 else 3359 { 3360 // First try resolving with the service name. If that fails try resolving 3361 // but allow the service to be returned as a number. 3362 int flags = (sock_type == SOCK_DGRAM) ? NI_DGRAM : 0; 3363 socket_ops::getnameinfo(addr, addrlen, host, 3364 hostlen, serv, servlen, flags, ec); 3365 if (ec) 3366 { 3367 socket_ops::getnameinfo(addr, addrlen, host, hostlen, 3368 serv, servlen, flags | NI_NUMERICSERV, ec); 3369 } 3370 } 3371 3372 return ec; 3373} 3374 3375#endif // !defined(ASIO_WINDOWS_RUNTIME) 3376 3377u_long_type network_to_host_long(u_long_type value) 3378{ 3379#if defined(ASIO_WINDOWS_RUNTIME) 3380 unsigned char* value_p = reinterpret_cast<unsigned char*>(&value); 3381 u_long_type result = (static_cast<u_long_type>(value_p[0]) << 24) 3382 | (static_cast<u_long_type>(value_p[1]) << 16) 3383 | (static_cast<u_long_type>(value_p[2]) << 8) 3384 | static_cast<u_long_type>(value_p[3]); 3385 return result; 3386#else // defined(ASIO_WINDOWS_RUNTIME) 3387 return ntohl(value); 3388#endif // defined(ASIO_WINDOWS_RUNTIME) 3389} 3390 3391u_long_type host_to_network_long(u_long_type value) 3392{ 3393#if defined(ASIO_WINDOWS_RUNTIME) 3394 u_long_type result; 3395 unsigned char* result_p = reinterpret_cast<unsigned char*>(&result); 3396 result_p[0] = static_cast<unsigned char>((value >> 24) & 0xFF); 3397 result_p[1] = static_cast<unsigned char>((value >> 16) & 0xFF); 3398 result_p[2] = static_cast<unsigned char>((value >> 8) & 0xFF); 3399 result_p[3] = static_cast<unsigned char>(value & 0xFF); 3400 return result; 3401#else // defined(ASIO_WINDOWS_RUNTIME) 3402 return htonl(value); 3403#endif // defined(ASIO_WINDOWS_RUNTIME) 3404} 3405 3406u_short_type network_to_host_short(u_short_type value) 3407{ 3408#if defined(ASIO_WINDOWS_RUNTIME) 3409 unsigned char* value_p = reinterpret_cast<unsigned char*>(&value); 3410 u_short_type result = (static_cast<u_short_type>(value_p[0]) << 8) 3411 | static_cast<u_short_type>(value_p[1]); 3412 return result; 3413#else // defined(ASIO_WINDOWS_RUNTIME) 3414 return ntohs(value); 3415#endif // defined(ASIO_WINDOWS_RUNTIME) 3416} 3417 3418u_short_type host_to_network_short(u_short_type value) 3419{ 3420#if defined(ASIO_WINDOWS_RUNTIME) 3421 u_short_type result; 3422 unsigned char* result_p = reinterpret_cast<unsigned char*>(&result); 3423 result_p[0] = static_cast<unsigned char>((value >> 8) & 0xFF); 3424 result_p[1] = static_cast<unsigned char>(value & 0xFF); 3425 return result; 3426#else // defined(ASIO_WINDOWS_RUNTIME) 3427 return htons(value); 3428#endif // defined(ASIO_WINDOWS_RUNTIME) 3429} 3430 3431} // namespace socket_ops 3432} // namespace detail 3433} // namespace asio 3434 3435#include "asio/detail/pop_options.hpp" 3436 3437#endif // ASIO_DETAIL_SOCKET_OPS_IPP 3438