Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:28:35

0001 //
0002 // detail/impl/socket_ops.ipp
0003 // ~~~~~~~~~~~~~~~~~~~~~~~~~~
0004 //
0005 // Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
0006 //
0007 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0009 //
0010 
0011 #ifndef BOOST_ASIO_DETAIL_SOCKET_OPS_IPP
0012 #define BOOST_ASIO_DETAIL_SOCKET_OPS_IPP
0013 
0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0015 # pragma once
0016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
0017 
0018 #include <boost/asio/detail/config.hpp>
0019 
0020 #include <cctype>
0021 #include <cstdio>
0022 #include <cstdlib>
0023 #include <cstring>
0024 #include <cerrno>
0025 #include <new>
0026 #include <boost/asio/detail/assert.hpp>
0027 #include <boost/asio/detail/socket_ops.hpp>
0028 #include <boost/asio/error.hpp>
0029 
0030 #if defined(BOOST_ASIO_WINDOWS_RUNTIME)
0031 # include <codecvt>
0032 # include <locale>
0033 # include <string>
0034 #endif // defined(BOOST_ASIO_WINDOWS_RUNTIME)
0035 
0036 #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) \
0037   || defined(__MACH__) && defined(__APPLE__)
0038 # if defined(BOOST_ASIO_HAS_PTHREADS)
0039 #  include <pthread.h>
0040 # endif // defined(BOOST_ASIO_HAS_PTHREADS)
0041 #endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0042        // || defined(__MACH__) && defined(__APPLE__)
0043 
0044 #include <boost/asio/detail/push_options.hpp>
0045 
0046 namespace boost {
0047 namespace asio {
0048 namespace detail {
0049 namespace socket_ops {
0050 
0051 #if !defined(BOOST_ASIO_WINDOWS_RUNTIME)
0052 
0053 #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0054 struct msghdr { int msg_namelen; };
0055 #endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0056 
0057 #if defined(__hpux)
0058 // HP-UX doesn't declare these functions extern "C", so they are declared again
0059 // here to avoid linker errors about undefined symbols.
0060 extern "C" char* if_indextoname(unsigned int, char*);
0061 extern "C" unsigned int if_nametoindex(const char*);
0062 #endif // defined(__hpux)
0063 
0064 #endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME)
0065 
0066 inline void clear_last_error()
0067 {
0068 #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0069   WSASetLastError(0);
0070 #else
0071   errno = 0;
0072 #endif
0073 }
0074 
0075 #if !defined(BOOST_ASIO_WINDOWS_RUNTIME)
0076 
0077 inline void get_last_error(
0078     boost::system::error_code& ec, bool is_error_condition)
0079 {
0080   if (!is_error_condition)
0081   {
0082     boost::asio::error::clear(ec);
0083   }
0084   else
0085   {
0086 #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0087     ec = boost::system::error_code(WSAGetLastError(),
0088         boost::asio::error::get_system_category());
0089 #else
0090     ec = boost::system::error_code(errno,
0091         boost::asio::error::get_system_category());
0092 #endif
0093   }
0094 }
0095 
0096 template <typename SockLenType>
0097 inline socket_type call_accept(SockLenType msghdr::*,
0098     socket_type s, void* addr, std::size_t* addrlen)
0099 {
0100   SockLenType tmp_addrlen = addrlen ? (SockLenType)*addrlen : 0;
0101   socket_type result = ::accept(s,
0102       static_cast<socket_addr_type*>(addr),
0103       addrlen ? &tmp_addrlen : 0);
0104   if (addrlen)
0105     *addrlen = (std::size_t)tmp_addrlen;
0106   return result;
0107 }
0108 
0109 socket_type accept(socket_type s, void* addr,
0110     std::size_t* addrlen, boost::system::error_code& ec)
0111 {
0112   if (s == invalid_socket)
0113   {
0114     ec = boost::asio::error::bad_descriptor;
0115     return invalid_socket;
0116   }
0117 
0118   socket_type new_s = call_accept(&msghdr::msg_namelen, s, addr, addrlen);
0119   get_last_error(ec, new_s == invalid_socket);
0120   if (new_s == invalid_socket)
0121     return new_s;
0122 
0123 #if defined(__MACH__) && defined(__APPLE__) || defined(__FreeBSD__)
0124   int optval = 1;
0125   int result = ::setsockopt(new_s, SOL_SOCKET,
0126       SO_NOSIGPIPE, &optval, sizeof(optval));
0127   get_last_error(ec, result != 0);
0128   if (result != 0)
0129   {
0130     ::close(new_s);
0131     return invalid_socket;
0132   }
0133 #endif
0134 
0135   boost::asio::error::clear(ec);
0136   return new_s;
0137 }
0138 
0139 socket_type sync_accept(socket_type s, state_type state,
0140     void* addr, std::size_t* addrlen, boost::system::error_code& ec)
0141 {
0142   // Accept a socket.
0143   for (;;)
0144   {
0145     // Try to complete the operation without blocking.
0146     socket_type new_socket = socket_ops::accept(s, addr, addrlen, ec);
0147 
0148     // Check if operation succeeded.
0149     if (new_socket != invalid_socket)
0150       return new_socket;
0151 
0152     // Operation failed.
0153     if (ec == boost::asio::error::would_block
0154         || ec == boost::asio::error::try_again)
0155     {
0156       if (state & user_set_non_blocking)
0157         return invalid_socket;
0158       // Fall through to retry operation.
0159     }
0160     else if (ec == boost::asio::error::connection_aborted)
0161     {
0162       if (state & enable_connection_aborted)
0163         return invalid_socket;
0164       // Fall through to retry operation.
0165     }
0166 #if defined(EPROTO)
0167     else if (ec.value() == EPROTO)
0168     {
0169       if (state & enable_connection_aborted)
0170         return invalid_socket;
0171       // Fall through to retry operation.
0172     }
0173 #endif // defined(EPROTO)
0174     else
0175       return invalid_socket;
0176 
0177     // Wait for socket to become ready.
0178     if (socket_ops::poll_read(s, 0, -1, ec) < 0)
0179       return invalid_socket;
0180   }
0181 }
0182 
0183 #if defined(BOOST_ASIO_HAS_IOCP)
0184 
0185 void complete_iocp_accept(socket_type s, void* output_buffer,
0186     DWORD address_length, void* addr, std::size_t* addrlen,
0187     socket_type new_socket, boost::system::error_code& ec)
0188 {
0189   // Map non-portable errors to their portable counterparts.
0190   if (ec.value() == ERROR_NETNAME_DELETED)
0191     ec = boost::asio::error::connection_aborted;
0192 
0193   if (!ec)
0194   {
0195     // Get the address of the peer.
0196     if (addr && addrlen)
0197     {
0198       LPSOCKADDR local_addr = 0;
0199       int local_addr_length = 0;
0200       LPSOCKADDR remote_addr = 0;
0201       int remote_addr_length = 0;
0202       GetAcceptExSockaddrs(output_buffer, 0, address_length,
0203           address_length, &local_addr, &local_addr_length,
0204           &remote_addr, &remote_addr_length);
0205       if (static_cast<std::size_t>(remote_addr_length) > *addrlen)
0206       {
0207         ec = boost::asio::error::invalid_argument;
0208       }
0209       else
0210       {
0211         using namespace std; // For memcpy.
0212         memcpy(addr, remote_addr, remote_addr_length);
0213         *addrlen = static_cast<std::size_t>(remote_addr_length);
0214       }
0215     }
0216 
0217     // Need to set the SO_UPDATE_ACCEPT_CONTEXT option so that getsockname
0218     // and getpeername will work on the accepted socket.
0219     SOCKET update_ctx_param = s;
0220     socket_ops::state_type state = 0;
0221     socket_ops::setsockopt(new_socket, state,
0222           SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,
0223           &update_ctx_param, sizeof(SOCKET), ec);
0224   }
0225 }
0226 
0227 #else // defined(BOOST_ASIO_HAS_IOCP)
0228 
0229 bool non_blocking_accept(socket_type s,
0230     state_type state, void* addr, std::size_t* addrlen,
0231     boost::system::error_code& ec, socket_type& new_socket)
0232 {
0233   for (;;)
0234   {
0235     // Accept the waiting connection.
0236     new_socket = socket_ops::accept(s, addr, addrlen, ec);
0237 
0238     // Check if operation succeeded.
0239     if (new_socket != invalid_socket)
0240       return true;
0241 
0242     // Retry operation if interrupted by signal.
0243     if (ec == boost::asio::error::interrupted)
0244       continue;
0245 
0246     // Operation failed.
0247     if (ec == boost::asio::error::would_block
0248         || ec == boost::asio::error::try_again)
0249     {
0250       // Fall through to retry operation.
0251     }
0252     else if (ec == boost::asio::error::connection_aborted)
0253     {
0254       if (state & enable_connection_aborted)
0255         return true;
0256       // Fall through to retry operation.
0257     }
0258 #if defined(EPROTO)
0259     else if (ec.value() == EPROTO)
0260     {
0261       if (state & enable_connection_aborted)
0262         return true;
0263       // Fall through to retry operation.
0264     }
0265 #endif // defined(EPROTO)
0266     else
0267       return true;
0268 
0269     return false;
0270   }
0271 }
0272 
0273 #endif // defined(BOOST_ASIO_HAS_IOCP)
0274 
0275 template <typename SockLenType>
0276 inline int call_bind(SockLenType msghdr::*,
0277     socket_type s, const void* addr, std::size_t addrlen)
0278 {
0279   return ::bind(s, static_cast<const socket_addr_type*>(addr),
0280       (SockLenType)addrlen);
0281 }
0282 
0283 int bind(socket_type s, const void* addr,
0284     std::size_t addrlen, boost::system::error_code& ec)
0285 {
0286   if (s == invalid_socket)
0287   {
0288     ec = boost::asio::error::bad_descriptor;
0289     return socket_error_retval;
0290   }
0291 
0292   int result = call_bind(&msghdr::msg_namelen, s, addr, addrlen);
0293   get_last_error(ec, result != 0);
0294   return result;
0295 }
0296 
0297 int close(socket_type s, state_type& state,
0298     bool destruction, boost::system::error_code& ec)
0299 {
0300   int result = 0;
0301   if (s != invalid_socket)
0302   {
0303     // We don't want the destructor to block, so set the socket to linger in
0304     // the background. If the user doesn't like this behaviour then they need
0305     // to explicitly close the socket.
0306     if (destruction && (state & user_set_linger))
0307     {
0308       ::linger opt;
0309       opt.l_onoff = 0;
0310       opt.l_linger = 0;
0311       boost::system::error_code ignored_ec;
0312       socket_ops::setsockopt(s, state, SOL_SOCKET,
0313           SO_LINGER, &opt, sizeof(opt), ignored_ec);
0314     }
0315 
0316 #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0317     result = ::closesocket(s);
0318 #else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0319     result = ::close(s);
0320 #endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0321     get_last_error(ec, result != 0);
0322 
0323     if (result != 0
0324         && (ec == boost::asio::error::would_block
0325           || ec == boost::asio::error::try_again))
0326     {
0327       // According to UNIX Network Programming Vol. 1, it is possible for
0328       // close() to fail with EWOULDBLOCK under certain circumstances. What
0329       // isn't clear is the state of the descriptor after this error. The one
0330       // current OS where this behaviour is seen, Windows, says that the socket
0331       // remains open. Therefore we'll put the descriptor back into blocking
0332       // mode and have another attempt at closing it.
0333 #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0334       ioctl_arg_type arg = 0;
0335       ::ioctlsocket(s, FIONBIO, &arg);
0336 #else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0337 # if defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)
0338       int flags = ::fcntl(s, F_GETFL, 0);
0339       if (flags >= 0)
0340         ::fcntl(s, F_SETFL, flags & ~O_NONBLOCK);
0341 # else // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)
0342       ioctl_arg_type arg = 0;
0343       ::ioctl(s, FIONBIO, &arg);
0344 # endif // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)
0345 #endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0346       state &= ~non_blocking;
0347 
0348 #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0349       result = ::closesocket(s);
0350 #else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0351       result = ::close(s);
0352 #endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0353       get_last_error(ec, result != 0);
0354     }
0355   }
0356 
0357   return result;
0358 }
0359 
0360 bool set_user_non_blocking(socket_type s,
0361     state_type& state, bool value, boost::system::error_code& ec)
0362 {
0363   if (s == invalid_socket)
0364   {
0365     ec = boost::asio::error::bad_descriptor;
0366     return false;
0367   }
0368 
0369 #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0370   ioctl_arg_type arg = (value ? 1 : 0);
0371   int result = ::ioctlsocket(s, FIONBIO, &arg);
0372   get_last_error(ec, result < 0);
0373 #elif defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)
0374   int result = ::fcntl(s, F_GETFL, 0);
0375   get_last_error(ec, result < 0);
0376   if (result >= 0)
0377   {
0378     int flag = (value ? (result | O_NONBLOCK) : (result & ~O_NONBLOCK));
0379     result = ::fcntl(s, F_SETFL, flag);
0380     get_last_error(ec, result < 0);
0381   }
0382 #else
0383   ioctl_arg_type arg = (value ? 1 : 0);
0384   int result = ::ioctl(s, FIONBIO, &arg);
0385   get_last_error(ec, result < 0);
0386 #endif
0387 
0388   if (result >= 0)
0389   {
0390     if (value)
0391       state |= user_set_non_blocking;
0392     else
0393     {
0394       // Clearing the user-set non-blocking mode always overrides any
0395       // internally-set non-blocking flag. Any subsequent asynchronous
0396       // operations will need to re-enable non-blocking I/O.
0397       state &= ~(user_set_non_blocking | internal_non_blocking);
0398     }
0399     return true;
0400   }
0401 
0402   return false;
0403 }
0404 
0405 bool set_internal_non_blocking(socket_type s,
0406     state_type& state, bool value, boost::system::error_code& ec)
0407 {
0408   if (s == invalid_socket)
0409   {
0410     ec = boost::asio::error::bad_descriptor;
0411     return false;
0412   }
0413 
0414   if (!value && (state & user_set_non_blocking))
0415   {
0416     // It does not make sense to clear the internal non-blocking flag if the
0417     // user still wants non-blocking behaviour. Return an error and let the
0418     // caller figure out whether to update the user-set non-blocking flag.
0419     ec = boost::asio::error::invalid_argument;
0420     return false;
0421   }
0422 
0423 #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0424   ioctl_arg_type arg = (value ? 1 : 0);
0425   int result = ::ioctlsocket(s, FIONBIO, &arg);
0426   get_last_error(ec, result < 0);
0427 #elif defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)
0428   int result = ::fcntl(s, F_GETFL, 0);
0429   get_last_error(ec, result < 0);
0430   if (result >= 0)
0431   {
0432     int flag = (value ? (result | O_NONBLOCK) : (result & ~O_NONBLOCK));
0433     result = ::fcntl(s, F_SETFL, flag);
0434     get_last_error(ec, result < 0);
0435   }
0436 #else
0437   ioctl_arg_type arg = (value ? 1 : 0);
0438   int result = ::ioctl(s, FIONBIO, &arg);
0439   get_last_error(ec, result < 0);
0440 #endif
0441 
0442   if (result >= 0)
0443   {
0444     if (value)
0445       state |= internal_non_blocking;
0446     else
0447       state &= ~internal_non_blocking;
0448     return true;
0449   }
0450 
0451   return false;
0452 }
0453 
0454 int shutdown(socket_type s, int what, boost::system::error_code& ec)
0455 {
0456   if (s == invalid_socket)
0457   {
0458     ec = boost::asio::error::bad_descriptor;
0459     return socket_error_retval;
0460   }
0461 
0462   int result = ::shutdown(s, what);
0463   get_last_error(ec, result != 0);
0464   return result;
0465 }
0466 
0467 template <typename SockLenType>
0468 inline int call_connect(SockLenType msghdr::*,
0469     socket_type s, const void* addr, std::size_t addrlen)
0470 {
0471   return ::connect(s, static_cast<const socket_addr_type*>(addr),
0472       (SockLenType)addrlen);
0473 }
0474 
0475 int connect(socket_type s, const void* addr,
0476     std::size_t addrlen, boost::system::error_code& ec)
0477 {
0478   if (s == invalid_socket)
0479   {
0480     ec = boost::asio::error::bad_descriptor;
0481     return socket_error_retval;
0482   }
0483 
0484   int result = call_connect(&msghdr::msg_namelen, s, addr, addrlen);
0485   get_last_error(ec, result != 0);
0486 #if defined(__linux__)
0487   if (result != 0 && ec == boost::asio::error::try_again)
0488   {
0489     if (static_cast<const socket_addr_type*>(addr)->sa_family == AF_UNIX)
0490       ec = boost::asio::error::in_progress;
0491     else
0492       ec = boost::asio::error::no_buffer_space;
0493   }
0494 #endif // defined(__linux__)
0495   return result;
0496 }
0497 
0498 void sync_connect(socket_type s, const void* addr,
0499     std::size_t addrlen, boost::system::error_code& ec)
0500 {
0501   // Perform the connect operation.
0502   socket_ops::connect(s, addr, addrlen, ec);
0503   if (ec != boost::asio::error::in_progress
0504       && ec != boost::asio::error::would_block)
0505   {
0506     // The connect operation finished immediately.
0507     return;
0508   }
0509 
0510   // Wait for socket to become ready.
0511   if (socket_ops::poll_connect(s, -1, ec) < 0)
0512     return;
0513 
0514   // Get the error code from the connect operation.
0515   int connect_error = 0;
0516   size_t connect_error_len = sizeof(connect_error);
0517   if (socket_ops::getsockopt(s, 0, SOL_SOCKET, SO_ERROR,
0518         &connect_error, &connect_error_len, ec) == socket_error_retval)
0519     return;
0520 
0521   // Return the result of the connect operation.
0522   ec = boost::system::error_code(connect_error,
0523       boost::asio::error::get_system_category());
0524 }
0525 
0526 #if defined(BOOST_ASIO_HAS_IOCP)
0527 
0528 void complete_iocp_connect(socket_type s, boost::system::error_code& ec)
0529 {
0530   // Map non-portable errors to their portable counterparts.
0531   switch (ec.value())
0532   {
0533   case ERROR_CONNECTION_REFUSED:
0534     ec = boost::asio::error::connection_refused;
0535     break;
0536   case ERROR_NETWORK_UNREACHABLE:
0537     ec = boost::asio::error::network_unreachable;
0538     break;
0539   case ERROR_HOST_UNREACHABLE:
0540     ec = boost::asio::error::host_unreachable;
0541     break;
0542   case ERROR_SEM_TIMEOUT:
0543     ec = boost::asio::error::timed_out;
0544     break;
0545   default:
0546     break;
0547   }
0548 
0549   if (!ec)
0550   {
0551     // Need to set the SO_UPDATE_CONNECT_CONTEXT option so that getsockname
0552     // and getpeername will work on the connected socket.
0553     socket_ops::state_type state = 0;
0554     const int so_update_connect_context = 0x7010;
0555     socket_ops::setsockopt(s, state, SOL_SOCKET,
0556         so_update_connect_context, 0, 0, ec);
0557   }
0558 }
0559 
0560 #endif // defined(BOOST_ASIO_HAS_IOCP)
0561 
0562 bool non_blocking_connect(socket_type s, boost::system::error_code& ec)
0563 {
0564   // Check if the connect operation has finished. This is required since we may
0565   // get spurious readiness notifications from the reactor.
0566 #if defined(BOOST_ASIO_WINDOWS) \
0567   || defined(__CYGWIN__) \
0568   || defined(__SYMBIAN32__)
0569   fd_set write_fds;
0570   FD_ZERO(&write_fds);
0571   FD_SET(s, &write_fds);
0572   fd_set except_fds;
0573   FD_ZERO(&except_fds);
0574   FD_SET(s, &except_fds);
0575   timeval zero_timeout;
0576   zero_timeout.tv_sec = 0;
0577   zero_timeout.tv_usec = 0;
0578   int ready = ::select(s + 1, 0, &write_fds, &except_fds, &zero_timeout);
0579 #else // defined(BOOST_ASIO_WINDOWS)
0580       // || defined(__CYGWIN__)
0581       // || defined(__SYMBIAN32__)
0582   pollfd fds;
0583   fds.fd = s;
0584   fds.events = POLLOUT;
0585   fds.revents = 0;
0586   int ready = ::poll(&fds, 1, 0);
0587 #endif // defined(BOOST_ASIO_WINDOWS)
0588        // || defined(__CYGWIN__)
0589        // || defined(__SYMBIAN32__)
0590   if (ready == 0)
0591   {
0592     // The asynchronous connect operation is still in progress.
0593     return false;
0594   }
0595 
0596   // Get the error code from the connect operation.
0597   int connect_error = 0;
0598   size_t connect_error_len = sizeof(connect_error);
0599   if (socket_ops::getsockopt(s, 0, SOL_SOCKET, SO_ERROR,
0600         &connect_error, &connect_error_len, ec) == 0)
0601   {
0602     if (connect_error)
0603     {
0604       ec = boost::system::error_code(connect_error,
0605           boost::asio::error::get_system_category());
0606     }
0607     else
0608       boost::asio::error::clear(ec);
0609   }
0610 
0611   return true;
0612 }
0613 
0614 int socketpair(int af, int type, int protocol,
0615     socket_type sv[2], boost::system::error_code& ec)
0616 {
0617 #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0618   (void)(af);
0619   (void)(type);
0620   (void)(protocol);
0621   (void)(sv);
0622   ec = boost::asio::error::operation_not_supported;
0623   return socket_error_retval;
0624 #else
0625   int result = ::socketpair(af, type, protocol, sv);
0626   get_last_error(ec, result != 0);
0627   return result;
0628 #endif
0629 }
0630 
0631 bool sockatmark(socket_type s, boost::system::error_code& ec)
0632 {
0633   if (s == invalid_socket)
0634   {
0635     ec = boost::asio::error::bad_descriptor;
0636     return false;
0637   }
0638 
0639 #if defined(SIOCATMARK)
0640   ioctl_arg_type value = 0;
0641 # if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0642   int result = ::ioctlsocket(s, SIOCATMARK, &value);
0643 # else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0644   int result = ::ioctl(s, SIOCATMARK, &value);
0645 # endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0646   get_last_error(ec, result < 0);
0647 # if defined(ENOTTY)
0648   if (ec.value() == ENOTTY)
0649     ec = boost::asio::error::not_socket;
0650 # endif // defined(ENOTTY)
0651 #else // defined(SIOCATMARK)
0652   int value = ::sockatmark(s);
0653   get_last_error(ec, value < 0);
0654 #endif // defined(SIOCATMARK)
0655 
0656   return ec ? false : value != 0;
0657 }
0658 
0659 size_t available(socket_type s, boost::system::error_code& ec)
0660 {
0661   if (s == invalid_socket)
0662   {
0663     ec = boost::asio::error::bad_descriptor;
0664     return 0;
0665   }
0666 
0667   ioctl_arg_type value = 0;
0668 #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0669   int result = ::ioctlsocket(s, FIONREAD, &value);
0670 #else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0671   int result = ::ioctl(s, FIONREAD, &value);
0672 #endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0673   get_last_error(ec, result < 0);
0674 #if defined(ENOTTY)
0675   if (ec.value() == ENOTTY)
0676     ec = boost::asio::error::not_socket;
0677 #endif // defined(ENOTTY)
0678 
0679   return ec ? static_cast<size_t>(0) : static_cast<size_t>(value);
0680 }
0681 
0682 int listen(socket_type s, int backlog, boost::system::error_code& ec)
0683 {
0684   if (s == invalid_socket)
0685   {
0686     ec = boost::asio::error::bad_descriptor;
0687     return socket_error_retval;
0688   }
0689 
0690   int result = ::listen(s, backlog);
0691   get_last_error(ec, result != 0);
0692   return result;
0693 }
0694 
0695 inline void init_buf_iov_base(void*& base, void* addr)
0696 {
0697   base = addr;
0698 }
0699 
0700 template <typename T>
0701 inline void init_buf_iov_base(T& base, void* addr)
0702 {
0703   base = static_cast<T>(addr);
0704 }
0705 
0706 #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0707 typedef WSABUF buf;
0708 #else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0709 typedef iovec buf;
0710 #endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0711 
0712 void init_buf(buf& b, void* data, size_t size)
0713 {
0714 #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0715   b.buf = static_cast<char*>(data);
0716   b.len = static_cast<u_long>(size);
0717 #else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0718   init_buf_iov_base(b.iov_base, data);
0719   b.iov_len = size;
0720 #endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0721 }
0722 
0723 void init_buf(buf& b, const void* data, size_t size)
0724 {
0725 #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0726   b.buf = static_cast<char*>(const_cast<void*>(data));
0727   b.len = static_cast<u_long>(size);
0728 #else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0729   init_buf_iov_base(b.iov_base, const_cast<void*>(data));
0730   b.iov_len = size;
0731 #endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0732 }
0733 
0734 inline void init_msghdr_msg_name(void*& name, void* addr)
0735 {
0736   name = static_cast<socket_addr_type*>(addr);
0737 }
0738 
0739 inline void init_msghdr_msg_name(void*& name, const socket_addr_type* addr)
0740 {
0741   name = const_cast<socket_addr_type*>(addr);
0742 }
0743 
0744 template <typename T>
0745 inline void init_msghdr_msg_name(T& name, void* addr)
0746 {
0747   name = static_cast<T>(addr);
0748 }
0749 
0750 template <typename T>
0751 inline void init_msghdr_msg_name(T& name, const void* addr)
0752 {
0753   name = static_cast<T>(const_cast<void*>(addr));
0754 }
0755 
0756 signed_size_type recv(socket_type s, buf* bufs, size_t count,
0757     int flags, boost::system::error_code& ec)
0758 {
0759 #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0760   // Receive some data.
0761   DWORD recv_buf_count = static_cast<DWORD>(count);
0762   DWORD bytes_transferred = 0;
0763   DWORD recv_flags = flags;
0764   int result = ::WSARecv(s, bufs, recv_buf_count,
0765       &bytes_transferred, &recv_flags, 0, 0);
0766   get_last_error(ec, true);
0767   if (ec.value() == ERROR_NETNAME_DELETED)
0768     ec = boost::asio::error::connection_reset;
0769   else if (ec.value() == ERROR_PORT_UNREACHABLE)
0770     ec = boost::asio::error::connection_refused;
0771   else if (ec.value() == WSAEMSGSIZE || ec.value() == ERROR_MORE_DATA)
0772     result = 0;
0773   if (result != 0)
0774     return socket_error_retval;
0775   boost::asio::error::clear(ec);
0776   return bytes_transferred;
0777 #else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0778   msghdr msg = msghdr();
0779   msg.msg_iov = bufs;
0780   msg.msg_iovlen = static_cast<int>(count);
0781   signed_size_type result = ::recvmsg(s, &msg, flags);
0782   get_last_error(ec, result < 0);
0783   return result;
0784 #endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0785 }
0786 
0787 signed_size_type recv1(socket_type s, void* data, size_t size,
0788     int flags, boost::system::error_code& ec)
0789 {
0790 #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0791   // Receive some data.
0792   WSABUF buf;
0793   buf.buf = const_cast<char*>(static_cast<const char*>(data));
0794   buf.len = static_cast<ULONG>(size);
0795   DWORD bytes_transferred = 0;
0796   DWORD recv_flags = flags;
0797   int result = ::WSARecv(s, &buf, 1,
0798       &bytes_transferred, &recv_flags, 0, 0);
0799   get_last_error(ec, true);
0800   if (ec.value() == ERROR_NETNAME_DELETED)
0801     ec = boost::asio::error::connection_reset;
0802   else if (ec.value() == ERROR_PORT_UNREACHABLE)
0803     ec = boost::asio::error::connection_refused;
0804   else if (ec.value() == WSAEMSGSIZE || ec.value() == ERROR_MORE_DATA)
0805     result = 0;
0806   if (result != 0)
0807     return socket_error_retval;
0808   boost::asio::error::clear(ec);
0809   return bytes_transferred;
0810 #else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0811   signed_size_type result = ::recv(s, static_cast<char*>(data), size, flags);
0812   get_last_error(ec, result < 0);
0813   return result;
0814 #endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0815 }
0816 
0817 size_t sync_recv(socket_type s, state_type state, buf* bufs,
0818     size_t count, int flags, bool all_empty, boost::system::error_code& ec)
0819 {
0820   if (s == invalid_socket)
0821   {
0822     ec = boost::asio::error::bad_descriptor;
0823     return 0;
0824   }
0825 
0826   // A request to read 0 bytes on a stream is a no-op.
0827   if (all_empty && (state & stream_oriented))
0828   {
0829     boost::asio::error::clear(ec);
0830     return 0;
0831   }
0832 
0833   // Read some data.
0834   for (;;)
0835   {
0836     // Try to complete the operation without blocking.
0837     signed_size_type bytes = socket_ops::recv(s, bufs, count, flags, ec);
0838 
0839     // Check for EOF.
0840     if ((state & stream_oriented) && bytes == 0)
0841     {
0842       ec = boost::asio::error::eof;
0843       return 0;
0844     }
0845 
0846     // Check if operation succeeded.
0847     if (bytes >= 0)
0848       return bytes;
0849 
0850     // Operation failed.
0851     if ((state & user_set_non_blocking)
0852         || (ec != boost::asio::error::would_block
0853           && ec != boost::asio::error::try_again))
0854       return 0;
0855 
0856     // Wait for socket to become ready.
0857     if (socket_ops::poll_read(s, 0, -1, ec) < 0)
0858       return 0;
0859   }
0860 }
0861 
0862 size_t sync_recv1(socket_type s, state_type state, void* data,
0863     size_t size, int flags, boost::system::error_code& ec)
0864 {
0865   if (s == invalid_socket)
0866   {
0867     ec = boost::asio::error::bad_descriptor;
0868     return 0;
0869   }
0870 
0871   // A request to read 0 bytes on a stream is a no-op.
0872   if (size == 0 && (state & stream_oriented))
0873   {
0874     boost::asio::error::clear(ec);
0875     return 0;
0876   }
0877 
0878   // Read some data.
0879   for (;;)
0880   {
0881     // Try to complete the operation without blocking.
0882     signed_size_type bytes = socket_ops::recv1(s, data, size, flags, ec);
0883 
0884     // Check for EOF.
0885     if ((state & stream_oriented) && bytes == 0)
0886     {
0887       ec = boost::asio::error::eof;
0888       return 0;
0889     }
0890 
0891     // Check if operation succeeded.
0892     if (bytes >= 0)
0893       return bytes;
0894 
0895     // Operation failed.
0896     if ((state & user_set_non_blocking)
0897         || (ec != boost::asio::error::would_block
0898           && ec != boost::asio::error::try_again))
0899       return 0;
0900 
0901     // Wait for socket to become ready.
0902     if (socket_ops::poll_read(s, 0, -1, ec) < 0)
0903       return 0;
0904   }
0905 }
0906 
0907 #if defined(BOOST_ASIO_HAS_IOCP)
0908 
0909 void complete_iocp_recv(state_type state,
0910     const weak_cancel_token_type& cancel_token, bool all_empty,
0911     boost::system::error_code& ec, size_t bytes_transferred)
0912 {
0913   // Map non-portable errors to their portable counterparts.
0914   if (ec.value() == ERROR_NETNAME_DELETED)
0915   {
0916     if (cancel_token.expired())
0917       ec = boost::asio::error::operation_aborted;
0918     else
0919       ec = boost::asio::error::connection_reset;
0920   }
0921   else if (ec.value() == ERROR_PORT_UNREACHABLE)
0922   {
0923     ec = boost::asio::error::connection_refused;
0924   }
0925   else if (ec.value() == WSAEMSGSIZE || ec.value() == ERROR_MORE_DATA)
0926   {
0927     boost::asio::error::clear(ec);
0928   }
0929 
0930   // Check for connection closed.
0931   else if (!ec && bytes_transferred == 0
0932       && (state & stream_oriented) != 0
0933       && !all_empty)
0934   {
0935     ec = boost::asio::error::eof;
0936   }
0937 }
0938 
0939 #else // defined(BOOST_ASIO_HAS_IOCP)
0940 
0941 bool non_blocking_recv(socket_type s,
0942     buf* bufs, size_t count, int flags, bool is_stream,
0943     boost::system::error_code& ec, size_t& bytes_transferred)
0944 {
0945   for (;;)
0946   {
0947     // Read some data.
0948     signed_size_type bytes = socket_ops::recv(s, bufs, count, flags, ec);
0949 
0950     // Check for end of stream.
0951     if (is_stream && bytes == 0)
0952     {
0953       ec = boost::asio::error::eof;
0954       return true;
0955     }
0956 
0957     // Check if operation succeeded.
0958     if (bytes >= 0)
0959     {
0960       bytes_transferred = bytes;
0961       return true;
0962     }
0963 
0964     // Retry operation if interrupted by signal.
0965     if (ec == boost::asio::error::interrupted)
0966       continue;
0967 
0968     // Check if we need to run the operation again.
0969     if (ec == boost::asio::error::would_block
0970         || ec == boost::asio::error::try_again)
0971       return false;
0972 
0973     // Operation failed.
0974     bytes_transferred = 0;
0975     return true;
0976   }
0977 }
0978 
0979 bool non_blocking_recv1(socket_type s,
0980     void* data, size_t size, int flags, bool is_stream,
0981     boost::system::error_code& ec, size_t& bytes_transferred)
0982 {
0983   for (;;)
0984   {
0985     // Read some data.
0986     signed_size_type bytes = socket_ops::recv1(s, data, size, flags, ec);
0987 
0988     // Check for end of stream.
0989     if (is_stream && bytes == 0)
0990     {
0991       ec = boost::asio::error::eof;
0992       return true;
0993     }
0994 
0995     // Check if operation succeeded.
0996     if (bytes >= 0)
0997     {
0998       bytes_transferred = bytes;
0999       return true;
1000     }
1001 
1002     // Retry operation if interrupted by signal.
1003     if (ec == boost::asio::error::interrupted)
1004       continue;
1005 
1006     // Check if we need to run the operation again.
1007     if (ec == boost::asio::error::would_block
1008         || ec == boost::asio::error::try_again)
1009       return false;
1010 
1011     // Operation failed.
1012     bytes_transferred = 0;
1013     return true;
1014   }
1015 }
1016 
1017 #endif // defined(BOOST_ASIO_HAS_IOCP)
1018 
1019 signed_size_type recvfrom(socket_type s, buf* bufs, size_t count,
1020     int flags, void* addr, std::size_t* addrlen, boost::system::error_code& ec)
1021 {
1022 #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
1023   // Receive some data.
1024   DWORD recv_buf_count = static_cast<DWORD>(count);
1025   DWORD bytes_transferred = 0;
1026   DWORD recv_flags = flags;
1027   int tmp_addrlen = (int)*addrlen;
1028   int result = ::WSARecvFrom(s, bufs, recv_buf_count, &bytes_transferred,
1029       &recv_flags, static_cast<socket_addr_type*>(addr), &tmp_addrlen, 0, 0);
1030   get_last_error(ec, true);
1031   *addrlen = (std::size_t)tmp_addrlen;
1032   if (ec.value() == ERROR_NETNAME_DELETED)
1033     ec = boost::asio::error::connection_reset;
1034   else if (ec.value() == ERROR_PORT_UNREACHABLE)
1035     ec = boost::asio::error::connection_refused;
1036   else if (ec.value() == WSAEMSGSIZE || ec.value() == ERROR_MORE_DATA)
1037     result = 0;
1038   if (result != 0)
1039     return socket_error_retval;
1040   boost::asio::error::clear(ec);
1041   return bytes_transferred;
1042 #else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
1043   msghdr msg = msghdr();
1044   init_msghdr_msg_name(msg.msg_name, addr);
1045   msg.msg_namelen = static_cast<int>(*addrlen);
1046   msg.msg_iov = bufs;
1047   msg.msg_iovlen = static_cast<int>(count);
1048   signed_size_type result = ::recvmsg(s, &msg, flags);
1049   get_last_error(ec, result < 0);
1050   *addrlen = msg.msg_namelen;
1051   return result;
1052 #endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
1053 }
1054 
1055 template <typename SockLenType>
1056 inline signed_size_type call_recvfrom(SockLenType msghdr::*, socket_type s,
1057     void* data, size_t size, int flags, void* addr, std::size_t* addrlen)
1058 {
1059   SockLenType tmp_addrlen = addrlen ? (SockLenType)*addrlen : 0;
1060   signed_size_type result = ::recvfrom(s, static_cast<char*>(data), size,
1061       flags, static_cast<socket_addr_type*>(addr), addrlen ? &tmp_addrlen : 0);
1062   if (addrlen)
1063     *addrlen = (std::size_t)tmp_addrlen;
1064   return result;
1065 }
1066 
1067 signed_size_type recvfrom1(socket_type s, void* data, size_t size,
1068     int flags, void* addr, std::size_t* addrlen, boost::system::error_code& ec)
1069 {
1070 #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
1071   // Receive some data.
1072   WSABUF buf;
1073   buf.buf = static_cast<char*>(data);
1074   buf.len = static_cast<ULONG>(size);
1075   DWORD bytes_transferred = 0;
1076   DWORD recv_flags = flags;
1077   int tmp_addrlen = (int)*addrlen;
1078   int result = ::WSARecvFrom(s, &buf, 1, &bytes_transferred, &recv_flags,
1079       static_cast<socket_addr_type*>(addr), &tmp_addrlen, 0, 0);
1080   get_last_error(ec, true);
1081   *addrlen = (std::size_t)tmp_addrlen;
1082   if (ec.value() == ERROR_NETNAME_DELETED)
1083     ec = boost::asio::error::connection_reset;
1084   else if (ec.value() == ERROR_PORT_UNREACHABLE)
1085     ec = boost::asio::error::connection_refused;
1086   else if (ec.value() == WSAEMSGSIZE || ec.value() == ERROR_MORE_DATA)
1087     result = 0;
1088   if (result != 0)
1089     return socket_error_retval;
1090   boost::asio::error::clear(ec);
1091   return bytes_transferred;
1092 #else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
1093   signed_size_type result = call_recvfrom(&msghdr::msg_namelen,
1094       s, data, size, flags, addr, addrlen);
1095   get_last_error(ec, result < 0);
1096   return result;
1097 #endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
1098 }
1099 
1100 size_t sync_recvfrom(socket_type s, state_type state, buf* bufs, size_t count,
1101     int flags, void* addr, std::size_t* addrlen, boost::system::error_code& ec)
1102 {
1103   if (s == invalid_socket)
1104   {
1105     ec = boost::asio::error::bad_descriptor;
1106     return 0;
1107   }
1108 
1109   // Read some data.
1110   for (;;)
1111   {
1112     // Try to complete the operation without blocking.
1113     signed_size_type bytes = socket_ops::recvfrom(
1114         s, bufs, count, flags, addr, addrlen, ec);
1115 
1116     // Check if operation succeeded.
1117     if (bytes >= 0)
1118       return bytes;
1119 
1120     // Operation failed.
1121     if ((state & user_set_non_blocking)
1122         || (ec != boost::asio::error::would_block
1123           && ec != boost::asio::error::try_again))
1124       return 0;
1125 
1126     // Wait for socket to become ready.
1127     if (socket_ops::poll_read(s, 0, -1, ec) < 0)
1128       return 0;
1129   }
1130 }
1131 
1132 size_t sync_recvfrom1(socket_type s, state_type state, void* data, size_t size,
1133     int flags, void* addr, std::size_t* addrlen, boost::system::error_code& ec)
1134 {
1135   if (s == invalid_socket)
1136   {
1137     ec = boost::asio::error::bad_descriptor;
1138     return 0;
1139   }
1140 
1141   // Read some data.
1142   for (;;)
1143   {
1144     // Try to complete the operation without blocking.
1145     signed_size_type bytes = socket_ops::recvfrom1(
1146         s, data, size, flags, addr, addrlen, ec);
1147 
1148     // Check if operation succeeded.
1149     if (bytes >= 0)
1150       return bytes;
1151 
1152     // Operation failed.
1153     if ((state & user_set_non_blocking)
1154         || (ec != boost::asio::error::would_block
1155           && ec != boost::asio::error::try_again))
1156       return 0;
1157 
1158     // Wait for socket to become ready.
1159     if (socket_ops::poll_read(s, 0, -1, ec) < 0)
1160       return 0;
1161   }
1162 }
1163 
1164 #if defined(BOOST_ASIO_HAS_IOCP)
1165 
1166 void complete_iocp_recvfrom(
1167     const weak_cancel_token_type& cancel_token,
1168     boost::system::error_code& ec)
1169 {
1170   // Map non-portable errors to their portable counterparts.
1171   if (ec.value() == ERROR_NETNAME_DELETED)
1172   {
1173     if (cancel_token.expired())
1174       ec = boost::asio::error::operation_aborted;
1175     else
1176       ec = boost::asio::error::connection_reset;
1177   }
1178   else if (ec.value() == ERROR_PORT_UNREACHABLE)
1179   {
1180     ec = boost::asio::error::connection_refused;
1181   }
1182   else if (ec.value() == WSAEMSGSIZE || ec.value() == ERROR_MORE_DATA)
1183   {
1184     boost::asio::error::clear(ec);
1185   }
1186 }
1187 
1188 #else // defined(BOOST_ASIO_HAS_IOCP)
1189 
1190 bool non_blocking_recvfrom(socket_type s, buf* bufs,
1191     size_t count, int flags, void* addr, std::size_t* addrlen,
1192     boost::system::error_code& ec, size_t& bytes_transferred)
1193 {
1194   for (;;)
1195   {
1196     // Read some data.
1197     signed_size_type bytes = socket_ops::recvfrom(
1198         s, bufs, count, flags, addr, addrlen, ec);
1199 
1200     // Check if operation succeeded.
1201     if (bytes >= 0)
1202     {
1203       bytes_transferred = bytes;
1204       return true;
1205     }
1206 
1207     // Retry operation if interrupted by signal.
1208     if (ec == boost::asio::error::interrupted)
1209       continue;
1210 
1211     // Check if we need to run the operation again.
1212     if (ec == boost::asio::error::would_block
1213         || ec == boost::asio::error::try_again)
1214       return false;
1215 
1216     // Operation failed.
1217     bytes_transferred = 0;
1218     return true;
1219   }
1220 }
1221 
1222 bool non_blocking_recvfrom1(socket_type s, void* data,
1223     size_t size, int flags, void* addr, std::size_t* addrlen,
1224     boost::system::error_code& ec, size_t& bytes_transferred)
1225 {
1226   for (;;)
1227   {
1228     // Read some data.
1229     signed_size_type bytes = socket_ops::recvfrom1(
1230         s, data, size, flags, addr, addrlen, ec);
1231 
1232     // Check if operation succeeded.
1233     if (bytes >= 0)
1234     {
1235       bytes_transferred = bytes;
1236       return true;
1237     }
1238 
1239     // Retry operation if interrupted by signal.
1240     if (ec == boost::asio::error::interrupted)
1241       continue;
1242 
1243     // Check if we need to run the operation again.
1244     if (ec == boost::asio::error::would_block
1245         || ec == boost::asio::error::try_again)
1246       return false;
1247 
1248     // Operation failed.
1249     bytes_transferred = 0;
1250     return true;
1251   }
1252 }
1253 
1254 #endif // defined(BOOST_ASIO_HAS_IOCP)
1255 
1256 signed_size_type recvmsg(socket_type s, buf* bufs, size_t count,
1257     int in_flags, int& out_flags, boost::system::error_code& ec)
1258 {
1259 #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
1260   out_flags = 0;
1261   return socket_ops::recv(s, bufs, count, in_flags, ec);
1262 #else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
1263   msghdr msg = msghdr();
1264   msg.msg_iov = bufs;
1265   msg.msg_iovlen = static_cast<int>(count);
1266   signed_size_type result = ::recvmsg(s, &msg, in_flags);
1267   get_last_error(ec, result < 0);
1268   if (result >= 0)
1269     out_flags = msg.msg_flags;
1270   else
1271     out_flags = 0;
1272   return result;
1273 #endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
1274 }
1275 
1276 size_t sync_recvmsg(socket_type s, state_type state,
1277     buf* bufs, size_t count, int in_flags, int& out_flags,
1278     boost::system::error_code& ec)
1279 {
1280   if (s == invalid_socket)
1281   {
1282     ec = boost::asio::error::bad_descriptor;
1283     return 0;
1284   }
1285 
1286   // Read some data.
1287   for (;;)
1288   {
1289     // Try to complete the operation without blocking.
1290     signed_size_type bytes = socket_ops::recvmsg(
1291         s, bufs, count, in_flags, out_flags, ec);
1292 
1293     // Check if operation succeeded.
1294     if (bytes >= 0)
1295       return bytes;
1296 
1297     // Operation failed.
1298     if ((state & user_set_non_blocking)
1299         || (ec != boost::asio::error::would_block
1300           && ec != boost::asio::error::try_again))
1301       return 0;
1302 
1303     // Wait for socket to become ready.
1304     if (socket_ops::poll_read(s, 0, -1, ec) < 0)
1305       return 0;
1306   }
1307 }
1308 
1309 #if defined(BOOST_ASIO_HAS_IOCP)
1310 
1311 void complete_iocp_recvmsg(
1312     const weak_cancel_token_type& cancel_token,
1313     boost::system::error_code& ec)
1314 {
1315   // Map non-portable errors to their portable counterparts.
1316   if (ec.value() == ERROR_NETNAME_DELETED)
1317   {
1318     if (cancel_token.expired())
1319       ec = boost::asio::error::operation_aborted;
1320     else
1321       ec = boost::asio::error::connection_reset;
1322   }
1323   else if (ec.value() == ERROR_PORT_UNREACHABLE)
1324   {
1325     ec = boost::asio::error::connection_refused;
1326   }
1327   else if (ec.value() == WSAEMSGSIZE || ec.value() == ERROR_MORE_DATA)
1328   {
1329     boost::asio::error::clear(ec);
1330   }
1331 }
1332 
1333 #else // defined(BOOST_ASIO_HAS_IOCP)
1334 
1335 bool non_blocking_recvmsg(socket_type s,
1336     buf* bufs, size_t count, int in_flags, int& out_flags,
1337     boost::system::error_code& ec, size_t& bytes_transferred)
1338 {
1339   for (;;)
1340   {
1341     // Read some data.
1342     signed_size_type bytes = socket_ops::recvmsg(
1343         s, bufs, count, in_flags, out_flags, ec);
1344 
1345     // Check if operation succeeded.
1346     if (bytes >= 0)
1347     {
1348       bytes_transferred = bytes;
1349       return true;
1350     }
1351 
1352     // Retry operation if interrupted by signal.
1353     if (ec == boost::asio::error::interrupted)
1354       continue;
1355 
1356     // Check if we need to run the operation again.
1357     if (ec == boost::asio::error::would_block
1358         || ec == boost::asio::error::try_again)
1359       return false;
1360 
1361     // Operation failed.
1362     bytes_transferred = 0;
1363     return true;
1364   }
1365 }
1366 
1367 #endif // defined(BOOST_ASIO_HAS_IOCP)
1368 
1369 signed_size_type send(socket_type s, const buf* bufs, size_t count,
1370     int flags, boost::system::error_code& ec)
1371 {
1372 #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
1373   // Send the data.
1374   DWORD send_buf_count = static_cast<DWORD>(count);
1375   DWORD bytes_transferred = 0;
1376   DWORD send_flags = flags;
1377   int result = ::WSASend(s, const_cast<buf*>(bufs),
1378         send_buf_count, &bytes_transferred, send_flags, 0, 0);
1379   get_last_error(ec, true);
1380   if (ec.value() == ERROR_NETNAME_DELETED)
1381     ec = boost::asio::error::connection_reset;
1382   else if (ec.value() == ERROR_PORT_UNREACHABLE)
1383     ec = boost::asio::error::connection_refused;
1384   if (result != 0)
1385     return socket_error_retval;
1386   boost::asio::error::clear(ec);
1387   return bytes_transferred;
1388 #else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
1389   msghdr msg = msghdr();
1390   msg.msg_iov = const_cast<buf*>(bufs);
1391   msg.msg_iovlen = static_cast<int>(count);
1392 #if defined(BOOST_ASIO_HAS_MSG_NOSIGNAL)
1393   flags |= MSG_NOSIGNAL;
1394 #endif // defined(BOOST_ASIO_HAS_MSG_NOSIGNAL)
1395   signed_size_type result = ::sendmsg(s, &msg, flags);
1396   get_last_error(ec, result < 0);
1397   return result;
1398 #endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
1399 }
1400 
1401 signed_size_type send1(socket_type s, const void* data, size_t size,
1402     int flags, boost::system::error_code& ec)
1403 {
1404 #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
1405   // Send the data.
1406   WSABUF buf;
1407   buf.buf = const_cast<char*>(static_cast<const char*>(data));
1408   buf.len = static_cast<ULONG>(size);
1409   DWORD bytes_transferred = 0;
1410   DWORD send_flags = flags;
1411   int result = ::WSASend(s, &buf, 1,
1412         &bytes_transferred, send_flags, 0, 0);
1413   get_last_error(ec, true);
1414   if (ec.value() == ERROR_NETNAME_DELETED)
1415     ec = boost::asio::error::connection_reset;
1416   else if (ec.value() == ERROR_PORT_UNREACHABLE)
1417     ec = boost::asio::error::connection_refused;
1418   if (result != 0)
1419     return socket_error_retval;
1420   boost::asio::error::clear(ec);
1421   return bytes_transferred;
1422 #else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
1423 #if defined(BOOST_ASIO_HAS_MSG_NOSIGNAL)
1424   flags |= MSG_NOSIGNAL;
1425 #endif // defined(BOOST_ASIO_HAS_MSG_NOSIGNAL)
1426   signed_size_type result = ::send(s,
1427       static_cast<const char*>(data), size, flags);
1428   get_last_error(ec, result < 0);
1429   return result;
1430 #endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
1431 }
1432 
1433 size_t sync_send(socket_type s, state_type state, const buf* bufs,
1434     size_t count, int flags, bool all_empty, boost::system::error_code& ec)
1435 {
1436   if (s == invalid_socket)
1437   {
1438     ec = boost::asio::error::bad_descriptor;
1439     return 0;
1440   }
1441 
1442   // A request to write 0 bytes to a stream is a no-op.
1443   if (all_empty && (state & stream_oriented))
1444   {
1445     boost::asio::error::clear(ec);
1446     return 0;
1447   }
1448 
1449   // Read some data.
1450   for (;;)
1451   {
1452     // Try to complete the operation without blocking.
1453     signed_size_type bytes = socket_ops::send(s, bufs, count, flags, ec);
1454 
1455     // Check if operation succeeded.
1456     if (bytes >= 0)
1457       return bytes;
1458 
1459     // Operation failed.
1460     if ((state & user_set_non_blocking)
1461         || (ec != boost::asio::error::would_block
1462           && ec != boost::asio::error::try_again))
1463       return 0;
1464 
1465     // Wait for socket to become ready.
1466     if (socket_ops::poll_write(s, 0, -1, ec) < 0)
1467       return 0;
1468   }
1469 }
1470 
1471 size_t sync_send1(socket_type s, state_type state, const void* data,
1472     size_t size, int flags, boost::system::error_code& ec)
1473 {
1474   if (s == invalid_socket)
1475   {
1476     ec = boost::asio::error::bad_descriptor;
1477     return 0;
1478   }
1479 
1480   // A request to write 0 bytes to a stream is a no-op.
1481   if (size == 0 && (state & stream_oriented))
1482   {
1483     boost::asio::error::clear(ec);
1484     return 0;
1485   }
1486 
1487   // Read some data.
1488   for (;;)
1489   {
1490     // Try to complete the operation without blocking.
1491     signed_size_type bytes = socket_ops::send1(s, data, size, flags, ec);
1492 
1493     // Check if operation succeeded.
1494     if (bytes >= 0)
1495       return bytes;
1496 
1497     // Operation failed.
1498     if ((state & user_set_non_blocking)
1499         || (ec != boost::asio::error::would_block
1500           && ec != boost::asio::error::try_again))
1501       return 0;
1502 
1503     // Wait for socket to become ready.
1504     if (socket_ops::poll_write(s, 0, -1, ec) < 0)
1505       return 0;
1506   }
1507 }
1508 
1509 #if defined(BOOST_ASIO_HAS_IOCP)
1510 
1511 void complete_iocp_send(
1512     const weak_cancel_token_type& cancel_token,
1513     boost::system::error_code& ec)
1514 {
1515   // Map non-portable errors to their portable counterparts.
1516   if (ec.value() == ERROR_NETNAME_DELETED)
1517   {
1518     if (cancel_token.expired())
1519       ec = boost::asio::error::operation_aborted;
1520     else
1521       ec = boost::asio::error::connection_reset;
1522   }
1523   else if (ec.value() == ERROR_PORT_UNREACHABLE)
1524   {
1525     ec = boost::asio::error::connection_refused;
1526   }
1527 }
1528 
1529 #else // defined(BOOST_ASIO_HAS_IOCP)
1530 
1531 bool non_blocking_send(socket_type s,
1532     const buf* bufs, size_t count, int flags,
1533     boost::system::error_code& ec, size_t& bytes_transferred)
1534 {
1535   for (;;)
1536   {
1537     // Write some data.
1538     signed_size_type bytes = socket_ops::send(s, bufs, count, flags, ec);
1539 
1540     // Check if operation succeeded.
1541     if (bytes >= 0)
1542     {
1543       bytes_transferred = bytes;
1544       return true;
1545     }
1546 
1547     // Retry operation if interrupted by signal.
1548     if (ec == boost::asio::error::interrupted)
1549       continue;
1550 
1551     // Check if we need to run the operation again.
1552     if (ec == boost::asio::error::would_block
1553         || ec == boost::asio::error::try_again)
1554       return false;
1555 
1556     // Operation failed.
1557     bytes_transferred = 0;
1558     return true;
1559   }
1560 }
1561 
1562 bool non_blocking_send1(socket_type s,
1563     const void* data, size_t size, int flags,
1564     boost::system::error_code& ec, size_t& bytes_transferred)
1565 {
1566   for (;;)
1567   {
1568     // Write some data.
1569     signed_size_type bytes = socket_ops::send1(s, data, size, flags, ec);
1570 
1571     // Check if operation succeeded.
1572     if (bytes >= 0)
1573     {
1574       bytes_transferred = bytes;
1575       return true;
1576     }
1577 
1578     // Retry operation if interrupted by signal.
1579     if (ec == boost::asio::error::interrupted)
1580       continue;
1581 
1582     // Check if we need to run the operation again.
1583     if (ec == boost::asio::error::would_block
1584         || ec == boost::asio::error::try_again)
1585       return false;
1586 
1587     // Operation failed.
1588     bytes_transferred = 0;
1589     return true;
1590   }
1591 }
1592 
1593 #endif // defined(BOOST_ASIO_HAS_IOCP)
1594 
1595 signed_size_type sendto(socket_type s, const buf* bufs,
1596     size_t count, int flags, const void* addr,
1597     std::size_t addrlen, boost::system::error_code& ec)
1598 {
1599 #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
1600   // Send the data.
1601   DWORD send_buf_count = static_cast<DWORD>(count);
1602   DWORD bytes_transferred = 0;
1603   int result = ::WSASendTo(s, const_cast<buf*>(bufs),
1604         send_buf_count, &bytes_transferred, flags,
1605         static_cast<const socket_addr_type*>(addr),
1606         static_cast<int>(addrlen), 0, 0);
1607   get_last_error(ec, true);
1608   if (ec.value() == ERROR_NETNAME_DELETED)
1609     ec = boost::asio::error::connection_reset;
1610   else if (ec.value() == ERROR_PORT_UNREACHABLE)
1611     ec = boost::asio::error::connection_refused;
1612   if (result != 0)
1613     return socket_error_retval;
1614   boost::asio::error::clear(ec);
1615   return bytes_transferred;
1616 #else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
1617   msghdr msg = msghdr();
1618   init_msghdr_msg_name(msg.msg_name, addr);
1619   msg.msg_namelen = static_cast<int>(addrlen);
1620   msg.msg_iov = const_cast<buf*>(bufs);
1621   msg.msg_iovlen = static_cast<int>(count);
1622 #if defined(BOOST_ASIO_HAS_MSG_NOSIGNAL)
1623   flags |= MSG_NOSIGNAL;
1624 #endif // defined(BOOST_ASIO_HAS_MSG_NOSIGNAL)
1625   signed_size_type result = ::sendmsg(s, &msg, flags);
1626   get_last_error(ec, result < 0);
1627   return result;
1628 #endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
1629 }
1630 
1631 template <typename SockLenType>
1632 inline signed_size_type call_sendto(SockLenType msghdr::*,
1633     socket_type s, const void* data, size_t size, int flags,
1634     const void* addr, std::size_t addrlen)
1635 {
1636   return ::sendto(s, static_cast<char*>(const_cast<void*>(data)), size, flags,
1637       static_cast<const socket_addr_type*>(addr), (SockLenType)addrlen);
1638 }
1639 
1640 signed_size_type sendto1(socket_type s, const void* data,
1641     size_t size, int flags, const void* addr,
1642     std::size_t addrlen, boost::system::error_code& ec)
1643 {
1644 #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
1645   // Send the data.
1646   WSABUF buf;
1647   buf.buf = const_cast<char*>(static_cast<const char*>(data));
1648   buf.len = static_cast<ULONG>(size);
1649   DWORD bytes_transferred = 0;
1650   int result = ::WSASendTo(s, &buf, 1, &bytes_transferred, flags,
1651       static_cast<const socket_addr_type*>(addr),
1652       static_cast<int>(addrlen), 0, 0);
1653   get_last_error(ec, true);
1654   if (ec.value() == ERROR_NETNAME_DELETED)
1655     ec = boost::asio::error::connection_reset;
1656   else if (ec.value() == ERROR_PORT_UNREACHABLE)
1657     ec = boost::asio::error::connection_refused;
1658   if (result != 0)
1659     return socket_error_retval;
1660   boost::asio::error::clear(ec);
1661   return bytes_transferred;
1662 #else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
1663 #if defined(BOOST_ASIO_HAS_MSG_NOSIGNAL)
1664   flags |= MSG_NOSIGNAL;
1665 #endif // defined(BOOST_ASIO_HAS_MSG_NOSIGNAL)
1666   signed_size_type result = call_sendto(&msghdr::msg_namelen,
1667       s, data, size, flags, addr, addrlen);
1668   get_last_error(ec, result < 0);
1669   return result;
1670 #endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
1671 }
1672 
1673 size_t sync_sendto(socket_type s, state_type state,
1674     const buf* bufs, size_t count, int flags, const void* addr,
1675     std::size_t addrlen, boost::system::error_code& ec)
1676 {
1677   if (s == invalid_socket)
1678   {
1679     ec = boost::asio::error::bad_descriptor;
1680     return 0;
1681   }
1682 
1683   // Write some data.
1684   for (;;)
1685   {
1686     // Try to complete the operation without blocking.
1687     signed_size_type bytes = socket_ops::sendto(
1688         s, bufs, count, flags, addr, addrlen, ec);
1689 
1690     // Check if operation succeeded.
1691     if (bytes >= 0)
1692       return bytes;
1693 
1694     // Operation failed.
1695     if ((state & user_set_non_blocking)
1696         || (ec != boost::asio::error::would_block
1697           && ec != boost::asio::error::try_again))
1698       return 0;
1699 
1700     // Wait for socket to become ready.
1701     if (socket_ops::poll_write(s, 0, -1, ec) < 0)
1702       return 0;
1703   }
1704 }
1705 
1706 size_t sync_sendto1(socket_type s, state_type state,
1707     const void* data, size_t size, int flags, const void* addr,
1708     std::size_t addrlen, boost::system::error_code& ec)
1709 {
1710   if (s == invalid_socket)
1711   {
1712     ec = boost::asio::error::bad_descriptor;
1713     return 0;
1714   }
1715 
1716   // Write some data.
1717   for (;;)
1718   {
1719     // Try to complete the operation without blocking.
1720     signed_size_type bytes = socket_ops::sendto1(
1721         s, data, size, flags, addr, addrlen, ec);
1722 
1723     // Check if operation succeeded.
1724     if (bytes >= 0)
1725       return bytes;
1726 
1727     // Operation failed.
1728     if ((state & user_set_non_blocking)
1729         || (ec != boost::asio::error::would_block
1730           && ec != boost::asio::error::try_again))
1731       return 0;
1732 
1733     // Wait for socket to become ready.
1734     if (socket_ops::poll_write(s, 0, -1, ec) < 0)
1735       return 0;
1736   }
1737 }
1738 
1739 #if !defined(BOOST_ASIO_HAS_IOCP)
1740 
1741 bool non_blocking_sendto(socket_type s,
1742     const buf* bufs, size_t count, int flags,
1743     const void* addr, std::size_t addrlen,
1744     boost::system::error_code& ec, size_t& bytes_transferred)
1745 {
1746   for (;;)
1747   {
1748     // Write some data.
1749     signed_size_type bytes = socket_ops::sendto(
1750         s, bufs, count, flags, addr, addrlen, ec);
1751 
1752     // Check if operation succeeded.
1753     if (bytes >= 0)
1754     {
1755       bytes_transferred = bytes;
1756       return true;
1757     }
1758 
1759     // Retry operation if interrupted by signal.
1760     if (ec == boost::asio::error::interrupted)
1761       continue;
1762 
1763     // Check if we need to run the operation again.
1764     if (ec == boost::asio::error::would_block
1765         || ec == boost::asio::error::try_again)
1766       return false;
1767 
1768     // Operation failed.
1769     bytes_transferred = 0;
1770     return true;
1771   }
1772 }
1773 
1774 bool non_blocking_sendto1(socket_type s,
1775     const void* data, size_t size, int flags,
1776     const void* addr, std::size_t addrlen,
1777     boost::system::error_code& ec, size_t& bytes_transferred)
1778 {
1779   for (;;)
1780   {
1781     // Write some data.
1782     signed_size_type bytes = socket_ops::sendto1(
1783         s, data, size, flags, addr, addrlen, ec);
1784 
1785     // Check if operation succeeded.
1786     if (bytes >= 0)
1787     {
1788       bytes_transferred = bytes;
1789       return true;
1790     }
1791 
1792     // Retry operation if interrupted by signal.
1793     if (ec == boost::asio::error::interrupted)
1794       continue;
1795 
1796     // Check if we need to run the operation again.
1797     if (ec == boost::asio::error::would_block
1798         || ec == boost::asio::error::try_again)
1799       return false;
1800 
1801     // Operation failed.
1802     bytes_transferred = 0;
1803     return true;
1804   }
1805 }
1806 
1807 #endif // !defined(BOOST_ASIO_HAS_IOCP)
1808 
1809 socket_type socket(int af, int type, int protocol,
1810     boost::system::error_code& ec)
1811 {
1812 #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
1813   socket_type s = ::WSASocketW(af, type, protocol, 0, 0, WSA_FLAG_OVERLAPPED);
1814   get_last_error(ec, s == invalid_socket);
1815   if (s == invalid_socket)
1816     return s;
1817 
1818   if (af == BOOST_ASIO_OS_DEF(AF_INET6))
1819   {
1820     // Try to enable the POSIX default behaviour of having IPV6_V6ONLY set to
1821     // false. This will only succeed on Windows Vista and later versions of
1822     // Windows, where a dual-stack IPv4/v6 implementation is available.
1823     DWORD optval = 0;
1824     ::setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
1825         reinterpret_cast<const char*>(&optval), sizeof(optval));
1826   }
1827 
1828   return s;
1829 #elif defined(__MACH__) && defined(__APPLE__) || defined(__FreeBSD__)
1830   socket_type s = ::socket(af, type, protocol);
1831   get_last_error(ec, s == invalid_socket);
1832   if (s == invalid_socket)
1833     return s;
1834 
1835   int optval = 1;
1836   int result = ::setsockopt(s, SOL_SOCKET,
1837       SO_NOSIGPIPE, &optval, sizeof(optval));
1838   get_last_error(ec, result != 0);
1839   if (result != 0)
1840   {
1841     ::close(s);
1842     return invalid_socket;
1843   }
1844 
1845   return s;
1846 #else
1847   int s = ::socket(af, type, protocol);
1848   get_last_error(ec, s < 0);
1849   return s;
1850 #endif
1851 }
1852 
1853 template <typename SockLenType>
1854 inline int call_setsockopt(SockLenType msghdr::*,
1855     socket_type s, int level, int optname,
1856     const void* optval, std::size_t optlen)
1857 {
1858   return ::setsockopt(s, level, optname,
1859       (const char*)optval, (SockLenType)optlen);
1860 }
1861 
1862 int setsockopt(socket_type s, state_type& state, int level, int optname,
1863     const void* optval, std::size_t optlen, boost::system::error_code& ec)
1864 {
1865   if (s == invalid_socket)
1866   {
1867     ec = boost::asio::error::bad_descriptor;
1868     return socket_error_retval;
1869   }
1870 
1871   if (level == custom_socket_option_level && optname == always_fail_option)
1872   {
1873     ec = boost::asio::error::invalid_argument;
1874     return socket_error_retval;
1875   }
1876 
1877   if (level == custom_socket_option_level
1878       && optname == enable_connection_aborted_option)
1879   {
1880     if (optlen != sizeof(int))
1881     {
1882       ec = boost::asio::error::invalid_argument;
1883       return socket_error_retval;
1884     }
1885 
1886     if (*static_cast<const int*>(optval))
1887       state |= enable_connection_aborted;
1888     else
1889       state &= ~enable_connection_aborted;
1890     boost::asio::error::clear(ec);
1891     return 0;
1892   }
1893 
1894   if (level == SOL_SOCKET && optname == SO_LINGER)
1895     state |= user_set_linger;
1896 
1897 #if defined(__BORLANDC__)
1898   // Mysteriously, using the getsockopt and setsockopt functions directly with
1899   // Borland C++ results in incorrect values being set and read. The bug can be
1900   // worked around by using function addresses resolved with GetProcAddress.
1901   if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32"))
1902   {
1903     typedef int (WSAAPI *sso_t)(SOCKET, int, int, const char*, int);
1904     if (sso_t sso = (sso_t)::GetProcAddress(winsock_module, "setsockopt"))
1905     {
1906       int result = sso(s, level, optname,
1907             reinterpret_cast<const char*>(optval),
1908             static_cast<int>(optlen));
1909       get_last_error(ec, result != 0);
1910       return result;
1911     }
1912   }
1913   ec = boost::asio::error::fault;
1914   return socket_error_retval;
1915 #else // defined(__BORLANDC__)
1916   int result = call_setsockopt(&msghdr::msg_namelen,
1917         s, level, optname, optval, optlen);
1918   get_last_error(ec, result != 0);
1919   if (result == 0)
1920   {
1921 #if defined(__MACH__) && defined(__APPLE__) \
1922   || defined(__NetBSD__) || defined(__FreeBSD__) \
1923   || defined(__OpenBSD__) || defined(__QNX__)
1924     // To implement portable behaviour for SO_REUSEADDR with UDP sockets we
1925     // need to also set SO_REUSEPORT on BSD-based platforms.
1926     if ((state & datagram_oriented)
1927         && level == SOL_SOCKET && optname == SO_REUSEADDR)
1928     {
1929       call_setsockopt(&msghdr::msg_namelen, s,
1930           SOL_SOCKET, SO_REUSEPORT, optval, optlen);
1931     }
1932 #endif
1933   }
1934 
1935   return result;
1936 #endif // defined(__BORLANDC__)
1937 }
1938 
1939 template <typename SockLenType>
1940 inline int call_getsockopt(SockLenType msghdr::*,
1941     socket_type s, int level, int optname,
1942     void* optval, std::size_t* optlen)
1943 {
1944   SockLenType tmp_optlen = (SockLenType)*optlen;
1945   int result = ::getsockopt(s, level, optname, (char*)optval, &tmp_optlen);
1946   *optlen = (std::size_t)tmp_optlen;
1947   return result;
1948 }
1949 
1950 int getsockopt(socket_type s, state_type state, int level, int optname,
1951     void* optval, size_t* optlen, boost::system::error_code& ec)
1952 {
1953   if (s == invalid_socket)
1954   {
1955     ec = boost::asio::error::bad_descriptor;
1956     return socket_error_retval;
1957   }
1958 
1959   if (level == custom_socket_option_level && optname == always_fail_option)
1960   {
1961     ec = boost::asio::error::invalid_argument;
1962     return socket_error_retval;
1963   }
1964 
1965   if (level == custom_socket_option_level
1966       && optname == enable_connection_aborted_option)
1967   {
1968     if (*optlen != sizeof(int))
1969     {
1970       ec = boost::asio::error::invalid_argument;
1971       return socket_error_retval;
1972     }
1973 
1974     *static_cast<int*>(optval) = (state & enable_connection_aborted) ? 1 : 0;
1975     boost::asio::error::clear(ec);
1976     return 0;
1977   }
1978 
1979 #if defined(__BORLANDC__)
1980   // Mysteriously, using the getsockopt and setsockopt functions directly with
1981   // Borland C++ results in incorrect values being set and read. The bug can be
1982   // worked around by using function addresses resolved with GetProcAddress.
1983   if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32"))
1984   {
1985     typedef int (WSAAPI *gso_t)(SOCKET, int, int, char*, int*);
1986     if (gso_t gso = (gso_t)::GetProcAddress(winsock_module, "getsockopt"))
1987     {
1988       int tmp_optlen = static_cast<int>(*optlen);
1989       int result = gso(s, level, optname,
1990             reinterpret_cast<char*>(optval), &tmp_optlen);
1991       get_last_error(ec, result != 0);
1992       *optlen = static_cast<size_t>(tmp_optlen);
1993       if (result != 0 && level == IPPROTO_IPV6 && optname == IPV6_V6ONLY
1994           && ec.value() == WSAENOPROTOOPT && *optlen == sizeof(DWORD))
1995       {
1996         // Dual-stack IPv4/v6 sockets, and the IPV6_V6ONLY socket option, are
1997         // only supported on Windows Vista and later. To simplify program logic
1998         // we will fake success of getting this option and specify that the
1999         // value is non-zero (i.e. true). This corresponds to the behavior of
2000         // IPv6 sockets on Windows platforms pre-Vista.
2001         *static_cast<DWORD*>(optval) = 1;
2002         boost::asio::error::clear(ec);
2003       }
2004       return result;
2005     }
2006   }
2007   ec = boost::asio::error::fault;
2008   return socket_error_retval;
2009 #elif defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
2010   int result = call_getsockopt(&msghdr::msg_namelen,
2011         s, level, optname, optval, optlen);
2012   get_last_error(ec, result != 0);
2013   if (result != 0 && level == IPPROTO_IPV6 && optname == IPV6_V6ONLY
2014       && ec.value() == WSAENOPROTOOPT && *optlen == sizeof(DWORD))
2015   {
2016     // Dual-stack IPv4/v6 sockets, and the IPV6_V6ONLY socket option, are only
2017     // supported on Windows Vista and later. To simplify program logic we will
2018     // fake success of getting this option and specify that the value is
2019     // non-zero (i.e. true). This corresponds to the behavior of IPv6 sockets
2020     // on Windows platforms pre-Vista.
2021     *static_cast<DWORD*>(optval) = 1;
2022     boost::asio::error::clear(ec);
2023   }
2024   return result;
2025 #else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
2026   int result = call_getsockopt(&msghdr::msg_namelen,
2027         s, level, optname, optval, optlen);
2028   get_last_error(ec, result != 0);
2029 #if defined(__linux__)
2030   if (result == 0 && level == SOL_SOCKET && *optlen == sizeof(int)
2031       && (optname == SO_SNDBUF || optname == SO_RCVBUF))
2032   {
2033     // On Linux, setting SO_SNDBUF or SO_RCVBUF to N actually causes the kernel
2034     // to set the buffer size to N*2. Linux puts additional stuff into the
2035     // buffers so that only about half is actually available to the application.
2036     // The retrieved value is divided by 2 here to make it appear as though the
2037     // correct value has been set.
2038     *static_cast<int*>(optval) /= 2;
2039   }
2040 #endif // defined(__linux__)
2041   return result;
2042 #endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
2043 }
2044 
2045 template <typename SockLenType>
2046 inline int call_getpeername(SockLenType msghdr::*,
2047     socket_type s, void* addr, std::size_t* addrlen)
2048 {
2049   SockLenType tmp_addrlen = (SockLenType)*addrlen;
2050   int result = ::getpeername(s,
2051       static_cast<socket_addr_type*>(addr), &tmp_addrlen);
2052   *addrlen = (std::size_t)tmp_addrlen;
2053   return result;
2054 }
2055 
2056 int getpeername(socket_type s, void* addr, std::size_t* addrlen,
2057     bool cached, boost::system::error_code& ec)
2058 {
2059   if (s == invalid_socket)
2060   {
2061     ec = boost::asio::error::bad_descriptor;
2062     return socket_error_retval;
2063   }
2064 
2065 #if defined(BOOST_ASIO_WINDOWS) && !defined(BOOST_ASIO_WINDOWS_APP) \
2066   || defined(__CYGWIN__)
2067   if (cached)
2068   {
2069     // Check if socket is still connected.
2070     DWORD connect_time = 0;
2071     size_t connect_time_len = sizeof(connect_time);
2072     if (socket_ops::getsockopt(s, 0, SOL_SOCKET, SO_CONNECT_TIME,
2073           &connect_time, &connect_time_len, ec) == socket_error_retval)
2074     {
2075       return socket_error_retval;
2076     }
2077     if (connect_time == 0xFFFFFFFF)
2078     {
2079       ec = boost::asio::error::not_connected;
2080       return socket_error_retval;
2081     }
2082 
2083     // The cached value is still valid.
2084     boost::asio::error::clear(ec);
2085     return 0;
2086   }
2087 #else // defined(BOOST_ASIO_WINDOWS) && !defined(BOOST_ASIO_WINDOWS_APP)
2088       // || defined(__CYGWIN__)
2089   (void)cached;
2090 #endif // defined(BOOST_ASIO_WINDOWS) && !defined(BOOST_ASIO_WINDOWS_APP)
2091        // || defined(__CYGWIN__)
2092 
2093   int result = call_getpeername(&msghdr::msg_namelen, s, addr, addrlen);
2094   get_last_error(ec, result != 0);
2095   return result;
2096 }
2097 
2098 template <typename SockLenType>
2099 inline int call_getsockname(SockLenType msghdr::*,
2100     socket_type s, void* addr, std::size_t* addrlen)
2101 {
2102   SockLenType tmp_addrlen = (SockLenType)*addrlen;
2103   int result = ::getsockname(s,
2104       static_cast<socket_addr_type*>(addr), &tmp_addrlen);
2105   *addrlen = (std::size_t)tmp_addrlen;
2106   return result;
2107 }
2108 
2109 int getsockname(socket_type s, void* addr,
2110     std::size_t* addrlen, boost::system::error_code& ec)
2111 {
2112   if (s == invalid_socket)
2113   {
2114     ec = boost::asio::error::bad_descriptor;
2115     return socket_error_retval;
2116   }
2117 
2118   int result = call_getsockname(&msghdr::msg_namelen, s, addr, addrlen);
2119   get_last_error(ec, result != 0);
2120   return result;
2121 }
2122 
2123 int ioctl(socket_type s, state_type& state, int cmd,
2124     ioctl_arg_type* arg, boost::system::error_code& ec)
2125 {
2126   if (s == invalid_socket)
2127   {
2128     ec = boost::asio::error::bad_descriptor;
2129     return socket_error_retval;
2130   }
2131 
2132 #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
2133   int result = ::ioctlsocket(s, cmd, arg);
2134 #elif defined(__MACH__) && defined(__APPLE__) \
2135   || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
2136   int result = ::ioctl(s, static_cast<unsigned int>(cmd), arg);
2137 #else
2138   int result = ::ioctl(s, cmd, arg);
2139 #endif
2140   get_last_error(ec, result < 0);
2141   if (result >= 0)
2142   {
2143     // When updating the non-blocking mode we always perform the ioctl syscall,
2144     // even if the flags would otherwise indicate that the socket is already in
2145     // the correct state. This ensures that the underlying socket is put into
2146     // the state that has been requested by the user. If the ioctl syscall was
2147     // successful then we need to update the flags to match.
2148     if (cmd == static_cast<int>(FIONBIO))
2149     {
2150       if (*arg)
2151       {
2152         state |= user_set_non_blocking;
2153       }
2154       else
2155       {
2156         // Clearing the non-blocking mode always overrides any internally-set
2157         // non-blocking flag. Any subsequent asynchronous operations will need
2158         // to re-enable non-blocking I/O.
2159         state &= ~(user_set_non_blocking | internal_non_blocking);
2160       }
2161     }
2162   }
2163 
2164   return result;
2165 }
2166 
2167 int select(int nfds, fd_set* readfds, fd_set* writefds,
2168     fd_set* exceptfds, timeval* timeout, boost::system::error_code& ec)
2169 {
2170 #if defined(__EMSCRIPTEN__)
2171   exceptfds = 0;
2172 #endif // defined(__EMSCRIPTEN__)
2173 #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
2174   if (!readfds && !writefds && !exceptfds && timeout)
2175   {
2176     DWORD milliseconds = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
2177     if (milliseconds == 0)
2178       milliseconds = 1; // Force context switch.
2179     ::Sleep(milliseconds);
2180     boost::asio::error::clear(ec);
2181     return 0;
2182   }
2183 
2184   // The select() call allows timeout values measured in microseconds, but the
2185   // system clock (as wrapped by boost::posix_time::microsec_clock) typically
2186   // has a resolution of 10 milliseconds. This can lead to a spinning select
2187   // reactor, meaning increased CPU usage, when waiting for the earliest
2188   // scheduled timeout if it's less than 10 milliseconds away. To avoid a tight
2189   // spin we'll use a minimum timeout of 1 millisecond.
2190   if (timeout && timeout->tv_sec == 0
2191       && timeout->tv_usec > 0 && timeout->tv_usec < 1000)
2192     timeout->tv_usec = 1000;
2193 #endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
2194 
2195 #if defined(__hpux) && defined(__SELECT)
2196   timespec ts;
2197   ts.tv_sec = timeout ? timeout->tv_sec : 0;
2198   ts.tv_nsec = timeout ? timeout->tv_usec * 1000 : 0;
2199   int result = ::pselect(nfds, readfds,
2200         writefds, exceptfds, timeout ? &ts : 0, 0);
2201 #else
2202   int result = ::select(nfds, readfds, writefds, exceptfds, timeout);
2203 #endif
2204   get_last_error(ec, result < 0);
2205   return result;
2206 }
2207 
2208 int poll_read(socket_type s, state_type state,
2209     int msec, boost::system::error_code& ec)
2210 {
2211   if (s == invalid_socket)
2212   {
2213     ec = boost::asio::error::bad_descriptor;
2214     return socket_error_retval;
2215   }
2216 
2217 #if defined(BOOST_ASIO_WINDOWS) \
2218   || defined(__CYGWIN__) \
2219   || defined(__SYMBIAN32__)
2220   fd_set fds;
2221   FD_ZERO(&fds);
2222   FD_SET(s, &fds);
2223   timeval timeout_obj;
2224   timeval* timeout;
2225   if (state & user_set_non_blocking)
2226   {
2227     timeout_obj.tv_sec = 0;
2228     timeout_obj.tv_usec = 0;
2229     timeout = &timeout_obj;
2230   }
2231   else if (msec >= 0)
2232   {
2233     timeout_obj.tv_sec = msec / 1000;
2234     timeout_obj.tv_usec = (msec % 1000) * 1000;
2235     timeout = &timeout_obj;
2236   }
2237   else
2238     timeout = 0;
2239   int result = ::select(s + 1, &fds, 0, 0, timeout);
2240   get_last_error(ec, result < 0);
2241 #else // defined(BOOST_ASIO_WINDOWS)
2242       // || defined(__CYGWIN__)
2243       // || defined(__SYMBIAN32__)
2244   pollfd fds;
2245   fds.fd = s;
2246   fds.events = POLLIN;
2247   fds.revents = 0;
2248   int timeout = (state & user_set_non_blocking) ? 0 : msec;
2249   int result = ::poll(&fds, 1, timeout);
2250   get_last_error(ec, result < 0);
2251 #endif // defined(BOOST_ASIO_WINDOWS)
2252        // || defined(__CYGWIN__)
2253        // || defined(__SYMBIAN32__)
2254   if (result == 0)
2255     if (state & user_set_non_blocking)
2256       ec = boost::asio::error::would_block;
2257   return result;
2258 }
2259 
2260 int poll_write(socket_type s, state_type state,
2261     int msec, boost::system::error_code& ec)
2262 {
2263   if (s == invalid_socket)
2264   {
2265     ec = boost::asio::error::bad_descriptor;
2266     return socket_error_retval;
2267   }
2268 
2269 #if defined(BOOST_ASIO_WINDOWS) \
2270   || defined(__CYGWIN__) \
2271   || defined(__SYMBIAN32__)
2272   fd_set fds;
2273   FD_ZERO(&fds);
2274   FD_SET(s, &fds);
2275   timeval timeout_obj;
2276   timeval* timeout;
2277   if (state & user_set_non_blocking)
2278   {
2279     timeout_obj.tv_sec = 0;
2280     timeout_obj.tv_usec = 0;
2281     timeout = &timeout_obj;
2282   }
2283   else if (msec >= 0)
2284   {
2285     timeout_obj.tv_sec = msec / 1000;
2286     timeout_obj.tv_usec = (msec % 1000) * 1000;
2287     timeout = &timeout_obj;
2288   }
2289   else
2290     timeout = 0;
2291   int result = ::select(s + 1, 0, &fds, 0, timeout);
2292   get_last_error(ec, result < 0);
2293 #else // defined(BOOST_ASIO_WINDOWS)
2294       // || defined(__CYGWIN__)
2295       // || defined(__SYMBIAN32__)
2296   pollfd fds;
2297   fds.fd = s;
2298   fds.events = POLLOUT;
2299   fds.revents = 0;
2300   int timeout = (state & user_set_non_blocking) ? 0 : msec;
2301   int result = ::poll(&fds, 1, timeout);
2302   get_last_error(ec, result < 0);
2303 #endif // defined(BOOST_ASIO_WINDOWS)
2304        // || defined(__CYGWIN__)
2305        // || defined(__SYMBIAN32__)
2306   if (result == 0)
2307     if (state & user_set_non_blocking)
2308       ec = boost::asio::error::would_block;
2309   return result;
2310 }
2311 
2312 int poll_error(socket_type s, state_type state,
2313     int msec, boost::system::error_code& ec)
2314 {
2315   if (s == invalid_socket)
2316   {
2317     ec = boost::asio::error::bad_descriptor;
2318     return socket_error_retval;
2319   }
2320 
2321 #if defined(BOOST_ASIO_WINDOWS) \
2322   || defined(__CYGWIN__) \
2323   || defined(__SYMBIAN32__)
2324   fd_set fds;
2325   FD_ZERO(&fds);
2326   FD_SET(s, &fds);
2327   timeval timeout_obj;
2328   timeval* timeout;
2329   if (state & user_set_non_blocking)
2330   {
2331     timeout_obj.tv_sec = 0;
2332     timeout_obj.tv_usec = 0;
2333     timeout = &timeout_obj;
2334   }
2335   else if (msec >= 0)
2336   {
2337     timeout_obj.tv_sec = msec / 1000;
2338     timeout_obj.tv_usec = (msec % 1000) * 1000;
2339     timeout = &timeout_obj;
2340   }
2341   else
2342     timeout = 0;
2343   int result = ::select(s + 1, 0, 0, &fds, timeout);
2344   get_last_error(ec, result < 0);
2345 #else // defined(BOOST_ASIO_WINDOWS)
2346       // || defined(__CYGWIN__)
2347       // || defined(__SYMBIAN32__)
2348   pollfd fds;
2349   fds.fd = s;
2350   fds.events = POLLPRI | POLLERR | POLLHUP;
2351   fds.revents = 0;
2352   int timeout = (state & user_set_non_blocking) ? 0 : msec;
2353   int result = ::poll(&fds, 1, timeout);
2354   get_last_error(ec, result < 0);
2355 #endif // defined(BOOST_ASIO_WINDOWS)
2356        // || defined(__CYGWIN__)
2357        // || defined(__SYMBIAN32__)
2358   if (result == 0)
2359     if (state & user_set_non_blocking)
2360       ec = boost::asio::error::would_block;
2361   return result;
2362 }
2363 
2364 int poll_connect(socket_type s, int msec, boost::system::error_code& ec)
2365 {
2366   if (s == invalid_socket)
2367   {
2368     ec = boost::asio::error::bad_descriptor;
2369     return socket_error_retval;
2370   }
2371 
2372 #if defined(BOOST_ASIO_WINDOWS) \
2373   || defined(__CYGWIN__) \
2374   || defined(__SYMBIAN32__)
2375   fd_set write_fds;
2376   FD_ZERO(&write_fds);
2377   FD_SET(s, &write_fds);
2378   fd_set except_fds;
2379   FD_ZERO(&except_fds);
2380   FD_SET(s, &except_fds);
2381   timeval timeout_obj;
2382   timeval* timeout;
2383   if (msec >= 0)
2384   {
2385     timeout_obj.tv_sec = msec / 1000;
2386     timeout_obj.tv_usec = (msec % 1000) * 1000;
2387     timeout = &timeout_obj;
2388   }
2389   else
2390     timeout = 0;
2391   int result = ::select(s + 1, 0, &write_fds, &except_fds, timeout);
2392   get_last_error(ec, result < 0);
2393   return result;
2394 #else // defined(BOOST_ASIO_WINDOWS)
2395       // || defined(__CYGWIN__)
2396       // || defined(__SYMBIAN32__)
2397   pollfd fds;
2398   fds.fd = s;
2399   fds.events = POLLOUT;
2400   fds.revents = 0;
2401   int result = ::poll(&fds, 1, msec);
2402   get_last_error(ec, result < 0);
2403   return result;
2404 #endif // defined(BOOST_ASIO_WINDOWS)
2405        // || defined(__CYGWIN__)
2406        // || defined(__SYMBIAN32__)
2407 }
2408 
2409 #endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME)
2410 
2411 const char* inet_ntop(int af, const void* src, char* dest, size_t length,
2412     unsigned long scope_id, boost::system::error_code& ec)
2413 {
2414   clear_last_error();
2415 #if defined(BOOST_ASIO_WINDOWS_RUNTIME)
2416   using namespace std; // For sprintf.
2417   const unsigned char* bytes = static_cast<const unsigned char*>(src);
2418   if (af == BOOST_ASIO_OS_DEF(AF_INET))
2419   {
2420     sprintf_s(dest, length, "%u.%u.%u.%u",
2421         bytes[0], bytes[1], bytes[2], bytes[3]);
2422     return dest;
2423   }
2424   else if (af == BOOST_ASIO_OS_DEF(AF_INET6))
2425   {
2426     size_t n = 0, b = 0, z = 0;
2427     while (n < length && b < 16)
2428     {
2429       if (bytes[b] == 0 && bytes[b + 1] == 0 && z == 0)
2430       {
2431         do b += 2; while (b < 16 && bytes[b] == 0 && bytes[b + 1] == 0);
2432         n += sprintf_s(dest + n, length - n, ":%s", b < 16 ? "" : ":"), ++z;
2433       }
2434       else
2435       {
2436         n += sprintf_s(dest + n, length - n, "%s%x", b ? ":" : "",
2437             (static_cast<u_long_type>(bytes[b]) << 8) | bytes[b + 1]);
2438         b += 2;
2439       }
2440     }
2441     if (scope_id)
2442       n += sprintf_s(dest + n, length - n, "%%%lu", scope_id);
2443     return dest;
2444   }
2445   else
2446   {
2447     ec = boost::asio::error::address_family_not_supported;
2448     return 0;
2449   }
2450 #elif defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
2451   using namespace std; // For memcpy.
2452 
2453   if (af != BOOST_ASIO_OS_DEF(AF_INET) && af != BOOST_ASIO_OS_DEF(AF_INET6))
2454   {
2455     ec = boost::asio::error::address_family_not_supported;
2456     return 0;
2457   }
2458 
2459   union
2460   {
2461     socket_addr_type base;
2462     sockaddr_storage_type storage;
2463     sockaddr_in4_type v4;
2464     sockaddr_in6_type v6;
2465   } address;
2466   DWORD address_length;
2467   if (af == BOOST_ASIO_OS_DEF(AF_INET))
2468   {
2469     address_length = sizeof(sockaddr_in4_type);
2470     address.v4.sin_family = BOOST_ASIO_OS_DEF(AF_INET);
2471     address.v4.sin_port = 0;
2472     memcpy(&address.v4.sin_addr, src, sizeof(in4_addr_type));
2473   }
2474   else // AF_INET6
2475   {
2476     address_length = sizeof(sockaddr_in6_type);
2477     address.v6.sin6_family = BOOST_ASIO_OS_DEF(AF_INET6);
2478     address.v6.sin6_port = 0;
2479     address.v6.sin6_flowinfo = 0;
2480     address.v6.sin6_scope_id = scope_id;
2481     memcpy(&address.v6.sin6_addr, src, sizeof(in6_addr_type));
2482   }
2483 
2484   DWORD string_length = static_cast<DWORD>(length);
2485 #if defined(BOOST_NO_ANSI_APIS) || (defined(_MSC_VER) && (_MSC_VER >= 1800))
2486   LPWSTR string_buffer = (LPWSTR)_alloca(length * sizeof(WCHAR));
2487   int result = ::WSAAddressToStringW(&address.base,
2488         address_length, 0, string_buffer, &string_length);
2489   get_last_error(ec, true);
2490   ::WideCharToMultiByte(CP_ACP, 0, string_buffer, -1,
2491       dest, static_cast<int>(length), 0, 0);
2492 #else
2493   int result = ::WSAAddressToStringA(&address.base,
2494       address_length, 0, dest, &string_length);
2495   get_last_error(ec, true);
2496 #endif
2497 
2498   // Windows may set error code on success.
2499   if (result != socket_error_retval)
2500     boost::asio::error::clear(ec);
2501 
2502   // Windows may not set an error code on failure.
2503   else if (result == socket_error_retval && !ec)
2504     ec = boost::asio::error::invalid_argument;
2505 
2506   return result == socket_error_retval ? 0 : dest;
2507 #else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
2508   const char* result = ::inet_ntop(af, src, dest, static_cast<int>(length));
2509   get_last_error(ec, true);
2510   if (result == 0 && !ec)
2511     ec = boost::asio::error::invalid_argument;
2512   if (result != 0 && af == BOOST_ASIO_OS_DEF(AF_INET6) && scope_id != 0)
2513   {
2514     using namespace std; // For strcat and sprintf.
2515     char if_name[(IF_NAMESIZE > 21 ? IF_NAMESIZE : 21) + 1] = "%";
2516     const in6_addr_type* ipv6_address = static_cast<const in6_addr_type*>(src);
2517     bool is_link_local = ((ipv6_address->s6_addr[0] == 0xfe)
2518         && ((ipv6_address->s6_addr[1] & 0xc0) == 0x80));
2519     bool is_multicast_link_local = ((ipv6_address->s6_addr[0] == 0xff)
2520         && ((ipv6_address->s6_addr[1] & 0x0f) == 0x02));
2521     if ((!is_link_local && !is_multicast_link_local)
2522         || if_indextoname(static_cast<unsigned>(scope_id), if_name + 1) == 0)
2523 #if defined(BOOST_ASIO_HAS_SNPRINTF)
2524       snprintf(if_name + 1, sizeof(if_name) - 1, "%lu", scope_id);
2525 #else // defined(BOOST_ASIO_HAS_SNPRINTF)
2526       sprintf(if_name + 1, "%lu", scope_id);
2527 #endif // defined(BOOST_ASIO_HAS_SNPRINTF)
2528     strcat(dest, if_name);
2529   }
2530   return result;
2531 #endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
2532 }
2533 
2534 int inet_pton(int af, const char* src, void* dest,
2535     unsigned long* scope_id, boost::system::error_code& ec)
2536 {
2537   clear_last_error();
2538 #if defined(BOOST_ASIO_WINDOWS_RUNTIME)
2539   using namespace std; // For sscanf.
2540   unsigned char* bytes = static_cast<unsigned char*>(dest);
2541   if (af == BOOST_ASIO_OS_DEF(AF_INET))
2542   {
2543     unsigned int b0, b1, b2, b3;
2544     if (sscanf_s(src, "%u.%u.%u.%u", &b0, &b1, &b2, &b3) != 4)
2545     {
2546       ec = boost::asio::error::invalid_argument;
2547       return -1;
2548     }
2549     if (b0 > 255 || b1 > 255 || b2 > 255 || b3 > 255)
2550     {
2551       ec = boost::asio::error::invalid_argument;
2552       return -1;
2553     }
2554     bytes[0] = static_cast<unsigned char>(b0);
2555     bytes[1] = static_cast<unsigned char>(b1);
2556     bytes[2] = static_cast<unsigned char>(b2);
2557     bytes[3] = static_cast<unsigned char>(b3);
2558     boost::asio::error::clear(ec);
2559     return 1;
2560   }
2561   else if (af == BOOST_ASIO_OS_DEF(AF_INET6))
2562   {
2563     unsigned char* bytes = static_cast<unsigned char*>(dest);
2564     std::memset(bytes, 0, 16);
2565     unsigned char back_bytes[16] = { 0 };
2566     int num_front_bytes = 0, num_back_bytes = 0;
2567     const char* p = src;
2568 
2569     enum { fword, fcolon, bword, scope, done } state = fword;
2570     unsigned long current_word = 0;
2571     while (state != done)
2572     {
2573       if (current_word > 0xFFFF)
2574       {
2575         ec = boost::asio::error::invalid_argument;
2576         return -1;
2577       }
2578 
2579       switch (state)
2580       {
2581       case fword:
2582         if (*p >= '0' && *p <= '9')
2583           current_word = current_word * 16 + *p++ - '0';
2584         else if (*p >= 'a' && *p <= 'f')
2585           current_word = current_word * 16 + *p++ - 'a' + 10;
2586         else if (*p >= 'A' && *p <= 'F')
2587           current_word = current_word * 16 + *p++ - 'A' + 10;
2588         else
2589         {
2590           if (num_front_bytes == 16)
2591           {
2592             ec = boost::asio::error::invalid_argument;
2593             return -1;
2594           }
2595 
2596           bytes[num_front_bytes++] = (current_word >> 8) & 0xFF;
2597           bytes[num_front_bytes++] = current_word & 0xFF;
2598           current_word = 0;
2599 
2600           if (*p == ':')
2601             state = fcolon, ++p;
2602           else if (*p == '%')
2603             state = scope, ++p;
2604           else if (*p == 0)
2605             state = done;
2606           else
2607           {
2608             ec = boost::asio::error::invalid_argument;
2609             return -1;
2610           }
2611         }
2612         break;
2613 
2614       case fcolon:
2615         if (*p == ':')
2616           state = bword, ++p;
2617         else
2618           state = fword;
2619         break;
2620 
2621       case bword:
2622         if (*p >= '0' && *p <= '9')
2623           current_word = current_word * 16 + *p++ - '0';
2624         else if (*p >= 'a' && *p <= 'f')
2625           current_word = current_word * 16 + *p++ - 'a' + 10;
2626         else if (*p >= 'A' && *p <= 'F')
2627           current_word = current_word * 16 + *p++ - 'A' + 10;
2628         else
2629         {
2630           if (num_front_bytes + num_back_bytes == 16)
2631           {
2632             ec = boost::asio::error::invalid_argument;
2633             return -1;
2634           }
2635 
2636           back_bytes[num_back_bytes++] = (current_word >> 8) & 0xFF;
2637           back_bytes[num_back_bytes++] = current_word & 0xFF;
2638           current_word = 0;
2639 
2640           if (*p == ':')
2641             state = bword, ++p;
2642           else if (*p == '%')
2643             state = scope, ++p;
2644           else if (*p == 0)
2645             state = done;
2646           else
2647           {
2648             ec = boost::asio::error::invalid_argument;
2649             return -1;
2650           }
2651         }
2652         break;
2653 
2654       case scope:
2655         if (*p >= '0' && *p <= '9')
2656           current_word = current_word * 10 + *p++ - '0';
2657         else if (*p == 0)
2658           *scope_id = current_word, state = done;
2659         else
2660         {
2661           ec = boost::asio::error::invalid_argument;
2662           return -1;
2663         }
2664         break;
2665 
2666       default:
2667         break;
2668       }
2669     }
2670 
2671     for (int i = 0; i < num_back_bytes; ++i)
2672       bytes[16 - num_back_bytes + i] = back_bytes[i];
2673 
2674     boost::asio::error::clear(ec);
2675     return 1;
2676   }
2677   else
2678   {
2679     ec = boost::asio::error::address_family_not_supported;
2680     return -1;
2681   }
2682 #elif defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
2683   using namespace std; // For memcpy and strcmp.
2684 
2685   if (af != BOOST_ASIO_OS_DEF(AF_INET) && af != BOOST_ASIO_OS_DEF(AF_INET6))
2686   {
2687     ec = boost::asio::error::address_family_not_supported;
2688     return -1;
2689   }
2690 
2691   union
2692   {
2693     socket_addr_type base;
2694     sockaddr_storage_type storage;
2695     sockaddr_in4_type v4;
2696     sockaddr_in6_type v6;
2697   } address;
2698   int address_length = sizeof(sockaddr_storage_type);
2699 #if defined(BOOST_NO_ANSI_APIS) || (defined(_MSC_VER) && (_MSC_VER >= 1800))
2700   int num_wide_chars = static_cast<int>(strlen(src)) + 1;
2701   LPWSTR wide_buffer = (LPWSTR)_alloca(num_wide_chars * sizeof(WCHAR));
2702   ::MultiByteToWideChar(CP_ACP, 0, src, -1, wide_buffer, num_wide_chars);
2703   int result = ::WSAStringToAddressW(wide_buffer,
2704       af, 0, &address.base, &address_length);
2705   get_last_error(ec, true);
2706 #else
2707   int result = ::WSAStringToAddressA(const_cast<char*>(src),
2708       af, 0, &address.base, &address_length);
2709   get_last_error(ec, true);
2710 #endif
2711 
2712   if (af == BOOST_ASIO_OS_DEF(AF_INET))
2713   {
2714     if (result != socket_error_retval)
2715     {
2716       memcpy(dest, &address.v4.sin_addr, sizeof(in4_addr_type));
2717       boost::asio::error::clear(ec);
2718     }
2719     else if (strcmp(src, "255.255.255.255") == 0)
2720     {
2721       static_cast<in4_addr_type*>(dest)->s_addr = INADDR_NONE;
2722       boost::asio::error::clear(ec);
2723     }
2724   }
2725   else // AF_INET6
2726   {
2727     if (result != socket_error_retval)
2728     {
2729       memcpy(dest, &address.v6.sin6_addr, sizeof(in6_addr_type));
2730       if (scope_id)
2731         *scope_id = address.v6.sin6_scope_id;
2732       boost::asio::error::clear(ec);
2733     }
2734   }
2735 
2736   // Windows may not set an error code on failure.
2737   if (result == socket_error_retval && !ec)
2738     ec = boost::asio::error::invalid_argument;
2739 
2740   if (result != socket_error_retval)
2741     boost::asio::error::clear(ec);
2742 
2743   return result == socket_error_retval ? -1 : 1;
2744 #else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
2745   using namespace std; // For strchr, memcpy and atoi.
2746 
2747   // On some platforms, inet_pton fails if an address string contains a scope
2748   // id. Detect and remove the scope id before passing the string to inet_pton.
2749   const bool is_v6 = (af == BOOST_ASIO_OS_DEF(AF_INET6));
2750   const char* if_name = is_v6 ? strchr(src, '%') : 0;
2751   char src_buf[max_addr_v6_str_len + 1];
2752   const char* src_ptr = src;
2753   if (if_name != 0)
2754   {
2755     if (if_name - src > max_addr_v6_str_len)
2756     {
2757       ec = boost::asio::error::invalid_argument;
2758       return 0;
2759     }
2760     memcpy(src_buf, src, if_name - src);
2761     src_buf[if_name - src] = 0;
2762     src_ptr = src_buf;
2763   }
2764 
2765   int result = ::inet_pton(af, src_ptr, dest);
2766   get_last_error(ec, true);
2767   if (result <= 0 && !ec)
2768     ec = boost::asio::error::invalid_argument;
2769   if (result > 0 && is_v6 && scope_id)
2770   {
2771     using namespace std; // For strchr and atoi.
2772     *scope_id = 0;
2773     if (if_name != 0)
2774     {
2775       in6_addr_type* ipv6_address = static_cast<in6_addr_type*>(dest);
2776       bool is_link_local = ((ipv6_address->s6_addr[0] == 0xfe)
2777           && ((ipv6_address->s6_addr[1] & 0xc0) == 0x80));
2778       bool is_multicast_link_local = ((ipv6_address->s6_addr[0] == 0xff)
2779           && ((ipv6_address->s6_addr[1] & 0x0f) == 0x02));
2780       if (is_link_local || is_multicast_link_local)
2781         *scope_id = if_nametoindex(if_name + 1);
2782       if (*scope_id == 0)
2783         *scope_id = atoi(if_name + 1);
2784     }
2785   }
2786   return result;
2787 #endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
2788 }
2789 
2790 int gethostname(char* name, int namelen, boost::system::error_code& ec)
2791 {
2792 #if defined(BOOST_ASIO_WINDOWS_RUNTIME)
2793   try
2794   {
2795     using namespace Windows::Foundation::Collections;
2796     using namespace Windows::Networking;
2797     using namespace Windows::Networking::Connectivity;
2798     IVectorView<HostName^>^ hostnames = NetworkInformation::GetHostNames();
2799     for (unsigned i = 0; i < hostnames->Size; ++i)
2800     {
2801       HostName^ hostname = hostnames->GetAt(i);
2802       if (hostname->Type == HostNameType::DomainName)
2803       {
2804         std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
2805         std::string raw_name = converter.to_bytes(hostname->RawName->Data());
2806         if (namelen > 0 && raw_name.size() < static_cast<std::size_t>(namelen))
2807         {
2808           strcpy_s(name, namelen, raw_name.c_str());
2809           return 0;
2810         }
2811       }
2812     }
2813     return -1;
2814   }
2815   catch (Platform::Exception^ e)
2816   {
2817     ec = boost::system::error_code(e->HResult,
2818         boost::system::system_category());
2819     return -1;
2820   }
2821 #else // defined(BOOST_ASIO_WINDOWS_RUNTIME)
2822   int result = ::gethostname(name, namelen);
2823   get_last_error(ec, result != 0);
2824   return result;
2825 #endif // defined(BOOST_ASIO_WINDOWS_RUNTIME)
2826 }
2827 
2828 #if !defined(BOOST_ASIO_WINDOWS_RUNTIME)
2829 
2830 #if !defined(BOOST_ASIO_HAS_GETADDRINFO)
2831 
2832 // The following functions are only needed for emulation of getaddrinfo and
2833 // getnameinfo.
2834 
2835 inline boost::system::error_code translate_netdb_error(int error)
2836 {
2837   switch (error)
2838   {
2839   case 0:
2840     return boost::system::error_code();
2841   case HOST_NOT_FOUND:
2842     return boost::asio::error::host_not_found;
2843   case TRY_AGAIN:
2844     return boost::asio::error::host_not_found_try_again;
2845   case NO_RECOVERY:
2846     return boost::asio::error::no_recovery;
2847   case NO_DATA:
2848     return boost::asio::error::no_data;
2849   default:
2850     BOOST_ASIO_ASSERT(false);
2851     return boost::asio::error::invalid_argument;
2852   }
2853 }
2854 
2855 inline hostent* gethostbyaddr(const char* addr, int length, int af,
2856     hostent* result, char* buffer, int buflength, boost::system::error_code& ec)
2857 {
2858 #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
2859   (void)(buffer);
2860   (void)(buflength);
2861   hostent* retval = ::gethostbyaddr(addr, length, af);
2862   get_last_error(ec, !retval);
2863   if (!retval)
2864     return 0;
2865   *result = *retval;
2866   return retval;
2867 #elif defined(__sun) || defined(__QNX__)
2868   int error = 0;
2869   hostent* retval = ::gethostbyaddr_r(addr, length,
2870       af, result, buffer, buflength, &error);
2871   get_last_error(ec, !retval);
2872   if (error)
2873     ec = translate_netdb_error(error);
2874   return retval;
2875 #elif defined(__MACH__) && defined(__APPLE__)
2876   (void)(buffer);
2877   (void)(buflength);
2878   int error = 0;
2879   hostent* retval = ::getipnodebyaddr(addr, length, af, &error);
2880   get_last_error(ec, !retval);
2881   if (error)
2882     ec = translate_netdb_error(error);
2883   if (!retval)
2884     return 0;
2885   *result = *retval;
2886   return retval;
2887 #else
2888   hostent* retval = 0;
2889   int error = 0;
2890   clear_last_error();
2891   ::gethostbyaddr_r(addr, length, af, result,
2892       buffer, buflength, &retval, &error);
2893   get_last_error(ec, true);
2894   if (error)
2895     ec = translate_netdb_error(error);
2896   return retval;
2897 #endif
2898 }
2899 
2900 inline hostent* gethostbyname(const char* name, int af, struct hostent* result,
2901     char* buffer, int buflength, int ai_flags, boost::system::error_code& ec)
2902 {
2903 #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
2904   (void)(buffer);
2905   (void)(buflength);
2906   (void)(ai_flags);
2907   if (af != BOOST_ASIO_OS_DEF(AF_INET))
2908   {
2909     ec = boost::asio::error::address_family_not_supported;
2910     return 0;
2911   }
2912   hostent* retval = ::gethostbyname(name);
2913   get_last_error(ec, !retval);
2914   if (!retval)
2915     return 0;
2916   *result = *retval;
2917   return result;
2918 #elif defined(__sun) || defined(__QNX__)
2919   (void)(ai_flags);
2920   if (af != BOOST_ASIO_OS_DEF(AF_INET))
2921   {
2922     ec = boost::asio::error::address_family_not_supported;
2923     return 0;
2924   }
2925   int error = 0;
2926   hostent* retval = ::gethostbyname_r(name, result, buffer, buflength, &error);
2927   get_last_error(ec, !retval);
2928   if (error)
2929     ec = translate_netdb_error(error);
2930   return retval;
2931 #elif defined(__MACH__) && defined(__APPLE__)
2932   (void)(buffer);
2933   (void)(buflength);
2934   int error = 0;
2935   hostent* retval = ::getipnodebyname(name, af, ai_flags, &error);
2936   get_last_error(ec, !retval);
2937   if (error)
2938     ec = translate_netdb_error(error);
2939   if (!retval)
2940     return 0;
2941   *result = *retval;
2942   return retval;
2943 #else
2944   (void)(ai_flags);
2945   if (af != BOOST_ASIO_OS_DEF(AF_INET))
2946   {
2947     ec = boost::asio::error::address_family_not_supported;
2948     return 0;
2949   }
2950   hostent* retval = 0;
2951   int error = 0;
2952   clear_last_error();
2953   ::gethostbyname_r(name, result, buffer, buflength, &retval, &error);
2954   get_last_error(ec, true);
2955   if (error)
2956     ec = translate_netdb_error(error);
2957   return retval;
2958 #endif
2959 }
2960 
2961 inline void freehostent(hostent* h)
2962 {
2963 #if defined(__MACH__) && defined(__APPLE__)
2964   if (h)
2965     ::freehostent(h);
2966 #else
2967   (void)(h);
2968 #endif
2969 }
2970 
2971 // Emulation of getaddrinfo based on implementation in:
2972 // Stevens, W. R., UNIX Network Programming Vol. 1, 2nd Ed., Prentice-Hall 1998.
2973 
2974 struct gai_search
2975 {
2976   const char* host;
2977   int family;
2978 };
2979 
2980 inline int gai_nsearch(const char* host,
2981     const addrinfo_type* hints, gai_search (&search)[2])
2982 {
2983   int search_count = 0;
2984   if (host == 0 || host[0] == '\0')
2985   {
2986     if (hints->ai_flags & AI_PASSIVE)
2987     {
2988       // No host and AI_PASSIVE implies wildcard bind.
2989       switch (hints->ai_family)
2990       {
2991       case BOOST_ASIO_OS_DEF(AF_INET):
2992         search[search_count].host = "0.0.0.0";
2993         search[search_count].family = BOOST_ASIO_OS_DEF(AF_INET);
2994         ++search_count;
2995         break;
2996       case BOOST_ASIO_OS_DEF(AF_INET6):
2997         search[search_count].host = "0::0";
2998         search[search_count].family = BOOST_ASIO_OS_DEF(AF_INET6);
2999         ++search_count;
3000         break;
3001       case BOOST_ASIO_OS_DEF(AF_UNSPEC):
3002         search[search_count].host = "0::0";
3003         search[search_count].family = BOOST_ASIO_OS_DEF(AF_INET6);
3004         ++search_count;
3005         search[search_count].host = "0.0.0.0";
3006         search[search_count].family = BOOST_ASIO_OS_DEF(AF_INET);
3007         ++search_count;
3008         break;
3009       default:
3010         break;
3011       }
3012     }
3013     else
3014     {
3015       // No host and not AI_PASSIVE means connect to local host.
3016       switch (hints->ai_family)
3017       {
3018       case BOOST_ASIO_OS_DEF(AF_INET):
3019         search[search_count].host = "localhost";
3020         search[search_count].family = BOOST_ASIO_OS_DEF(AF_INET);
3021         ++search_count;
3022         break;
3023       case BOOST_ASIO_OS_DEF(AF_INET6):
3024         search[search_count].host = "localhost";
3025         search[search_count].family = BOOST_ASIO_OS_DEF(AF_INET6);
3026         ++search_count;
3027         break;
3028       case BOOST_ASIO_OS_DEF(AF_UNSPEC):
3029         search[search_count].host = "localhost";
3030         search[search_count].family = BOOST_ASIO_OS_DEF(AF_INET6);
3031         ++search_count;
3032         search[search_count].host = "localhost";
3033         search[search_count].family = BOOST_ASIO_OS_DEF(AF_INET);
3034         ++search_count;
3035         break;
3036       default:
3037         break;
3038       }
3039     }
3040   }
3041   else
3042   {
3043     // Host is specified.
3044     switch (hints->ai_family)
3045     {
3046     case BOOST_ASIO_OS_DEF(AF_INET):
3047       search[search_count].host = host;
3048       search[search_count].family = BOOST_ASIO_OS_DEF(AF_INET);
3049       ++search_count;
3050       break;
3051     case BOOST_ASIO_OS_DEF(AF_INET6):
3052       search[search_count].host = host;
3053       search[search_count].family = BOOST_ASIO_OS_DEF(AF_INET6);
3054       ++search_count;
3055       break;
3056     case BOOST_ASIO_OS_DEF(AF_UNSPEC):
3057       search[search_count].host = host;
3058       search[search_count].family = BOOST_ASIO_OS_DEF(AF_INET6);
3059       ++search_count;
3060       search[search_count].host = host;
3061       search[search_count].family = BOOST_ASIO_OS_DEF(AF_INET);
3062       ++search_count;
3063       break;
3064     default:
3065       break;
3066     }
3067   }
3068   return search_count;
3069 }
3070 
3071 template <typename T>
3072 inline T* gai_alloc(std::size_t size = sizeof(T))
3073 {
3074   using namespace std;
3075   T* p = static_cast<T*>(::operator new(size, std::nothrow));
3076   if (p)
3077     memset(p, 0, size);
3078   return p;
3079 }
3080 
3081 inline void gai_free(void* p)
3082 {
3083   ::operator delete(p);
3084 }
3085 
3086 inline void gai_strcpy(char* target, const char* source, std::size_t max_size)
3087 {
3088   using namespace std;
3089 #if defined(BOOST_ASIO_HAS_SECURE_RTL)
3090   strcpy_s(target, max_size, source);
3091 #else // defined(BOOST_ASIO_HAS_SECURE_RTL)
3092   *target = 0;
3093   if (max_size > 0)
3094     strncat(target, source, max_size - 1);
3095 #endif // defined(BOOST_ASIO_HAS_SECURE_RTL)
3096 }
3097 
3098 enum { gai_clone_flag = 1 << 30 };
3099 
3100 inline int gai_aistruct(addrinfo_type*** next, const addrinfo_type* hints,
3101     const void* addr, int family)
3102 {
3103   using namespace std;
3104 
3105   addrinfo_type* ai = gai_alloc<addrinfo_type>();
3106   if (ai == 0)
3107     return EAI_MEMORY;
3108 
3109   ai->ai_next = 0;
3110   **next = ai;
3111   *next = &ai->ai_next;
3112 
3113   ai->ai_canonname = 0;
3114   ai->ai_socktype = hints->ai_socktype;
3115   if (ai->ai_socktype == 0)
3116     ai->ai_flags |= gai_clone_flag;
3117   ai->ai_protocol = hints->ai_protocol;
3118   ai->ai_family = family;
3119 
3120   switch (ai->ai_family)
3121   {
3122   case BOOST_ASIO_OS_DEF(AF_INET):
3123     {
3124       sockaddr_in4_type* sinptr = gai_alloc<sockaddr_in4_type>();
3125       if (sinptr == 0)
3126         return EAI_MEMORY;
3127       sinptr->sin_family = BOOST_ASIO_OS_DEF(AF_INET);
3128       memcpy(&sinptr->sin_addr, addr, sizeof(in4_addr_type));
3129       ai->ai_addr = reinterpret_cast<sockaddr*>(sinptr);
3130       ai->ai_addrlen = sizeof(sockaddr_in4_type);
3131       break;
3132     }
3133   case BOOST_ASIO_OS_DEF(AF_INET6):
3134     {
3135       sockaddr_in6_type* sin6ptr = gai_alloc<sockaddr_in6_type>();
3136       if (sin6ptr == 0)
3137         return EAI_MEMORY;
3138       sin6ptr->sin6_family = BOOST_ASIO_OS_DEF(AF_INET6);
3139       memcpy(&sin6ptr->sin6_addr, addr, sizeof(in6_addr_type));
3140       ai->ai_addr = reinterpret_cast<sockaddr*>(sin6ptr);
3141       ai->ai_addrlen = sizeof(sockaddr_in6_type);
3142       break;
3143     }
3144   default:
3145     break;
3146   }
3147 
3148   return 0;
3149 }
3150 
3151 inline addrinfo_type* gai_clone(addrinfo_type* ai)
3152 {
3153   using namespace std;
3154 
3155   addrinfo_type* new_ai = gai_alloc<addrinfo_type>();
3156   if (new_ai == 0)
3157     return new_ai;
3158 
3159   new_ai->ai_next = ai->ai_next;
3160   ai->ai_next = new_ai;
3161 
3162   new_ai->ai_flags = 0;
3163   new_ai->ai_family = ai->ai_family;
3164   new_ai->ai_socktype = ai->ai_socktype;
3165   new_ai->ai_protocol = ai->ai_protocol;
3166   new_ai->ai_canonname = 0;
3167   new_ai->ai_addrlen = ai->ai_addrlen;
3168   new_ai->ai_addr = gai_alloc<sockaddr>(ai->ai_addrlen);
3169   memcpy(new_ai->ai_addr, ai->ai_addr, ai->ai_addrlen);
3170 
3171   return new_ai;
3172 }
3173 
3174 inline int gai_port(addrinfo_type* aihead, int port, int socktype)
3175 {
3176   int num_found = 0;
3177 
3178   for (addrinfo_type* ai = aihead; ai; ai = ai->ai_next)
3179   {
3180     if (ai->ai_flags & gai_clone_flag)
3181     {
3182       if (ai->ai_socktype != 0)
3183       {
3184         ai = gai_clone(ai);
3185         if (ai == 0)
3186           return -1;
3187         // ai now points to newly cloned entry.
3188       }
3189     }
3190     else if (ai->ai_socktype != socktype)
3191     {
3192       // Ignore if mismatch on socket type.
3193       continue;
3194     }
3195 
3196     ai->ai_socktype = socktype;
3197 
3198     switch (ai->ai_family)
3199     {
3200     case BOOST_ASIO_OS_DEF(AF_INET):
3201       {
3202         sockaddr_in4_type* sinptr =
3203           reinterpret_cast<sockaddr_in4_type*>(ai->ai_addr);
3204         sinptr->sin_port = port;
3205         ++num_found;
3206         break;
3207       }
3208     case BOOST_ASIO_OS_DEF(AF_INET6):
3209       {
3210         sockaddr_in6_type* sin6ptr =
3211           reinterpret_cast<sockaddr_in6_type*>(ai->ai_addr);
3212         sin6ptr->sin6_port = port;
3213         ++num_found;
3214         break;
3215       }
3216     default:
3217       break;
3218     }
3219   }
3220 
3221   return num_found;
3222 }
3223 
3224 inline int gai_serv(addrinfo_type* aihead,
3225     const addrinfo_type* hints, const char* serv)
3226 {
3227   using namespace std;
3228 
3229   int num_found = 0;
3230 
3231   if (
3232 #if defined(AI_NUMERICSERV)
3233       (hints->ai_flags & AI_NUMERICSERV) ||
3234 #endif
3235       isdigit(static_cast<unsigned char>(serv[0])))
3236   {
3237     int port = htons(atoi(serv));
3238     if (hints->ai_socktype)
3239     {
3240       // Caller specifies socket type.
3241       int rc = gai_port(aihead, port, hints->ai_socktype);
3242       if (rc < 0)
3243         return EAI_MEMORY;
3244       num_found += rc;
3245     }
3246     else
3247     {
3248       // Caller does not specify socket type.
3249       int rc = gai_port(aihead, port, SOCK_STREAM);
3250       if (rc < 0)
3251         return EAI_MEMORY;
3252       num_found += rc;
3253       rc = gai_port(aihead, port, SOCK_DGRAM);
3254       if (rc < 0)
3255         return EAI_MEMORY;
3256       num_found += rc;
3257     }
3258   }
3259   else
3260   {
3261     // Try service name with TCP first, then UDP.
3262     if (hints->ai_socktype == 0 || hints->ai_socktype == SOCK_STREAM)
3263     {
3264       servent* sptr = getservbyname(serv, "tcp");
3265       if (sptr != 0)
3266       {
3267         int rc = gai_port(aihead, sptr->s_port, SOCK_STREAM);
3268         if (rc < 0)
3269           return EAI_MEMORY;
3270         num_found += rc;
3271       }
3272     }
3273     if (hints->ai_socktype == 0 || hints->ai_socktype == SOCK_DGRAM)
3274     {
3275       servent* sptr = getservbyname(serv, "udp");
3276       if (sptr != 0)
3277       {
3278         int rc = gai_port(aihead, sptr->s_port, SOCK_DGRAM);
3279         if (rc < 0)
3280           return EAI_MEMORY;
3281         num_found += rc;
3282       }
3283     }
3284   }
3285 
3286   if (num_found == 0)
3287   {
3288     if (hints->ai_socktype == 0)
3289     {
3290       // All calls to getservbyname() failed.
3291       return EAI_NONAME;
3292     }
3293     else
3294     {
3295       // Service not supported for socket type.
3296       return EAI_SERVICE;
3297     }
3298   }
3299 
3300   return 0;
3301 }
3302 
3303 inline int gai_echeck(const char* host, const char* service,
3304     int flags, int family, int socktype, int protocol)
3305 {
3306   (void)(flags);
3307   (void)(protocol);
3308 
3309   // Host or service must be specified.
3310   if (host == 0 || host[0] == '\0')
3311     if (service == 0 || service[0] == '\0')
3312       return EAI_NONAME;
3313 
3314   // Check combination of family and socket type.
3315   switch (family)
3316   {
3317   case BOOST_ASIO_OS_DEF(AF_UNSPEC):
3318     break;
3319   case BOOST_ASIO_OS_DEF(AF_INET):
3320   case BOOST_ASIO_OS_DEF(AF_INET6):
3321     if (service != 0 && service[0] != '\0')
3322       if (socktype != 0 && socktype != SOCK_STREAM && socktype != SOCK_DGRAM)
3323         return EAI_SOCKTYPE;
3324     break;
3325   default:
3326     return EAI_FAMILY;
3327   }
3328 
3329   return 0;
3330 }
3331 
3332 inline void freeaddrinfo_emulation(addrinfo_type* aihead)
3333 {
3334   addrinfo_type* ai = aihead;
3335   while (ai)
3336   {
3337     gai_free(ai->ai_addr);
3338     gai_free(ai->ai_canonname);
3339     addrinfo_type* ainext = ai->ai_next;
3340     gai_free(ai);
3341     ai = ainext;
3342   }
3343 }
3344 
3345 inline int getaddrinfo_emulation(const char* host, const char* service,
3346     const addrinfo_type* hintsp, addrinfo_type** result)
3347 {
3348   // Set up linked list of addrinfo structures.
3349   addrinfo_type* aihead = 0;
3350   addrinfo_type** ainext = &aihead;
3351   char* canon = 0;
3352 
3353   // Supply default hints if not specified by caller.
3354   addrinfo_type hints = addrinfo_type();
3355   hints.ai_family = BOOST_ASIO_OS_DEF(AF_UNSPEC);
3356   if (hintsp)
3357     hints = *hintsp;
3358 
3359   // If the resolution is not specifically for AF_INET6, remove the AI_V4MAPPED
3360   // and AI_ALL flags.
3361 #if defined(AI_V4MAPPED)
3362   if (hints.ai_family != BOOST_ASIO_OS_DEF(AF_INET6))
3363     hints.ai_flags &= ~AI_V4MAPPED;
3364 #endif
3365 #if defined(AI_ALL)
3366   if (hints.ai_family != BOOST_ASIO_OS_DEF(AF_INET6))
3367     hints.ai_flags &= ~AI_ALL;
3368 #endif
3369 
3370   // Basic error checking.
3371   int rc = gai_echeck(host, service, hints.ai_flags, hints.ai_family,
3372       hints.ai_socktype, hints.ai_protocol);
3373   if (rc != 0)
3374   {
3375     freeaddrinfo_emulation(aihead);
3376     return rc;
3377   }
3378 
3379   gai_search search[2];
3380   int search_count = gai_nsearch(host, &hints, search);
3381   for (gai_search* sptr = search; sptr < search + search_count; ++sptr)
3382   {
3383     // Check for IPv4 dotted decimal string.
3384     in4_addr_type inaddr;
3385     boost::system::error_code ec;
3386     if (socket_ops::inet_pton(BOOST_ASIO_OS_DEF(AF_INET),
3387           sptr->host, &inaddr, 0, ec) == 1)
3388     {
3389       if (hints.ai_family != BOOST_ASIO_OS_DEF(AF_UNSPEC)
3390           && hints.ai_family != BOOST_ASIO_OS_DEF(AF_INET))
3391       {
3392         freeaddrinfo_emulation(aihead);
3393         gai_free(canon);
3394         return EAI_FAMILY;
3395       }
3396       if (sptr->family == BOOST_ASIO_OS_DEF(AF_INET))
3397       {
3398         rc = gai_aistruct(&ainext, &hints, &inaddr, BOOST_ASIO_OS_DEF(AF_INET));
3399         if (rc != 0)
3400         {
3401           freeaddrinfo_emulation(aihead);
3402           gai_free(canon);
3403           return rc;
3404         }
3405       }
3406       continue;
3407     }
3408 
3409     // Check for IPv6 hex string.
3410     in6_addr_type in6addr;
3411     if (socket_ops::inet_pton(BOOST_ASIO_OS_DEF(AF_INET6),
3412           sptr->host, &in6addr, 0, ec) == 1)
3413     {
3414       if (hints.ai_family != BOOST_ASIO_OS_DEF(AF_UNSPEC)
3415           && hints.ai_family != BOOST_ASIO_OS_DEF(AF_INET6))
3416       {
3417         freeaddrinfo_emulation(aihead);
3418         gai_free(canon);
3419         return EAI_FAMILY;
3420       }
3421       if (sptr->family == BOOST_ASIO_OS_DEF(AF_INET6))
3422       {
3423         rc = gai_aistruct(&ainext, &hints, &in6addr,
3424             BOOST_ASIO_OS_DEF(AF_INET6));
3425         if (rc != 0)
3426         {
3427           freeaddrinfo_emulation(aihead);
3428           gai_free(canon);
3429           return rc;
3430         }
3431       }
3432       continue;
3433     }
3434 
3435     // Look up hostname.
3436     hostent hent;
3437     char hbuf[8192] = "";
3438     hostent* hptr = socket_ops::gethostbyname(sptr->host,
3439         sptr->family, &hent, hbuf, sizeof(hbuf), hints.ai_flags, ec);
3440     if (hptr == 0)
3441     {
3442       if (search_count == 2)
3443       {
3444         // Failure is OK if there are multiple searches.
3445         continue;
3446       }
3447       freeaddrinfo_emulation(aihead);
3448       gai_free(canon);
3449       if (ec == boost::asio::error::host_not_found)
3450         return EAI_NONAME;
3451       if (ec == boost::asio::error::host_not_found_try_again)
3452         return EAI_AGAIN;
3453       if (ec == boost::asio::error::no_recovery)
3454         return EAI_FAIL;
3455       if (ec == boost::asio::error::no_data)
3456         return EAI_NONAME;
3457       return EAI_NONAME;
3458     }
3459 
3460     // Check for address family mismatch if one was specified.
3461     if (hints.ai_family != BOOST_ASIO_OS_DEF(AF_UNSPEC)
3462         && hints.ai_family != hptr->h_addrtype)
3463     {
3464       freeaddrinfo_emulation(aihead);
3465       gai_free(canon);
3466       socket_ops::freehostent(hptr);
3467       return EAI_FAMILY;
3468     }
3469 
3470     // Save canonical name first time.
3471     if (host != 0 && host[0] != '\0' && hptr->h_name && hptr->h_name[0]
3472         && (hints.ai_flags & AI_CANONNAME) && canon == 0)
3473     {
3474       std::size_t canon_len = strlen(hptr->h_name) + 1;
3475       canon = gai_alloc<char>(canon_len);
3476       if (canon == 0)
3477       {
3478         freeaddrinfo_emulation(aihead);
3479         socket_ops::freehostent(hptr);
3480         return EAI_MEMORY;
3481       }
3482       gai_strcpy(canon, hptr->h_name, canon_len);
3483     }
3484 
3485     // Create an addrinfo structure for each returned address.
3486     for (char** ap = hptr->h_addr_list; *ap; ++ap)
3487     {
3488       rc = gai_aistruct(&ainext, &hints, *ap, hptr->h_addrtype);
3489       if (rc != 0)
3490       {
3491         freeaddrinfo_emulation(aihead);
3492         gai_free(canon);
3493         socket_ops::freehostent(hptr);
3494         return EAI_FAMILY;
3495       }
3496     }
3497 
3498     socket_ops::freehostent(hptr);
3499   }
3500 
3501   // Check if we found anything.
3502   if (aihead == 0)
3503   {
3504     gai_free(canon);
3505     return EAI_NONAME;
3506   }
3507 
3508   // Return canonical name in first entry.
3509   if (host != 0 && host[0] != '\0' && (hints.ai_flags & AI_CANONNAME))
3510   {
3511     if (canon)
3512     {
3513       aihead->ai_canonname = canon;
3514       canon = 0;
3515     }
3516     else
3517     {
3518       std::size_t canonname_len = strlen(search[0].host) + 1;
3519       aihead->ai_canonname = gai_alloc<char>(canonname_len);
3520       if (aihead->ai_canonname == 0)
3521       {
3522         freeaddrinfo_emulation(aihead);
3523         return EAI_MEMORY;
3524       }
3525       gai_strcpy(aihead->ai_canonname, search[0].host, canonname_len);
3526     }
3527   }
3528   gai_free(canon);
3529 
3530   // Process the service name.
3531   if (service != 0 && service[0] != '\0')
3532   {
3533     rc = gai_serv(aihead, &hints, service);
3534     if (rc != 0)
3535     {
3536       freeaddrinfo_emulation(aihead);
3537       return rc;
3538     }
3539   }
3540 
3541   // Return result to caller.
3542   *result = aihead;
3543   return 0;
3544 }
3545 
3546 inline boost::system::error_code getnameinfo_emulation(
3547     const socket_addr_type* sa, std::size_t salen, char* host,
3548     std::size_t hostlen, char* serv, std::size_t servlen, int flags,
3549     boost::system::error_code& ec)
3550 {
3551   using namespace std;
3552 
3553   const char* addr;
3554   size_t addr_len;
3555   unsigned short port;
3556   switch (sa->sa_family)
3557   {
3558   case BOOST_ASIO_OS_DEF(AF_INET):
3559     if (salen != sizeof(sockaddr_in4_type))
3560     {
3561       return ec = boost::asio::error::invalid_argument;
3562     }
3563     addr = reinterpret_cast<const char*>(
3564         &reinterpret_cast<const sockaddr_in4_type*>(sa)->sin_addr);
3565     addr_len = sizeof(in4_addr_type);
3566     port = reinterpret_cast<const sockaddr_in4_type*>(sa)->sin_port;
3567     break;
3568   case BOOST_ASIO_OS_DEF(AF_INET6):
3569     if (salen != sizeof(sockaddr_in6_type))
3570     {
3571       return ec = boost::asio::error::invalid_argument;
3572     }
3573     addr = reinterpret_cast<const char*>(
3574         &reinterpret_cast<const sockaddr_in6_type*>(sa)->sin6_addr);
3575     addr_len = sizeof(in6_addr_type);
3576     port = reinterpret_cast<const sockaddr_in6_type*>(sa)->sin6_port;
3577     break;
3578   default:
3579     return ec = boost::asio::error::address_family_not_supported;
3580   }
3581 
3582   if (host && hostlen > 0)
3583   {
3584     if (flags & NI_NUMERICHOST)
3585     {
3586       if (socket_ops::inet_ntop(sa->sa_family, addr, host, hostlen, 0, ec) == 0)
3587       {
3588         return ec;
3589       }
3590     }
3591     else
3592     {
3593       hostent hent;
3594       char hbuf[8192] = "";
3595       hostent* hptr = socket_ops::gethostbyaddr(addr,
3596           static_cast<int>(addr_len), sa->sa_family,
3597           &hent, hbuf, sizeof(hbuf), ec);
3598       if (hptr && hptr->h_name && hptr->h_name[0] != '\0')
3599       {
3600         if (flags & NI_NOFQDN)
3601         {
3602           char* dot = strchr(hptr->h_name, '.');
3603           if (dot)
3604           {
3605             *dot = 0;
3606           }
3607         }
3608         gai_strcpy(host, hptr->h_name, hostlen);
3609         socket_ops::freehostent(hptr);
3610       }
3611       else
3612       {
3613         socket_ops::freehostent(hptr);
3614         if (flags & NI_NAMEREQD)
3615         {
3616           return ec = boost::asio::error::host_not_found;
3617         }
3618         if (socket_ops::inet_ntop(sa->sa_family,
3619               addr, host, hostlen, 0, ec) == 0)
3620         {
3621           return ec;
3622         }
3623       }
3624     }
3625   }
3626 
3627   if (serv && servlen > 0)
3628   {
3629     if (flags & NI_NUMERICSERV)
3630     {
3631       if (servlen < 6)
3632       {
3633         return ec = boost::asio::error::no_buffer_space;
3634       }
3635 #if defined(BOOST_ASIO_HAS_SNPRINTF)
3636       snprintf(serv, servlen, "%u", ntohs(port));
3637 #elif defined(BOOST_ASIO_HAS_SECURE_RTL)
3638       sprintf_s(serv, servlen, "%u", ntohs(port));
3639 #else // defined(BOOST_ASIO_HAS_SECURE_RTL)
3640       sprintf(serv, "%u", ntohs(port));
3641 #endif // defined(BOOST_ASIO_HAS_SECURE_RTL)
3642     }
3643     else
3644     {
3645 #if defined(BOOST_ASIO_HAS_PTHREADS)
3646       static ::pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
3647       ::pthread_mutex_lock(&mutex);
3648 #endif // defined(BOOST_ASIO_HAS_PTHREADS)
3649       servent* sptr = ::getservbyport(port, (flags & NI_DGRAM) ? "udp" : 0);
3650       if (sptr && sptr->s_name && sptr->s_name[0] != '\0')
3651       {
3652         gai_strcpy(serv, sptr->s_name, servlen);
3653       }
3654       else
3655       {
3656         if (servlen < 6)
3657         {
3658           return ec = boost::asio::error::no_buffer_space;
3659         }
3660 #if defined(BOOST_ASIO_HAS_SNPRINTF)
3661         snprintf(serv, servlen, "%u", ntohs(port));
3662 #elif defined(BOOST_ASIO_HAS_SECURE_RTL)
3663         sprintf_s(serv, servlen, "%u", ntohs(port));
3664 #else // defined(BOOST_ASIO_HAS_SECURE_RTL)
3665         sprintf(serv, "%u", ntohs(port));
3666 #endif // defined(BOOST_ASIO_HAS_SECURE_RTL)
3667       }
3668 #if defined(BOOST_ASIO_HAS_PTHREADS)
3669       ::pthread_mutex_unlock(&mutex);
3670 #endif // defined(BOOST_ASIO_HAS_PTHREADS)
3671     }
3672   }
3673 
3674   boost::asio::error::clear(ec);
3675   return ec;
3676 }
3677 
3678 #endif // !defined(BOOST_ASIO_HAS_GETADDRINFO)
3679 
3680 inline boost::system::error_code translate_addrinfo_error(int error)
3681 {
3682   switch (error)
3683   {
3684   case 0:
3685     return boost::system::error_code();
3686   case EAI_AGAIN:
3687     return boost::asio::error::host_not_found_try_again;
3688   case EAI_BADFLAGS:
3689     return boost::asio::error::invalid_argument;
3690   case EAI_FAIL:
3691     return boost::asio::error::no_recovery;
3692   case EAI_FAMILY:
3693     return boost::asio::error::address_family_not_supported;
3694   case EAI_MEMORY:
3695     return boost::asio::error::no_memory;
3696   case EAI_NONAME:
3697 #if defined(EAI_ADDRFAMILY)
3698   case EAI_ADDRFAMILY:
3699 #endif
3700 #if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
3701   case EAI_NODATA:
3702 #endif
3703     return boost::asio::error::host_not_found;
3704   case EAI_SERVICE:
3705     return boost::asio::error::service_not_found;
3706   case EAI_SOCKTYPE:
3707     return boost::asio::error::socket_type_not_supported;
3708   default: // Possibly the non-portable EAI_SYSTEM.
3709 #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
3710     return boost::system::error_code(
3711         WSAGetLastError(), boost::asio::error::get_system_category());
3712 #else
3713     return boost::system::error_code(
3714         errno, boost::asio::error::get_system_category());
3715 #endif
3716   }
3717 }
3718 
3719 boost::system::error_code getaddrinfo(const char* host,
3720     const char* service, const addrinfo_type& hints,
3721     addrinfo_type** result, boost::system::error_code& ec)
3722 {
3723   host = (host && *host) ? host : 0;
3724   service = (service && *service) ? service : 0;
3725   clear_last_error();
3726 #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
3727 # if defined(BOOST_ASIO_HAS_GETADDRINFO)
3728   // Building for Windows XP, Windows Server 2003, or later.
3729   int error = ::getaddrinfo(host, service, &hints, result);
3730   return ec = translate_addrinfo_error(error);
3731 # else
3732   // Building for Windows 2000 or earlier.
3733   typedef int (WSAAPI *gai_t)(const char*,
3734       const char*, const addrinfo_type*, addrinfo_type**);
3735   if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32"))
3736   {
3737     if (gai_t gai = (gai_t)::GetProcAddress(winsock_module, "getaddrinfo"))
3738     {
3739       int error = gai(host, service, &hints, result);
3740       return ec = translate_addrinfo_error(error);
3741     }
3742   }
3743   int error = getaddrinfo_emulation(host, service, &hints, result);
3744   return ec = translate_addrinfo_error(error);
3745 # endif
3746 #elif !defined(BOOST_ASIO_HAS_GETADDRINFO)
3747   int error = getaddrinfo_emulation(host, service, &hints, result);
3748   return ec = translate_addrinfo_error(error);
3749 #else
3750   int error = ::getaddrinfo(host, service, &hints, result);
3751 #if defined(__MACH__) && defined(__APPLE__)
3752   using namespace std; // For isdigit and atoi.
3753   if (error == 0 && service && isdigit(static_cast<unsigned char>(service[0])))
3754   {
3755     u_short_type port = host_to_network_short(atoi(service));
3756     for (addrinfo_type* ai = *result; ai; ai = ai->ai_next)
3757     {
3758       switch (ai->ai_family)
3759       {
3760       case BOOST_ASIO_OS_DEF(AF_INET):
3761         {
3762           sockaddr_in4_type* sinptr =
3763             reinterpret_cast<sockaddr_in4_type*>(ai->ai_addr);
3764           if (sinptr->sin_port == 0)
3765             sinptr->sin_port = port;
3766           break;
3767         }
3768       case BOOST_ASIO_OS_DEF(AF_INET6):
3769         {
3770           sockaddr_in6_type* sin6ptr =
3771             reinterpret_cast<sockaddr_in6_type*>(ai->ai_addr);
3772           if (sin6ptr->sin6_port == 0)
3773             sin6ptr->sin6_port = port;
3774           break;
3775         }
3776       default:
3777         break;
3778       }
3779     }
3780   }
3781 #endif
3782   return ec = translate_addrinfo_error(error);
3783 #endif
3784 }
3785 
3786 boost::system::error_code background_getaddrinfo(
3787     const weak_cancel_token_type& cancel_token, const char* host,
3788     const char* service, const addrinfo_type& hints,
3789     addrinfo_type** result, boost::system::error_code& ec)
3790 {
3791   if (cancel_token.expired())
3792     ec = boost::asio::error::operation_aborted;
3793   else
3794     socket_ops::getaddrinfo(host, service, hints, result, ec);
3795   return ec;
3796 }
3797 
3798 void freeaddrinfo(addrinfo_type* ai)
3799 {
3800 #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
3801 # if defined(BOOST_ASIO_HAS_GETADDRINFO)
3802   // Building for Windows XP, Windows Server 2003, or later.
3803   ::freeaddrinfo(ai);
3804 # else
3805   // Building for Windows 2000 or earlier.
3806   typedef int (WSAAPI *fai_t)(addrinfo_type*);
3807   if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32"))
3808   {
3809     if (fai_t fai = (fai_t)::GetProcAddress(winsock_module, "freeaddrinfo"))
3810     {
3811       fai(ai);
3812       return;
3813     }
3814   }
3815   freeaddrinfo_emulation(ai);
3816 # endif
3817 #elif !defined(BOOST_ASIO_HAS_GETADDRINFO)
3818   freeaddrinfo_emulation(ai);
3819 #else
3820   ::freeaddrinfo(ai);
3821 #endif
3822 }
3823 
3824 boost::system::error_code getnameinfo(const void* addr,
3825     std::size_t addrlen, char* host, std::size_t hostlen,
3826     char* serv, std::size_t servlen, int flags, boost::system::error_code& ec)
3827 {
3828 #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
3829 # if defined(BOOST_ASIO_HAS_GETADDRINFO)
3830   // Building for Windows XP, Windows Server 2003, or later.
3831   clear_last_error();
3832   int error = ::getnameinfo(static_cast<const socket_addr_type*>(addr),
3833       static_cast<socklen_t>(addrlen), host, static_cast<DWORD>(hostlen),
3834       serv, static_cast<DWORD>(servlen), flags);
3835   return ec = translate_addrinfo_error(error);
3836 # else
3837   // Building for Windows 2000 or earlier.
3838   typedef int (WSAAPI *gni_t)(const socket_addr_type*,
3839       int, char*, DWORD, char*, DWORD, int);
3840   if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32"))
3841   {
3842     if (gni_t gni = (gni_t)::GetProcAddress(winsock_module, "getnameinfo"))
3843     {
3844       clear_last_error();
3845       int error = gni(static_cast<const socket_addr_type*>(addr),
3846           static_cast<int>(addrlen), host, static_cast<DWORD>(hostlen),
3847           serv, static_cast<DWORD>(servlen), flags);
3848       return ec = translate_addrinfo_error(error);
3849     }
3850   }
3851   clear_last_error();
3852   return getnameinfo_emulation(static_cast<const socket_addr_type*>(addr),
3853       addrlen, host, hostlen, serv, servlen, flags, ec);
3854 # endif
3855 #elif !defined(BOOST_ASIO_HAS_GETADDRINFO)
3856   using namespace std; // For memcpy.
3857   sockaddr_storage_type tmp_addr;
3858   memcpy(&tmp_addr, addr, addrlen);
3859   addr = &tmp_addr;
3860   clear_last_error();
3861   return getnameinfo_emulation(static_cast<const socket_addr_type*>(addr),
3862       addrlen, host, hostlen, serv, servlen, flags, ec);
3863 #else
3864   clear_last_error();
3865   int error = ::getnameinfo(static_cast<const socket_addr_type*>(addr),
3866       addrlen, host, hostlen, serv, servlen, flags);
3867   return ec = translate_addrinfo_error(error);
3868 #endif
3869 }
3870 
3871 boost::system::error_code sync_getnameinfo(const void* addr,
3872     std::size_t addrlen, char* host, std::size_t hostlen, char* serv,
3873     std::size_t servlen, int sock_type, boost::system::error_code& ec)
3874 {
3875   // First try resolving with the service name. If that fails try resolving
3876   // but allow the service to be returned as a number.
3877   int flags = (sock_type == SOCK_DGRAM) ? NI_DGRAM : 0;
3878   socket_ops::getnameinfo(addr, addrlen, host,
3879       hostlen, serv, servlen, flags, ec);
3880   if (ec)
3881   {
3882     socket_ops::getnameinfo(addr, addrlen, host, hostlen,
3883         serv, servlen, flags | NI_NUMERICSERV, ec);
3884   }
3885 
3886   return ec;
3887 }
3888 
3889 boost::system::error_code background_getnameinfo(
3890     const weak_cancel_token_type& cancel_token,
3891     const void* addr, std::size_t addrlen,
3892     char* host, std::size_t hostlen, char* serv,
3893     std::size_t servlen, int sock_type, boost::system::error_code& ec)
3894 {
3895   if (cancel_token.expired())
3896   {
3897     ec = boost::asio::error::operation_aborted;
3898   }
3899   else
3900   {
3901     // First try resolving with the service name. If that fails try resolving
3902     // but allow the service to be returned as a number.
3903     int flags = (sock_type == SOCK_DGRAM) ? NI_DGRAM : 0;
3904     socket_ops::getnameinfo(addr, addrlen, host,
3905         hostlen, serv, servlen, flags, ec);
3906     if (ec)
3907     {
3908       socket_ops::getnameinfo(addr, addrlen, host, hostlen,
3909           serv, servlen, flags | NI_NUMERICSERV, ec);
3910     }
3911   }
3912 
3913   return ec;
3914 }
3915 
3916 #endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME)
3917 
3918 u_long_type network_to_host_long(u_long_type value)
3919 {
3920 #if defined(BOOST_ASIO_WINDOWS_RUNTIME)
3921   unsigned char* value_p = reinterpret_cast<unsigned char*>(&value);
3922   u_long_type result = (static_cast<u_long_type>(value_p[0]) << 24)
3923     | (static_cast<u_long_type>(value_p[1]) << 16)
3924     | (static_cast<u_long_type>(value_p[2]) << 8)
3925     | static_cast<u_long_type>(value_p[3]);
3926   return result;
3927 #else // defined(BOOST_ASIO_WINDOWS_RUNTIME)
3928   return ntohl(value);
3929 #endif // defined(BOOST_ASIO_WINDOWS_RUNTIME)
3930 }
3931 
3932 u_long_type host_to_network_long(u_long_type value)
3933 {
3934 #if defined(BOOST_ASIO_WINDOWS_RUNTIME)
3935   u_long_type result;
3936   unsigned char* result_p = reinterpret_cast<unsigned char*>(&result);
3937   result_p[0] = static_cast<unsigned char>((value >> 24) & 0xFF);
3938   result_p[1] = static_cast<unsigned char>((value >> 16) & 0xFF);
3939   result_p[2] = static_cast<unsigned char>((value >> 8) & 0xFF);
3940   result_p[3] = static_cast<unsigned char>(value & 0xFF);
3941   return result;
3942 #else // defined(BOOST_ASIO_WINDOWS_RUNTIME)
3943   return htonl(value);
3944 #endif // defined(BOOST_ASIO_WINDOWS_RUNTIME)
3945 }
3946 
3947 u_short_type network_to_host_short(u_short_type value)
3948 {
3949 #if defined(BOOST_ASIO_WINDOWS_RUNTIME)
3950   unsigned char* value_p = reinterpret_cast<unsigned char*>(&value);
3951   u_short_type result = (static_cast<u_short_type>(value_p[0]) << 8)
3952     | static_cast<u_short_type>(value_p[1]);
3953   return result;
3954 #else // defined(BOOST_ASIO_WINDOWS_RUNTIME)
3955   return ntohs(value);
3956 #endif // defined(BOOST_ASIO_WINDOWS_RUNTIME)
3957 }
3958 
3959 u_short_type host_to_network_short(u_short_type value)
3960 {
3961 #if defined(BOOST_ASIO_WINDOWS_RUNTIME)
3962   u_short_type result;
3963   unsigned char* result_p = reinterpret_cast<unsigned char*>(&result);
3964   result_p[0] = static_cast<unsigned char>((value >> 8) & 0xFF);
3965   result_p[1] = static_cast<unsigned char>(value & 0xFF);
3966   return result;
3967 #else // defined(BOOST_ASIO_WINDOWS_RUNTIME)
3968   return htons(value);
3969 #endif // defined(BOOST_ASIO_WINDOWS_RUNTIME)
3970 }
3971 
3972 } // namespace socket_ops
3973 } // namespace detail
3974 } // namespace asio
3975 } // namespace boost
3976 
3977 #include <boost/asio/detail/pop_options.hpp>
3978 
3979 #endif // BOOST_ASIO_DETAIL_SOCKET_OPS_IPP