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