asyn.h (8715B)
1 #ifndef HEADER_CURL_ASYN_H 2 #define HEADER_CURL_ASYN_H 3 /*************************************************************************** 4 * _ _ ____ _ 5 * Project ___| | | | _ \| | 6 * / __| | | | |_) | | 7 * | (__| |_| | _ <| |___ 8 * \___|\___/|_| \_\_____| 9 * 10 * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 11 * 12 * This software is licensed as described in the file COPYING, which 13 * you should have received as part of this distribution. The terms 14 * are also available at https://curl.se/docs/copyright.html. 15 * 16 * You may opt to use, copy, modify, merge, publish, distribute and/or sell 17 * copies of the Software, and permit persons to whom the Software is 18 * furnished to do so, under the terms of the COPYING file. 19 * 20 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 21 * KIND, either express or implied. 22 * 23 * SPDX-License-Identifier: curl 24 * 25 ***************************************************************************/ 26 27 #include "curl_setup.h" 28 29 struct Curl_easy; 30 struct Curl_dns_entry; 31 32 #ifdef CURLRES_ASYNCH 33 34 #include "curl_addrinfo.h" 35 #include "httpsrr.h" 36 37 struct addrinfo; 38 struct hostent; 39 struct connectdata; 40 41 #if defined(CURLRES_ARES) && defined(CURLRES_THREADED) 42 #error cannot have both CURLRES_ARES and CURLRES_THREADED defined 43 #endif 44 45 /* 46 * This header defines all functions in the internal asynch resolver interface. 47 * All asynch resolvers need to provide these functions. 48 * asyn-ares.c and asyn-thread.c are the current implementations of asynch 49 * resolver backends. 50 */ 51 52 /* 53 * Curl_async_global_init() 54 * 55 * Called from curl_global_init() to initialize global resolver environment. 56 * Returning anything else than CURLE_OK fails curl_global_init(). 57 */ 58 int Curl_async_global_init(void); 59 60 /* 61 * Curl_async_global_cleanup() 62 * Called from curl_global_cleanup() to destroy global resolver environment. 63 */ 64 void Curl_async_global_cleanup(void); 65 66 /* 67 * Curl_async_get_impl() 68 * Get the resolver implementation instance (c-ares channel) or NULL 69 * for passing to application callback. 70 */ 71 CURLcode Curl_async_get_impl(struct Curl_easy *easy, void **impl); 72 73 /* Curl_async_getsock() 74 * 75 * This function is called from the Curl_multi_getsock() function. 'sock' is a 76 * pointer to an array to hold the file descriptors, with 'numsock' being the 77 * size of that array (in number of entries). This function is supposed to 78 * return bitmask indicating what file descriptors (referring to array indexes 79 * in the 'sock' array) to wait for, read/write. 80 */ 81 int Curl_async_getsock(struct Curl_easy *data, curl_socket_t *sock); 82 83 /* 84 * Curl_async_is_resolved() 85 * 86 * Called repeatedly to check if a previous name resolve request has 87 * completed. It should also make sure to time-out if the operation seems to 88 * take too long. 89 * 90 * Returns normal CURLcode errors. 91 */ 92 CURLcode Curl_async_is_resolved(struct Curl_easy *data, 93 struct Curl_dns_entry **dns); 94 95 /* 96 * Curl_async_await() 97 * 98 * Waits for a resolve to finish. This function should be avoided since using 99 * this risk getting the multi interface to "hang". 100 * 101 * On return 'entry' is assigned the resolved dns (CURLE_OK or NULL otherwise. 102 * 103 * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved, 104 * CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors. 105 */ 106 CURLcode Curl_async_await(struct Curl_easy *data, 107 struct Curl_dns_entry **dnsentry); 108 109 /* 110 * Curl_async_getaddrinfo() - when using this resolver 111 * 112 * Returns name information about the given hostname and port number. If 113 * successful, the 'hostent' is returned and the fourth argument will point to 114 * memory we need to free after use. That memory *MUST* be freed with 115 * Curl_freeaddrinfo(), nothing else. 116 * 117 * Each resolver backend must of course make sure to return data in the 118 * correct format to comply with this. 119 */ 120 struct Curl_addrinfo *Curl_async_getaddrinfo(struct Curl_easy *data, 121 const char *hostname, 122 int port, 123 int ip_version, 124 int *waitp); 125 126 #ifdef USE_ARES 127 /* common functions for c-ares and threaded resolver with HTTPSRR */ 128 #include <ares.h> 129 130 int Curl_ares_getsock(struct Curl_easy *data, 131 ares_channel channel, 132 curl_socket_t *socks); 133 int Curl_ares_perform(ares_channel channel, 134 timediff_t timeout_ms); 135 #endif 136 137 #ifdef CURLRES_ARES 138 /* async resolving implementation using c-ares alone */ 139 struct async_ares_ctx { 140 ares_channel channel; 141 int num_pending; /* number of outstanding c-ares requests */ 142 struct Curl_addrinfo *temp_ai; /* intermediary result while fetching c-ares 143 parts */ 144 int last_status; 145 CURLcode result; /* CURLE_OK or error handling response */ 146 #ifndef HAVE_CARES_GETADDRINFO 147 struct curltime happy_eyeballs_dns_time; /* when this timer started, or 0 */ 148 #endif 149 #ifdef USE_HTTPSRR 150 struct Curl_https_rrinfo hinfo; 151 #endif 152 }; 153 154 void Curl_async_ares_shutdown(struct Curl_easy *data); 155 void Curl_async_ares_destroy(struct Curl_easy *data); 156 157 /* Set the DNS server to use by ares, from `data` settings. */ 158 CURLcode Curl_async_ares_set_dns_servers(struct Curl_easy *data); 159 160 /* Set the DNS interfacer to use by ares, from `data` settings. */ 161 CURLcode Curl_async_ares_set_dns_interface(struct Curl_easy *data); 162 163 /* Set the local ipv4 address to use by ares, from `data` settings. */ 164 CURLcode Curl_async_ares_set_dns_local_ip4(struct Curl_easy *data); 165 166 /* Set the local ipv6 address to use by ares, from `data` settings. */ 167 CURLcode Curl_async_ares_set_dns_local_ip6(struct Curl_easy *data); 168 169 #endif /* CURLRES_ARES */ 170 171 #ifdef CURLRES_THREADED 172 /* async resolving implementation using POSIX threads */ 173 #include "curl_threads.h" 174 175 /* Context for threaded address resolver */ 176 struct async_thrdd_addr_ctx { 177 curl_thread_t thread_hnd; 178 char *hostname; /* hostname to resolve, Curl_async.hostname 179 duplicate */ 180 curl_mutex_t mutx; 181 #ifndef CURL_DISABLE_SOCKETPAIR 182 curl_socket_t sock_pair[2]; /* eventfd/pipes/socket pair */ 183 #endif 184 struct Curl_addrinfo *res; 185 #ifdef HAVE_GETADDRINFO 186 struct addrinfo hints; 187 #endif 188 struct curltime start; 189 timediff_t interval_end; 190 unsigned int poll_interval; 191 int port; 192 int sock_error; 193 int ref_count; 194 }; 195 196 /* Context for threaded resolver */ 197 struct async_thrdd_ctx { 198 /* `addr` is a pointer since this memory is shared with a started 199 * thread. Since threads cannot be killed, we use reference counting 200 * so that we can "release" our pointer to this memory while the 201 * thread is still running. */ 202 struct async_thrdd_addr_ctx *addr; 203 #if defined(USE_HTTPSRR) && defined(USE_ARES) 204 struct { 205 ares_channel channel; 206 struct Curl_https_rrinfo hinfo; 207 CURLcode result; 208 BIT(done); 209 } rr; 210 #endif 211 }; 212 213 void Curl_async_thrdd_shutdown(struct Curl_easy *data); 214 void Curl_async_thrdd_destroy(struct Curl_easy *data); 215 216 #endif /* CURLRES_THREADED */ 217 218 #ifndef CURL_DISABLE_DOH 219 struct doh_probes; 220 #endif 221 222 #else /* CURLRES_ASYNCH */ 223 224 /* convert these functions if an asynch resolver is not used */ 225 #define Curl_async_get_impl(x,y) (*(y) = NULL, CURLE_OK) 226 #define Curl_async_is_resolved(x,y) CURLE_COULDNT_RESOLVE_HOST 227 #define Curl_async_await(x,y) CURLE_COULDNT_RESOLVE_HOST 228 #define Curl_async_global_init() CURLE_OK 229 #define Curl_async_global_cleanup() Curl_nop_stmt 230 231 #endif /* !CURLRES_ASYNCH */ 232 233 #if defined(CURLRES_ASYNCH) || !defined(CURL_DISABLE_DOH) 234 #define USE_CURL_ASYNC 235 #endif 236 237 #ifdef USE_CURL_ASYNC 238 struct Curl_async { 239 #ifdef CURLRES_ARES /* */ 240 struct async_ares_ctx ares; 241 #elif defined(CURLRES_THREADED) 242 struct async_thrdd_ctx thrdd; 243 #endif 244 #ifndef CURL_DISABLE_DOH 245 struct doh_probes *doh; /* DoH specific data for this request */ 246 #endif 247 struct Curl_dns_entry *dns; /* result of resolving on success */ 248 char *hostname; /* copy of the params resolv started with */ 249 int port; 250 int ip_version; 251 BIT(done); 252 }; 253 254 /* 255 * Curl_async_shutdown(). 256 * 257 * This shuts down all ongoing operations. 258 */ 259 void Curl_async_shutdown(struct Curl_easy *data); 260 261 /* 262 * Curl_async_destroy(). 263 * 264 * This frees the resources of any async resolve. 265 */ 266 void Curl_async_destroy(struct Curl_easy *data); 267 #else /* !USE_CURL_ASYNC */ 268 #define Curl_async_shutdown(x) Curl_nop_stmt 269 #define Curl_async_destroy(x) Curl_nop_stmt 270 #endif /* USE_CURL_ASYNC */ 271 272 273 /********** end of generic resolver interface functions *****************/ 274 #endif /* HEADER_CURL_ASYN_H */