E-MailRelay

ggetaddrinfo.h
Go to the documentation of this file.
1//
2// Copyright (C) 2001-2024 Graeme Walker <graeme_walker@users.sourceforge.net>
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program. If not, see <http://www.gnu.org/licenses/>.
16// ===
17///
18/// \file ggetaddrinfo.h
19///
20
21#ifndef G_GETADDRINFO_H
22#define G_GETADDRINFO_H
23
24#include "gdef.h"
25#ifdef G_WINDOWS
26#include "gnowide.h"
27#include "gstr.h"
28#include <cstdlib> // std::malloc()
29#include <cstring> // _strdup(), std::memcpy()
30#include <stdexcept>
31 namespace GNet
32{
33 namespace GetAddrInfo
34 {
35 inline int getaddrinfo( const char * host_in , const char * service_in , addrinfo * hint_in , addrinfo ** results_out )
36 {
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 {} ;
41 if( hint_in )
42 {
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 ;
51 }
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 ) ;
55 if( rc == 0 )
56 {
57 addrinfo * last_result = nullptr ;
58 for( ADDRINFO_type * p = win_results ; p ; p = p->ai_next )
59 {
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 ;
76
77 if( *results_out == nullptr )
78 *results_out = result ;
79 if( last_result )
80 last_result->ai_next = result ;
81 last_result = result ;
82 }
83 }
84 G::nowide::freeAddrInfo( win_results ) ;
85 return rc ;
86 }
87 inline void freeaddrinfo( addrinfo * results ) noexcept
88 {
89 for( addrinfo * p = results ; p ; )
90 {
91 std::free( p->ai_canonname ) ;
92 std::free( p->ai_addr ) ;
93 auto next = p->ai_next ;
94 delete p ;
95 p = next ;
96 }
97 }
98 inline const char * gai_strerror( int rc ) noexcept
99 {
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" ;
109 }
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 , "" ) ;
118 }
119}
120#else
121 namespace GNet
122{
123 namespace GetAddrInfo
124 {
125 using ::getaddrinfo ;
126 using ::freeaddrinfo ;
127 using ::gai_strerror ;
128 }
129}
130#endif
131
132#endif
gnowide.h
Contains inline functions that convert to and from UTF-8 strings in order to call wide-character "W()...
gstr.h
GNet
Network classes.
Definition: gdef.h:1243