📄 socket_ops.hpp
字号:
freeaddrinfo_emulation(aihead); return rc; } gai_search search[2]; int search_count = gai_nsearch(host, &hints, search); for (gai_search* sptr = search; sptr < search + search_count; ++sptr) { // Check for IPv4 dotted decimal string. in4_addr_type inaddr; asio::error_code ec; if (socket_ops::inet_pton(AF_INET, sptr->host, &inaddr, 0, ec) == 1) { if (hints.ai_family != AF_UNSPEC && hints.ai_family != AF_INET) { freeaddrinfo_emulation(aihead); gai_free(canon); return EAI_FAMILY; } if (sptr->family == AF_INET) { rc = gai_aistruct(&ainext, &hints, &inaddr, AF_INET); if (rc != 0) { freeaddrinfo_emulation(aihead); gai_free(canon); return rc; } } continue; } // Check for IPv6 hex string. in6_addr_type in6addr; if (socket_ops::inet_pton(AF_INET6, sptr->host, &in6addr, 0, ec) == 1) { if (hints.ai_family != AF_UNSPEC && hints.ai_family != AF_INET6) { freeaddrinfo_emulation(aihead); gai_free(canon); return EAI_FAMILY; } if (sptr->family == AF_INET6) { rc = gai_aistruct(&ainext, &hints, &in6addr, AF_INET6); if (rc != 0) { freeaddrinfo_emulation(aihead); gai_free(canon); return rc; } } continue; } // Look up hostname. hostent hent; char hbuf[8192] = ""; hostent* hptr = socket_ops::gethostbyname(sptr->host, sptr->family, &hent, hbuf, sizeof(hbuf), hints.ai_flags, ec); if (hptr == 0) { if (search_count == 2) { // Failure is OK if there are multiple searches. continue; } freeaddrinfo_emulation(aihead); gai_free(canon); if (ec == asio::error::host_not_found) return EAI_NONAME; if (ec == asio::error::host_not_found_try_again) return EAI_AGAIN; if (ec == asio::error::no_recovery) return EAI_FAIL; if (ec == asio::error::no_data) return EAI_NONAME; return EAI_NONAME; } // Check for address family mismatch if one was specified. if (hints.ai_family != AF_UNSPEC && hints.ai_family != hptr->h_addrtype) { freeaddrinfo_emulation(aihead); gai_free(canon); socket_ops::freehostent(hptr); return EAI_FAMILY; } // Save canonical name first time. if (host != 0 && host[0] != '\0' && hptr->h_name && hptr->h_name[0] && (hints.ai_flags & AI_CANONNAME) && canon == 0) { std::size_t canon_len = strlen(hptr->h_name) + 1; canon = gai_alloc<char>(canon_len); if (canon == 0) { freeaddrinfo_emulation(aihead); socket_ops::freehostent(hptr); return EAI_MEMORY; } gai_strcpy(canon, hptr->h_name, canon_len); } // Create an addrinfo structure for each returned address. for (char** ap = hptr->h_addr_list; *ap; ++ap) { rc = gai_aistruct(&ainext, &hints, *ap, hptr->h_addrtype); if (rc != 0) { freeaddrinfo_emulation(aihead); gai_free(canon); socket_ops::freehostent(hptr); return EAI_FAMILY; } } socket_ops::freehostent(hptr); } // Check if we found anything. if (aihead == 0) { gai_free(canon); return EAI_NONAME; } // Return canonical name in first entry. if (host != 0 && host[0] != '\0' && (hints.ai_flags & AI_CANONNAME)) { if (canon) { aihead->ai_canonname = canon; canon = 0; } else { std::size_t canonname_len = strlen(search[0].host) + 1; aihead->ai_canonname = gai_alloc<char>(canonname_len); if (aihead->ai_canonname == 0) { freeaddrinfo_emulation(aihead); return EAI_MEMORY; } gai_strcpy(aihead->ai_canonname, search[0].host, canonname_len); } } gai_free(canon); // Process the service name. if (service != 0 && service[0] != '\0') { rc = gai_serv(aihead, &hints, service); if (rc != 0) { freeaddrinfo_emulation(aihead); return rc; } } // Return result to caller. *result = aihead; return 0;}inline asio::error_code getnameinfo_emulation( const socket_addr_type* sa, std::size_t salen, char* host, std::size_t hostlen, char* serv, std::size_t servlen, int flags, asio::error_code& ec){ using namespace std; const char* addr; size_t addr_len; unsigned short port; switch (sa->sa_family) { case AF_INET: if (salen != sizeof(sockaddr_in4_type)) { return ec = asio::error::invalid_argument; } addr = reinterpret_cast<const char*>( &reinterpret_cast<const sockaddr_in4_type*>(sa)->sin_addr); addr_len = sizeof(in4_addr_type); port = reinterpret_cast<const sockaddr_in4_type*>(sa)->sin_port; break; case AF_INET6: if (salen != sizeof(sockaddr_in6_type)) { return ec = asio::error::invalid_argument; } addr = reinterpret_cast<const char*>( &reinterpret_cast<const sockaddr_in6_type*>(sa)->sin6_addr); addr_len = sizeof(in6_addr_type); port = reinterpret_cast<const sockaddr_in6_type*>(sa)->sin6_port; break; default: return ec = asio::error::address_family_not_supported; } if (host && hostlen > 0) { if (flags & NI_NUMERICHOST) { if (socket_ops::inet_ntop(sa->sa_family, addr, host, hostlen, 0, ec) == 0) { return ec; } } else { hostent hent; char hbuf[8192] = ""; hostent* hptr = socket_ops::gethostbyaddr(addr, static_cast<int>(addr_len), sa->sa_family, &hent, hbuf, sizeof(hbuf), ec); if (hptr && hptr->h_name && hptr->h_name[0] != '\0') { if (flags & NI_NOFQDN) { char* dot = strchr(hptr->h_name, '.'); if (dot) { *dot = 0; } } gai_strcpy(host, hptr->h_name, hostlen); socket_ops::freehostent(hptr); } else { socket_ops::freehostent(hptr); if (flags & NI_NAMEREQD) { return ec = asio::error::host_not_found; } if (socket_ops::inet_ntop(sa->sa_family, addr, host, hostlen, 0, ec) == 0) { return ec; } } } } if (serv && servlen > 0) { if (flags & NI_NUMERICSERV) { if (servlen < 6) { return ec = asio::error::no_buffer_space; }#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE) sprintf_s(serv, servlen, "%u", ntohs(port));#else sprintf(serv, "%u", ntohs(port));#endif } else {#if defined(BOOST_HAS_THREADS) && defined(BOOST_HAS_PTHREADS) static ::pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; ::pthread_mutex_lock(&mutex);#endif // defined(BOOST_HAS_THREADS) && defined(BOOST_HAS_PTHREADS) servent* sptr = ::getservbyport(port, (flags & NI_DGRAM) ? "udp" : 0); if (sptr && sptr->s_name && sptr->s_name[0] != '\0') { gai_strcpy(serv, sptr->s_name, servlen); } else { if (servlen < 6) { return ec = asio::error::no_buffer_space; }#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE) sprintf_s(serv, servlen, "%u", ntohs(port));#else sprintf(serv, "%u", ntohs(port));#endif }#if defined(BOOST_HAS_THREADS) && defined(BOOST_HAS_PTHREADS) ::pthread_mutex_unlock(&mutex);#endif // defined(BOOST_HAS_THREADS) && defined(BOOST_HAS_PTHREADS) } } clear_error(ec); return ec;}#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) // || defined(__MACH__) && defined(__APPLE__)inline asio::error_code translate_addrinfo_error(int error){ switch (error) { case 0: return asio::error_code(); case EAI_AGAIN: return asio::error::host_not_found_try_again; case EAI_BADFLAGS: return asio::error::invalid_argument; case EAI_FAIL: return asio::error::no_recovery; case EAI_FAMILY: return asio::error::address_family_not_supported; case EAI_MEMORY: return asio::error::no_memory; case EAI_NONAME:#if defined(EAI_ADDRFAMILY) case EAI_ADDRFAMILY:#endif#if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME) case EAI_NODATA:#endif return asio::error::host_not_found; case EAI_SERVICE: return asio::error::service_not_found; case EAI_SOCKTYPE: return asio::error::socket_type_not_supported; default: // Possibly the non-portable EAI_SYSTEM.#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) return asio::error_code( WSAGetLastError(), asio::error::get_system_category());#else return asio::error_code( errno, asio::error::get_system_category());#endif }}inline asio::error_code getaddrinfo(const char* host, const char* service, const addrinfo_type* hints, addrinfo_type** result, asio::error_code& ec){ clear_error(ec);#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) || defined(UNDER_CE) // Building for Windows XP, Windows Server 2003, or later. int error = ::getaddrinfo(host, service, hints, result); return ec = translate_addrinfo_error(error);# else // Building for Windows 2000 or earlier. typedef int (WSAAPI *gai_t)(const char*, const char*, const addrinfo_type*, addrinfo_type**); if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32")) { if (gai_t gai = (gai_t)::GetProcAddress(winsock_module, "getaddrinfo")) { int error = gai(host, service, hints, result); return ec = translate_addrinfo_error(error); } } int error = getaddrinfo_emulation(host, service, hints, result); return ec = translate_addrinfo_error(error);# endif#elif defined(__MACH__) && defined(__APPLE__) int error = getaddrinfo_emulation(host, service, hints, result); return ec = translate_addrinfo_error(error);#else int error = ::getaddrinfo(host, service, hints, result); return ec = translate_addrinfo_error(error);#endif}inline void freeaddrinfo(addrinfo_type* ai){#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) || defined(UNDER_CE) // Building for Windows XP, Windows Server 2003, or later. ::freeaddrinfo(ai);# else // Building for Windows 2000 or earlier. typedef int (WSAAPI *fai_t)(addrinfo_type*); if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32")) { if (fai_t fai = (fai_t)::GetProcAddress(winsock_module, "freeaddrinfo")) { fai(ai); return; } } freeaddrinfo_emulation(ai);# endif#elif defined(__MACH__) && defined(__APPLE__) freeaddrinfo_emulation(ai);#else ::freeaddrinfo(ai);#endif}inline asio::error_code getnameinfo(const socket_addr_type* addr, std::size_t addrlen, char* host, std::size_t hostlen, char* serv, std::size_t servlen, int flags, asio::error_code& ec){#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) || defined(UNDER_CE) // Building for Windows XP, Windows Server 2003, or later. clear_error(ec); int error = ::getnameinfo(addr, addrlen, host, static_cast<DWORD>(hostlen), serv, static_cast<DWORD>(servlen), flags); return ec = translate_addrinfo_error(error);# else // Building for Windows 2000 or earlier. typedef int (WSAAPI *gni_t)(const socket_addr_type*, int, char*, std::size_t, char*, std::size_t, int); if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32")) { if (gni_t gni = (gni_t)::GetProcAddress(winsock_module, "getnameinfo")) { clear_error(ec); int error = gni(addr, addrlen, host, hostlen, serv, servlen, flags); return ec = translate_addrinfo_error(error); } } clear_error(ec); return getnameinfo_emulation(addr, addrlen, host, hostlen, serv, servlen, flags, ec);# endif#elif defined(__MACH__) && defined(__APPLE__) using namespace std; // For memcpy. sockaddr_storage_type tmp_addr; memcpy(&tmp_addr, addr, addrlen); tmp_addr.ss_len = addrlen; addr = reinterpret_cast<socket_addr_type*>(&tmp_addr); clear_error(ec); return getnameinfo_emulation(addr, addrlen, host, hostlen, serv, servlen, flags, ec);#else clear_error(ec); int error = ::getnameinfo(addr, addrlen, host, hostlen, serv, servlen, flags); return ec = translate_addrinfo_error(error);#endif}inline u_long_type network_to_host_long(u_long_type value){ return ntohl(value);}inline u_long_type host_to_network_long(u_long_type value){ return htonl(value);}inline u_short_type network_to_host_short(u_short_type value){ return ntohs(value);}inline u_short_type host_to_network_short(u_short_type value){ return htons(value);}} // namespace socket_ops} // namespace detail} // namespace asio#include "asio/detail/pop_options.hpp"#endif // ASIO_DETAIL_SOCKET_OPS_HPP
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -