annotate DEPENDENCIES/generic/include/boost/asio/detail/impl/socket_ops.ipp @ 133:4acb5d8d80b6 tip

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