5 // Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
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)
11 #ifndef BOOST_ASIO_DETAIL_SOCKET_OPS_HPP
12 #define BOOST_ASIO_DETAIL_SOCKET_OPS_HPP
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
18 #include <boost/asio/detail/push_options.hpp>
20 #include <boost/asio/detail/push_options.hpp>
21 #include <boost/config.hpp>
22 #include <boost/assert.hpp>
27 #include <boost/detail/workaround.hpp>
29 #include <boost/asio/detail/pop_options.hpp>
31 #include <boost/asio/error.hpp>
32 #include <boost/asio/detail/socket_types.hpp>
37 namespace socket_ops
{
39 #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
40 struct msghdr
{ int msg_namelen
; };
41 #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
44 // HP-UX doesn't declare these functions extern "C", so they are declared again
45 // here to avoid linker errors about undefined symbols.
46 extern "C" char* if_indextoname(unsigned int, char*);
47 extern "C" unsigned int if_nametoindex(const char*);
48 #endif // defined(__hpux)
50 inline void clear_error(boost::system::error_code
& ec
)
52 #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
57 ec
= boost::system::error_code();
60 template <typename ReturnType
>
61 inline ReturnType
error_wrapper(ReturnType return_value
,
62 boost::system::error_code
& ec
)
64 #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
65 ec
= boost::system::error_code(WSAGetLastError(),
66 boost::asio::error::get_system_category());
68 ec
= boost::system::error_code(errno
,
69 boost::asio::error::get_system_category());
74 template <typename SockLenType
>
75 inline socket_type
call_accept(SockLenType
msghdr::*,
76 socket_type s
, socket_addr_type
* addr
, std::size_t* addrlen
)
78 SockLenType tmp_addrlen
= addrlen
? (SockLenType
)*addrlen
: 0;
79 socket_type result
= ::accept(s
, addr
, addrlen
? &tmp_addrlen
: 0);
81 *addrlen
= (std::size_t)tmp_addrlen
;
85 inline socket_type
accept(socket_type s
, socket_addr_type
* addr
,
86 std::size_t* addrlen
, boost::system::error_code
& ec
)
90 socket_type new_s
= error_wrapper(call_accept(
91 &msghdr::msg_namelen
, s
, addr
, addrlen
), ec
);
92 if (new_s
== invalid_socket
)
95 #if defined(__MACH__) && defined(__APPLE__) || defined(__FreeBSD__)
97 int result
= error_wrapper(::setsockopt(new_s
,
98 SOL_SOCKET
, SO_NOSIGPIPE
, &optval
, sizeof(optval
)), ec
);
102 return invalid_socket
;
110 template <typename SockLenType
>
111 inline int call_bind(SockLenType
msghdr::*,
112 socket_type s
, const socket_addr_type
* addr
, std::size_t addrlen
)
114 return ::bind(s
, addr
, (SockLenType
)addrlen
);
117 inline int bind(socket_type s
, const socket_addr_type
* addr
,
118 std::size_t addrlen
, boost::system::error_code
& ec
)
121 int result
= error_wrapper(call_bind(
122 &msghdr::msg_namelen
, s
, addr
, addrlen
), ec
);
128 inline int close(socket_type s
, boost::system::error_code
& ec
)
131 #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
132 int result
= error_wrapper(::closesocket(s
), ec
);
133 #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
134 int result
= error_wrapper(::close(s
), ec
);
135 #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
141 inline int shutdown(socket_type s
, int what
, boost::system::error_code
& ec
)
144 int result
= error_wrapper(::shutdown(s
, what
), ec
);
150 template <typename SockLenType
>
151 inline int call_connect(SockLenType
msghdr::*,
152 socket_type s
, const socket_addr_type
* addr
, std::size_t addrlen
)
154 return ::connect(s
, addr
, (SockLenType
)addrlen
);
157 inline int connect(socket_type s
, const socket_addr_type
* addr
,
158 std::size_t addrlen
, boost::system::error_code
& ec
)
161 int result
= error_wrapper(call_connect(
162 &msghdr::msg_namelen
, s
, addr
, addrlen
), ec
);
168 inline int socketpair(int af
, int type
, int protocol
,
169 socket_type sv
[2], boost::system::error_code
& ec
)
171 #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
176 ec
= boost::asio::error::operation_not_supported
;
180 int result
= error_wrapper(::socketpair(af
, type
, protocol
, sv
), ec
);
187 inline int listen(socket_type s
, int backlog
, boost::system::error_code
& ec
)
190 int result
= error_wrapper(::listen(s
, backlog
), ec
);
196 inline void init_buf_iov_base(void*& base
, void* addr
)
201 template <typename T
>
202 inline void init_buf_iov_base(T
& base
, void* addr
)
204 base
= static_cast<T
>(addr
);
207 #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
209 #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
211 #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
213 inline void init_buf(buf
& b
, void* data
, size_t size
)
215 #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
216 b
.buf
= static_cast<char*>(data
);
217 b
.len
= static_cast<u_long
>(size
);
218 #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
219 init_buf_iov_base(b
.iov_base
, data
);
221 #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
224 inline void init_buf(buf
& b
, const void* data
, size_t size
)
226 #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
227 b
.buf
= static_cast<char*>(const_cast<void*>(data
));
228 b
.len
= static_cast<u_long
>(size
);
229 #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
230 init_buf_iov_base(b
.iov_base
, const_cast<void*>(data
));
232 #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
235 inline void init_msghdr_msg_name(void*& name
, socket_addr_type
* addr
)
240 inline void init_msghdr_msg_name(void*& name
, const socket_addr_type
* addr
)
242 name
= const_cast<socket_addr_type
*>(addr
);
245 template <typename T
>
246 inline void init_msghdr_msg_name(T
& name
, socket_addr_type
* addr
)
248 name
= reinterpret_cast<T
>(addr
);
251 template <typename T
>
252 inline void init_msghdr_msg_name(T
& name
, const socket_addr_type
* addr
)
254 name
= reinterpret_cast<T
>(const_cast<socket_addr_type
*>(addr
));
257 inline int recv(socket_type s
, buf
* bufs
, size_t count
, int flags
,
258 boost::system::error_code
& ec
)
261 #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
262 // Receive some data.
263 DWORD recv_buf_count
= static_cast<DWORD
>(count
);
264 DWORD bytes_transferred
= 0;
265 DWORD recv_flags
= flags
;
266 int result
= error_wrapper(::WSARecv(s
, bufs
,
267 recv_buf_count
, &bytes_transferred
, &recv_flags
, 0, 0), ec
);
271 return bytes_transferred
;
272 #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
273 msghdr msg
= msghdr();
275 msg
.msg_iovlen
= count
;
276 int result
= error_wrapper(::recvmsg(s
, &msg
, flags
), ec
);
280 #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
283 inline int recvfrom(socket_type s
, buf
* bufs
, size_t count
, int flags
,
284 socket_addr_type
* addr
, std::size_t* addrlen
,
285 boost::system::error_code
& ec
)
288 #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
289 // Receive some data.
290 DWORD recv_buf_count
= static_cast<DWORD
>(count
);
291 DWORD bytes_transferred
= 0;
292 DWORD recv_flags
= flags
;
293 int tmp_addrlen
= (int)*addrlen
;
294 int result
= error_wrapper(::WSARecvFrom(s
, bufs
, recv_buf_count
,
295 &bytes_transferred
, &recv_flags
, addr
, &tmp_addrlen
, 0, 0), ec
);
296 *addrlen
= (std::size_t)tmp_addrlen
;
300 return bytes_transferred
;
301 #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
302 msghdr msg
= msghdr();
303 init_msghdr_msg_name(msg
.msg_name
, addr
);
304 msg
.msg_namelen
= *addrlen
;
306 msg
.msg_iovlen
= count
;
307 int result
= error_wrapper(::recvmsg(s
, &msg
, flags
), ec
);
308 *addrlen
= msg
.msg_namelen
;
312 #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
315 inline int send(socket_type s
, const buf
* bufs
, size_t count
, int flags
,
316 boost::system::error_code
& ec
)
319 #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
321 DWORD send_buf_count
= static_cast<DWORD
>(count
);
322 DWORD bytes_transferred
= 0;
323 DWORD send_flags
= flags
;
324 int result
= error_wrapper(::WSASend(s
, const_cast<buf
*>(bufs
),
325 send_buf_count
, &bytes_transferred
, send_flags
, 0, 0), ec
);
329 return bytes_transferred
;
330 #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
331 msghdr msg
= msghdr();
332 msg
.msg_iov
= const_cast<buf
*>(bufs
);
333 msg
.msg_iovlen
= count
;
334 #if defined(__linux__)
335 flags
|= MSG_NOSIGNAL
;
336 #endif // defined(__linux__)
337 int result
= error_wrapper(::sendmsg(s
, &msg
, flags
), ec
);
341 #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
344 inline int sendto(socket_type s
, const buf
* bufs
, size_t count
, int flags
,
345 const socket_addr_type
* addr
, std::size_t addrlen
,
346 boost::system::error_code
& ec
)
349 #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
351 DWORD send_buf_count
= static_cast<DWORD
>(count
);
352 DWORD bytes_transferred
= 0;
353 int result
= error_wrapper(::WSASendTo(s
, const_cast<buf
*>(bufs
),
354 send_buf_count
, &bytes_transferred
, flags
, addr
,
355 static_cast<int>(addrlen
), 0, 0), ec
);
359 return bytes_transferred
;
360 #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
361 msghdr msg
= msghdr();
362 init_msghdr_msg_name(msg
.msg_name
, addr
);
363 msg
.msg_namelen
= addrlen
;
364 msg
.msg_iov
= const_cast<buf
*>(bufs
);
365 msg
.msg_iovlen
= count
;
366 #if defined(__linux__)
367 flags
|= MSG_NOSIGNAL
;
368 #endif // defined(__linux__)
369 int result
= error_wrapper(::sendmsg(s
, &msg
, flags
), ec
);
373 #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
376 inline socket_type
socket(int af
, int type
, int protocol
,
377 boost::system::error_code
& ec
)
380 #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
381 socket_type s
= error_wrapper(::WSASocket(af
, type
, protocol
, 0, 0,
382 WSA_FLAG_OVERLAPPED
), ec
);
383 if (s
== invalid_socket
)
388 // Try to enable the POSIX default behaviour of having IPV6_V6ONLY set to
389 // false. This will only succeed on Windows Vista and later versions of
390 // Windows, where a dual-stack IPv4/v6 implementation is available.
392 ::setsockopt(s
, IPPROTO_IPV6
, IPV6_V6ONLY
,
393 reinterpret_cast<const char*>(&optval
), sizeof(optval
));
399 #elif defined(__MACH__) && defined(__APPLE__) || defined(__FreeBSD__)
400 socket_type s
= error_wrapper(::socket(af
, type
, protocol
), ec
);
401 if (s
== invalid_socket
)
405 int result
= error_wrapper(::setsockopt(s
,
406 SOL_SOCKET
, SO_NOSIGPIPE
, &optval
, sizeof(optval
)), ec
);
410 return invalid_socket
;
415 int s
= error_wrapper(::socket(af
, type
, protocol
), ec
);
422 template <typename SockLenType
>
423 inline int call_setsockopt(SockLenType
msghdr::*,
424 socket_type s
, int level
, int optname
,
425 const void* optval
, std::size_t optlen
)
427 return ::setsockopt(s
, level
, optname
,
428 (const char*)optval
, (SockLenType
)optlen
);
431 inline int setsockopt(socket_type s
, int level
, int optname
,
432 const void* optval
, std::size_t optlen
, boost::system::error_code
& ec
)
434 if (level
== custom_socket_option_level
&& optname
== always_fail_option
)
436 ec
= boost::asio::error::invalid_argument
;
440 #if defined(__BORLANDC__)
441 // Mysteriously, using the getsockopt and setsockopt functions directly with
442 // Borland C++ results in incorrect values being set and read. The bug can be
443 // worked around by using function addresses resolved with GetProcAddress.
444 if (HMODULE winsock_module
= ::GetModuleHandleA("ws2_32"))
446 typedef int (WSAAPI
*sso_t
)(SOCKET
, int, int, const char*, int);
447 if (sso_t sso
= (sso_t
)::GetProcAddress(winsock_module
, "setsockopt"))
450 return error_wrapper(sso(s
, level
, optname
,
451 reinterpret_cast<const char*>(optval
),
452 static_cast<int>(optlen
)), ec
);
455 ec
= boost::asio::error::fault
;
457 #else // defined(__BORLANDC__)
459 int result
= error_wrapper(call_setsockopt(&msghdr::msg_namelen
,
460 s
, level
, optname
, optval
, optlen
), ec
);
464 #endif // defined(__BORLANDC__)
467 template <typename SockLenType
>
468 inline int call_getsockopt(SockLenType
msghdr::*,
469 socket_type s
, int level
, int optname
,
470 void* optval
, std::size_t* optlen
)
472 SockLenType tmp_optlen
= (SockLenType
)*optlen
;
473 int result
= ::getsockopt(s
, level
, optname
, (char*)optval
, &tmp_optlen
);
474 *optlen
= (std::size_t)tmp_optlen
;
478 inline int getsockopt(socket_type s
, int level
, int optname
, void* optval
,
479 size_t* optlen
, boost::system::error_code
& ec
)
481 if (level
== custom_socket_option_level
&& optname
== always_fail_option
)
483 ec
= boost::asio::error::invalid_argument
;
487 #if defined(__BORLANDC__)
488 // Mysteriously, using the getsockopt and setsockopt functions directly with
489 // Borland C++ results in incorrect values being set and read. The bug can be
490 // worked around by using function addresses resolved with GetProcAddress.
491 if (HMODULE winsock_module
= ::GetModuleHandleA("ws2_32"))
493 typedef int (WSAAPI
*gso_t
)(SOCKET
, int, int, char*, int*);
494 if (gso_t gso
= (gso_t
)::GetProcAddress(winsock_module
, "getsockopt"))
497 int tmp_optlen
= static_cast<int>(*optlen
);
498 int result
= error_wrapper(gso(s
, level
, optname
,
499 reinterpret_cast<char*>(optval
), &tmp_optlen
), ec
);
500 *optlen
= static_cast<size_t>(tmp_optlen
);
501 if (result
!= 0 && level
== IPPROTO_IPV6
&& optname
== IPV6_V6ONLY
502 && ec
.value() == WSAENOPROTOOPT
&& *optlen
== sizeof(DWORD
))
504 // Dual-stack IPv4/v6 sockets, and the IPV6_V6ONLY socket option, are
505 // only supported on Windows Vista and later. To simplify program logic
506 // we will fake success of getting this option and specify that the
507 // value is non-zero (i.e. true). This corresponds to the behavior of
508 // IPv6 sockets on Windows platforms pre-Vista.
509 *static_cast<DWORD
*>(optval
) = 1;
515 ec
= boost::asio::error::fault
;
517 #elif defined(BOOST_WINDOWS) || defined(__CYGWIN__)
519 int result
= error_wrapper(call_getsockopt(&msghdr::msg_namelen
,
520 s
, level
, optname
, optval
, optlen
), ec
);
521 if (result
!= 0 && level
== IPPROTO_IPV6
&& optname
== IPV6_V6ONLY
522 && ec
.value() == WSAENOPROTOOPT
&& *optlen
== sizeof(DWORD
))
524 // Dual-stack IPv4/v6 sockets, and the IPV6_V6ONLY socket option, are only
525 // supported on Windows Vista and later. To simplify program logic we will
526 // fake success of getting this option and specify that the value is
527 // non-zero (i.e. true). This corresponds to the behavior of IPv6 sockets
528 // on Windows platforms pre-Vista.
529 *static_cast<DWORD
*>(optval
) = 1;
535 #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
537 int result
= error_wrapper(call_getsockopt(&msghdr::msg_namelen
,
538 s
, level
, optname
, optval
, optlen
), ec
);
539 #if defined(__linux__)
540 if (result
== 0 && level
== SOL_SOCKET
&& *optlen
== sizeof(int)
541 && (optname
== SO_SNDBUF
|| optname
== SO_RCVBUF
))
543 // On Linux, setting SO_SNDBUF or SO_RCVBUF to N actually causes the kernel
544 // to set the buffer size to N*2. Linux puts additional stuff into the
545 // buffers so that only about half is actually available to the application.
546 // The retrieved value is divided by 2 here to make it appear as though the
547 // correct value has been set.
548 *static_cast<int*>(optval
) /= 2;
550 #endif // defined(__linux__)
554 #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
557 template <typename SockLenType
>
558 inline int call_getpeername(SockLenType
msghdr::*,
559 socket_type s
, socket_addr_type
* addr
, std::size_t* addrlen
)
561 SockLenType tmp_addrlen
= (SockLenType
)*addrlen
;
562 int result
= ::getpeername(s
, addr
, &tmp_addrlen
);
563 *addrlen
= (std::size_t)tmp_addrlen
;
567 inline int getpeername(socket_type s
, socket_addr_type
* addr
,
568 std::size_t* addrlen
, boost::system::error_code
& ec
)
571 int result
= error_wrapper(call_getpeername(
572 &msghdr::msg_namelen
, s
, addr
, addrlen
), ec
);
578 template <typename SockLenType
>
579 inline int call_getsockname(SockLenType
msghdr::*,
580 socket_type s
, socket_addr_type
* addr
, std::size_t* addrlen
)
582 SockLenType tmp_addrlen
= (SockLenType
)*addrlen
;
583 int result
= ::getsockname(s
, addr
, &tmp_addrlen
);
584 *addrlen
= (std::size_t)tmp_addrlen
;
588 inline int getsockname(socket_type s
, socket_addr_type
* addr
,
589 std::size_t* addrlen
, boost::system::error_code
& ec
)
592 int result
= error_wrapper(call_getsockname(
593 &msghdr::msg_namelen
, s
, addr
, addrlen
), ec
);
599 inline int ioctl(socket_type s
, long cmd
, ioctl_arg_type
* arg
,
600 boost::system::error_code
& ec
)
603 #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
604 int result
= error_wrapper(::ioctlsocket(s
, cmd
, arg
), ec
);
605 #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
606 int result
= error_wrapper(::ioctl(s
, cmd
, arg
), ec
);
607 #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
613 inline int select(int nfds
, fd_set
* readfds
, fd_set
* writefds
,
614 fd_set
* exceptfds
, timeval
* timeout
, boost::system::error_code
& ec
)
617 #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
618 if (!readfds
&& !writefds
&& !exceptfds
&& timeout
)
620 DWORD milliseconds
= timeout
->tv_sec
* 1000 + timeout
->tv_usec
/ 1000;
621 if (milliseconds
== 0)
622 milliseconds
= 1; // Force context switch.
623 ::Sleep(milliseconds
);
624 ec
= boost::system::error_code();
628 // The select() call allows timeout values measured in microseconds, but the
629 // system clock (as wrapped by boost::posix_time::microsec_clock) typically
630 // has a resolution of 10 milliseconds. This can lead to a spinning select
631 // reactor, meaning increased CPU usage, when waiting for the earliest
632 // scheduled timeout if it's less than 10 milliseconds away. To avoid a tight
633 // spin we'll use a minimum timeout of 1 millisecond.
634 if (timeout
&& timeout
->tv_sec
== 0
635 && timeout
->tv_usec
> 0 && timeout
->tv_usec
< 1000)
636 timeout
->tv_usec
= 1000;
637 #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
639 #if defined(__hpux) && defined(__HP_aCC)
641 ts
.tv_sec
= timeout
? timeout
->tv_sec
: 0;
642 ts
.tv_nsec
= timeout
? timeout
->tv_usec
* 1000 : 0;
643 return error_wrapper(::pselect(nfds
, readfds
,
644 writefds
, exceptfds
, timeout
? &ts
: 0, 0), ec
);
646 int result
= error_wrapper(::select(nfds
, readfds
,
647 writefds
, exceptfds
, timeout
), ec
);
654 inline int poll_read(socket_type s
, boost::system::error_code
& ec
)
656 #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
661 int result
= error_wrapper(::select(s
, &fds
, 0, 0, 0), ec
);
665 #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
671 int result
= error_wrapper(::poll(&fds
, 1, -1), ec
);
675 #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
678 inline int poll_write(socket_type s
, boost::system::error_code
& ec
)
680 #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
685 int result
= error_wrapper(::select(s
, 0, &fds
, 0, 0), ec
);
689 #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
692 fds
.events
= POLLOUT
;
695 int result
= error_wrapper(::poll(&fds
, 1, -1), ec
);
699 #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
702 inline int poll_connect(socket_type s
, boost::system::error_code
& ec
)
704 #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
707 FD_SET(s
, &write_fds
);
709 FD_ZERO(&except_fds
);
710 FD_SET(s
, &except_fds
);
712 int result
= error_wrapper(::select(s
, 0, &write_fds
, &except_fds
, 0), ec
);
716 #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
719 fds
.events
= POLLOUT
;
722 int result
= error_wrapper(::poll(&fds
, 1, -1), ec
);
726 #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
729 inline const char* inet_ntop(int af
, const void* src
, char* dest
, size_t length
,
730 unsigned long scope_id
, boost::system::error_code
& ec
)
733 #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
734 using namespace std
; // For memcpy.
736 if (af
!= AF_INET
&& af
!= AF_INET6
)
738 ec
= boost::asio::error::address_family_not_supported
;
744 socket_addr_type base
;
745 sockaddr_storage_type storage
;
746 sockaddr_in4_type v4
;
747 sockaddr_in6_type v6
;
749 DWORD address_length
;
752 address_length
= sizeof(sockaddr_in4_type
);
753 address
.v4
.sin_family
= AF_INET
;
754 address
.v4
.sin_port
= 0;
755 memcpy(&address
.v4
.sin_addr
, src
, sizeof(in4_addr_type
));
759 address_length
= sizeof(sockaddr_in6_type
);
760 address
.v6
.sin6_family
= AF_INET6
;
761 address
.v6
.sin6_port
= 0;
762 address
.v6
.sin6_flowinfo
= 0;
763 address
.v6
.sin6_scope_id
= scope_id
;
764 memcpy(&address
.v6
.sin6_addr
, src
, sizeof(in6_addr_type
));
767 DWORD string_length
= static_cast<DWORD
>(length
);
768 #if defined(BOOST_NO_ANSI_APIS)
769 LPWSTR string_buffer
= (LPWSTR
)_alloca(length
* sizeof(WCHAR
));
770 int result
= error_wrapper(::WSAAddressToStringW(&address
.base
,
771 address_length
, 0, string_buffer
, &string_length
), ec
);
772 ::WideCharToMultiByte(CP_ACP
, 0, string_buffer
, -1, dest
, length
, 0, 0);
774 int result
= error_wrapper(::WSAAddressToStringA(
775 &address
.base
, address_length
, 0, dest
, &string_length
), ec
);
778 // Windows may set error code on success.
779 if (result
!= socket_error_retval
)
782 // Windows may not set an error code on failure.
783 else if (result
== socket_error_retval
&& !ec
)
784 ec
= boost::asio::error::invalid_argument
;
786 return result
== socket_error_retval
? 0 : dest
;
787 #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
788 const char* result
= error_wrapper(::inet_ntop(af
, src
, dest
, length
), ec
);
789 if (result
== 0 && !ec
)
790 ec
= boost::asio::error::invalid_argument
;
791 if (result
!= 0 && af
== AF_INET6
&& scope_id
!= 0)
793 using namespace std
; // For strcat and sprintf.
794 char if_name
[IF_NAMESIZE
+ 1] = "%";
795 const in6_addr_type
* ipv6_address
= static_cast<const in6_addr_type
*>(src
);
796 bool is_link_local
= IN6_IS_ADDR_LINKLOCAL(ipv6_address
);
797 if (!is_link_local
|| if_indextoname(scope_id
, if_name
+ 1) == 0)
798 sprintf(if_name
+ 1, "%lu", scope_id
);
799 strcat(dest
, if_name
);
802 #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
805 inline int inet_pton(int af
, const char* src
, void* dest
,
806 unsigned long* scope_id
, boost::system::error_code
& ec
)
809 #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
810 using namespace std
; // For memcpy and strcmp.
812 if (af
!= AF_INET
&& af
!= AF_INET6
)
814 ec
= boost::asio::error::address_family_not_supported
;
820 socket_addr_type base
;
821 sockaddr_storage_type storage
;
822 sockaddr_in4_type v4
;
823 sockaddr_in6_type v6
;
825 int address_length
= sizeof(sockaddr_storage_type
);
826 #if defined(BOOST_NO_ANSI_APIS)
827 int num_wide_chars
= strlen(src
) + 1;
828 LPWSTR wide_buffer
= (LPWSTR
)_alloca(num_wide_chars
* sizeof(WCHAR
));
829 ::MultiByteToWideChar(CP_ACP
, 0, src
, -1, wide_buffer
, num_wide_chars
);
830 int result
= error_wrapper(::WSAStringToAddressW(
831 wide_buffer
, af
, 0, &address
.base
, &address_length
), ec
);
833 int result
= error_wrapper(::WSAStringToAddressA(
834 const_cast<char*>(src
), af
, 0, &address
.base
, &address_length
), ec
);
839 if (result
!= socket_error_retval
)
841 memcpy(dest
, &address
.v4
.sin_addr
, sizeof(in4_addr_type
));
844 else if (strcmp(src
, "255.255.255.255") == 0)
846 static_cast<in4_addr_type
*>(dest
)->s_addr
= INADDR_NONE
;
852 if (result
!= socket_error_retval
)
854 memcpy(dest
, &address
.v6
.sin6_addr
, sizeof(in6_addr_type
));
856 *scope_id
= address
.v6
.sin6_scope_id
;
861 // Windows may not set an error code on failure.
862 if (result
== socket_error_retval
&& !ec
)
863 ec
= boost::asio::error::invalid_argument
;
865 if (result
!= socket_error_retval
)
868 return result
== socket_error_retval
? -1 : 1;
869 #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
870 int result
= error_wrapper(::inet_pton(af
, src
, dest
), ec
);
871 if (result
<= 0 && !ec
)
872 ec
= boost::asio::error::invalid_argument
;
873 if (result
> 0 && af
== AF_INET6
&& scope_id
)
875 using namespace std
; // For strchr and atoi.
877 if (const char* if_name
= strchr(src
, '%'))
879 in6_addr_type
* ipv6_address
= static_cast<in6_addr_type
*>(dest
);
880 bool is_link_local
= IN6_IS_ADDR_LINKLOCAL(ipv6_address
);
882 *scope_id
= if_nametoindex(if_name
+ 1);
884 *scope_id
= atoi(if_name
+ 1);
888 #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
891 inline int gethostname(char* name
, int namelen
, boost::system::error_code
& ec
)
894 int result
= error_wrapper(::gethostname(name
, namelen
), ec
);
895 #if defined(BOOST_WINDOWS)
902 #if defined(BOOST_WINDOWS) || defined(__CYGWIN__) \
903 || defined(__MACH__) && defined(__APPLE__)
905 // The following functions are only needed for emulation of getaddrinfo and
908 inline boost::system::error_code
translate_netdb_error(int error
)
913 return boost::system::error_code();
915 return boost::asio::error::host_not_found
;
917 return boost::asio::error::host_not_found_try_again
;
919 return boost::asio::error::no_recovery
;
921 return boost::asio::error::no_data
;
924 return boost::asio::error::invalid_argument
;
928 inline hostent
* gethostbyaddr(const char* addr
, int length
, int af
,
929 hostent
* result
, char* buffer
, int buflength
, boost::system::error_code
& ec
)
932 #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
935 hostent
* retval
= error_wrapper(::gethostbyaddr(addr
, length
, af
), ec
);
941 #elif defined(__sun) || defined(__QNX__)
943 hostent
* retval
= error_wrapper(::gethostbyaddr_r(addr
, length
, af
, result
,
944 buffer
, buflength
, &error
), ec
);
946 ec
= translate_netdb_error(error
);
948 #elif defined(__MACH__) && defined(__APPLE__)
952 hostent
* retval
= error_wrapper(::getipnodebyaddr(
953 addr
, length
, af
, &error
), ec
);
955 ec
= translate_netdb_error(error
);
963 error_wrapper(::gethostbyaddr_r(addr
, length
, af
, result
, buffer
,
964 buflength
, &retval
, &error
), ec
);
966 ec
= translate_netdb_error(error
);
971 inline hostent
* gethostbyname(const char* name
, int af
, struct hostent
* result
,
972 char* buffer
, int buflength
, int ai_flags
, boost::system::error_code
& ec
)
975 #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
981 ec
= boost::asio::error::address_family_not_supported
;
984 hostent
* retval
= error_wrapper(::gethostbyname(name
), ec
);
990 #elif defined(__sun) || defined(__QNX__)
994 ec
= boost::asio::error::address_family_not_supported
;
998 hostent
* retval
= error_wrapper(::gethostbyname_r(name
, result
, buffer
,
999 buflength
, &error
), ec
);
1001 ec
= translate_netdb_error(error
);
1003 #elif defined(__MACH__) && defined(__APPLE__)
1007 hostent
* retval
= error_wrapper(::getipnodebyname(
1008 name
, af
, ai_flags
, &error
), ec
);
1010 ec
= translate_netdb_error(error
);
1019 ec
= boost::asio::error::address_family_not_supported
;
1022 hostent
* retval
= 0;
1024 error_wrapper(::gethostbyname_r(name
, result
,
1025 buffer
, buflength
, &retval
, &error
), ec
);
1027 ec
= translate_netdb_error(error
);
1032 inline void freehostent(hostent
* h
)
1034 #if defined(__MACH__) && defined(__APPLE__)
1042 // Emulation of getaddrinfo based on implementation in:
1043 // Stevens, W. R., UNIX Network Programming Vol. 1, 2nd Ed., Prentice-Hall 1998.
1051 inline int gai_nsearch(const char* host
,
1052 const addrinfo_type
* hints
, gai_search (&search
)[2])
1054 int search_count
= 0;
1055 if (host
== 0 || host
[0] == '\0')
1057 if (hints
->ai_flags
& AI_PASSIVE
)
1059 // No host and AI_PASSIVE implies wildcard bind.
1060 switch (hints
->ai_family
)
1063 search
[search_count
].host
= "0.0.0.0";
1064 search
[search_count
].family
= AF_INET
;
1068 search
[search_count
].host
= "0::0";
1069 search
[search_count
].family
= AF_INET6
;
1073 search
[search_count
].host
= "0::0";
1074 search
[search_count
].family
= AF_INET6
;
1076 search
[search_count
].host
= "0.0.0.0";
1077 search
[search_count
].family
= AF_INET
;
1086 // No host and not AI_PASSIVE means connect to local host.
1087 switch (hints
->ai_family
)
1090 search
[search_count
].host
= "localhost";
1091 search
[search_count
].family
= AF_INET
;
1095 search
[search_count
].host
= "localhost";
1096 search
[search_count
].family
= AF_INET6
;
1100 search
[search_count
].host
= "localhost";
1101 search
[search_count
].family
= AF_INET6
;
1103 search
[search_count
].host
= "localhost";
1104 search
[search_count
].family
= AF_INET
;
1114 // Host is specified.
1115 switch (hints
->ai_family
)
1118 search
[search_count
].host
= host
;
1119 search
[search_count
].family
= AF_INET
;
1123 search
[search_count
].host
= host
;
1124 search
[search_count
].family
= AF_INET6
;
1128 search
[search_count
].host
= host
;
1129 search
[search_count
].family
= AF_INET6
;
1131 search
[search_count
].host
= host
;
1132 search
[search_count
].family
= AF_INET
;
1139 return search_count
;
1142 template <typename T
>
1143 inline T
* gai_alloc(std::size_t size
= sizeof(T
))
1145 using namespace std
;
1146 T
* p
= static_cast<T
*>(::operator new(size
, std::nothrow
));
1152 inline void gai_free(void* p
)
1154 ::operator delete(p
);
1157 inline void gai_strcpy(char* target
, const char* source
, std::size_t max_size
)
1159 using namespace std
;
1160 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE)
1161 strcpy_s(target
, max_size
, source
);
1164 strncat(target
, source
, max_size
);
1168 enum { gai_clone_flag
= 1 << 30 };
1170 inline int gai_aistruct(addrinfo_type
*** next
, const addrinfo_type
* hints
,
1171 const void* addr
, int family
)
1173 using namespace std
;
1175 addrinfo_type
* ai
= gai_alloc
<addrinfo_type
>();
1181 *next
= &ai
->ai_next
;
1183 ai
->ai_canonname
= 0;
1184 ai
->ai_socktype
= hints
->ai_socktype
;
1185 if (ai
->ai_socktype
== 0)
1186 ai
->ai_flags
|= gai_clone_flag
;
1187 ai
->ai_protocol
= hints
->ai_protocol
;
1188 ai
->ai_family
= family
;
1190 switch (ai
->ai_family
)
1194 sockaddr_in4_type
* sinptr
= gai_alloc
<sockaddr_in4_type
>();
1197 sinptr
->sin_family
= AF_INET
;
1198 memcpy(&sinptr
->sin_addr
, addr
, sizeof(in4_addr_type
));
1199 ai
->ai_addr
= reinterpret_cast<sockaddr
*>(sinptr
);
1200 ai
->ai_addrlen
= sizeof(sockaddr_in4_type
);
1205 sockaddr_in6_type
* sin6ptr
= gai_alloc
<sockaddr_in6_type
>();
1208 sin6ptr
->sin6_family
= AF_INET6
;
1209 memcpy(&sin6ptr
->sin6_addr
, addr
, sizeof(in6_addr_type
));
1210 ai
->ai_addr
= reinterpret_cast<sockaddr
*>(sin6ptr
);
1211 ai
->ai_addrlen
= sizeof(sockaddr_in6_type
);
1221 inline addrinfo_type
* gai_clone(addrinfo_type
* ai
)
1223 using namespace std
;
1225 addrinfo_type
* new_ai
= gai_alloc
<addrinfo_type
>();
1229 new_ai
->ai_next
= ai
->ai_next
;
1230 ai
->ai_next
= new_ai
;
1232 new_ai
->ai_flags
= 0;
1233 new_ai
->ai_family
= ai
->ai_family
;
1234 new_ai
->ai_socktype
= ai
->ai_socktype
;
1235 new_ai
->ai_protocol
= ai
->ai_protocol
;
1236 new_ai
->ai_canonname
= 0;
1237 new_ai
->ai_addrlen
= ai
->ai_addrlen
;
1238 new_ai
->ai_addr
= gai_alloc
<sockaddr
>(ai
->ai_addrlen
);
1239 memcpy(new_ai
->ai_addr
, ai
->ai_addr
, ai
->ai_addrlen
);
1244 inline int gai_port(addrinfo_type
* aihead
, int port
, int socktype
)
1248 for (addrinfo_type
* ai
= aihead
; ai
; ai
= ai
->ai_next
)
1250 if (ai
->ai_flags
& gai_clone_flag
)
1252 if (ai
->ai_socktype
!= 0)
1257 // ai now points to newly cloned entry.
1260 else if (ai
->ai_socktype
!= socktype
)
1262 // Ignore if mismatch on socket type.
1266 ai
->ai_socktype
= socktype
;
1268 switch (ai
->ai_family
)
1272 sockaddr_in4_type
* sinptr
=
1273 reinterpret_cast<sockaddr_in4_type
*>(ai
->ai_addr
);
1274 sinptr
->sin_port
= port
;
1280 sockaddr_in6_type
* sin6ptr
=
1281 reinterpret_cast<sockaddr_in6_type
*>(ai
->ai_addr
);
1282 sin6ptr
->sin6_port
= port
;
1294 inline int gai_serv(addrinfo_type
* aihead
,
1295 const addrinfo_type
* hints
, const char* serv
)
1297 using namespace std
;
1302 #if defined(AI_NUMERICSERV)
1303 (hints
->ai_flags
& AI_NUMERICSERV
) ||
1307 int port
= htons(atoi(serv
));
1308 if (hints
->ai_socktype
)
1310 // Caller specifies socket type.
1311 int rc
= gai_port(aihead
, port
, hints
->ai_socktype
);
1318 // Caller does not specify socket type.
1319 int rc
= gai_port(aihead
, port
, SOCK_STREAM
);
1323 rc
= gai_port(aihead
, port
, SOCK_DGRAM
);
1331 // Try service name with TCP first, then UDP.
1332 if (hints
->ai_socktype
== 0 || hints
->ai_socktype
== SOCK_STREAM
)
1334 servent
* sptr
= getservbyname(serv
, "tcp");
1337 int rc
= gai_port(aihead
, sptr
->s_port
, SOCK_STREAM
);
1343 if (hints
->ai_socktype
== 0 || hints
->ai_socktype
== SOCK_DGRAM
)
1345 servent
* sptr
= getservbyname(serv
, "udp");
1348 int rc
= gai_port(aihead
, sptr
->s_port
, SOCK_DGRAM
);
1358 if (hints
->ai_socktype
== 0)
1360 // All calls to getservbyname() failed.
1365 // Service not supported for socket type.
1373 inline int gai_echeck(const char* host
, const char* service
,
1374 int flags
, int family
, int socktype
, int protocol
)
1379 // Host or service must be specified.
1380 if (host
== 0 || host
[0] == '\0')
1381 if (service
== 0 || service
[0] == '\0')
1384 // Check combination of family and socket type.
1391 if (socktype
!= 0 && socktype
!= SOCK_STREAM
&& socktype
!= SOCK_DGRAM
)
1392 return EAI_SOCKTYPE
;
1401 inline void freeaddrinfo_emulation(addrinfo_type
* aihead
)
1403 addrinfo_type
* ai
= aihead
;
1406 gai_free(ai
->ai_addr
);
1407 gai_free(ai
->ai_canonname
);
1408 addrinfo_type
* ainext
= ai
->ai_next
;
1414 inline int getaddrinfo_emulation(const char* host
, const char* service
,
1415 const addrinfo_type
* hintsp
, addrinfo_type
** result
)
1417 // Set up linked list of addrinfo structures.
1418 addrinfo_type
* aihead
= 0;
1419 addrinfo_type
** ainext
= &aihead
;
1422 // Supply default hints if not specified by caller.
1423 addrinfo_type hints
= addrinfo_type();
1424 hints
.ai_family
= AF_UNSPEC
;
1428 // If the resolution is not specifically for AF_INET6, remove the AI_V4MAPPED
1429 // and AI_ALL flags.
1430 #if defined(AI_V4MAPPED)
1431 if (hints
.ai_family
!= AF_INET6
)
1432 hints
.ai_flags
&= ~AI_V4MAPPED
;
1435 if (hints
.ai_family
!= AF_INET6
)
1436 hints
.ai_flags
&= ~AI_ALL
;
1439 // Basic error checking.
1440 int rc
= gai_echeck(host
, service
, hints
.ai_flags
, hints
.ai_family
,
1441 hints
.ai_socktype
, hints
.ai_protocol
);
1444 freeaddrinfo_emulation(aihead
);
1448 gai_search search
[2];
1449 int search_count
= gai_nsearch(host
, &hints
, search
);
1450 for (gai_search
* sptr
= search
; sptr
< search
+ search_count
; ++sptr
)
1452 // Check for IPv4 dotted decimal string.
1453 in4_addr_type inaddr
;
1454 boost::system::error_code ec
;
1455 if (socket_ops::inet_pton(AF_INET
, sptr
->host
, &inaddr
, 0, ec
) == 1)
1457 if (hints
.ai_family
!= AF_UNSPEC
&& hints
.ai_family
!= AF_INET
)
1459 freeaddrinfo_emulation(aihead
);
1463 if (sptr
->family
== AF_INET
)
1465 rc
= gai_aistruct(&ainext
, &hints
, &inaddr
, AF_INET
);
1468 freeaddrinfo_emulation(aihead
);
1476 // Check for IPv6 hex string.
1477 in6_addr_type in6addr
;
1478 if (socket_ops::inet_pton(AF_INET6
, sptr
->host
, &in6addr
, 0, ec
) == 1)
1480 if (hints
.ai_family
!= AF_UNSPEC
&& hints
.ai_family
!= AF_INET6
)
1482 freeaddrinfo_emulation(aihead
);
1486 if (sptr
->family
== AF_INET6
)
1488 rc
= gai_aistruct(&ainext
, &hints
, &in6addr
, AF_INET6
);
1491 freeaddrinfo_emulation(aihead
);
1499 // Look up hostname.
1501 char hbuf
[8192] = "";
1502 hostent
* hptr
= socket_ops::gethostbyname(sptr
->host
,
1503 sptr
->family
, &hent
, hbuf
, sizeof(hbuf
), hints
.ai_flags
, ec
);
1506 if (search_count
== 2)
1508 // Failure is OK if there are multiple searches.
1511 freeaddrinfo_emulation(aihead
);
1513 if (ec
== boost::asio::error::host_not_found
)
1515 if (ec
== boost::asio::error::host_not_found_try_again
)
1517 if (ec
== boost::asio::error::no_recovery
)
1519 if (ec
== boost::asio::error::no_data
)
1524 // Check for address family mismatch if one was specified.
1525 if (hints
.ai_family
!= AF_UNSPEC
&& hints
.ai_family
!= hptr
->h_addrtype
)
1527 freeaddrinfo_emulation(aihead
);
1529 socket_ops::freehostent(hptr
);
1533 // Save canonical name first time.
1534 if (host
!= 0 && host
[0] != '\0' && hptr
->h_name
&& hptr
->h_name
[0]
1535 && (hints
.ai_flags
& AI_CANONNAME
) && canon
== 0)
1537 std::size_t canon_len
= strlen(hptr
->h_name
) + 1;
1538 canon
= gai_alloc
<char>(canon_len
);
1541 freeaddrinfo_emulation(aihead
);
1542 socket_ops::freehostent(hptr
);
1545 gai_strcpy(canon
, hptr
->h_name
, canon_len
);
1548 // Create an addrinfo structure for each returned address.
1549 for (char** ap
= hptr
->h_addr_list
; *ap
; ++ap
)
1551 rc
= gai_aistruct(&ainext
, &hints
, *ap
, hptr
->h_addrtype
);
1554 freeaddrinfo_emulation(aihead
);
1556 socket_ops::freehostent(hptr
);
1561 socket_ops::freehostent(hptr
);
1564 // Check if we found anything.
1571 // Return canonical name in first entry.
1572 if (host
!= 0 && host
[0] != '\0' && (hints
.ai_flags
& AI_CANONNAME
))
1576 aihead
->ai_canonname
= canon
;
1581 std::size_t canonname_len
= strlen(search
[0].host
) + 1;
1582 aihead
->ai_canonname
= gai_alloc
<char>(canonname_len
);
1583 if (aihead
->ai_canonname
== 0)
1585 freeaddrinfo_emulation(aihead
);
1588 gai_strcpy(aihead
->ai_canonname
, search
[0].host
, canonname_len
);
1593 // Process the service name.
1594 if (service
!= 0 && service
[0] != '\0')
1596 rc
= gai_serv(aihead
, &hints
, service
);
1599 freeaddrinfo_emulation(aihead
);
1604 // Return result to caller.
1609 inline boost::system::error_code
getnameinfo_emulation(
1610 const socket_addr_type
* sa
, std::size_t salen
, char* host
,
1611 std::size_t hostlen
, char* serv
, std::size_t servlen
, int flags
,
1612 boost::system::error_code
& ec
)
1614 using namespace std
;
1618 unsigned short port
;
1619 switch (sa
->sa_family
)
1622 if (salen
!= sizeof(sockaddr_in4_type
))
1624 return ec
= boost::asio::error::invalid_argument
;
1626 addr
= reinterpret_cast<const char*>(
1627 &reinterpret_cast<const sockaddr_in4_type
*>(sa
)->sin_addr
);
1628 addr_len
= sizeof(in4_addr_type
);
1629 port
= reinterpret_cast<const sockaddr_in4_type
*>(sa
)->sin_port
;
1632 if (salen
!= sizeof(sockaddr_in6_type
))
1634 return ec
= boost::asio::error::invalid_argument
;
1636 addr
= reinterpret_cast<const char*>(
1637 &reinterpret_cast<const sockaddr_in6_type
*>(sa
)->sin6_addr
);
1638 addr_len
= sizeof(in6_addr_type
);
1639 port
= reinterpret_cast<const sockaddr_in6_type
*>(sa
)->sin6_port
;
1642 return ec
= boost::asio::error::address_family_not_supported
;
1645 if (host
&& hostlen
> 0)
1647 if (flags
& NI_NUMERICHOST
)
1649 if (socket_ops::inet_ntop(sa
->sa_family
, addr
, host
, hostlen
, 0, ec
) == 0)
1657 char hbuf
[8192] = "";
1658 hostent
* hptr
= socket_ops::gethostbyaddr(addr
,
1659 static_cast<int>(addr_len
), sa
->sa_family
,
1660 &hent
, hbuf
, sizeof(hbuf
), ec
);
1661 if (hptr
&& hptr
->h_name
&& hptr
->h_name
[0] != '\0')
1663 if (flags
& NI_NOFQDN
)
1665 char* dot
= strchr(hptr
->h_name
, '.');
1671 gai_strcpy(host
, hptr
->h_name
, hostlen
);
1672 socket_ops::freehostent(hptr
);
1676 socket_ops::freehostent(hptr
);
1677 if (flags
& NI_NAMEREQD
)
1679 return ec
= boost::asio::error::host_not_found
;
1681 if (socket_ops::inet_ntop(sa
->sa_family
,
1682 addr
, host
, hostlen
, 0, ec
) == 0)
1690 if (serv
&& servlen
> 0)
1692 if (flags
& NI_NUMERICSERV
)
1696 return ec
= boost::asio::error::no_buffer_space
;
1698 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE)
1699 sprintf_s(serv
, servlen
, "%u", ntohs(port
));
1701 sprintf(serv
, "%u", ntohs(port
));
1706 #if defined(BOOST_HAS_THREADS) && defined(BOOST_HAS_PTHREADS)
1707 static ::pthread_mutex_t mutex
= PTHREAD_MUTEX_INITIALIZER
;
1708 ::pthread_mutex_lock(&mutex
);
1709 #endif // defined(BOOST_HAS_THREADS) && defined(BOOST_HAS_PTHREADS)
1710 servent
* sptr
= ::getservbyport(port
, (flags
& NI_DGRAM
) ? "udp" : 0);
1711 if (sptr
&& sptr
->s_name
&& sptr
->s_name
[0] != '\0')
1713 gai_strcpy(serv
, sptr
->s_name
, servlen
);
1719 return ec
= boost::asio::error::no_buffer_space
;
1721 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE)
1722 sprintf_s(serv
, servlen
, "%u", ntohs(port
));
1724 sprintf(serv
, "%u", ntohs(port
));
1727 #if defined(BOOST_HAS_THREADS) && defined(BOOST_HAS_PTHREADS)
1728 ::pthread_mutex_unlock(&mutex
);
1729 #endif // defined(BOOST_HAS_THREADS) && defined(BOOST_HAS_PTHREADS)
1737 #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
1738 // || defined(__MACH__) && defined(__APPLE__)
1740 inline boost::system::error_code
translate_addrinfo_error(int error
)
1745 return boost::system::error_code();
1747 return boost::asio::error::host_not_found_try_again
;
1749 return boost::asio::error::invalid_argument
;
1751 return boost::asio::error::no_recovery
;
1753 return boost::asio::error::address_family_not_supported
;
1755 return boost::asio::error::no_memory
;
1757 #if defined(EAI_ADDRFAMILY)
1758 case EAI_ADDRFAMILY
:
1760 #if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
1763 return boost::asio::error::host_not_found
;
1765 return boost::asio::error::service_not_found
;
1767 return boost::asio::error::socket_type_not_supported
;
1768 default: // Possibly the non-portable EAI_SYSTEM.
1769 #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
1770 return boost::system::error_code(
1771 WSAGetLastError(), boost::asio::error::get_system_category());
1773 return boost::system::error_code(
1774 errno
, boost::asio::error::get_system_category());
1779 inline boost::system::error_code
getaddrinfo(const char* host
,
1780 const char* service
, const addrinfo_type
* hints
, addrinfo_type
** result
,
1781 boost::system::error_code
& ec
)
1784 #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
1785 # if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) || defined(UNDER_CE)
1786 // Building for Windows XP, Windows Server 2003, or later.
1787 int error
= ::getaddrinfo(host
, service
, hints
, result
);
1788 return ec
= translate_addrinfo_error(error
);
1790 // Building for Windows 2000 or earlier.
1791 typedef int (WSAAPI
*gai_t
)(const char*,
1792 const char*, const addrinfo_type
*, addrinfo_type
**);
1793 if (HMODULE winsock_module
= ::GetModuleHandleA("ws2_32"))
1795 if (gai_t gai
= (gai_t
)::GetProcAddress(winsock_module
, "getaddrinfo"))
1797 int error
= gai(host
, service
, hints
, result
);
1798 return ec
= translate_addrinfo_error(error
);
1801 int error
= getaddrinfo_emulation(host
, service
, hints
, result
);
1802 return ec
= translate_addrinfo_error(error
);
1804 #elif defined(__MACH__) && defined(__APPLE__)
1805 int error
= getaddrinfo_emulation(host
, service
, hints
, result
);
1806 return ec
= translate_addrinfo_error(error
);
1808 int error
= ::getaddrinfo(host
, service
, hints
, result
);
1809 return ec
= translate_addrinfo_error(error
);
1813 inline void freeaddrinfo(addrinfo_type
* ai
)
1815 #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
1816 # if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) || defined(UNDER_CE)
1817 // Building for Windows XP, Windows Server 2003, or later.
1820 // Building for Windows 2000 or earlier.
1821 typedef int (WSAAPI
*fai_t
)(addrinfo_type
*);
1822 if (HMODULE winsock_module
= ::GetModuleHandleA("ws2_32"))
1824 if (fai_t fai
= (fai_t
)::GetProcAddress(winsock_module
, "freeaddrinfo"))
1830 freeaddrinfo_emulation(ai
);
1832 #elif defined(__MACH__) && defined(__APPLE__)
1833 freeaddrinfo_emulation(ai
);
1839 inline boost::system::error_code
getnameinfo(const socket_addr_type
* addr
,
1840 std::size_t addrlen
, char* host
, std::size_t hostlen
,
1841 char* serv
, std::size_t servlen
, int flags
, boost::system::error_code
& ec
)
1843 #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
1844 # if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) || defined(UNDER_CE)
1845 // Building for Windows XP, Windows Server 2003, or later.
1847 int error
= ::getnameinfo(addr
, static_cast<socklen_t
>(addrlen
),
1848 host
, static_cast<DWORD
>(hostlen
),
1849 serv
, static_cast<DWORD
>(servlen
), flags
);
1850 return ec
= translate_addrinfo_error(error
);
1852 // Building for Windows 2000 or earlier.
1853 typedef int (WSAAPI
*gni_t
)(const socket_addr_type
*,
1854 int, char*, DWORD
, char*, DWORD
, int);
1855 if (HMODULE winsock_module
= ::GetModuleHandleA("ws2_32"))
1857 if (gni_t gni
= (gni_t
)::GetProcAddress(winsock_module
, "getnameinfo"))
1860 int error
= gni(addr
, static_cast<int>(addrlen
),
1861 host
, static_cast<DWORD
>(hostlen
),
1862 serv
, static_cast<DWORD
>(servlen
), flags
);
1863 return ec
= translate_addrinfo_error(error
);
1867 return getnameinfo_emulation(addr
, addrlen
,
1868 host
, hostlen
, serv
, servlen
, flags
, ec
);
1870 #elif defined(__MACH__) && defined(__APPLE__)
1871 using namespace std
; // For memcpy.
1872 sockaddr_storage_type tmp_addr
;
1873 memcpy(&tmp_addr
, addr
, addrlen
);
1874 tmp_addr
.ss_len
= addrlen
;
1875 addr
= reinterpret_cast<socket_addr_type
*>(&tmp_addr
);
1877 return getnameinfo_emulation(addr
, addrlen
,
1878 host
, hostlen
, serv
, servlen
, flags
, ec
);
1881 int error
= ::getnameinfo(addr
, addrlen
, host
, hostlen
, serv
, servlen
, flags
);
1882 return ec
= translate_addrinfo_error(error
);
1886 inline u_long_type
network_to_host_long(u_long_type value
)
1888 return ntohl(value
);
1891 inline u_long_type
host_to_network_long(u_long_type value
)
1893 return htonl(value
);
1896 inline u_short_type
network_to_host_short(u_short_type value
)
1898 return ntohs(value
);
1901 inline u_short_type
host_to_network_short(u_short_type value
)
1903 return htons(value
);
1906 } // namespace socket_ops
1907 } // namespace detail
1909 } // namespace boost
1911 #include <boost/asio/detail/pop_options.hpp>
1913 #endif // BOOST_ASIO_DETAIL_SOCKET_OPS_HPP