21#ifndef G_GETADDRINFO_H
22#define G_GETADDRINFO_H
35 inline int getaddrinfo(
const char * host_in ,
const char * service_in , addrinfo * hint_in , addrinfo ** results_out )
37 using ADDRINFO_type = G::nowide::ADDRINFO_type ;
38 std::string host( host_in ? host_in :
"" ) ;
39 std::string service( service_in ? service_in :
"" ) ;
40 ADDRINFO_type win_hint {} ;
43 win_hint.ai_flags = hint_in->ai_flags ;
44 win_hint.ai_family = hint_in->ai_family ;
45 win_hint.ai_socktype = hint_in->ai_socktype ;
46 win_hint.ai_protocol = hint_in->ai_protocol ;
47 win_hint.ai_addrlen = hint_in->ai_addrlen ;
48 win_hint.ai_addr = hint_in->ai_addr ;
49 win_hint.ai_next = nullptr ;
50 win_hint.ai_canonname = nullptr ;
52 *results_out = nullptr ;
53 ADDRINFO_type * win_results = nullptr ;
54 auto rc = G::nowide::getAddrInfo( host , service , hint_in ? &win_hint :
nullptr , &win_results ) ;
57 addrinfo * last_result = nullptr ;
58 for( ADDRINFO_type * p = win_results ; p ; p = p->ai_next )
60 addrinfo * result =
new addrinfo ;
61 std::memset( result , 0 ,
sizeof(*result) ) ;
62 result->ai_flags = p->ai_flags ;
63 result->ai_family = p->ai_family ;
64 result->ai_socktype = p->ai_socktype ;
65 result->ai_protocol = p->ai_protocol ;
66 result->ai_addrlen = p->ai_addrlen ;
67 result->ai_canonname = nullptr ;
68 std::string canonical_name = G::nowide::canonicalName( *p ) ;
69 result->ai_addr =
static_cast<sockaddr*
>( std::malloc( p->ai_addrlen ) ) ;
70 if( result->ai_addr ==
nullptr )
71 throw std::bad_alloc() ;
72 std::memcpy( result->ai_addr , p->ai_addr , p->ai_addrlen ) ;
73 if( !canonical_name.empty() )
74 result->ai_canonname = _strdup( canonical_name.c_str() ) ;
75 result->ai_next = nullptr ;
77 if( *results_out ==
nullptr )
78 *results_out = result ;
80 last_result->ai_next = result ;
81 last_result = result ;
84 G::nowide::freeAddrInfo( win_results ) ;
87 inline void freeaddrinfo( addrinfo * results )
noexcept
89 for( addrinfo * p = results ; p ; )
91 std::free( p->ai_canonname ) ;
92 std::free( p->ai_addr ) ;
93 auto next = p->ai_next ;
98 inline const char * gai_strerror(
int rc )
noexcept
100 if( rc == EAI_AGAIN )
return "temporary failure in name resolution" ;
101 if( rc == EAI_BADFLAGS )
return "invalid value in ai_flags" ;
102 if( rc == EAI_FAIL )
return "nonrecoverable failure in name resolution" ;
103 if( rc == EAI_FAMILY )
return "ai_family not supported" ;
104 if( rc == EAI_MEMORY )
return "memory allocation failure" ;
105 if( rc == EAI_NONAME )
return "name does not resolve" ;
106 if( rc == EAI_SERVICE )
return "invalid service" ;
107 if( rc == EAI_SOCKTYPE )
return "ai_socktype not supported" ;
108 return "getaddrinfo error" ;
110 static_assert( EAI_AGAIN == WSATRY_AGAIN ,
"" ) ;
111 static_assert( EAI_BADFLAGS == WSAEINVAL ,
"" ) ;
112 static_assert( EAI_FAIL == WSANO_RECOVERY ,
"" ) ;
113 static_assert( EAI_FAMILY == WSAEAFNOSUPPORT ,
"" ) ;
114 static_assert( EAI_MEMORY == WSA_NOT_ENOUGH_MEMORY ,
"" ) ;
115 static_assert( EAI_NONAME == WSAHOST_NOT_FOUND ,
"" ) ;
116 static_assert( EAI_SERVICE == WSATYPE_NOT_FOUND ,
"" ) ;
117 static_assert( EAI_SOCKTYPE == WSAESOCKTNOSUPPORT ,
"" ) ;
123 namespace GetAddrInfo
125 using ::getaddrinfo ;
126 using ::freeaddrinfo ;
127 using ::gai_strerror ;
Contains inline functions that convert to and from UTF-8 strings in order to call wide-character "W()...