/src/gdal/curl/lib/asyn-base.c
Line  | Count  | Source  | 
1  |  | /***************************************************************************  | 
2  |  |  *                                  _   _ ____  _  | 
3  |  |  *  Project                     ___| | | |  _ \| |  | 
4  |  |  *                             / __| | | | |_) | |  | 
5  |  |  *                            | (__| |_| |  _ <| |___  | 
6  |  |  *                             \___|\___/|_| \_\_____|  | 
7  |  |  *  | 
8  |  |  * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.  | 
9  |  |  *  | 
10  |  |  * This software is licensed as described in the file COPYING, which  | 
11  |  |  * you should have received as part of this distribution. The terms  | 
12  |  |  * are also available at https://curl.se/docs/copyright.html.  | 
13  |  |  *  | 
14  |  |  * You may opt to use, copy, modify, merge, publish, distribute and/or sell  | 
15  |  |  * copies of the Software, and permit persons to whom the Software is  | 
16  |  |  * furnished to do so, under the terms of the COPYING file.  | 
17  |  |  *  | 
18  |  |  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY  | 
19  |  |  * KIND, either express or implied.  | 
20  |  |  *  | 
21  |  |  * SPDX-License-Identifier: curl  | 
22  |  |  *  | 
23  |  |  ***************************************************************************/  | 
24  |  |  | 
25  |  | #include "curl_setup.h"  | 
26  |  |  | 
27  |  | #ifdef HAVE_NETINET_IN_H  | 
28  |  | #include <netinet/in.h>  | 
29  |  | #endif  | 
30  |  | #ifdef HAVE_NETDB_H  | 
31  |  | #include <netdb.h>  | 
32  |  | #endif  | 
33  |  | #ifdef HAVE_ARPA_INET_H  | 
34  |  | #include <arpa/inet.h>  | 
35  |  | #endif  | 
36  |  | #ifdef __VMS  | 
37  |  | #include <in.h>  | 
38  |  | #include <inet.h>  | 
39  |  | #endif  | 
40  |  |  | 
41  |  | #ifdef USE_ARES  | 
42  |  | #include <ares.h>  | 
43  |  | #include <ares_version.h> /* really old c-ares did not include this by  | 
44  |  |                              itself */  | 
45  |  | #endif  | 
46  |  |  | 
47  |  | #include "urldata.h"  | 
48  |  | #include "asyn.h"  | 
49  |  | #include "sendf.h"  | 
50  |  | #include "hostip.h"  | 
51  |  | #include "hash.h"  | 
52  |  | #include "multiif.h"  | 
53  |  | #include "select.h"  | 
54  |  | #include "share.h"  | 
55  |  | #include "url.h"  | 
56  |  | #include "curl_memory.h"  | 
57  |  | /* The last #include file should be: */  | 
58  |  | #include "memdebug.h"  | 
59  |  |  | 
60  |  | /***********************************************************************  | 
61  |  |  * Only for builds using asynchronous name resolves  | 
62  |  |  **********************************************************************/  | 
63  |  | #ifdef CURLRES_ASYNCH  | 
64  |  |  | 
65  |  |  | 
66  |  | #ifdef USE_ARES  | 
67  |  |  | 
68  |  | #if ARES_VERSION < 0x010600  | 
69  |  | #error "requires c-ares 1.6.0 or newer"  | 
70  |  | #endif  | 
71  |  |  | 
72  |  | /*  | 
73  |  |  * Curl_ares_getsock() is called when the outside world (using  | 
74  |  |  * curl_multi_fdset()) wants to get our fd_set setup and we are talking with  | 
75  |  |  * ares. The caller must make sure that this function is only called when we  | 
76  |  |  * have a working ares channel.  | 
77  |  |  *  | 
78  |  |  * Returns: sockets-in-use-bitmap  | 
79  |  |  */  | 
80  |  |  | 
81  |  | int Curl_ares_getsock(struct Curl_easy *data,  | 
82  |  |                       ares_channel channel,  | 
83  |  |                       curl_socket_t *socks)  | 
84  |  | { | 
85  |  |   struct timeval maxtime = { CURL_TIMEOUT_RESOLVE, 0 }; | 
86  |  |   struct timeval timebuf;  | 
87  |  |   int max = ares_getsock(channel,  | 
88  |  |                          (ares_socket_t *)socks, MAX_SOCKSPEREASYHANDLE);  | 
89  |  |   struct timeval *timeout = ares_timeout(channel, &maxtime, &timebuf);  | 
90  |  |   timediff_t milli = curlx_tvtoms(timeout);  | 
91  |  |   Curl_expire(data, milli, EXPIRE_ASYNC_NAME);  | 
92  |  |   return max;  | 
93  |  | }  | 
94  |  |  | 
95  |  | /*  | 
96  |  |  * Curl_ares_perform()  | 
97  |  |  *  | 
98  |  |  * 1) Ask ares what sockets it currently plays with, then  | 
99  |  |  * 2) wait for the timeout period to check for action on ares' sockets.  | 
100  |  |  * 3) tell ares to act on all the sockets marked as "with action"  | 
101  |  |  *  | 
102  |  |  * return number of sockets it worked on, or -1 on error  | 
103  |  |  */  | 
104  |  | int Curl_ares_perform(ares_channel channel,  | 
105  |  |                       timediff_t timeout_ms)  | 
106  |  | { | 
107  |  |   int nfds;  | 
108  |  |   int bitmask;  | 
109  |  |   ares_socket_t socks[ARES_GETSOCK_MAXNUM];  | 
110  |  |   struct pollfd pfd[ARES_GETSOCK_MAXNUM];  | 
111  |  |   int i;  | 
112  |  |   int num = 0;  | 
113  |  |  | 
114  |  |   if(!channel)  | 
115  |  |     return 0;  | 
116  |  |  | 
117  |  |   bitmask = ares_getsock(channel, socks, ARES_GETSOCK_MAXNUM);  | 
118  |  |  | 
119  |  |   for(i = 0; i < ARES_GETSOCK_MAXNUM; i++) { | 
120  |  |     pfd[i].events = 0;  | 
121  |  |     pfd[i].revents = 0;  | 
122  |  |     if(ARES_GETSOCK_READABLE(bitmask, i)) { | 
123  |  |       pfd[i].fd = socks[i];  | 
124  |  |       pfd[i].events |= POLLRDNORM|POLLIN;  | 
125  |  |     }  | 
126  |  |     if(ARES_GETSOCK_WRITABLE(bitmask, i)) { | 
127  |  |       pfd[i].fd = socks[i];  | 
128  |  |       pfd[i].events |= POLLWRNORM|POLLOUT;  | 
129  |  |     }  | 
130  |  |     if(pfd[i].events)  | 
131  |  |       num++;  | 
132  |  |     else  | 
133  |  |       break;  | 
134  |  |   }  | 
135  |  |  | 
136  |  |   if(num) { | 
137  |  |     nfds = Curl_poll(pfd, (unsigned int)num, timeout_ms);  | 
138  |  |     if(nfds < 0)  | 
139  |  |       return -1;  | 
140  |  |   }  | 
141  |  |   else  | 
142  |  |     nfds = 0;  | 
143  |  |  | 
144  |  |   if(!nfds)  | 
145  |  |     /* Call ares_process() unconditionally here, even if we simply timed out  | 
146  |  |        above, as otherwise the ares name resolve will not timeout! */  | 
147  |  |     ares_process_fd(channel, ARES_SOCKET_BAD, ARES_SOCKET_BAD);  | 
148  |  |   else { | 
149  |  |     /* move through the descriptors and ask for processing on them */  | 
150  |  |     for(i = 0; i < num; i++)  | 
151  |  |       ares_process_fd(channel,  | 
152  |  |                       (pfd[i].revents & (POLLRDNORM|POLLIN)) ?  | 
153  |  |                       pfd[i].fd : ARES_SOCKET_BAD,  | 
154  |  |                       (pfd[i].revents & (POLLWRNORM|POLLOUT)) ?  | 
155  |  |                       pfd[i].fd : ARES_SOCKET_BAD);  | 
156  |  |   }  | 
157  |  |   return nfds;  | 
158  |  | }  | 
159  |  |  | 
160  |  | #endif  | 
161  |  |  | 
162  |  | #endif /* CURLRES_ASYNCH */  | 
163  |  |  | 
164  |  | #ifdef USE_CURL_ASYNC  | 
165  |  |  | 
166  |  | #include "doh.h"  | 
167  |  |  | 
168  |  | void Curl_async_shutdown(struct Curl_easy *data)  | 
169  | 1.12k  | { | 
170  |  | #ifdef CURLRES_ARES  | 
171  |  |   Curl_async_ares_shutdown(data);  | 
172  |  | #endif  | 
173  | 1.12k  | #ifdef CURLRES_THREADED  | 
174  | 1.12k  |   Curl_async_thrdd_shutdown(data);  | 
175  | 1.12k  | #endif  | 
176  | 1.12k  | #ifndef CURL_DISABLE_DOH  | 
177  | 1.12k  |   Curl_doh_cleanup(data);  | 
178  | 1.12k  | #endif  | 
179  | 1.12k  |   Curl_safefree(data->state.async.hostname);  | 
180  | 1.12k  | }  | 
181  |  |  | 
182  |  | void Curl_async_destroy(struct Curl_easy *data)  | 
183  | 142k  | { | 
184  |  | #ifdef CURLRES_ARES  | 
185  |  |   Curl_async_ares_destroy(data);  | 
186  |  | #endif  | 
187  | 142k  | #ifdef CURLRES_THREADED  | 
188  | 142k  |   Curl_async_thrdd_destroy(data);  | 
189  | 142k  | #endif  | 
190  | 142k  | #ifndef CURL_DISABLE_DOH  | 
191  | 142k  |   Curl_doh_cleanup(data);  | 
192  | 142k  | #endif  | 
193  | 142k  |   Curl_safefree(data->state.async.hostname);  | 
194  | 142k  | }  | 
195  |  |  | 
196  |  | #endif /* USE_CURL_ASYNC */  |