3 /* async_netdb.h, Copyright (c) Dave Odell <dmo2118@gmail.com>
5 * Permission to use, copy, modify, distribute, and sell this software and its
6 * documentation for any purpose is hereby granted without fee, provided that
7 * the above copyright notice appear in all copies and that both that
8 * copyright notice and this permission notice appear in supporting
9 * documentation. No representations are made about the suitability of this
10 * software for any purpose. It is provided "as is" without express or
17 #include "thread_util.h"
20 #include <netinet/in.h>
21 #include <sys/socket.h>
25 Both async_name_from_addr_* and async_addr_from_name_* follow basic pattern
26 for io_thread clients as described in thread_util.h:
27 1. async_*_from_*_start
28 2. async_*_from_*_is_done (repeat as necessary)
29 3a. async_*_from_*_finish to retrieve the results, or:
30 3b. async_*_from_*_cancel to abort the lookup.
32 On systems that can't do asynchronous host lookups, the *_finish functions
38 From the glibc man page for getnameinfo(3):
39 Since glibc 2.8, these definitions are exposed only if one of the
40 feature test macros _BSD_SOURCE, _SVID_SOURCE, or _GNU_SOURCE is
43 # define NI_MAXHOST 1025
46 #if HAVE_PTHREAD && HAVE_GETADDRINFO
48 If threads or getaddrinfo() are unavailable, then the older gethostbyname()
49 and gethostbyaddr() functions are used, and IPv6 is disabled.
51 # define ASYNC_NETDB_USE_GAI 1
54 #if ASYNC_NETDB_USE_GAI
56 /* Without using union, gcc-6 warns for
57 breaking strict aliasing rules
60 struct sockaddr_storage x_sockaddr_storage;
61 struct sockaddr_in x_sockaddr_in;
62 struct sockaddr_in6 x_sockaddr_in6;
63 } async_netdb_sockaddr_storage_t;
65 int _async_netdb_is_done (struct io_thread *io);
69 /* Because the definition for the above case is now union,
70 the definition for this case must also be union...
73 struct sockaddr_in x_sockaddr_in;
74 } async_netdb_sockaddr_storage_t;
77 /* The EAI_* codes are specified specifically as preprocessor macros, so
78 the #ifdef here should always work...
79 http://pubs.opengroup.org/onlinepubs/009604499/basedefs/netdb.h.html */
81 # define ASYNC_NETDB_FAKE_EAI 1
83 /* Even without addrinfo, the EAI_* error codes are used. The numbers are from
85 # define EAI_NONAME -2
88 # define EAI_MEMORY -10
89 # define EAI_SYSTEM -11
91 const char *_async_netdb_strerror (int errcode);
93 # define gai_strerror(errcode) _async_netdb_strerror (errcode)
96 # define _async_netdb_is_done(io) 1
100 /* In non-threaded mode, _async_name_from_addr_param is used in place of
101 async_name_from_addr. */
102 struct _async_name_from_addr_param
105 async_netdb_sockaddr_storage_t addr;
108 typedef struct async_name_from_addr
111 Stupid memory trick, thwarted: The host string could be at the beginning
112 of this structure, and the memory block that contains this struct could
113 be resized and returned directly in async_name_from_addr_finish. But...
115 There is no aligned_realloc. In fact, aligned_realloc is a bit of a
116 problem, mostly because:
117 1. realloc() is the only way to resize a heap-allocated memory block.
118 2. realloc() moves memory.
119 3. The location that realloc() moves memory to won't be aligned.
122 struct _async_name_from_addr_param param;
125 char host[NI_MAXHOST];
129 } *async_name_from_addr_t;
131 async_name_from_addr_t async_name_from_addr_start (Display *dpy,
132 const struct sockaddr *addr,
135 Starts an asynchronous name-from-address lookup.
136 dpy: An X11 Display with a .useThreads resource.
137 addr: An address. Like various socket functions (e.g. bind(2),
138 connect(2), sendto(2)), this isn't really a struct sockaddr so
139 much as a "subtype" of sockaddr, like sockaddr_in, or
140 sockaddr_in6, or whatever.
141 addrlen: The (actual) length of *addr.
142 Returns NULL if the request couldn't be created (due to low memory).
145 #define async_name_from_addr_is_done(self) _async_netdb_is_done (&(self)->io)
147 #if ASYNC_NETDB_USE_GAI
148 void async_name_from_addr_cancel (async_name_from_addr_t self);
150 # define async_name_from_addr_cancel(self) (free (self))
153 int async_name_from_addr_finish (async_name_from_addr_t self,
154 char **host, int *errno_error);
156 Gets the result of an asynchronous name-from-address lookup. If the lookup
157 operation is still in progress, or if the system can't do async lookups,
158 this will block. This cleans up the lookup operation; do not use 'self'
159 after calling this function.
160 self: The lookup operation.
161 host: If no error, the name of the host. Free this with free(3).
162 errno_error: The value of errno if EAI_SYSTEM is returned. Can be NULL.
163 Returns 0 on success, otherwise an error from getnameinfo(3).
166 /* In non-threaded mode, async_addr_from_name contains different stuff. */
167 typedef struct async_addr_from_name
169 #if ASYNC_NETDB_USE_GAI
175 struct addrinfo *res;
177 char dont_complain_about_empty_structs;
179 } *async_addr_from_name_t;
181 async_addr_from_name_t async_addr_from_name_start (Display *dpy,
184 Starts an asynchronous address-from-name lookup.
186 host: The hostname to look up.
187 Returns NULL if the request couldn't be created (due to low memory).
190 #define async_addr_from_name_is_done(self) _async_netdb_is_done (&(self)->io)
192 #if ASYNC_NETDB_USE_GAI
193 void async_addr_from_name_cancel (async_addr_from_name_t self);
195 # define async_addr_from_name_cancel(self) (thread_free (self));
198 /* sockaddr must be sizeof(async_netdb_sockaddr_storage_t) in size. */
199 int async_addr_from_name_finish (async_addr_from_name_t self, void *addr,
200 socklen_t *addrlen, int *errno_error);
202 Returns the address from an asynchronous address-from-name operation. If
203 the lookup is still in progress, or the system can't do an asynchronous
204 lookup, this blocks. This cleans up the lookup operation; do not use 'self'
205 after calling this function.
206 self: The lookup operation.
207 addr: A sockaddr. This must be as large as or larger than
208 sizeof(async_netdb_sockaddr_storage_t). (Hint: just use an
209 instance of async_netdb_sockaddr_storage_t itself here.)
210 addrlen: The length of the obtained sockaddr.
211 errno_error: The value of errno if EAI_SYSTEM is returned. Can be NULL.
212 Returns 0 on success, or an error from getaddrinfo(3).
217 /* Local Variables: */
219 /* fill-column: 78 */
220 /* c-file-style: "gnu" */
221 /* c-basic-offset: 2 */
222 /* indent-tabs-mode: nil */