Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-13 08:05:42

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