📄 socket_ops.hpp
字号:
(void)(buffer); (void)(buflength); (void)(ai_flags); if (af != AF_INET) { ec = asio::error::address_family_not_supported; return 0; } hostent* retval = error_wrapper(::gethostbyname(name), ec); if (!retval) return 0;# if defined(UNDER_CE) clear_error(ec);# endif *result = *retval; return result;#elif defined(__sun) || defined(__QNX__) (void)(ai_flags); if (af != AF_INET) { ec = asio::error::address_family_not_supported; return 0; } int error = 0; hostent* retval = error_wrapper(::gethostbyname_r(name, result, buffer, buflength, &error), ec); if (error) ec = translate_netdb_error(error); return retval;#elif defined(__MACH__) && defined(__APPLE__) (void)(buffer); (void)(buflength); int error = 0; hostent* retval = error_wrapper(::getipnodebyname( name, af, ai_flags, &error), ec); if (error) ec = translate_netdb_error(error); if (!retval) return 0; *result = *retval; return retval;#else (void)(ai_flags); if (af != AF_INET) { ec = asio::error::address_family_not_supported; return 0; } hostent* retval = 0; int error = 0; error_wrapper(::gethostbyname_r(name, result, buffer, buflength, &retval, &error), ec); if (error) ec = translate_netdb_error(error); return retval;#endif}inline void freehostent(hostent* h){#if defined(__MACH__) && defined(__APPLE__) if (h) ::freehostent(h);#else (void)(h);#endif}// Emulation of getaddrinfo based on implementation in:// Stevens, W. R., UNIX Network Programming Vol. 1, 2nd Ed., Prentice-Hall 1998.struct gai_search{ const char* host; int family;};inline int gai_nsearch(const char* host, const addrinfo_type* hints, gai_search (&search)[2]){ int search_count = 0; if (host == 0 || host[0] == '\0') { if (hints->ai_flags & AI_PASSIVE) { // No host and AI_PASSIVE implies wildcard bind. switch (hints->ai_family) { case AF_INET: search[search_count].host = "0.0.0.0"; search[search_count].family = AF_INET; ++search_count; break; case AF_INET6: search[search_count].host = "0::0"; search[search_count].family = AF_INET6; ++search_count; break; case AF_UNSPEC: search[search_count].host = "0::0"; search[search_count].family = AF_INET6; ++search_count; search[search_count].host = "0.0.0.0"; search[search_count].family = AF_INET; ++search_count; break; default: break; } } else { // No host and not AI_PASSIVE means connect to local host. switch (hints->ai_family) { case AF_INET: search[search_count].host = "localhost"; search[search_count].family = AF_INET; ++search_count; break; case AF_INET6: search[search_count].host = "localhost"; search[search_count].family = AF_INET6; ++search_count; break; case AF_UNSPEC: search[search_count].host = "localhost"; search[search_count].family = AF_INET6; ++search_count; search[search_count].host = "localhost"; search[search_count].family = AF_INET; ++search_count; break; default: break; } } } else { // Host is specified. switch (hints->ai_family) { case AF_INET: search[search_count].host = host; search[search_count].family = AF_INET; ++search_count; break; case AF_INET6: search[search_count].host = host; search[search_count].family = AF_INET6; ++search_count; break; case AF_UNSPEC: search[search_count].host = host; search[search_count].family = AF_INET6; ++search_count; search[search_count].host = host; search[search_count].family = AF_INET; ++search_count; break; default: break; } } return search_count;}template <typename T>inline T* gai_alloc(std::size_t size = sizeof(T)){ using namespace std; T* p = static_cast<T*>(::operator new(size, std::nothrow)); if (p) memset(p, 0, size); return p;}inline void gai_free(void* p){ ::operator delete(p);}inline void gai_strcpy(char* target, const char* source, std::size_t max_size){ using namespace std;#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE) strcpy_s(target, max_size, source);#else *target = 0; strncat(target, source, max_size);#endif}enum { gai_clone_flag = 1 << 30 };inline int gai_aistruct(addrinfo_type*** next, const addrinfo_type* hints, const void* addr, int family){ using namespace std; addrinfo_type* ai = gai_alloc<addrinfo_type>(); if (ai == 0) return EAI_MEMORY; ai->ai_next = 0; **next = ai; *next = &ai->ai_next; ai->ai_canonname = 0; ai->ai_socktype = hints->ai_socktype; if (ai->ai_socktype == 0) ai->ai_flags |= gai_clone_flag; ai->ai_protocol = hints->ai_protocol; ai->ai_family = family; switch (ai->ai_family) { case AF_INET: { sockaddr_in4_type* sinptr = gai_alloc<sockaddr_in4_type>(); if (sinptr == 0) return EAI_MEMORY; sinptr->sin_family = AF_INET; memcpy(&sinptr->sin_addr, addr, sizeof(in4_addr_type)); ai->ai_addr = reinterpret_cast<sockaddr*>(sinptr); ai->ai_addrlen = sizeof(sockaddr_in4_type); break; } case AF_INET6: { sockaddr_in6_type* sin6ptr = gai_alloc<sockaddr_in6_type>(); if (sin6ptr == 0) return EAI_MEMORY; sin6ptr->sin6_family = AF_INET6; memcpy(&sin6ptr->sin6_addr, addr, sizeof(in6_addr_type)); ai->ai_addr = reinterpret_cast<sockaddr*>(sin6ptr); ai->ai_addrlen = sizeof(sockaddr_in6_type); break; } default: break; } return 0;}inline addrinfo_type* gai_clone(addrinfo_type* ai){ using namespace std; addrinfo_type* new_ai = gai_alloc<addrinfo_type>(); if (new_ai == 0) return new_ai; new_ai->ai_next = ai->ai_next; ai->ai_next = new_ai; new_ai->ai_flags = 0; new_ai->ai_family = ai->ai_family; new_ai->ai_socktype = ai->ai_socktype; new_ai->ai_protocol = ai->ai_protocol; new_ai->ai_canonname = 0; new_ai->ai_addrlen = ai->ai_addrlen; new_ai->ai_addr = gai_alloc<sockaddr>(ai->ai_addrlen); memcpy(new_ai->ai_addr, ai->ai_addr, ai->ai_addrlen); return new_ai;}inline int gai_port(addrinfo_type* aihead, int port, int socktype){ int num_found = 0; for (addrinfo_type* ai = aihead; ai; ai = ai->ai_next) { if (ai->ai_flags & gai_clone_flag) { if (ai->ai_socktype != 0) { ai = gai_clone(ai); if (ai == 0) return -1; // ai now points to newly cloned entry. } } else if (ai->ai_socktype != socktype) { // Ignore if mismatch on socket type. continue; } ai->ai_socktype = socktype; switch (ai->ai_family) { case AF_INET: { sockaddr_in4_type* sinptr = reinterpret_cast<sockaddr_in4_type*>(ai->ai_addr); sinptr->sin_port = port; ++num_found; break; } case AF_INET6: { sockaddr_in6_type* sin6ptr = reinterpret_cast<sockaddr_in6_type*>(ai->ai_addr); sin6ptr->sin6_port = port; ++num_found; break; } default: break; } } return num_found;}inline int gai_serv(addrinfo_type* aihead, const addrinfo_type* hints, const char* serv){ using namespace std; int num_found = 0; if (#if defined(AI_NUMERICSERV) (hints->ai_flags & AI_NUMERICSERV) ||#endif isdigit(serv[0])) { int port = htons(atoi(serv)); if (hints->ai_socktype) { // Caller specifies socket type. int rc = gai_port(aihead, port, hints->ai_socktype); if (rc < 0) return EAI_MEMORY; num_found += rc; } else { // Caller does not specify socket type. int rc = gai_port(aihead, port, SOCK_STREAM); if (rc < 0) return EAI_MEMORY; num_found += rc; rc = gai_port(aihead, port, SOCK_DGRAM); if (rc < 0) return EAI_MEMORY; num_found += rc; } } else { // Try service name with TCP first, then UDP. if (hints->ai_socktype == 0 || hints->ai_socktype == SOCK_STREAM) { servent* sptr = getservbyname(serv, "tcp"); if (sptr != 0) { int rc = gai_port(aihead, sptr->s_port, SOCK_STREAM); if (rc < 0) return EAI_MEMORY; num_found += rc; } } if (hints->ai_socktype == 0 || hints->ai_socktype == SOCK_DGRAM) { servent* sptr = getservbyname(serv, "udp"); if (sptr != 0) { int rc = gai_port(aihead, sptr->s_port, SOCK_DGRAM); if (rc < 0) return EAI_MEMORY; num_found += rc; } } } if (num_found == 0) { if (hints->ai_socktype == 0) { // All calls to getservbyname() failed. return EAI_NONAME; } else { // Service not supported for socket type. return EAI_SERVICE; } } return 0;}inline int gai_echeck(const char* host, const char* service, int flags, int family, int socktype, int protocol){ (void)(flags); (void)(protocol); // Host or service must be specified. if (host == 0 || host[0] == '\0') if (service == 0 || service[0] == '\0') return EAI_NONAME; // Check combination of family and socket type. switch (family) { case AF_UNSPEC: break; case AF_INET: case AF_INET6: if (socktype != 0 && socktype != SOCK_STREAM && socktype != SOCK_DGRAM) return EAI_SOCKTYPE; break; default: return EAI_FAMILY; } return 0;}inline void freeaddrinfo_emulation(addrinfo_type* aihead){ addrinfo_type* ai = aihead; while (ai) { gai_free(ai->ai_addr); gai_free(ai->ai_canonname); addrinfo_type* ainext = ai->ai_next; gai_free(ai); ai = ainext; }}inline int getaddrinfo_emulation(const char* host, const char* service, const addrinfo_type* hintsp, addrinfo_type** result){ // Set up linked list of addrinfo structures. addrinfo_type* aihead = 0; addrinfo_type** ainext = &aihead; char* canon = 0; // Supply default hints if not specified by caller. addrinfo_type hints = addrinfo_type(); hints.ai_family = AF_UNSPEC; if (hintsp) hints = *hintsp; // If the resolution is not specifically for AF_INET6, remove the AI_V4MAPPED // and AI_ALL flags.#if defined(AI_V4MAPPED) if (hints.ai_family != AF_INET6) hints.ai_flags &= ~AI_V4MAPPED;#endif#if defined(AI_ALL) if (hints.ai_family != AF_INET6) hints.ai_flags &= ~AI_ALL;#endif // Basic error checking. int rc = gai_echeck(host, service, hints.ai_flags, hints.ai_family, hints.ai_socktype, hints.ai_protocol); if (rc != 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -