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