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