1*6236dae4SAndroid Build Coastguard Worker /***************************************************************************
2*6236dae4SAndroid Build Coastguard Worker * _ _ ____ _
3*6236dae4SAndroid Build Coastguard Worker * Project ___| | | | _ \| |
4*6236dae4SAndroid Build Coastguard Worker * / __| | | | |_) | |
5*6236dae4SAndroid Build Coastguard Worker * | (__| |_| | _ <| |___
6*6236dae4SAndroid Build Coastguard Worker * \___|\___/|_| \_\_____|
7*6236dae4SAndroid Build Coastguard Worker *
8*6236dae4SAndroid Build Coastguard Worker * Copyright (C) Daniel Stenberg, <[email protected]>, et al.
9*6236dae4SAndroid Build Coastguard Worker *
10*6236dae4SAndroid Build Coastguard Worker * This software is licensed as described in the file COPYING, which
11*6236dae4SAndroid Build Coastguard Worker * you should have received as part of this distribution. The terms
12*6236dae4SAndroid Build Coastguard Worker * are also available at https://curl.se/docs/copyright.html.
13*6236dae4SAndroid Build Coastguard Worker *
14*6236dae4SAndroid Build Coastguard Worker * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15*6236dae4SAndroid Build Coastguard Worker * copies of the Software, and permit persons to whom the Software is
16*6236dae4SAndroid Build Coastguard Worker * furnished to do so, under the terms of the COPYING file.
17*6236dae4SAndroid Build Coastguard Worker *
18*6236dae4SAndroid Build Coastguard Worker * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19*6236dae4SAndroid Build Coastguard Worker * KIND, either express or implied.
20*6236dae4SAndroid Build Coastguard Worker *
21*6236dae4SAndroid Build Coastguard Worker * SPDX-License-Identifier: curl
22*6236dae4SAndroid Build Coastguard Worker *
23*6236dae4SAndroid Build Coastguard Worker ***************************************************************************/
24*6236dae4SAndroid Build Coastguard Worker
25*6236dae4SAndroid Build Coastguard Worker #include "curl_setup.h"
26*6236dae4SAndroid Build Coastguard Worker
27*6236dae4SAndroid Build Coastguard Worker #include <curl/curl.h>
28*6236dae4SAndroid Build Coastguard Worker
29*6236dae4SAndroid Build Coastguard Worker #include "urldata.h"
30*6236dae4SAndroid Build Coastguard Worker #include "transfer.h"
31*6236dae4SAndroid Build Coastguard Worker #include "url.h"
32*6236dae4SAndroid Build Coastguard Worker #include "cfilters.h"
33*6236dae4SAndroid Build Coastguard Worker #include "connect.h"
34*6236dae4SAndroid Build Coastguard Worker #include "progress.h"
35*6236dae4SAndroid Build Coastguard Worker #include "easyif.h"
36*6236dae4SAndroid Build Coastguard Worker #include "share.h"
37*6236dae4SAndroid Build Coastguard Worker #include "psl.h"
38*6236dae4SAndroid Build Coastguard Worker #include "multiif.h"
39*6236dae4SAndroid Build Coastguard Worker #include "sendf.h"
40*6236dae4SAndroid Build Coastguard Worker #include "timeval.h"
41*6236dae4SAndroid Build Coastguard Worker #include "http.h"
42*6236dae4SAndroid Build Coastguard Worker #include "select.h"
43*6236dae4SAndroid Build Coastguard Worker #include "warnless.h"
44*6236dae4SAndroid Build Coastguard Worker #include "speedcheck.h"
45*6236dae4SAndroid Build Coastguard Worker #include "conncache.h"
46*6236dae4SAndroid Build Coastguard Worker #include "multihandle.h"
47*6236dae4SAndroid Build Coastguard Worker #include "sigpipe.h"
48*6236dae4SAndroid Build Coastguard Worker #include "vtls/vtls.h"
49*6236dae4SAndroid Build Coastguard Worker #include "http_proxy.h"
50*6236dae4SAndroid Build Coastguard Worker #include "http2.h"
51*6236dae4SAndroid Build Coastguard Worker #include "socketpair.h"
52*6236dae4SAndroid Build Coastguard Worker #include "socks.h"
53*6236dae4SAndroid Build Coastguard Worker #include "urlapi-int.h"
54*6236dae4SAndroid Build Coastguard Worker /* The last 3 #include files should be in this order */
55*6236dae4SAndroid Build Coastguard Worker #include "curl_printf.h"
56*6236dae4SAndroid Build Coastguard Worker #include "curl_memory.h"
57*6236dae4SAndroid Build Coastguard Worker #include "memdebug.h"
58*6236dae4SAndroid Build Coastguard Worker
59*6236dae4SAndroid Build Coastguard Worker /*
60*6236dae4SAndroid Build Coastguard Worker CURL_SOCKET_HASH_TABLE_SIZE should be a prime number. Increasing it from 97
61*6236dae4SAndroid Build Coastguard Worker to 911 takes on a 32-bit machine 4 x 804 = 3211 more bytes. Still, every
62*6236dae4SAndroid Build Coastguard Worker CURL handle takes 45-50 K memory, therefore this 3K are not significant.
63*6236dae4SAndroid Build Coastguard Worker */
64*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_SOCKET_HASH_TABLE_SIZE
65*6236dae4SAndroid Build Coastguard Worker #define CURL_SOCKET_HASH_TABLE_SIZE 911
66*6236dae4SAndroid Build Coastguard Worker #endif
67*6236dae4SAndroid Build Coastguard Worker
68*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_CONNECTION_HASH_SIZE
69*6236dae4SAndroid Build Coastguard Worker #define CURL_CONNECTION_HASH_SIZE 97
70*6236dae4SAndroid Build Coastguard Worker #endif
71*6236dae4SAndroid Build Coastguard Worker
72*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DNS_HASH_SIZE
73*6236dae4SAndroid Build Coastguard Worker #define CURL_DNS_HASH_SIZE 71
74*6236dae4SAndroid Build Coastguard Worker #endif
75*6236dae4SAndroid Build Coastguard Worker
76*6236dae4SAndroid Build Coastguard Worker #define CURL_MULTI_HANDLE 0x000bab1e
77*6236dae4SAndroid Build Coastguard Worker
78*6236dae4SAndroid Build Coastguard Worker #ifdef DEBUGBUILD
79*6236dae4SAndroid Build Coastguard Worker /* On a debug build, we want to fail hard on multi handles that
80*6236dae4SAndroid Build Coastguard Worker * are not NULL, but no longer have the MAGIC touch. This gives
81*6236dae4SAndroid Build Coastguard Worker * us early warning on things only discovered by valgrind otherwise. */
82*6236dae4SAndroid Build Coastguard Worker #define GOOD_MULTI_HANDLE(x) \
83*6236dae4SAndroid Build Coastguard Worker (((x) && (x)->magic == CURL_MULTI_HANDLE)? TRUE: \
84*6236dae4SAndroid Build Coastguard Worker (DEBUGASSERT(!(x)), FALSE))
85*6236dae4SAndroid Build Coastguard Worker #else
86*6236dae4SAndroid Build Coastguard Worker #define GOOD_MULTI_HANDLE(x) \
87*6236dae4SAndroid Build Coastguard Worker ((x) && (x)->magic == CURL_MULTI_HANDLE)
88*6236dae4SAndroid Build Coastguard Worker #endif
89*6236dae4SAndroid Build Coastguard Worker
90*6236dae4SAndroid Build Coastguard Worker static void move_pending_to_connect(struct Curl_multi *multi,
91*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data);
92*6236dae4SAndroid Build Coastguard Worker static CURLMcode singlesocket(struct Curl_multi *multi,
93*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data);
94*6236dae4SAndroid Build Coastguard Worker static CURLMcode add_next_timeout(struct curltime now,
95*6236dae4SAndroid Build Coastguard Worker struct Curl_multi *multi,
96*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *d);
97*6236dae4SAndroid Build Coastguard Worker static CURLMcode multi_timeout(struct Curl_multi *multi,
98*6236dae4SAndroid Build Coastguard Worker struct curltime *expire_time,
99*6236dae4SAndroid Build Coastguard Worker long *timeout_ms);
100*6236dae4SAndroid Build Coastguard Worker static void process_pending_handles(struct Curl_multi *multi);
101*6236dae4SAndroid Build Coastguard Worker static void multi_xfer_bufs_free(struct Curl_multi *multi);
102*6236dae4SAndroid Build Coastguard Worker static void expire_ex(struct Curl_easy *data, const struct curltime *nowp,
103*6236dae4SAndroid Build Coastguard Worker timediff_t milli, expire_id id);
104*6236dae4SAndroid Build Coastguard Worker
105*6236dae4SAndroid Build Coastguard Worker #if defined( DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
106*6236dae4SAndroid Build Coastguard Worker static const char * const multi_statename[]={
107*6236dae4SAndroid Build Coastguard Worker "INIT",
108*6236dae4SAndroid Build Coastguard Worker "PENDING",
109*6236dae4SAndroid Build Coastguard Worker "SETUP",
110*6236dae4SAndroid Build Coastguard Worker "CONNECT",
111*6236dae4SAndroid Build Coastguard Worker "RESOLVING",
112*6236dae4SAndroid Build Coastguard Worker "CONNECTING",
113*6236dae4SAndroid Build Coastguard Worker "TUNNELING",
114*6236dae4SAndroid Build Coastguard Worker "PROTOCONNECT",
115*6236dae4SAndroid Build Coastguard Worker "PROTOCONNECTING",
116*6236dae4SAndroid Build Coastguard Worker "DO",
117*6236dae4SAndroid Build Coastguard Worker "DOING",
118*6236dae4SAndroid Build Coastguard Worker "DOING_MORE",
119*6236dae4SAndroid Build Coastguard Worker "DID",
120*6236dae4SAndroid Build Coastguard Worker "PERFORMING",
121*6236dae4SAndroid Build Coastguard Worker "RATELIMITING",
122*6236dae4SAndroid Build Coastguard Worker "DONE",
123*6236dae4SAndroid Build Coastguard Worker "COMPLETED",
124*6236dae4SAndroid Build Coastguard Worker "MSGSENT",
125*6236dae4SAndroid Build Coastguard Worker };
126*6236dae4SAndroid Build Coastguard Worker #endif
127*6236dae4SAndroid Build Coastguard Worker
128*6236dae4SAndroid Build Coastguard Worker /* function pointer called once when switching TO a state */
129*6236dae4SAndroid Build Coastguard Worker typedef void (*init_multistate_func)(struct Curl_easy *data);
130*6236dae4SAndroid Build Coastguard Worker
131*6236dae4SAndroid Build Coastguard Worker /* called in DID state, before PERFORMING state */
before_perform(struct Curl_easy * data)132*6236dae4SAndroid Build Coastguard Worker static void before_perform(struct Curl_easy *data)
133*6236dae4SAndroid Build Coastguard Worker {
134*6236dae4SAndroid Build Coastguard Worker data->req.chunk = FALSE;
135*6236dae4SAndroid Build Coastguard Worker Curl_pgrsTime(data, TIMER_PRETRANSFER);
136*6236dae4SAndroid Build Coastguard Worker }
137*6236dae4SAndroid Build Coastguard Worker
init_completed(struct Curl_easy * data)138*6236dae4SAndroid Build Coastguard Worker static void init_completed(struct Curl_easy *data)
139*6236dae4SAndroid Build Coastguard Worker {
140*6236dae4SAndroid Build Coastguard Worker /* this is a completed transfer */
141*6236dae4SAndroid Build Coastguard Worker
142*6236dae4SAndroid Build Coastguard Worker /* Important: reset the conn pointer so that we do not point to memory
143*6236dae4SAndroid Build Coastguard Worker that could be freed anytime */
144*6236dae4SAndroid Build Coastguard Worker Curl_detach_connection(data);
145*6236dae4SAndroid Build Coastguard Worker Curl_expire_clear(data); /* stop all timers */
146*6236dae4SAndroid Build Coastguard Worker }
147*6236dae4SAndroid Build Coastguard Worker
148*6236dae4SAndroid Build Coastguard Worker /* always use this function to change state, to make debugging easier */
mstate(struct Curl_easy * data,CURLMstate state,int lineno)149*6236dae4SAndroid Build Coastguard Worker static void mstate(struct Curl_easy *data, CURLMstate state
150*6236dae4SAndroid Build Coastguard Worker #ifdef DEBUGBUILD
151*6236dae4SAndroid Build Coastguard Worker , int lineno
152*6236dae4SAndroid Build Coastguard Worker #endif
153*6236dae4SAndroid Build Coastguard Worker )
154*6236dae4SAndroid Build Coastguard Worker {
155*6236dae4SAndroid Build Coastguard Worker CURLMstate oldstate = data->mstate;
156*6236dae4SAndroid Build Coastguard Worker static const init_multistate_func finit[MSTATE_LAST] = {
157*6236dae4SAndroid Build Coastguard Worker NULL, /* INIT */
158*6236dae4SAndroid Build Coastguard Worker NULL, /* PENDING */
159*6236dae4SAndroid Build Coastguard Worker NULL, /* SETUP */
160*6236dae4SAndroid Build Coastguard Worker Curl_init_CONNECT, /* CONNECT */
161*6236dae4SAndroid Build Coastguard Worker NULL, /* RESOLVING */
162*6236dae4SAndroid Build Coastguard Worker NULL, /* CONNECTING */
163*6236dae4SAndroid Build Coastguard Worker NULL, /* TUNNELING */
164*6236dae4SAndroid Build Coastguard Worker NULL, /* PROTOCONNECT */
165*6236dae4SAndroid Build Coastguard Worker NULL, /* PROTOCONNECTING */
166*6236dae4SAndroid Build Coastguard Worker NULL, /* DO */
167*6236dae4SAndroid Build Coastguard Worker NULL, /* DOING */
168*6236dae4SAndroid Build Coastguard Worker NULL, /* DOING_MORE */
169*6236dae4SAndroid Build Coastguard Worker before_perform, /* DID */
170*6236dae4SAndroid Build Coastguard Worker NULL, /* PERFORMING */
171*6236dae4SAndroid Build Coastguard Worker NULL, /* RATELIMITING */
172*6236dae4SAndroid Build Coastguard Worker NULL, /* DONE */
173*6236dae4SAndroid Build Coastguard Worker init_completed, /* COMPLETED */
174*6236dae4SAndroid Build Coastguard Worker NULL /* MSGSENT */
175*6236dae4SAndroid Build Coastguard Worker };
176*6236dae4SAndroid Build Coastguard Worker
177*6236dae4SAndroid Build Coastguard Worker #if defined(DEBUGBUILD) && defined(CURL_DISABLE_VERBOSE_STRINGS)
178*6236dae4SAndroid Build Coastguard Worker (void) lineno;
179*6236dae4SAndroid Build Coastguard Worker #endif
180*6236dae4SAndroid Build Coastguard Worker
181*6236dae4SAndroid Build Coastguard Worker if(oldstate == state)
182*6236dae4SAndroid Build Coastguard Worker /* do not bother when the new state is the same as the old state */
183*6236dae4SAndroid Build Coastguard Worker return;
184*6236dae4SAndroid Build Coastguard Worker
185*6236dae4SAndroid Build Coastguard Worker data->mstate = state;
186*6236dae4SAndroid Build Coastguard Worker
187*6236dae4SAndroid Build Coastguard Worker #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
188*6236dae4SAndroid Build Coastguard Worker if(data->mstate >= MSTATE_PENDING &&
189*6236dae4SAndroid Build Coastguard Worker data->mstate < MSTATE_COMPLETED) {
190*6236dae4SAndroid Build Coastguard Worker infof(data,
191*6236dae4SAndroid Build Coastguard Worker "STATE: %s => %s handle %p; line %d",
192*6236dae4SAndroid Build Coastguard Worker multi_statename[oldstate], multi_statename[data->mstate],
193*6236dae4SAndroid Build Coastguard Worker (void *)data, lineno);
194*6236dae4SAndroid Build Coastguard Worker }
195*6236dae4SAndroid Build Coastguard Worker #endif
196*6236dae4SAndroid Build Coastguard Worker
197*6236dae4SAndroid Build Coastguard Worker if(state == MSTATE_COMPLETED) {
198*6236dae4SAndroid Build Coastguard Worker /* changing to COMPLETED means there is one less easy handle 'alive' */
199*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(data->multi->num_alive > 0);
200*6236dae4SAndroid Build Coastguard Worker data->multi->num_alive--;
201*6236dae4SAndroid Build Coastguard Worker if(!data->multi->num_alive) {
202*6236dae4SAndroid Build Coastguard Worker /* free the transfer buffer when we have no more active transfers */
203*6236dae4SAndroid Build Coastguard Worker multi_xfer_bufs_free(data->multi);
204*6236dae4SAndroid Build Coastguard Worker }
205*6236dae4SAndroid Build Coastguard Worker }
206*6236dae4SAndroid Build Coastguard Worker
207*6236dae4SAndroid Build Coastguard Worker /* if this state has an init-function, run it */
208*6236dae4SAndroid Build Coastguard Worker if(finit[state])
209*6236dae4SAndroid Build Coastguard Worker finit[state](data);
210*6236dae4SAndroid Build Coastguard Worker }
211*6236dae4SAndroid Build Coastguard Worker
212*6236dae4SAndroid Build Coastguard Worker #ifndef DEBUGBUILD
213*6236dae4SAndroid Build Coastguard Worker #define multistate(x,y) mstate(x,y)
214*6236dae4SAndroid Build Coastguard Worker #else
215*6236dae4SAndroid Build Coastguard Worker #define multistate(x,y) mstate(x,y, __LINE__)
216*6236dae4SAndroid Build Coastguard Worker #endif
217*6236dae4SAndroid Build Coastguard Worker
218*6236dae4SAndroid Build Coastguard Worker /*
219*6236dae4SAndroid Build Coastguard Worker * We add one of these structs to the sockhash for each socket
220*6236dae4SAndroid Build Coastguard Worker */
221*6236dae4SAndroid Build Coastguard Worker
222*6236dae4SAndroid Build Coastguard Worker struct Curl_sh_entry {
223*6236dae4SAndroid Build Coastguard Worker struct Curl_hash transfers; /* hash of transfers using this socket */
224*6236dae4SAndroid Build Coastguard Worker unsigned int action; /* what combined action READ/WRITE this socket waits
225*6236dae4SAndroid Build Coastguard Worker for */
226*6236dae4SAndroid Build Coastguard Worker unsigned int users; /* number of transfers using this */
227*6236dae4SAndroid Build Coastguard Worker void *socketp; /* settable by users with curl_multi_assign() */
228*6236dae4SAndroid Build Coastguard Worker unsigned int readers; /* this many transfers want to read */
229*6236dae4SAndroid Build Coastguard Worker unsigned int writers; /* this many transfers want to write */
230*6236dae4SAndroid Build Coastguard Worker };
231*6236dae4SAndroid Build Coastguard Worker
232*6236dae4SAndroid Build Coastguard Worker /* look up a given socket in the socket hash, skip invalid sockets */
sh_getentry(struct Curl_hash * sh,curl_socket_t s)233*6236dae4SAndroid Build Coastguard Worker static struct Curl_sh_entry *sh_getentry(struct Curl_hash *sh,
234*6236dae4SAndroid Build Coastguard Worker curl_socket_t s)
235*6236dae4SAndroid Build Coastguard Worker {
236*6236dae4SAndroid Build Coastguard Worker if(s != CURL_SOCKET_BAD) {
237*6236dae4SAndroid Build Coastguard Worker /* only look for proper sockets */
238*6236dae4SAndroid Build Coastguard Worker return Curl_hash_pick(sh, (char *)&s, sizeof(curl_socket_t));
239*6236dae4SAndroid Build Coastguard Worker }
240*6236dae4SAndroid Build Coastguard Worker return NULL;
241*6236dae4SAndroid Build Coastguard Worker }
242*6236dae4SAndroid Build Coastguard Worker
243*6236dae4SAndroid Build Coastguard Worker #define TRHASH_SIZE 13
244*6236dae4SAndroid Build Coastguard Worker
245*6236dae4SAndroid Build Coastguard Worker /* the given key here is a struct Curl_easy pointer */
trhash(void * key,size_t key_length,size_t slots_num)246*6236dae4SAndroid Build Coastguard Worker static size_t trhash(void *key, size_t key_length, size_t slots_num)
247*6236dae4SAndroid Build Coastguard Worker {
248*6236dae4SAndroid Build Coastguard Worker unsigned char bytes = ((unsigned char *)key)[key_length - 1] ^
249*6236dae4SAndroid Build Coastguard Worker ((unsigned char *)key)[0];
250*6236dae4SAndroid Build Coastguard Worker return (bytes % slots_num);
251*6236dae4SAndroid Build Coastguard Worker }
252*6236dae4SAndroid Build Coastguard Worker
trhash_compare(void * k1,size_t k1_len,void * k2,size_t k2_len)253*6236dae4SAndroid Build Coastguard Worker static size_t trhash_compare(void *k1, size_t k1_len, void *k2, size_t k2_len)
254*6236dae4SAndroid Build Coastguard Worker {
255*6236dae4SAndroid Build Coastguard Worker (void)k2_len;
256*6236dae4SAndroid Build Coastguard Worker return !memcmp(k1, k2, k1_len);
257*6236dae4SAndroid Build Coastguard Worker }
258*6236dae4SAndroid Build Coastguard Worker
trhash_dtor(void * nada)259*6236dae4SAndroid Build Coastguard Worker static void trhash_dtor(void *nada)
260*6236dae4SAndroid Build Coastguard Worker {
261*6236dae4SAndroid Build Coastguard Worker (void)nada;
262*6236dae4SAndroid Build Coastguard Worker }
263*6236dae4SAndroid Build Coastguard Worker
264*6236dae4SAndroid Build Coastguard Worker /*
265*6236dae4SAndroid Build Coastguard Worker * The sockhash has its own separate subhash in each entry that need to be
266*6236dae4SAndroid Build Coastguard Worker * safely destroyed first.
267*6236dae4SAndroid Build Coastguard Worker */
sockhash_destroy(struct Curl_hash * h)268*6236dae4SAndroid Build Coastguard Worker static void sockhash_destroy(struct Curl_hash *h)
269*6236dae4SAndroid Build Coastguard Worker {
270*6236dae4SAndroid Build Coastguard Worker struct Curl_hash_iterator iter;
271*6236dae4SAndroid Build Coastguard Worker struct Curl_hash_element *he;
272*6236dae4SAndroid Build Coastguard Worker
273*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(h);
274*6236dae4SAndroid Build Coastguard Worker Curl_hash_start_iterate(h, &iter);
275*6236dae4SAndroid Build Coastguard Worker he = Curl_hash_next_element(&iter);
276*6236dae4SAndroid Build Coastguard Worker while(he) {
277*6236dae4SAndroid Build Coastguard Worker struct Curl_sh_entry *sh = (struct Curl_sh_entry *)he->ptr;
278*6236dae4SAndroid Build Coastguard Worker Curl_hash_destroy(&sh->transfers);
279*6236dae4SAndroid Build Coastguard Worker he = Curl_hash_next_element(&iter);
280*6236dae4SAndroid Build Coastguard Worker }
281*6236dae4SAndroid Build Coastguard Worker Curl_hash_destroy(h);
282*6236dae4SAndroid Build Coastguard Worker }
283*6236dae4SAndroid Build Coastguard Worker
284*6236dae4SAndroid Build Coastguard Worker
285*6236dae4SAndroid Build Coastguard Worker /* make sure this socket is present in the hash for this handle */
sh_addentry(struct Curl_hash * sh,curl_socket_t s)286*6236dae4SAndroid Build Coastguard Worker static struct Curl_sh_entry *sh_addentry(struct Curl_hash *sh,
287*6236dae4SAndroid Build Coastguard Worker curl_socket_t s)
288*6236dae4SAndroid Build Coastguard Worker {
289*6236dae4SAndroid Build Coastguard Worker struct Curl_sh_entry *there = sh_getentry(sh, s);
290*6236dae4SAndroid Build Coastguard Worker struct Curl_sh_entry *check;
291*6236dae4SAndroid Build Coastguard Worker
292*6236dae4SAndroid Build Coastguard Worker if(there) {
293*6236dae4SAndroid Build Coastguard Worker /* it is present, return fine */
294*6236dae4SAndroid Build Coastguard Worker return there;
295*6236dae4SAndroid Build Coastguard Worker }
296*6236dae4SAndroid Build Coastguard Worker
297*6236dae4SAndroid Build Coastguard Worker /* not present, add it */
298*6236dae4SAndroid Build Coastguard Worker check = calloc(1, sizeof(struct Curl_sh_entry));
299*6236dae4SAndroid Build Coastguard Worker if(!check)
300*6236dae4SAndroid Build Coastguard Worker return NULL; /* major failure */
301*6236dae4SAndroid Build Coastguard Worker
302*6236dae4SAndroid Build Coastguard Worker Curl_hash_init(&check->transfers, TRHASH_SIZE, trhash, trhash_compare,
303*6236dae4SAndroid Build Coastguard Worker trhash_dtor);
304*6236dae4SAndroid Build Coastguard Worker
305*6236dae4SAndroid Build Coastguard Worker /* make/add new hash entry */
306*6236dae4SAndroid Build Coastguard Worker if(!Curl_hash_add(sh, (char *)&s, sizeof(curl_socket_t), check)) {
307*6236dae4SAndroid Build Coastguard Worker Curl_hash_destroy(&check->transfers);
308*6236dae4SAndroid Build Coastguard Worker free(check);
309*6236dae4SAndroid Build Coastguard Worker return NULL; /* major failure */
310*6236dae4SAndroid Build Coastguard Worker }
311*6236dae4SAndroid Build Coastguard Worker
312*6236dae4SAndroid Build Coastguard Worker return check; /* things are good in sockhash land */
313*6236dae4SAndroid Build Coastguard Worker }
314*6236dae4SAndroid Build Coastguard Worker
315*6236dae4SAndroid Build Coastguard Worker
316*6236dae4SAndroid Build Coastguard Worker /* delete the given socket + handle from the hash */
sh_delentry(struct Curl_sh_entry * entry,struct Curl_hash * sh,curl_socket_t s)317*6236dae4SAndroid Build Coastguard Worker static void sh_delentry(struct Curl_sh_entry *entry,
318*6236dae4SAndroid Build Coastguard Worker struct Curl_hash *sh, curl_socket_t s)
319*6236dae4SAndroid Build Coastguard Worker {
320*6236dae4SAndroid Build Coastguard Worker Curl_hash_destroy(&entry->transfers);
321*6236dae4SAndroid Build Coastguard Worker
322*6236dae4SAndroid Build Coastguard Worker /* We remove the hash entry. This will end up in a call to
323*6236dae4SAndroid Build Coastguard Worker sh_freeentry(). */
324*6236dae4SAndroid Build Coastguard Worker Curl_hash_delete(sh, (char *)&s, sizeof(curl_socket_t));
325*6236dae4SAndroid Build Coastguard Worker }
326*6236dae4SAndroid Build Coastguard Worker
327*6236dae4SAndroid Build Coastguard Worker /*
328*6236dae4SAndroid Build Coastguard Worker * free a sockhash entry
329*6236dae4SAndroid Build Coastguard Worker */
sh_freeentry(void * freethis)330*6236dae4SAndroid Build Coastguard Worker static void sh_freeentry(void *freethis)
331*6236dae4SAndroid Build Coastguard Worker {
332*6236dae4SAndroid Build Coastguard Worker struct Curl_sh_entry *p = (struct Curl_sh_entry *) freethis;
333*6236dae4SAndroid Build Coastguard Worker
334*6236dae4SAndroid Build Coastguard Worker free(p);
335*6236dae4SAndroid Build Coastguard Worker }
336*6236dae4SAndroid Build Coastguard Worker
fd_key_compare(void * k1,size_t k1_len,void * k2,size_t k2_len)337*6236dae4SAndroid Build Coastguard Worker static size_t fd_key_compare(void *k1, size_t k1_len, void *k2, size_t k2_len)
338*6236dae4SAndroid Build Coastguard Worker {
339*6236dae4SAndroid Build Coastguard Worker (void) k1_len; (void) k2_len;
340*6236dae4SAndroid Build Coastguard Worker
341*6236dae4SAndroid Build Coastguard Worker return (*((curl_socket_t *) k1)) == (*((curl_socket_t *) k2));
342*6236dae4SAndroid Build Coastguard Worker }
343*6236dae4SAndroid Build Coastguard Worker
hash_fd(void * key,size_t key_length,size_t slots_num)344*6236dae4SAndroid Build Coastguard Worker static size_t hash_fd(void *key, size_t key_length, size_t slots_num)
345*6236dae4SAndroid Build Coastguard Worker {
346*6236dae4SAndroid Build Coastguard Worker curl_socket_t fd = *((curl_socket_t *) key);
347*6236dae4SAndroid Build Coastguard Worker (void) key_length;
348*6236dae4SAndroid Build Coastguard Worker
349*6236dae4SAndroid Build Coastguard Worker return (fd % (curl_socket_t)slots_num);
350*6236dae4SAndroid Build Coastguard Worker }
351*6236dae4SAndroid Build Coastguard Worker
352*6236dae4SAndroid Build Coastguard Worker /*
353*6236dae4SAndroid Build Coastguard Worker * sh_init() creates a new socket hash and returns the handle for it.
354*6236dae4SAndroid Build Coastguard Worker *
355*6236dae4SAndroid Build Coastguard Worker * Quote from README.multi_socket:
356*6236dae4SAndroid Build Coastguard Worker *
357*6236dae4SAndroid Build Coastguard Worker * "Some tests at 7000 and 9000 connections showed that the socket hash lookup
358*6236dae4SAndroid Build Coastguard Worker * is somewhat of a bottle neck. Its current implementation may be a bit too
359*6236dae4SAndroid Build Coastguard Worker * limiting. It simply has a fixed-size array, and on each entry in the array
360*6236dae4SAndroid Build Coastguard Worker * it has a linked list with entries. The hash only checks which list to scan
361*6236dae4SAndroid Build Coastguard Worker * through. The code I had used so for used a list with merely 7 slots (as
362*6236dae4SAndroid Build Coastguard Worker * that is what the DNS hash uses) but with 7000 connections that would make
363*6236dae4SAndroid Build Coastguard Worker * an average of 1000 nodes in each list to run through. I upped that to 97
364*6236dae4SAndroid Build Coastguard Worker * slots (I believe a prime is suitable) and noticed a significant speed
365*6236dae4SAndroid Build Coastguard Worker * increase. I need to reconsider the hash implementation or use a rather
366*6236dae4SAndroid Build Coastguard Worker * large default value like this. At 9000 connections I was still below 10us
367*6236dae4SAndroid Build Coastguard Worker * per call."
368*6236dae4SAndroid Build Coastguard Worker *
369*6236dae4SAndroid Build Coastguard Worker */
sh_init(struct Curl_hash * hash,size_t hashsize)370*6236dae4SAndroid Build Coastguard Worker static void sh_init(struct Curl_hash *hash, size_t hashsize)
371*6236dae4SAndroid Build Coastguard Worker {
372*6236dae4SAndroid Build Coastguard Worker Curl_hash_init(hash, hashsize, hash_fd, fd_key_compare,
373*6236dae4SAndroid Build Coastguard Worker sh_freeentry);
374*6236dae4SAndroid Build Coastguard Worker }
375*6236dae4SAndroid Build Coastguard Worker
376*6236dae4SAndroid Build Coastguard Worker /* multi->proto_hash destructor. Should never be called as elements
377*6236dae4SAndroid Build Coastguard Worker * MUST be added with their own destructor */
ph_freeentry(void * p)378*6236dae4SAndroid Build Coastguard Worker static void ph_freeentry(void *p)
379*6236dae4SAndroid Build Coastguard Worker {
380*6236dae4SAndroid Build Coastguard Worker (void)p;
381*6236dae4SAndroid Build Coastguard Worker /* Will always be FALSE. Cannot use a 0 assert here since compilers
382*6236dae4SAndroid Build Coastguard Worker * are not in agreement if they then want a NORETURN attribute or
383*6236dae4SAndroid Build Coastguard Worker * not. *sigh* */
384*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(p == NULL);
385*6236dae4SAndroid Build Coastguard Worker }
386*6236dae4SAndroid Build Coastguard Worker
387*6236dae4SAndroid Build Coastguard Worker /*
388*6236dae4SAndroid Build Coastguard Worker * multi_addmsg()
389*6236dae4SAndroid Build Coastguard Worker *
390*6236dae4SAndroid Build Coastguard Worker * Called when a transfer is completed. Adds the given msg pointer to
391*6236dae4SAndroid Build Coastguard Worker * the list kept in the multi handle.
392*6236dae4SAndroid Build Coastguard Worker */
multi_addmsg(struct Curl_multi * multi,struct Curl_message * msg)393*6236dae4SAndroid Build Coastguard Worker static void multi_addmsg(struct Curl_multi *multi, struct Curl_message *msg)
394*6236dae4SAndroid Build Coastguard Worker {
395*6236dae4SAndroid Build Coastguard Worker Curl_llist_append(&multi->msglist, msg, &msg->list);
396*6236dae4SAndroid Build Coastguard Worker }
397*6236dae4SAndroid Build Coastguard Worker
Curl_multi_handle(size_t hashsize,size_t chashsize,size_t dnssize)398*6236dae4SAndroid Build Coastguard Worker struct Curl_multi *Curl_multi_handle(size_t hashsize, /* socket hash */
399*6236dae4SAndroid Build Coastguard Worker size_t chashsize, /* connection hash */
400*6236dae4SAndroid Build Coastguard Worker size_t dnssize) /* dns hash */
401*6236dae4SAndroid Build Coastguard Worker {
402*6236dae4SAndroid Build Coastguard Worker struct Curl_multi *multi = calloc(1, sizeof(struct Curl_multi));
403*6236dae4SAndroid Build Coastguard Worker
404*6236dae4SAndroid Build Coastguard Worker if(!multi)
405*6236dae4SAndroid Build Coastguard Worker return NULL;
406*6236dae4SAndroid Build Coastguard Worker
407*6236dae4SAndroid Build Coastguard Worker multi->magic = CURL_MULTI_HANDLE;
408*6236dae4SAndroid Build Coastguard Worker
409*6236dae4SAndroid Build Coastguard Worker Curl_init_dnscache(&multi->hostcache, dnssize);
410*6236dae4SAndroid Build Coastguard Worker
411*6236dae4SAndroid Build Coastguard Worker sh_init(&multi->sockhash, hashsize);
412*6236dae4SAndroid Build Coastguard Worker
413*6236dae4SAndroid Build Coastguard Worker Curl_hash_init(&multi->proto_hash, 23,
414*6236dae4SAndroid Build Coastguard Worker Curl_hash_str, Curl_str_key_compare, ph_freeentry);
415*6236dae4SAndroid Build Coastguard Worker
416*6236dae4SAndroid Build Coastguard Worker if(Curl_cpool_init(&multi->cpool, Curl_on_disconnect,
417*6236dae4SAndroid Build Coastguard Worker multi, NULL, chashsize))
418*6236dae4SAndroid Build Coastguard Worker goto error;
419*6236dae4SAndroid Build Coastguard Worker
420*6236dae4SAndroid Build Coastguard Worker Curl_llist_init(&multi->msglist, NULL);
421*6236dae4SAndroid Build Coastguard Worker Curl_llist_init(&multi->process, NULL);
422*6236dae4SAndroid Build Coastguard Worker Curl_llist_init(&multi->pending, NULL);
423*6236dae4SAndroid Build Coastguard Worker Curl_llist_init(&multi->msgsent, NULL);
424*6236dae4SAndroid Build Coastguard Worker
425*6236dae4SAndroid Build Coastguard Worker multi->multiplexing = TRUE;
426*6236dae4SAndroid Build Coastguard Worker multi->max_concurrent_streams = 100;
427*6236dae4SAndroid Build Coastguard Worker multi->last_timeout_ms = -1;
428*6236dae4SAndroid Build Coastguard Worker
429*6236dae4SAndroid Build Coastguard Worker #ifdef USE_WINSOCK
430*6236dae4SAndroid Build Coastguard Worker multi->wsa_event = WSACreateEvent();
431*6236dae4SAndroid Build Coastguard Worker if(multi->wsa_event == WSA_INVALID_EVENT)
432*6236dae4SAndroid Build Coastguard Worker goto error;
433*6236dae4SAndroid Build Coastguard Worker #else
434*6236dae4SAndroid Build Coastguard Worker #ifdef ENABLE_WAKEUP
435*6236dae4SAndroid Build Coastguard Worker if(wakeup_create(multi->wakeup_pair, TRUE) < 0) {
436*6236dae4SAndroid Build Coastguard Worker multi->wakeup_pair[0] = CURL_SOCKET_BAD;
437*6236dae4SAndroid Build Coastguard Worker multi->wakeup_pair[1] = CURL_SOCKET_BAD;
438*6236dae4SAndroid Build Coastguard Worker }
439*6236dae4SAndroid Build Coastguard Worker #endif
440*6236dae4SAndroid Build Coastguard Worker #endif
441*6236dae4SAndroid Build Coastguard Worker
442*6236dae4SAndroid Build Coastguard Worker return multi;
443*6236dae4SAndroid Build Coastguard Worker
444*6236dae4SAndroid Build Coastguard Worker error:
445*6236dae4SAndroid Build Coastguard Worker
446*6236dae4SAndroid Build Coastguard Worker sockhash_destroy(&multi->sockhash);
447*6236dae4SAndroid Build Coastguard Worker Curl_hash_destroy(&multi->proto_hash);
448*6236dae4SAndroid Build Coastguard Worker Curl_hash_destroy(&multi->hostcache);
449*6236dae4SAndroid Build Coastguard Worker Curl_cpool_destroy(&multi->cpool);
450*6236dae4SAndroid Build Coastguard Worker free(multi);
451*6236dae4SAndroid Build Coastguard Worker return NULL;
452*6236dae4SAndroid Build Coastguard Worker }
453*6236dae4SAndroid Build Coastguard Worker
curl_multi_init(void)454*6236dae4SAndroid Build Coastguard Worker CURLM *curl_multi_init(void)
455*6236dae4SAndroid Build Coastguard Worker {
456*6236dae4SAndroid Build Coastguard Worker return Curl_multi_handle(CURL_SOCKET_HASH_TABLE_SIZE,
457*6236dae4SAndroid Build Coastguard Worker CURL_CONNECTION_HASH_SIZE,
458*6236dae4SAndroid Build Coastguard Worker CURL_DNS_HASH_SIZE);
459*6236dae4SAndroid Build Coastguard Worker }
460*6236dae4SAndroid Build Coastguard Worker
461*6236dae4SAndroid Build Coastguard Worker #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
multi_warn_debug(struct Curl_multi * multi,struct Curl_easy * data)462*6236dae4SAndroid Build Coastguard Worker static void multi_warn_debug(struct Curl_multi *multi, struct Curl_easy *data)
463*6236dae4SAndroid Build Coastguard Worker {
464*6236dae4SAndroid Build Coastguard Worker if(!multi->warned) {
465*6236dae4SAndroid Build Coastguard Worker infof(data, "!!! WARNING !!!");
466*6236dae4SAndroid Build Coastguard Worker infof(data, "This is a debug build of libcurl, "
467*6236dae4SAndroid Build Coastguard Worker "do not use in production.");
468*6236dae4SAndroid Build Coastguard Worker multi->warned = TRUE;
469*6236dae4SAndroid Build Coastguard Worker }
470*6236dae4SAndroid Build Coastguard Worker }
471*6236dae4SAndroid Build Coastguard Worker #else
472*6236dae4SAndroid Build Coastguard Worker #define multi_warn_debug(x,y) Curl_nop_stmt
473*6236dae4SAndroid Build Coastguard Worker #endif
474*6236dae4SAndroid Build Coastguard Worker
curl_multi_add_handle(CURLM * m,CURL * d)475*6236dae4SAndroid Build Coastguard Worker CURLMcode curl_multi_add_handle(CURLM *m, CURL *d)
476*6236dae4SAndroid Build Coastguard Worker {
477*6236dae4SAndroid Build Coastguard Worker CURLMcode rc;
478*6236dae4SAndroid Build Coastguard Worker struct Curl_multi *multi = m;
479*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data = d;
480*6236dae4SAndroid Build Coastguard Worker /* First, make some basic checks that the CURLM handle is a good handle */
481*6236dae4SAndroid Build Coastguard Worker if(!GOOD_MULTI_HANDLE(multi))
482*6236dae4SAndroid Build Coastguard Worker return CURLM_BAD_HANDLE;
483*6236dae4SAndroid Build Coastguard Worker
484*6236dae4SAndroid Build Coastguard Worker /* Verify that we got a somewhat good easy handle too */
485*6236dae4SAndroid Build Coastguard Worker if(!GOOD_EASY_HANDLE(data))
486*6236dae4SAndroid Build Coastguard Worker return CURLM_BAD_EASY_HANDLE;
487*6236dae4SAndroid Build Coastguard Worker
488*6236dae4SAndroid Build Coastguard Worker /* Prevent users from adding same easy handle more than once and prevent
489*6236dae4SAndroid Build Coastguard Worker adding to more than one multi stack */
490*6236dae4SAndroid Build Coastguard Worker if(data->multi)
491*6236dae4SAndroid Build Coastguard Worker return CURLM_ADDED_ALREADY;
492*6236dae4SAndroid Build Coastguard Worker
493*6236dae4SAndroid Build Coastguard Worker if(multi->in_callback)
494*6236dae4SAndroid Build Coastguard Worker return CURLM_RECURSIVE_API_CALL;
495*6236dae4SAndroid Build Coastguard Worker
496*6236dae4SAndroid Build Coastguard Worker if(multi->dead) {
497*6236dae4SAndroid Build Coastguard Worker /* a "dead" handle cannot get added transfers while any existing easy
498*6236dae4SAndroid Build Coastguard Worker handles are still alive - but if there are none alive anymore, it is
499*6236dae4SAndroid Build Coastguard Worker fine to start over and unmark the "deadness" of this handle */
500*6236dae4SAndroid Build Coastguard Worker if(multi->num_alive)
501*6236dae4SAndroid Build Coastguard Worker return CURLM_ABORTED_BY_CALLBACK;
502*6236dae4SAndroid Build Coastguard Worker multi->dead = FALSE;
503*6236dae4SAndroid Build Coastguard Worker }
504*6236dae4SAndroid Build Coastguard Worker
505*6236dae4SAndroid Build Coastguard Worker if(data->multi_easy) {
506*6236dae4SAndroid Build Coastguard Worker /* if this easy handle was previously used for curl_easy_perform(), there
507*6236dae4SAndroid Build Coastguard Worker is a private multi handle here that we can kill */
508*6236dae4SAndroid Build Coastguard Worker curl_multi_cleanup(data->multi_easy);
509*6236dae4SAndroid Build Coastguard Worker data->multi_easy = NULL;
510*6236dae4SAndroid Build Coastguard Worker }
511*6236dae4SAndroid Build Coastguard Worker
512*6236dae4SAndroid Build Coastguard Worker /* Initialize timeout list for this handle */
513*6236dae4SAndroid Build Coastguard Worker Curl_llist_init(&data->state.timeoutlist, NULL);
514*6236dae4SAndroid Build Coastguard Worker
515*6236dae4SAndroid Build Coastguard Worker /*
516*6236dae4SAndroid Build Coastguard Worker * No failure allowed in this function beyond this point. No modification of
517*6236dae4SAndroid Build Coastguard Worker * easy nor multi handle allowed before this except for potential multi's
518*6236dae4SAndroid Build Coastguard Worker * connection pool growing which will not be undone in this function no
519*6236dae4SAndroid Build Coastguard Worker * matter what.
520*6236dae4SAndroid Build Coastguard Worker */
521*6236dae4SAndroid Build Coastguard Worker if(data->set.errorbuffer)
522*6236dae4SAndroid Build Coastguard Worker data->set.errorbuffer[0] = 0;
523*6236dae4SAndroid Build Coastguard Worker
524*6236dae4SAndroid Build Coastguard Worker data->state.os_errno = 0;
525*6236dae4SAndroid Build Coastguard Worker
526*6236dae4SAndroid Build Coastguard Worker /* make the Curl_easy refer back to this multi handle - before Curl_expire()
527*6236dae4SAndroid Build Coastguard Worker is called. */
528*6236dae4SAndroid Build Coastguard Worker data->multi = multi;
529*6236dae4SAndroid Build Coastguard Worker
530*6236dae4SAndroid Build Coastguard Worker /* Set the timeout for this handle to expire really soon so that it will
531*6236dae4SAndroid Build Coastguard Worker be taken care of even when this handle is added in the midst of operation
532*6236dae4SAndroid Build Coastguard Worker when only the curl_multi_socket() API is used. During that flow, only
533*6236dae4SAndroid Build Coastguard Worker sockets that time-out or have actions will be dealt with. Since this
534*6236dae4SAndroid Build Coastguard Worker handle has no action yet, we make sure it times out to get things to
535*6236dae4SAndroid Build Coastguard Worker happen. */
536*6236dae4SAndroid Build Coastguard Worker Curl_expire(data, 0, EXPIRE_RUN_NOW);
537*6236dae4SAndroid Build Coastguard Worker
538*6236dae4SAndroid Build Coastguard Worker rc = Curl_update_timer(multi);
539*6236dae4SAndroid Build Coastguard Worker if(rc) {
540*6236dae4SAndroid Build Coastguard Worker data->multi = NULL; /* not anymore */
541*6236dae4SAndroid Build Coastguard Worker return rc;
542*6236dae4SAndroid Build Coastguard Worker }
543*6236dae4SAndroid Build Coastguard Worker
544*6236dae4SAndroid Build Coastguard Worker /* set the easy handle */
545*6236dae4SAndroid Build Coastguard Worker multistate(data, MSTATE_INIT);
546*6236dae4SAndroid Build Coastguard Worker
547*6236dae4SAndroid Build Coastguard Worker /* for multi interface connections, we share DNS cache automatically if the
548*6236dae4SAndroid Build Coastguard Worker easy handle's one is currently not set. */
549*6236dae4SAndroid Build Coastguard Worker if(!data->dns.hostcache ||
550*6236dae4SAndroid Build Coastguard Worker (data->dns.hostcachetype == HCACHE_NONE)) {
551*6236dae4SAndroid Build Coastguard Worker data->dns.hostcache = &multi->hostcache;
552*6236dae4SAndroid Build Coastguard Worker data->dns.hostcachetype = HCACHE_MULTI;
553*6236dae4SAndroid Build Coastguard Worker }
554*6236dae4SAndroid Build Coastguard Worker
555*6236dae4SAndroid Build Coastguard Worker #ifdef USE_LIBPSL
556*6236dae4SAndroid Build Coastguard Worker /* Do the same for PSL. */
557*6236dae4SAndroid Build Coastguard Worker if(data->share && (data->share->specifier & (1 << CURL_LOCK_DATA_PSL)))
558*6236dae4SAndroid Build Coastguard Worker data->psl = &data->share->psl;
559*6236dae4SAndroid Build Coastguard Worker else
560*6236dae4SAndroid Build Coastguard Worker data->psl = &multi->psl;
561*6236dae4SAndroid Build Coastguard Worker #endif
562*6236dae4SAndroid Build Coastguard Worker
563*6236dae4SAndroid Build Coastguard Worker /* add the easy handle to the process list */
564*6236dae4SAndroid Build Coastguard Worker Curl_llist_append(&multi->process, data, &data->multi_queue);
565*6236dae4SAndroid Build Coastguard Worker
566*6236dae4SAndroid Build Coastguard Worker /* increase the node-counter */
567*6236dae4SAndroid Build Coastguard Worker multi->num_easy++;
568*6236dae4SAndroid Build Coastguard Worker
569*6236dae4SAndroid Build Coastguard Worker /* increase the alive-counter */
570*6236dae4SAndroid Build Coastguard Worker multi->num_alive++;
571*6236dae4SAndroid Build Coastguard Worker
572*6236dae4SAndroid Build Coastguard Worker /* the identifier inside the multi instance */
573*6236dae4SAndroid Build Coastguard Worker data->mid = multi->next_easy_mid++;
574*6236dae4SAndroid Build Coastguard Worker if(multi->next_easy_mid <= 0)
575*6236dae4SAndroid Build Coastguard Worker multi->next_easy_mid = 0;
576*6236dae4SAndroid Build Coastguard Worker
577*6236dae4SAndroid Build Coastguard Worker Curl_cpool_xfer_init(data);
578*6236dae4SAndroid Build Coastguard Worker multi_warn_debug(multi, data);
579*6236dae4SAndroid Build Coastguard Worker
580*6236dae4SAndroid Build Coastguard Worker return CURLM_OK;
581*6236dae4SAndroid Build Coastguard Worker }
582*6236dae4SAndroid Build Coastguard Worker
583*6236dae4SAndroid Build Coastguard Worker #if 0
584*6236dae4SAndroid Build Coastguard Worker /* Debug-function, used like this:
585*6236dae4SAndroid Build Coastguard Worker *
586*6236dae4SAndroid Build Coastguard Worker * Curl_hash_print(&multi->sockhash, debug_print_sock_hash);
587*6236dae4SAndroid Build Coastguard Worker *
588*6236dae4SAndroid Build Coastguard Worker * Enable the hash print function first by editing hash.c
589*6236dae4SAndroid Build Coastguard Worker */
590*6236dae4SAndroid Build Coastguard Worker static void debug_print_sock_hash(void *p)
591*6236dae4SAndroid Build Coastguard Worker {
592*6236dae4SAndroid Build Coastguard Worker struct Curl_sh_entry *sh = (struct Curl_sh_entry *)p;
593*6236dae4SAndroid Build Coastguard Worker
594*6236dae4SAndroid Build Coastguard Worker fprintf(stderr, " [readers %u][writers %u]",
595*6236dae4SAndroid Build Coastguard Worker sh->readers, sh->writers);
596*6236dae4SAndroid Build Coastguard Worker }
597*6236dae4SAndroid Build Coastguard Worker #endif
598*6236dae4SAndroid Build Coastguard Worker
599*6236dae4SAndroid Build Coastguard Worker struct multi_done_ctx {
600*6236dae4SAndroid Build Coastguard Worker BIT(premature);
601*6236dae4SAndroid Build Coastguard Worker };
602*6236dae4SAndroid Build Coastguard Worker
multi_done_locked(struct connectdata * conn,struct Curl_easy * data,void * userdata)603*6236dae4SAndroid Build Coastguard Worker static void multi_done_locked(struct connectdata *conn,
604*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data,
605*6236dae4SAndroid Build Coastguard Worker void *userdata)
606*6236dae4SAndroid Build Coastguard Worker {
607*6236dae4SAndroid Build Coastguard Worker struct multi_done_ctx *mdctx = userdata;
608*6236dae4SAndroid Build Coastguard Worker
609*6236dae4SAndroid Build Coastguard Worker Curl_detach_connection(data);
610*6236dae4SAndroid Build Coastguard Worker
611*6236dae4SAndroid Build Coastguard Worker if(CONN_INUSE(conn)) {
612*6236dae4SAndroid Build Coastguard Worker /* Stop if still used. */
613*6236dae4SAndroid Build Coastguard Worker DEBUGF(infof(data, "Connection still in use %zu, "
614*6236dae4SAndroid Build Coastguard Worker "no more multi_done now!",
615*6236dae4SAndroid Build Coastguard Worker Curl_llist_count(&conn->easyq)));
616*6236dae4SAndroid Build Coastguard Worker return;
617*6236dae4SAndroid Build Coastguard Worker }
618*6236dae4SAndroid Build Coastguard Worker
619*6236dae4SAndroid Build Coastguard Worker data->state.done = TRUE; /* called just now! */
620*6236dae4SAndroid Build Coastguard Worker data->state.recent_conn_id = conn->connection_id;
621*6236dae4SAndroid Build Coastguard Worker
622*6236dae4SAndroid Build Coastguard Worker if(conn->dns_entry)
623*6236dae4SAndroid Build Coastguard Worker Curl_resolv_unlink(data, &conn->dns_entry); /* done with this */
624*6236dae4SAndroid Build Coastguard Worker Curl_hostcache_prune(data);
625*6236dae4SAndroid Build Coastguard Worker
626*6236dae4SAndroid Build Coastguard Worker /* if data->set.reuse_forbid is TRUE, it means the libcurl client has
627*6236dae4SAndroid Build Coastguard Worker forced us to close this connection. This is ignored for requests taking
628*6236dae4SAndroid Build Coastguard Worker place in a NTLM/NEGOTIATE authentication handshake
629*6236dae4SAndroid Build Coastguard Worker
630*6236dae4SAndroid Build Coastguard Worker if conn->bits.close is TRUE, it means that the connection should be
631*6236dae4SAndroid Build Coastguard Worker closed in spite of all our efforts to be nice, due to protocol
632*6236dae4SAndroid Build Coastguard Worker restrictions in our or the server's end
633*6236dae4SAndroid Build Coastguard Worker
634*6236dae4SAndroid Build Coastguard Worker if premature is TRUE, it means this connection was said to be DONE before
635*6236dae4SAndroid Build Coastguard Worker the entire request operation is complete and thus we cannot know in what
636*6236dae4SAndroid Build Coastguard Worker state it is for reusing, so we are forced to close it. In a perfect world
637*6236dae4SAndroid Build Coastguard Worker we can add code that keep track of if we really must close it here or not,
638*6236dae4SAndroid Build Coastguard Worker but currently we have no such detail knowledge.
639*6236dae4SAndroid Build Coastguard Worker */
640*6236dae4SAndroid Build Coastguard Worker
641*6236dae4SAndroid Build Coastguard Worker if((data->set.reuse_forbid
642*6236dae4SAndroid Build Coastguard Worker #if defined(USE_NTLM)
643*6236dae4SAndroid Build Coastguard Worker && !(conn->http_ntlm_state == NTLMSTATE_TYPE2 ||
644*6236dae4SAndroid Build Coastguard Worker conn->proxy_ntlm_state == NTLMSTATE_TYPE2)
645*6236dae4SAndroid Build Coastguard Worker #endif
646*6236dae4SAndroid Build Coastguard Worker #if defined(USE_SPNEGO)
647*6236dae4SAndroid Build Coastguard Worker && !(conn->http_negotiate_state == GSS_AUTHRECV ||
648*6236dae4SAndroid Build Coastguard Worker conn->proxy_negotiate_state == GSS_AUTHRECV)
649*6236dae4SAndroid Build Coastguard Worker #endif
650*6236dae4SAndroid Build Coastguard Worker ) || conn->bits.close
651*6236dae4SAndroid Build Coastguard Worker || (mdctx->premature && !Curl_conn_is_multiplex(conn, FIRSTSOCKET))) {
652*6236dae4SAndroid Build Coastguard Worker DEBUGF(infof(data, "multi_done, not reusing connection=%"
653*6236dae4SAndroid Build Coastguard Worker FMT_OFF_T ", forbid=%d"
654*6236dae4SAndroid Build Coastguard Worker ", close=%d, premature=%d, conn_multiplex=%d",
655*6236dae4SAndroid Build Coastguard Worker conn->connection_id, data->set.reuse_forbid,
656*6236dae4SAndroid Build Coastguard Worker conn->bits.close, mdctx->premature,
657*6236dae4SAndroid Build Coastguard Worker Curl_conn_is_multiplex(conn, FIRSTSOCKET)));
658*6236dae4SAndroid Build Coastguard Worker connclose(conn, "disconnecting");
659*6236dae4SAndroid Build Coastguard Worker Curl_cpool_disconnect(data, conn, mdctx->premature);
660*6236dae4SAndroid Build Coastguard Worker }
661*6236dae4SAndroid Build Coastguard Worker else {
662*6236dae4SAndroid Build Coastguard Worker /* the connection is no longer in use by any transfer */
663*6236dae4SAndroid Build Coastguard Worker if(Curl_cpool_conn_now_idle(data, conn)) {
664*6236dae4SAndroid Build Coastguard Worker /* connection kept in the cpool */
665*6236dae4SAndroid Build Coastguard Worker const char *host =
666*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_PROXY
667*6236dae4SAndroid Build Coastguard Worker conn->bits.socksproxy ?
668*6236dae4SAndroid Build Coastguard Worker conn->socks_proxy.host.dispname :
669*6236dae4SAndroid Build Coastguard Worker conn->bits.httpproxy ? conn->http_proxy.host.dispname :
670*6236dae4SAndroid Build Coastguard Worker #endif
671*6236dae4SAndroid Build Coastguard Worker conn->bits.conn_to_host ? conn->conn_to_host.dispname :
672*6236dae4SAndroid Build Coastguard Worker conn->host.dispname;
673*6236dae4SAndroid Build Coastguard Worker data->state.lastconnect_id = conn->connection_id;
674*6236dae4SAndroid Build Coastguard Worker infof(data, "Connection #%" FMT_OFF_T " to host %s left intact",
675*6236dae4SAndroid Build Coastguard Worker conn->connection_id, host);
676*6236dae4SAndroid Build Coastguard Worker }
677*6236dae4SAndroid Build Coastguard Worker else {
678*6236dae4SAndroid Build Coastguard Worker /* connection was removed from the cpool and destroyed. */
679*6236dae4SAndroid Build Coastguard Worker data->state.lastconnect_id = -1;
680*6236dae4SAndroid Build Coastguard Worker }
681*6236dae4SAndroid Build Coastguard Worker }
682*6236dae4SAndroid Build Coastguard Worker }
683*6236dae4SAndroid Build Coastguard Worker
multi_done(struct Curl_easy * data,CURLcode status,bool premature)684*6236dae4SAndroid Build Coastguard Worker static CURLcode multi_done(struct Curl_easy *data,
685*6236dae4SAndroid Build Coastguard Worker CURLcode status, /* an error if this is called
686*6236dae4SAndroid Build Coastguard Worker after an error was detected */
687*6236dae4SAndroid Build Coastguard Worker bool premature)
688*6236dae4SAndroid Build Coastguard Worker {
689*6236dae4SAndroid Build Coastguard Worker CURLcode result, r2;
690*6236dae4SAndroid Build Coastguard Worker struct connectdata *conn = data->conn;
691*6236dae4SAndroid Build Coastguard Worker struct multi_done_ctx mdctx;
692*6236dae4SAndroid Build Coastguard Worker
693*6236dae4SAndroid Build Coastguard Worker memset(&mdctx, 0, sizeof(mdctx));
694*6236dae4SAndroid Build Coastguard Worker
695*6236dae4SAndroid Build Coastguard Worker #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
696*6236dae4SAndroid Build Coastguard Worker DEBUGF(infof(data, "multi_done[%s]: status: %d prem: %d done: %d",
697*6236dae4SAndroid Build Coastguard Worker multi_statename[data->mstate],
698*6236dae4SAndroid Build Coastguard Worker (int)status, (int)premature, data->state.done));
699*6236dae4SAndroid Build Coastguard Worker #else
700*6236dae4SAndroid Build Coastguard Worker DEBUGF(infof(data, "multi_done: status: %d prem: %d done: %d",
701*6236dae4SAndroid Build Coastguard Worker (int)status, (int)premature, data->state.done));
702*6236dae4SAndroid Build Coastguard Worker #endif
703*6236dae4SAndroid Build Coastguard Worker
704*6236dae4SAndroid Build Coastguard Worker if(data->state.done)
705*6236dae4SAndroid Build Coastguard Worker /* Stop if multi_done() has already been called */
706*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
707*6236dae4SAndroid Build Coastguard Worker
708*6236dae4SAndroid Build Coastguard Worker /* Stop the resolver and free its own resources (but not dns_entry yet). */
709*6236dae4SAndroid Build Coastguard Worker Curl_resolver_kill(data);
710*6236dae4SAndroid Build Coastguard Worker
711*6236dae4SAndroid Build Coastguard Worker /* Cleanup possible redirect junk */
712*6236dae4SAndroid Build Coastguard Worker Curl_safefree(data->req.newurl);
713*6236dae4SAndroid Build Coastguard Worker Curl_safefree(data->req.location);
714*6236dae4SAndroid Build Coastguard Worker
715*6236dae4SAndroid Build Coastguard Worker switch(status) {
716*6236dae4SAndroid Build Coastguard Worker case CURLE_ABORTED_BY_CALLBACK:
717*6236dae4SAndroid Build Coastguard Worker case CURLE_READ_ERROR:
718*6236dae4SAndroid Build Coastguard Worker case CURLE_WRITE_ERROR:
719*6236dae4SAndroid Build Coastguard Worker /* When we are aborted due to a callback return code it basically have to
720*6236dae4SAndroid Build Coastguard Worker be counted as premature as there is trouble ahead if we do not. We have
721*6236dae4SAndroid Build Coastguard Worker many callbacks and protocols work differently, we could potentially do
722*6236dae4SAndroid Build Coastguard Worker this more fine-grained in the future. */
723*6236dae4SAndroid Build Coastguard Worker premature = TRUE;
724*6236dae4SAndroid Build Coastguard Worker FALLTHROUGH();
725*6236dae4SAndroid Build Coastguard Worker default:
726*6236dae4SAndroid Build Coastguard Worker break;
727*6236dae4SAndroid Build Coastguard Worker }
728*6236dae4SAndroid Build Coastguard Worker
729*6236dae4SAndroid Build Coastguard Worker /* this calls the protocol-specific function pointer previously set */
730*6236dae4SAndroid Build Coastguard Worker if(conn->handler->done)
731*6236dae4SAndroid Build Coastguard Worker result = conn->handler->done(data, status, premature);
732*6236dae4SAndroid Build Coastguard Worker else
733*6236dae4SAndroid Build Coastguard Worker result = status;
734*6236dae4SAndroid Build Coastguard Worker
735*6236dae4SAndroid Build Coastguard Worker if(CURLE_ABORTED_BY_CALLBACK != result) {
736*6236dae4SAndroid Build Coastguard Worker /* avoid this if we already aborted by callback to avoid this calling
737*6236dae4SAndroid Build Coastguard Worker another callback */
738*6236dae4SAndroid Build Coastguard Worker int rc = Curl_pgrsDone(data);
739*6236dae4SAndroid Build Coastguard Worker if(!result && rc)
740*6236dae4SAndroid Build Coastguard Worker result = CURLE_ABORTED_BY_CALLBACK;
741*6236dae4SAndroid Build Coastguard Worker }
742*6236dae4SAndroid Build Coastguard Worker
743*6236dae4SAndroid Build Coastguard Worker /* Make sure that transfer client writes are really done now. */
744*6236dae4SAndroid Build Coastguard Worker r2 = Curl_xfer_write_done(data, premature);
745*6236dae4SAndroid Build Coastguard Worker if(r2 && !result)
746*6236dae4SAndroid Build Coastguard Worker result = r2;
747*6236dae4SAndroid Build Coastguard Worker
748*6236dae4SAndroid Build Coastguard Worker /* Inform connection filters that this transfer is done */
749*6236dae4SAndroid Build Coastguard Worker Curl_conn_ev_data_done(data, premature);
750*6236dae4SAndroid Build Coastguard Worker
751*6236dae4SAndroid Build Coastguard Worker process_pending_handles(data->multi); /* connection / multiplex */
752*6236dae4SAndroid Build Coastguard Worker
753*6236dae4SAndroid Build Coastguard Worker if(!result)
754*6236dae4SAndroid Build Coastguard Worker result = Curl_req_done(&data->req, data, premature);
755*6236dae4SAndroid Build Coastguard Worker
756*6236dae4SAndroid Build Coastguard Worker /* Under the potential connection pool's share lock, decide what to
757*6236dae4SAndroid Build Coastguard Worker * do with the transfer's connection. */
758*6236dae4SAndroid Build Coastguard Worker mdctx.premature = premature;
759*6236dae4SAndroid Build Coastguard Worker Curl_cpool_do_locked(data, data->conn, multi_done_locked, &mdctx);
760*6236dae4SAndroid Build Coastguard Worker
761*6236dae4SAndroid Build Coastguard Worker /* flush the netrc cache */
762*6236dae4SAndroid Build Coastguard Worker Curl_netrc_cleanup(&data->state.netrc);
763*6236dae4SAndroid Build Coastguard Worker return result;
764*6236dae4SAndroid Build Coastguard Worker }
765*6236dae4SAndroid Build Coastguard Worker
close_connect_only(struct connectdata * conn,struct Curl_easy * data,void * userdata)766*6236dae4SAndroid Build Coastguard Worker static void close_connect_only(struct connectdata *conn,
767*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data,
768*6236dae4SAndroid Build Coastguard Worker void *userdata)
769*6236dae4SAndroid Build Coastguard Worker {
770*6236dae4SAndroid Build Coastguard Worker (void)userdata;
771*6236dae4SAndroid Build Coastguard Worker (void)data;
772*6236dae4SAndroid Build Coastguard Worker if(conn->connect_only)
773*6236dae4SAndroid Build Coastguard Worker connclose(conn, "Removing connect-only easy handle");
774*6236dae4SAndroid Build Coastguard Worker }
775*6236dae4SAndroid Build Coastguard Worker
curl_multi_remove_handle(CURLM * m,CURL * d)776*6236dae4SAndroid Build Coastguard Worker CURLMcode curl_multi_remove_handle(CURLM *m, CURL *d)
777*6236dae4SAndroid Build Coastguard Worker {
778*6236dae4SAndroid Build Coastguard Worker struct Curl_multi *multi = m;
779*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data = d;
780*6236dae4SAndroid Build Coastguard Worker bool premature;
781*6236dae4SAndroid Build Coastguard Worker struct Curl_llist_node *e;
782*6236dae4SAndroid Build Coastguard Worker CURLMcode rc;
783*6236dae4SAndroid Build Coastguard Worker bool removed_timer = FALSE;
784*6236dae4SAndroid Build Coastguard Worker
785*6236dae4SAndroid Build Coastguard Worker /* First, make some basic checks that the CURLM handle is a good handle */
786*6236dae4SAndroid Build Coastguard Worker if(!GOOD_MULTI_HANDLE(multi))
787*6236dae4SAndroid Build Coastguard Worker return CURLM_BAD_HANDLE;
788*6236dae4SAndroid Build Coastguard Worker
789*6236dae4SAndroid Build Coastguard Worker /* Verify that we got a somewhat good easy handle too */
790*6236dae4SAndroid Build Coastguard Worker if(!GOOD_EASY_HANDLE(data) || !multi->num_easy)
791*6236dae4SAndroid Build Coastguard Worker return CURLM_BAD_EASY_HANDLE;
792*6236dae4SAndroid Build Coastguard Worker
793*6236dae4SAndroid Build Coastguard Worker /* Prevent users from trying to remove same easy handle more than once */
794*6236dae4SAndroid Build Coastguard Worker if(!data->multi)
795*6236dae4SAndroid Build Coastguard Worker return CURLM_OK; /* it is already removed so let's say it is fine! */
796*6236dae4SAndroid Build Coastguard Worker
797*6236dae4SAndroid Build Coastguard Worker /* Prevent users from trying to remove an easy handle from the wrong multi */
798*6236dae4SAndroid Build Coastguard Worker if(data->multi != multi)
799*6236dae4SAndroid Build Coastguard Worker return CURLM_BAD_EASY_HANDLE;
800*6236dae4SAndroid Build Coastguard Worker
801*6236dae4SAndroid Build Coastguard Worker if(multi->in_callback)
802*6236dae4SAndroid Build Coastguard Worker return CURLM_RECURSIVE_API_CALL;
803*6236dae4SAndroid Build Coastguard Worker
804*6236dae4SAndroid Build Coastguard Worker premature = (data->mstate < MSTATE_COMPLETED);
805*6236dae4SAndroid Build Coastguard Worker
806*6236dae4SAndroid Build Coastguard Worker /* If the 'state' is not INIT or COMPLETED, we might need to do something
807*6236dae4SAndroid Build Coastguard Worker nice to put the easy_handle in a good known state when this returns. */
808*6236dae4SAndroid Build Coastguard Worker if(premature) {
809*6236dae4SAndroid Build Coastguard Worker /* this handle is "alive" so we need to count down the total number of
810*6236dae4SAndroid Build Coastguard Worker alive connections when this is removed */
811*6236dae4SAndroid Build Coastguard Worker multi->num_alive--;
812*6236dae4SAndroid Build Coastguard Worker }
813*6236dae4SAndroid Build Coastguard Worker
814*6236dae4SAndroid Build Coastguard Worker if(data->conn &&
815*6236dae4SAndroid Build Coastguard Worker data->mstate > MSTATE_DO &&
816*6236dae4SAndroid Build Coastguard Worker data->mstate < MSTATE_COMPLETED) {
817*6236dae4SAndroid Build Coastguard Worker /* Set connection owner so that the DONE function closes it. We can
818*6236dae4SAndroid Build Coastguard Worker safely do this here since connection is killed. */
819*6236dae4SAndroid Build Coastguard Worker streamclose(data->conn, "Removed with partial response");
820*6236dae4SAndroid Build Coastguard Worker }
821*6236dae4SAndroid Build Coastguard Worker
822*6236dae4SAndroid Build Coastguard Worker if(data->conn) {
823*6236dae4SAndroid Build Coastguard Worker /* multi_done() clears the association between the easy handle and the
824*6236dae4SAndroid Build Coastguard Worker connection.
825*6236dae4SAndroid Build Coastguard Worker
826*6236dae4SAndroid Build Coastguard Worker Note that this ignores the return code simply because there is
827*6236dae4SAndroid Build Coastguard Worker nothing really useful to do with it anyway! */
828*6236dae4SAndroid Build Coastguard Worker (void)multi_done(data, data->result, premature);
829*6236dae4SAndroid Build Coastguard Worker }
830*6236dae4SAndroid Build Coastguard Worker
831*6236dae4SAndroid Build Coastguard Worker /* The timer must be shut down before data->multi is set to NULL, else the
832*6236dae4SAndroid Build Coastguard Worker timenode will remain in the splay tree after curl_easy_cleanup is
833*6236dae4SAndroid Build Coastguard Worker called. Do it after multi_done() in case that sets another time! */
834*6236dae4SAndroid Build Coastguard Worker removed_timer = Curl_expire_clear(data);
835*6236dae4SAndroid Build Coastguard Worker
836*6236dae4SAndroid Build Coastguard Worker /* the handle is in a list, remove it from whichever it is */
837*6236dae4SAndroid Build Coastguard Worker Curl_node_remove(&data->multi_queue);
838*6236dae4SAndroid Build Coastguard Worker
839*6236dae4SAndroid Build Coastguard Worker if(data->dns.hostcachetype == HCACHE_MULTI) {
840*6236dae4SAndroid Build Coastguard Worker /* stop using the multi handle's DNS cache, *after* the possible
841*6236dae4SAndroid Build Coastguard Worker multi_done() call above */
842*6236dae4SAndroid Build Coastguard Worker data->dns.hostcache = NULL;
843*6236dae4SAndroid Build Coastguard Worker data->dns.hostcachetype = HCACHE_NONE;
844*6236dae4SAndroid Build Coastguard Worker }
845*6236dae4SAndroid Build Coastguard Worker
846*6236dae4SAndroid Build Coastguard Worker Curl_wildcard_dtor(&data->wildcard);
847*6236dae4SAndroid Build Coastguard Worker
848*6236dae4SAndroid Build Coastguard Worker /* change state without using multistate(), only to make singlesocket() do
849*6236dae4SAndroid Build Coastguard Worker what we want */
850*6236dae4SAndroid Build Coastguard Worker data->mstate = MSTATE_COMPLETED;
851*6236dae4SAndroid Build Coastguard Worker
852*6236dae4SAndroid Build Coastguard Worker /* This ignores the return code even in case of problems because there is
853*6236dae4SAndroid Build Coastguard Worker nothing more to do about that, here */
854*6236dae4SAndroid Build Coastguard Worker (void)singlesocket(multi, data); /* to let the application know what sockets
855*6236dae4SAndroid Build Coastguard Worker that vanish with this handle */
856*6236dae4SAndroid Build Coastguard Worker
857*6236dae4SAndroid Build Coastguard Worker /* Remove the association between the connection and the handle */
858*6236dae4SAndroid Build Coastguard Worker Curl_detach_connection(data);
859*6236dae4SAndroid Build Coastguard Worker
860*6236dae4SAndroid Build Coastguard Worker if(data->set.connect_only && !data->multi_easy) {
861*6236dae4SAndroid Build Coastguard Worker /* This removes a handle that was part the multi interface that used
862*6236dae4SAndroid Build Coastguard Worker CONNECT_ONLY, that connection is now left alive but since this handle
863*6236dae4SAndroid Build Coastguard Worker has bits.close set nothing can use that transfer anymore and it is
864*6236dae4SAndroid Build Coastguard Worker forbidden from reuse. This easy handle cannot find the connection
865*6236dae4SAndroid Build Coastguard Worker anymore once removed from the multi handle
866*6236dae4SAndroid Build Coastguard Worker
867*6236dae4SAndroid Build Coastguard Worker Better close the connection here, at once.
868*6236dae4SAndroid Build Coastguard Worker */
869*6236dae4SAndroid Build Coastguard Worker struct connectdata *c;
870*6236dae4SAndroid Build Coastguard Worker curl_socket_t s;
871*6236dae4SAndroid Build Coastguard Worker s = Curl_getconnectinfo(data, &c);
872*6236dae4SAndroid Build Coastguard Worker if((s != CURL_SOCKET_BAD) && c) {
873*6236dae4SAndroid Build Coastguard Worker Curl_cpool_disconnect(data, c, TRUE);
874*6236dae4SAndroid Build Coastguard Worker }
875*6236dae4SAndroid Build Coastguard Worker }
876*6236dae4SAndroid Build Coastguard Worker
877*6236dae4SAndroid Build Coastguard Worker if(data->state.lastconnect_id != -1) {
878*6236dae4SAndroid Build Coastguard Worker /* Mark any connect-only connection for closure */
879*6236dae4SAndroid Build Coastguard Worker Curl_cpool_do_by_id(data, data->state.lastconnect_id,
880*6236dae4SAndroid Build Coastguard Worker close_connect_only, NULL);
881*6236dae4SAndroid Build Coastguard Worker }
882*6236dae4SAndroid Build Coastguard Worker
883*6236dae4SAndroid Build Coastguard Worker #ifdef USE_LIBPSL
884*6236dae4SAndroid Build Coastguard Worker /* Remove the PSL association. */
885*6236dae4SAndroid Build Coastguard Worker if(data->psl == &multi->psl)
886*6236dae4SAndroid Build Coastguard Worker data->psl = NULL;
887*6236dae4SAndroid Build Coastguard Worker #endif
888*6236dae4SAndroid Build Coastguard Worker
889*6236dae4SAndroid Build Coastguard Worker /* make sure there is no pending message in the queue sent from this easy
890*6236dae4SAndroid Build Coastguard Worker handle */
891*6236dae4SAndroid Build Coastguard Worker for(e = Curl_llist_head(&multi->msglist); e; e = Curl_node_next(e)) {
892*6236dae4SAndroid Build Coastguard Worker struct Curl_message *msg = Curl_node_elem(e);
893*6236dae4SAndroid Build Coastguard Worker
894*6236dae4SAndroid Build Coastguard Worker if(msg->extmsg.easy_handle == data) {
895*6236dae4SAndroid Build Coastguard Worker Curl_node_remove(e);
896*6236dae4SAndroid Build Coastguard Worker /* there can only be one from this specific handle */
897*6236dae4SAndroid Build Coastguard Worker break;
898*6236dae4SAndroid Build Coastguard Worker }
899*6236dae4SAndroid Build Coastguard Worker }
900*6236dae4SAndroid Build Coastguard Worker
901*6236dae4SAndroid Build Coastguard Worker data->multi = NULL; /* clear the association to this multi handle */
902*6236dae4SAndroid Build Coastguard Worker data->mid = -1;
903*6236dae4SAndroid Build Coastguard Worker
904*6236dae4SAndroid Build Coastguard Worker /* NOTE NOTE NOTE
905*6236dae4SAndroid Build Coastguard Worker We do not touch the easy handle here! */
906*6236dae4SAndroid Build Coastguard Worker multi->num_easy--; /* one less to care about now */
907*6236dae4SAndroid Build Coastguard Worker process_pending_handles(multi);
908*6236dae4SAndroid Build Coastguard Worker
909*6236dae4SAndroid Build Coastguard Worker if(removed_timer) {
910*6236dae4SAndroid Build Coastguard Worker rc = Curl_update_timer(multi);
911*6236dae4SAndroid Build Coastguard Worker if(rc)
912*6236dae4SAndroid Build Coastguard Worker return rc;
913*6236dae4SAndroid Build Coastguard Worker }
914*6236dae4SAndroid Build Coastguard Worker return CURLM_OK;
915*6236dae4SAndroid Build Coastguard Worker }
916*6236dae4SAndroid Build Coastguard Worker
917*6236dae4SAndroid Build Coastguard Worker /* Return TRUE if the application asked for multiplexing */
Curl_multiplex_wanted(const struct Curl_multi * multi)918*6236dae4SAndroid Build Coastguard Worker bool Curl_multiplex_wanted(const struct Curl_multi *multi)
919*6236dae4SAndroid Build Coastguard Worker {
920*6236dae4SAndroid Build Coastguard Worker return (multi && (multi->multiplexing));
921*6236dae4SAndroid Build Coastguard Worker }
922*6236dae4SAndroid Build Coastguard Worker
923*6236dae4SAndroid Build Coastguard Worker /*
924*6236dae4SAndroid Build Coastguard Worker * Curl_detach_connection() removes the given transfer from the connection.
925*6236dae4SAndroid Build Coastguard Worker *
926*6236dae4SAndroid Build Coastguard Worker * This is the only function that should clear data->conn. This will
927*6236dae4SAndroid Build Coastguard Worker * occasionally be called with the data->conn pointer already cleared.
928*6236dae4SAndroid Build Coastguard Worker */
Curl_detach_connection(struct Curl_easy * data)929*6236dae4SAndroid Build Coastguard Worker void Curl_detach_connection(struct Curl_easy *data)
930*6236dae4SAndroid Build Coastguard Worker {
931*6236dae4SAndroid Build Coastguard Worker struct connectdata *conn = data->conn;
932*6236dae4SAndroid Build Coastguard Worker if(conn) {
933*6236dae4SAndroid Build Coastguard Worker Curl_conn_ev_data_detach(conn, data);
934*6236dae4SAndroid Build Coastguard Worker Curl_node_remove(&data->conn_queue);
935*6236dae4SAndroid Build Coastguard Worker }
936*6236dae4SAndroid Build Coastguard Worker data->conn = NULL;
937*6236dae4SAndroid Build Coastguard Worker }
938*6236dae4SAndroid Build Coastguard Worker
939*6236dae4SAndroid Build Coastguard Worker /*
940*6236dae4SAndroid Build Coastguard Worker * Curl_attach_connection() attaches this transfer to this connection.
941*6236dae4SAndroid Build Coastguard Worker *
942*6236dae4SAndroid Build Coastguard Worker * This is the only function that should assign data->conn
943*6236dae4SAndroid Build Coastguard Worker */
Curl_attach_connection(struct Curl_easy * data,struct connectdata * conn)944*6236dae4SAndroid Build Coastguard Worker void Curl_attach_connection(struct Curl_easy *data,
945*6236dae4SAndroid Build Coastguard Worker struct connectdata *conn)
946*6236dae4SAndroid Build Coastguard Worker {
947*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(data);
948*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(!data->conn);
949*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(conn);
950*6236dae4SAndroid Build Coastguard Worker data->conn = conn;
951*6236dae4SAndroid Build Coastguard Worker Curl_llist_append(&conn->easyq, data, &data->conn_queue);
952*6236dae4SAndroid Build Coastguard Worker if(conn->handler && conn->handler->attach)
953*6236dae4SAndroid Build Coastguard Worker conn->handler->attach(data, conn);
954*6236dae4SAndroid Build Coastguard Worker Curl_conn_ev_data_attach(conn, data);
955*6236dae4SAndroid Build Coastguard Worker }
956*6236dae4SAndroid Build Coastguard Worker
connecting_getsock(struct Curl_easy * data,curl_socket_t * socks)957*6236dae4SAndroid Build Coastguard Worker static int connecting_getsock(struct Curl_easy *data, curl_socket_t *socks)
958*6236dae4SAndroid Build Coastguard Worker {
959*6236dae4SAndroid Build Coastguard Worker struct connectdata *conn = data->conn;
960*6236dae4SAndroid Build Coastguard Worker curl_socket_t sockfd;
961*6236dae4SAndroid Build Coastguard Worker
962*6236dae4SAndroid Build Coastguard Worker if(!conn)
963*6236dae4SAndroid Build Coastguard Worker return GETSOCK_BLANK;
964*6236dae4SAndroid Build Coastguard Worker sockfd = Curl_conn_get_socket(data, FIRSTSOCKET);
965*6236dae4SAndroid Build Coastguard Worker if(sockfd != CURL_SOCKET_BAD) {
966*6236dae4SAndroid Build Coastguard Worker /* Default is to wait to something from the server */
967*6236dae4SAndroid Build Coastguard Worker socks[0] = sockfd;
968*6236dae4SAndroid Build Coastguard Worker return GETSOCK_READSOCK(0);
969*6236dae4SAndroid Build Coastguard Worker }
970*6236dae4SAndroid Build Coastguard Worker return GETSOCK_BLANK;
971*6236dae4SAndroid Build Coastguard Worker }
972*6236dae4SAndroid Build Coastguard Worker
protocol_getsock(struct Curl_easy * data,curl_socket_t * socks)973*6236dae4SAndroid Build Coastguard Worker static int protocol_getsock(struct Curl_easy *data, curl_socket_t *socks)
974*6236dae4SAndroid Build Coastguard Worker {
975*6236dae4SAndroid Build Coastguard Worker struct connectdata *conn = data->conn;
976*6236dae4SAndroid Build Coastguard Worker curl_socket_t sockfd;
977*6236dae4SAndroid Build Coastguard Worker
978*6236dae4SAndroid Build Coastguard Worker if(!conn)
979*6236dae4SAndroid Build Coastguard Worker return GETSOCK_BLANK;
980*6236dae4SAndroid Build Coastguard Worker if(conn->handler->proto_getsock)
981*6236dae4SAndroid Build Coastguard Worker return conn->handler->proto_getsock(data, conn, socks);
982*6236dae4SAndroid Build Coastguard Worker sockfd = Curl_conn_get_socket(data, FIRSTSOCKET);
983*6236dae4SAndroid Build Coastguard Worker if(sockfd != CURL_SOCKET_BAD) {
984*6236dae4SAndroid Build Coastguard Worker /* Default is to wait to something from the server */
985*6236dae4SAndroid Build Coastguard Worker socks[0] = sockfd;
986*6236dae4SAndroid Build Coastguard Worker return GETSOCK_READSOCK(0);
987*6236dae4SAndroid Build Coastguard Worker }
988*6236dae4SAndroid Build Coastguard Worker return GETSOCK_BLANK;
989*6236dae4SAndroid Build Coastguard Worker }
990*6236dae4SAndroid Build Coastguard Worker
domore_getsock(struct Curl_easy * data,curl_socket_t * socks)991*6236dae4SAndroid Build Coastguard Worker static int domore_getsock(struct Curl_easy *data, curl_socket_t *socks)
992*6236dae4SAndroid Build Coastguard Worker {
993*6236dae4SAndroid Build Coastguard Worker struct connectdata *conn = data->conn;
994*6236dae4SAndroid Build Coastguard Worker if(!conn)
995*6236dae4SAndroid Build Coastguard Worker return GETSOCK_BLANK;
996*6236dae4SAndroid Build Coastguard Worker if(conn->handler->domore_getsock)
997*6236dae4SAndroid Build Coastguard Worker return conn->handler->domore_getsock(data, conn, socks);
998*6236dae4SAndroid Build Coastguard Worker else if(conn->sockfd != CURL_SOCKET_BAD) {
999*6236dae4SAndroid Build Coastguard Worker /* Default is that we want to send something to the server */
1000*6236dae4SAndroid Build Coastguard Worker socks[0] = conn->sockfd;
1001*6236dae4SAndroid Build Coastguard Worker return GETSOCK_WRITESOCK(0);
1002*6236dae4SAndroid Build Coastguard Worker }
1003*6236dae4SAndroid Build Coastguard Worker return GETSOCK_BLANK;
1004*6236dae4SAndroid Build Coastguard Worker }
1005*6236dae4SAndroid Build Coastguard Worker
doing_getsock(struct Curl_easy * data,curl_socket_t * socks)1006*6236dae4SAndroid Build Coastguard Worker static int doing_getsock(struct Curl_easy *data, curl_socket_t *socks)
1007*6236dae4SAndroid Build Coastguard Worker {
1008*6236dae4SAndroid Build Coastguard Worker struct connectdata *conn = data->conn;
1009*6236dae4SAndroid Build Coastguard Worker if(!conn)
1010*6236dae4SAndroid Build Coastguard Worker return GETSOCK_BLANK;
1011*6236dae4SAndroid Build Coastguard Worker if(conn->handler->doing_getsock)
1012*6236dae4SAndroid Build Coastguard Worker return conn->handler->doing_getsock(data, conn, socks);
1013*6236dae4SAndroid Build Coastguard Worker else if(conn->sockfd != CURL_SOCKET_BAD) {
1014*6236dae4SAndroid Build Coastguard Worker /* Default is that we want to send something to the server */
1015*6236dae4SAndroid Build Coastguard Worker socks[0] = conn->sockfd;
1016*6236dae4SAndroid Build Coastguard Worker return GETSOCK_WRITESOCK(0);
1017*6236dae4SAndroid Build Coastguard Worker }
1018*6236dae4SAndroid Build Coastguard Worker return GETSOCK_BLANK;
1019*6236dae4SAndroid Build Coastguard Worker }
1020*6236dae4SAndroid Build Coastguard Worker
perform_getsock(struct Curl_easy * data,curl_socket_t * sock)1021*6236dae4SAndroid Build Coastguard Worker static int perform_getsock(struct Curl_easy *data, curl_socket_t *sock)
1022*6236dae4SAndroid Build Coastguard Worker {
1023*6236dae4SAndroid Build Coastguard Worker struct connectdata *conn = data->conn;
1024*6236dae4SAndroid Build Coastguard Worker if(!conn)
1025*6236dae4SAndroid Build Coastguard Worker return GETSOCK_BLANK;
1026*6236dae4SAndroid Build Coastguard Worker else if(conn->handler->perform_getsock)
1027*6236dae4SAndroid Build Coastguard Worker return conn->handler->perform_getsock(data, conn, sock);
1028*6236dae4SAndroid Build Coastguard Worker else {
1029*6236dae4SAndroid Build Coastguard Worker /* Default is to obey the data->req.keepon flags for send/recv */
1030*6236dae4SAndroid Build Coastguard Worker int bitmap = GETSOCK_BLANK;
1031*6236dae4SAndroid Build Coastguard Worker unsigned sockindex = 0;
1032*6236dae4SAndroid Build Coastguard Worker if(CURL_WANT_RECV(data)) {
1033*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(conn->sockfd != CURL_SOCKET_BAD);
1034*6236dae4SAndroid Build Coastguard Worker bitmap |= GETSOCK_READSOCK(sockindex);
1035*6236dae4SAndroid Build Coastguard Worker sock[sockindex] = conn->sockfd;
1036*6236dae4SAndroid Build Coastguard Worker }
1037*6236dae4SAndroid Build Coastguard Worker
1038*6236dae4SAndroid Build Coastguard Worker if(Curl_req_want_send(data)) {
1039*6236dae4SAndroid Build Coastguard Worker if((conn->sockfd != conn->writesockfd) ||
1040*6236dae4SAndroid Build Coastguard Worker bitmap == GETSOCK_BLANK) {
1041*6236dae4SAndroid Build Coastguard Worker /* only if they are not the same socket and we have a readable
1042*6236dae4SAndroid Build Coastguard Worker one, we increase index */
1043*6236dae4SAndroid Build Coastguard Worker if(bitmap != GETSOCK_BLANK)
1044*6236dae4SAndroid Build Coastguard Worker sockindex++; /* increase index if we need two entries */
1045*6236dae4SAndroid Build Coastguard Worker
1046*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(conn->writesockfd != CURL_SOCKET_BAD);
1047*6236dae4SAndroid Build Coastguard Worker sock[sockindex] = conn->writesockfd;
1048*6236dae4SAndroid Build Coastguard Worker }
1049*6236dae4SAndroid Build Coastguard Worker bitmap |= GETSOCK_WRITESOCK(sockindex);
1050*6236dae4SAndroid Build Coastguard Worker }
1051*6236dae4SAndroid Build Coastguard Worker return bitmap;
1052*6236dae4SAndroid Build Coastguard Worker }
1053*6236dae4SAndroid Build Coastguard Worker }
1054*6236dae4SAndroid Build Coastguard Worker
1055*6236dae4SAndroid Build Coastguard Worker /* Initializes `poll_set` with the current socket poll actions needed
1056*6236dae4SAndroid Build Coastguard Worker * for transfer `data`. */
multi_getsock(struct Curl_easy * data,struct easy_pollset * ps)1057*6236dae4SAndroid Build Coastguard Worker static void multi_getsock(struct Curl_easy *data,
1058*6236dae4SAndroid Build Coastguard Worker struct easy_pollset *ps)
1059*6236dae4SAndroid Build Coastguard Worker {
1060*6236dae4SAndroid Build Coastguard Worker bool expect_sockets = TRUE;
1061*6236dae4SAndroid Build Coastguard Worker /* The no connection case can happen when this is called from
1062*6236dae4SAndroid Build Coastguard Worker curl_multi_remove_handle() => singlesocket() => multi_getsock().
1063*6236dae4SAndroid Build Coastguard Worker */
1064*6236dae4SAndroid Build Coastguard Worker Curl_pollset_reset(data, ps);
1065*6236dae4SAndroid Build Coastguard Worker if(!data->conn)
1066*6236dae4SAndroid Build Coastguard Worker return;
1067*6236dae4SAndroid Build Coastguard Worker
1068*6236dae4SAndroid Build Coastguard Worker switch(data->mstate) {
1069*6236dae4SAndroid Build Coastguard Worker case MSTATE_INIT:
1070*6236dae4SAndroid Build Coastguard Worker case MSTATE_PENDING:
1071*6236dae4SAndroid Build Coastguard Worker case MSTATE_SETUP:
1072*6236dae4SAndroid Build Coastguard Worker case MSTATE_CONNECT:
1073*6236dae4SAndroid Build Coastguard Worker /* nothing to poll for yet */
1074*6236dae4SAndroid Build Coastguard Worker expect_sockets = FALSE;
1075*6236dae4SAndroid Build Coastguard Worker break;
1076*6236dae4SAndroid Build Coastguard Worker
1077*6236dae4SAndroid Build Coastguard Worker case MSTATE_RESOLVING:
1078*6236dae4SAndroid Build Coastguard Worker Curl_pollset_add_socks(data, ps, Curl_resolv_getsock);
1079*6236dae4SAndroid Build Coastguard Worker /* connection filters are not involved in this phase. It's ok if we get no
1080*6236dae4SAndroid Build Coastguard Worker * sockets to wait for. Resolving can wake up from other sources. */
1081*6236dae4SAndroid Build Coastguard Worker expect_sockets = FALSE;
1082*6236dae4SAndroid Build Coastguard Worker break;
1083*6236dae4SAndroid Build Coastguard Worker
1084*6236dae4SAndroid Build Coastguard Worker case MSTATE_CONNECTING:
1085*6236dae4SAndroid Build Coastguard Worker case MSTATE_TUNNELING:
1086*6236dae4SAndroid Build Coastguard Worker Curl_pollset_add_socks(data, ps, connecting_getsock);
1087*6236dae4SAndroid Build Coastguard Worker Curl_conn_adjust_pollset(data, ps);
1088*6236dae4SAndroid Build Coastguard Worker break;
1089*6236dae4SAndroid Build Coastguard Worker
1090*6236dae4SAndroid Build Coastguard Worker case MSTATE_PROTOCONNECT:
1091*6236dae4SAndroid Build Coastguard Worker case MSTATE_PROTOCONNECTING:
1092*6236dae4SAndroid Build Coastguard Worker Curl_pollset_add_socks(data, ps, protocol_getsock);
1093*6236dae4SAndroid Build Coastguard Worker Curl_conn_adjust_pollset(data, ps);
1094*6236dae4SAndroid Build Coastguard Worker break;
1095*6236dae4SAndroid Build Coastguard Worker
1096*6236dae4SAndroid Build Coastguard Worker case MSTATE_DO:
1097*6236dae4SAndroid Build Coastguard Worker case MSTATE_DOING:
1098*6236dae4SAndroid Build Coastguard Worker Curl_pollset_add_socks(data, ps, doing_getsock);
1099*6236dae4SAndroid Build Coastguard Worker Curl_conn_adjust_pollset(data, ps);
1100*6236dae4SAndroid Build Coastguard Worker break;
1101*6236dae4SAndroid Build Coastguard Worker
1102*6236dae4SAndroid Build Coastguard Worker case MSTATE_DOING_MORE:
1103*6236dae4SAndroid Build Coastguard Worker Curl_pollset_add_socks(data, ps, domore_getsock);
1104*6236dae4SAndroid Build Coastguard Worker Curl_conn_adjust_pollset(data, ps);
1105*6236dae4SAndroid Build Coastguard Worker break;
1106*6236dae4SAndroid Build Coastguard Worker
1107*6236dae4SAndroid Build Coastguard Worker case MSTATE_DID: /* same as PERFORMING in regard to polling */
1108*6236dae4SAndroid Build Coastguard Worker case MSTATE_PERFORMING:
1109*6236dae4SAndroid Build Coastguard Worker Curl_pollset_add_socks(data, ps, perform_getsock);
1110*6236dae4SAndroid Build Coastguard Worker Curl_conn_adjust_pollset(data, ps);
1111*6236dae4SAndroid Build Coastguard Worker break;
1112*6236dae4SAndroid Build Coastguard Worker
1113*6236dae4SAndroid Build Coastguard Worker case MSTATE_RATELIMITING:
1114*6236dae4SAndroid Build Coastguard Worker /* we need to let time pass, ignore socket(s) */
1115*6236dae4SAndroid Build Coastguard Worker expect_sockets = FALSE;
1116*6236dae4SAndroid Build Coastguard Worker break;
1117*6236dae4SAndroid Build Coastguard Worker
1118*6236dae4SAndroid Build Coastguard Worker case MSTATE_DONE:
1119*6236dae4SAndroid Build Coastguard Worker case MSTATE_COMPLETED:
1120*6236dae4SAndroid Build Coastguard Worker case MSTATE_MSGSENT:
1121*6236dae4SAndroid Build Coastguard Worker /* nothing more to poll for */
1122*6236dae4SAndroid Build Coastguard Worker expect_sockets = FALSE;
1123*6236dae4SAndroid Build Coastguard Worker break;
1124*6236dae4SAndroid Build Coastguard Worker
1125*6236dae4SAndroid Build Coastguard Worker default:
1126*6236dae4SAndroid Build Coastguard Worker failf(data, "multi_getsock: unexpected multi state %d", data->mstate);
1127*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(0);
1128*6236dae4SAndroid Build Coastguard Worker expect_sockets = FALSE;
1129*6236dae4SAndroid Build Coastguard Worker break;
1130*6236dae4SAndroid Build Coastguard Worker }
1131*6236dae4SAndroid Build Coastguard Worker
1132*6236dae4SAndroid Build Coastguard Worker if(expect_sockets && !ps->num &&
1133*6236dae4SAndroid Build Coastguard Worker !Curl_llist_count(&data->state.timeoutlist) &&
1134*6236dae4SAndroid Build Coastguard Worker !Curl_cwriter_is_paused(data) && !Curl_creader_is_paused(data) &&
1135*6236dae4SAndroid Build Coastguard Worker Curl_conn_is_ip_connected(data, FIRSTSOCKET)) {
1136*6236dae4SAndroid Build Coastguard Worker /* We expected sockets for POLL monitoring, but none are set.
1137*6236dae4SAndroid Build Coastguard Worker * We are not waiting on any timer.
1138*6236dae4SAndroid Build Coastguard Worker * None of the READ/WRITE directions are paused.
1139*6236dae4SAndroid Build Coastguard Worker * We are connected to the server on IP level, at least. */
1140*6236dae4SAndroid Build Coastguard Worker infof(data, "WARNING: no socket in pollset or timer, transfer may stall!");
1141*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(0);
1142*6236dae4SAndroid Build Coastguard Worker }
1143*6236dae4SAndroid Build Coastguard Worker }
1144*6236dae4SAndroid Build Coastguard Worker
curl_multi_fdset(CURLM * m,fd_set * read_fd_set,fd_set * write_fd_set,fd_set * exc_fd_set,int * max_fd)1145*6236dae4SAndroid Build Coastguard Worker CURLMcode curl_multi_fdset(CURLM *m,
1146*6236dae4SAndroid Build Coastguard Worker fd_set *read_fd_set, fd_set *write_fd_set,
1147*6236dae4SAndroid Build Coastguard Worker fd_set *exc_fd_set, int *max_fd)
1148*6236dae4SAndroid Build Coastguard Worker {
1149*6236dae4SAndroid Build Coastguard Worker /* Scan through all the easy handles to get the file descriptors set.
1150*6236dae4SAndroid Build Coastguard Worker Some easy handles may not have connected to the remote host yet,
1151*6236dae4SAndroid Build Coastguard Worker and then we must make sure that is done. */
1152*6236dae4SAndroid Build Coastguard Worker int this_max_fd = -1;
1153*6236dae4SAndroid Build Coastguard Worker struct Curl_llist_node *e;
1154*6236dae4SAndroid Build Coastguard Worker struct Curl_multi *multi = m;
1155*6236dae4SAndroid Build Coastguard Worker (void)exc_fd_set; /* not used */
1156*6236dae4SAndroid Build Coastguard Worker
1157*6236dae4SAndroid Build Coastguard Worker if(!GOOD_MULTI_HANDLE(multi))
1158*6236dae4SAndroid Build Coastguard Worker return CURLM_BAD_HANDLE;
1159*6236dae4SAndroid Build Coastguard Worker
1160*6236dae4SAndroid Build Coastguard Worker if(multi->in_callback)
1161*6236dae4SAndroid Build Coastguard Worker return CURLM_RECURSIVE_API_CALL;
1162*6236dae4SAndroid Build Coastguard Worker
1163*6236dae4SAndroid Build Coastguard Worker for(e = Curl_llist_head(&multi->process); e; e = Curl_node_next(e)) {
1164*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data = Curl_node_elem(e);
1165*6236dae4SAndroid Build Coastguard Worker unsigned int i;
1166*6236dae4SAndroid Build Coastguard Worker
1167*6236dae4SAndroid Build Coastguard Worker multi_getsock(data, &data->last_poll);
1168*6236dae4SAndroid Build Coastguard Worker
1169*6236dae4SAndroid Build Coastguard Worker for(i = 0; i < data->last_poll.num; i++) {
1170*6236dae4SAndroid Build Coastguard Worker if(!FDSET_SOCK(data->last_poll.sockets[i]))
1171*6236dae4SAndroid Build Coastguard Worker /* pretend it does not exist */
1172*6236dae4SAndroid Build Coastguard Worker continue;
1173*6236dae4SAndroid Build Coastguard Worker if(data->last_poll.actions[i] & CURL_POLL_IN)
1174*6236dae4SAndroid Build Coastguard Worker FD_SET(data->last_poll.sockets[i], read_fd_set);
1175*6236dae4SAndroid Build Coastguard Worker if(data->last_poll.actions[i] & CURL_POLL_OUT)
1176*6236dae4SAndroid Build Coastguard Worker FD_SET(data->last_poll.sockets[i], write_fd_set);
1177*6236dae4SAndroid Build Coastguard Worker if((int)data->last_poll.sockets[i] > this_max_fd)
1178*6236dae4SAndroid Build Coastguard Worker this_max_fd = (int)data->last_poll.sockets[i];
1179*6236dae4SAndroid Build Coastguard Worker }
1180*6236dae4SAndroid Build Coastguard Worker }
1181*6236dae4SAndroid Build Coastguard Worker
1182*6236dae4SAndroid Build Coastguard Worker *max_fd = this_max_fd;
1183*6236dae4SAndroid Build Coastguard Worker
1184*6236dae4SAndroid Build Coastguard Worker return CURLM_OK;
1185*6236dae4SAndroid Build Coastguard Worker }
1186*6236dae4SAndroid Build Coastguard Worker
curl_multi_waitfds(CURLM * m,struct curl_waitfd * ufds,unsigned int size,unsigned int * fd_count)1187*6236dae4SAndroid Build Coastguard Worker CURLMcode curl_multi_waitfds(CURLM *m,
1188*6236dae4SAndroid Build Coastguard Worker struct curl_waitfd *ufds,
1189*6236dae4SAndroid Build Coastguard Worker unsigned int size,
1190*6236dae4SAndroid Build Coastguard Worker unsigned int *fd_count)
1191*6236dae4SAndroid Build Coastguard Worker {
1192*6236dae4SAndroid Build Coastguard Worker struct curl_waitfds cwfds;
1193*6236dae4SAndroid Build Coastguard Worker CURLMcode result = CURLM_OK;
1194*6236dae4SAndroid Build Coastguard Worker struct Curl_llist_node *e;
1195*6236dae4SAndroid Build Coastguard Worker struct Curl_multi *multi = m;
1196*6236dae4SAndroid Build Coastguard Worker
1197*6236dae4SAndroid Build Coastguard Worker if(!ufds)
1198*6236dae4SAndroid Build Coastguard Worker return CURLM_BAD_FUNCTION_ARGUMENT;
1199*6236dae4SAndroid Build Coastguard Worker
1200*6236dae4SAndroid Build Coastguard Worker if(!GOOD_MULTI_HANDLE(multi))
1201*6236dae4SAndroid Build Coastguard Worker return CURLM_BAD_HANDLE;
1202*6236dae4SAndroid Build Coastguard Worker
1203*6236dae4SAndroid Build Coastguard Worker if(multi->in_callback)
1204*6236dae4SAndroid Build Coastguard Worker return CURLM_RECURSIVE_API_CALL;
1205*6236dae4SAndroid Build Coastguard Worker
1206*6236dae4SAndroid Build Coastguard Worker Curl_waitfds_init(&cwfds, ufds, size);
1207*6236dae4SAndroid Build Coastguard Worker for(e = Curl_llist_head(&multi->process); e; e = Curl_node_next(e)) {
1208*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data = Curl_node_elem(e);
1209*6236dae4SAndroid Build Coastguard Worker multi_getsock(data, &data->last_poll);
1210*6236dae4SAndroid Build Coastguard Worker if(Curl_waitfds_add_ps(&cwfds, &data->last_poll)) {
1211*6236dae4SAndroid Build Coastguard Worker result = CURLM_OUT_OF_MEMORY;
1212*6236dae4SAndroid Build Coastguard Worker goto out;
1213*6236dae4SAndroid Build Coastguard Worker }
1214*6236dae4SAndroid Build Coastguard Worker }
1215*6236dae4SAndroid Build Coastguard Worker
1216*6236dae4SAndroid Build Coastguard Worker if(Curl_cpool_add_waitfds(&multi->cpool, &cwfds)) {
1217*6236dae4SAndroid Build Coastguard Worker result = CURLM_OUT_OF_MEMORY;
1218*6236dae4SAndroid Build Coastguard Worker goto out;
1219*6236dae4SAndroid Build Coastguard Worker }
1220*6236dae4SAndroid Build Coastguard Worker
1221*6236dae4SAndroid Build Coastguard Worker out:
1222*6236dae4SAndroid Build Coastguard Worker if(fd_count)
1223*6236dae4SAndroid Build Coastguard Worker *fd_count = cwfds.n;
1224*6236dae4SAndroid Build Coastguard Worker return result;
1225*6236dae4SAndroid Build Coastguard Worker }
1226*6236dae4SAndroid Build Coastguard Worker
1227*6236dae4SAndroid Build Coastguard Worker #ifdef USE_WINSOCK
1228*6236dae4SAndroid Build Coastguard Worker /* Reset FD_WRITE for TCP sockets. Nothing is actually sent. UDP sockets cannot
1229*6236dae4SAndroid Build Coastguard Worker * be reset this way because an empty datagram would be sent. #9203
1230*6236dae4SAndroid Build Coastguard Worker *
1231*6236dae4SAndroid Build Coastguard Worker * "On Windows the internal state of FD_WRITE as returned from
1232*6236dae4SAndroid Build Coastguard Worker * WSAEnumNetworkEvents is only reset after successful send()."
1233*6236dae4SAndroid Build Coastguard Worker */
reset_socket_fdwrite(curl_socket_t s)1234*6236dae4SAndroid Build Coastguard Worker static void reset_socket_fdwrite(curl_socket_t s)
1235*6236dae4SAndroid Build Coastguard Worker {
1236*6236dae4SAndroid Build Coastguard Worker int t;
1237*6236dae4SAndroid Build Coastguard Worker int l = (int)sizeof(t);
1238*6236dae4SAndroid Build Coastguard Worker if(!getsockopt(s, SOL_SOCKET, SO_TYPE, (char *)&t, &l) && t == SOCK_STREAM)
1239*6236dae4SAndroid Build Coastguard Worker send(s, NULL, 0, 0);
1240*6236dae4SAndroid Build Coastguard Worker }
1241*6236dae4SAndroid Build Coastguard Worker #endif
1242*6236dae4SAndroid Build Coastguard Worker
1243*6236dae4SAndroid Build Coastguard Worker #define NUM_POLLS_ON_STACK 10
1244*6236dae4SAndroid Build Coastguard Worker
multi_wait(struct Curl_multi * multi,struct curl_waitfd extra_fds[],unsigned int extra_nfds,int timeout_ms,int * ret,bool extrawait,bool use_wakeup)1245*6236dae4SAndroid Build Coastguard Worker static CURLMcode multi_wait(struct Curl_multi *multi,
1246*6236dae4SAndroid Build Coastguard Worker struct curl_waitfd extra_fds[],
1247*6236dae4SAndroid Build Coastguard Worker unsigned int extra_nfds,
1248*6236dae4SAndroid Build Coastguard Worker int timeout_ms,
1249*6236dae4SAndroid Build Coastguard Worker int *ret,
1250*6236dae4SAndroid Build Coastguard Worker bool extrawait, /* when no socket, wait */
1251*6236dae4SAndroid Build Coastguard Worker bool use_wakeup)
1252*6236dae4SAndroid Build Coastguard Worker {
1253*6236dae4SAndroid Build Coastguard Worker size_t i;
1254*6236dae4SAndroid Build Coastguard Worker struct curltime expire_time;
1255*6236dae4SAndroid Build Coastguard Worker long timeout_internal;
1256*6236dae4SAndroid Build Coastguard Worker int retcode = 0;
1257*6236dae4SAndroid Build Coastguard Worker struct pollfd a_few_on_stack[NUM_POLLS_ON_STACK];
1258*6236dae4SAndroid Build Coastguard Worker struct curl_pollfds cpfds;
1259*6236dae4SAndroid Build Coastguard Worker unsigned int curl_nfds = 0; /* how many pfds are for curl transfers */
1260*6236dae4SAndroid Build Coastguard Worker CURLMcode result = CURLM_OK;
1261*6236dae4SAndroid Build Coastguard Worker struct Curl_llist_node *e;
1262*6236dae4SAndroid Build Coastguard Worker
1263*6236dae4SAndroid Build Coastguard Worker #ifdef USE_WINSOCK
1264*6236dae4SAndroid Build Coastguard Worker WSANETWORKEVENTS wsa_events;
1265*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(multi->wsa_event != WSA_INVALID_EVENT);
1266*6236dae4SAndroid Build Coastguard Worker #endif
1267*6236dae4SAndroid Build Coastguard Worker #ifndef ENABLE_WAKEUP
1268*6236dae4SAndroid Build Coastguard Worker (void)use_wakeup;
1269*6236dae4SAndroid Build Coastguard Worker #endif
1270*6236dae4SAndroid Build Coastguard Worker
1271*6236dae4SAndroid Build Coastguard Worker if(!GOOD_MULTI_HANDLE(multi))
1272*6236dae4SAndroid Build Coastguard Worker return CURLM_BAD_HANDLE;
1273*6236dae4SAndroid Build Coastguard Worker
1274*6236dae4SAndroid Build Coastguard Worker if(multi->in_callback)
1275*6236dae4SAndroid Build Coastguard Worker return CURLM_RECURSIVE_API_CALL;
1276*6236dae4SAndroid Build Coastguard Worker
1277*6236dae4SAndroid Build Coastguard Worker if(timeout_ms < 0)
1278*6236dae4SAndroid Build Coastguard Worker return CURLM_BAD_FUNCTION_ARGUMENT;
1279*6236dae4SAndroid Build Coastguard Worker
1280*6236dae4SAndroid Build Coastguard Worker Curl_pollfds_init(&cpfds, a_few_on_stack, NUM_POLLS_ON_STACK);
1281*6236dae4SAndroid Build Coastguard Worker
1282*6236dae4SAndroid Build Coastguard Worker /* Add the curl handles to our pollfds first */
1283*6236dae4SAndroid Build Coastguard Worker for(e = Curl_llist_head(&multi->process); e; e = Curl_node_next(e)) {
1284*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data = Curl_node_elem(e);
1285*6236dae4SAndroid Build Coastguard Worker
1286*6236dae4SAndroid Build Coastguard Worker multi_getsock(data, &data->last_poll);
1287*6236dae4SAndroid Build Coastguard Worker if(Curl_pollfds_add_ps(&cpfds, &data->last_poll)) {
1288*6236dae4SAndroid Build Coastguard Worker result = CURLM_OUT_OF_MEMORY;
1289*6236dae4SAndroid Build Coastguard Worker goto out;
1290*6236dae4SAndroid Build Coastguard Worker }
1291*6236dae4SAndroid Build Coastguard Worker }
1292*6236dae4SAndroid Build Coastguard Worker
1293*6236dae4SAndroid Build Coastguard Worker if(Curl_cpool_add_pollfds(&multi->cpool, &cpfds)) {
1294*6236dae4SAndroid Build Coastguard Worker result = CURLM_OUT_OF_MEMORY;
1295*6236dae4SAndroid Build Coastguard Worker goto out;
1296*6236dae4SAndroid Build Coastguard Worker }
1297*6236dae4SAndroid Build Coastguard Worker
1298*6236dae4SAndroid Build Coastguard Worker curl_nfds = cpfds.n; /* what curl internally uses in cpfds */
1299*6236dae4SAndroid Build Coastguard Worker /* Add external file descriptions from poll-like struct curl_waitfd */
1300*6236dae4SAndroid Build Coastguard Worker for(i = 0; i < extra_nfds; i++) {
1301*6236dae4SAndroid Build Coastguard Worker unsigned short events = 0;
1302*6236dae4SAndroid Build Coastguard Worker if(extra_fds[i].events & CURL_WAIT_POLLIN)
1303*6236dae4SAndroid Build Coastguard Worker events |= POLLIN;
1304*6236dae4SAndroid Build Coastguard Worker if(extra_fds[i].events & CURL_WAIT_POLLPRI)
1305*6236dae4SAndroid Build Coastguard Worker events |= POLLPRI;
1306*6236dae4SAndroid Build Coastguard Worker if(extra_fds[i].events & CURL_WAIT_POLLOUT)
1307*6236dae4SAndroid Build Coastguard Worker events |= POLLOUT;
1308*6236dae4SAndroid Build Coastguard Worker if(Curl_pollfds_add_sock(&cpfds, extra_fds[i].fd, events)) {
1309*6236dae4SAndroid Build Coastguard Worker result = CURLM_OUT_OF_MEMORY;
1310*6236dae4SAndroid Build Coastguard Worker goto out;
1311*6236dae4SAndroid Build Coastguard Worker }
1312*6236dae4SAndroid Build Coastguard Worker }
1313*6236dae4SAndroid Build Coastguard Worker
1314*6236dae4SAndroid Build Coastguard Worker #ifdef USE_WINSOCK
1315*6236dae4SAndroid Build Coastguard Worker /* Set the WSA events based on the collected pollds */
1316*6236dae4SAndroid Build Coastguard Worker for(i = 0; i < cpfds.n; i++) {
1317*6236dae4SAndroid Build Coastguard Worker long mask = 0;
1318*6236dae4SAndroid Build Coastguard Worker if(cpfds.pfds[i].events & POLLIN)
1319*6236dae4SAndroid Build Coastguard Worker mask |= FD_READ|FD_ACCEPT|FD_CLOSE;
1320*6236dae4SAndroid Build Coastguard Worker if(cpfds.pfds[i].events & POLLPRI)
1321*6236dae4SAndroid Build Coastguard Worker mask |= FD_OOB;
1322*6236dae4SAndroid Build Coastguard Worker if(cpfds.pfds[i].events & POLLOUT) {
1323*6236dae4SAndroid Build Coastguard Worker mask |= FD_WRITE|FD_CONNECT|FD_CLOSE;
1324*6236dae4SAndroid Build Coastguard Worker reset_socket_fdwrite(cpfds.pfds[i].fd);
1325*6236dae4SAndroid Build Coastguard Worker }
1326*6236dae4SAndroid Build Coastguard Worker if(mask) {
1327*6236dae4SAndroid Build Coastguard Worker if(WSAEventSelect(cpfds.pfds[i].fd, multi->wsa_event, mask) != 0) {
1328*6236dae4SAndroid Build Coastguard Worker result = CURLM_OUT_OF_MEMORY;
1329*6236dae4SAndroid Build Coastguard Worker goto out;
1330*6236dae4SAndroid Build Coastguard Worker }
1331*6236dae4SAndroid Build Coastguard Worker }
1332*6236dae4SAndroid Build Coastguard Worker }
1333*6236dae4SAndroid Build Coastguard Worker #endif
1334*6236dae4SAndroid Build Coastguard Worker
1335*6236dae4SAndroid Build Coastguard Worker #ifdef ENABLE_WAKEUP
1336*6236dae4SAndroid Build Coastguard Worker #ifndef USE_WINSOCK
1337*6236dae4SAndroid Build Coastguard Worker if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) {
1338*6236dae4SAndroid Build Coastguard Worker if(Curl_pollfds_add_sock(&cpfds, multi->wakeup_pair[0], POLLIN)) {
1339*6236dae4SAndroid Build Coastguard Worker result = CURLM_OUT_OF_MEMORY;
1340*6236dae4SAndroid Build Coastguard Worker goto out;
1341*6236dae4SAndroid Build Coastguard Worker }
1342*6236dae4SAndroid Build Coastguard Worker }
1343*6236dae4SAndroid Build Coastguard Worker #endif
1344*6236dae4SAndroid Build Coastguard Worker #endif
1345*6236dae4SAndroid Build Coastguard Worker
1346*6236dae4SAndroid Build Coastguard Worker /* We check the internal timeout *AFTER* we collected all sockets to
1347*6236dae4SAndroid Build Coastguard Worker * poll. Collecting the sockets may install new timers by protocols
1348*6236dae4SAndroid Build Coastguard Worker * and connection filters.
1349*6236dae4SAndroid Build Coastguard Worker * Use the shorter one of the internal and the caller requested timeout. */
1350*6236dae4SAndroid Build Coastguard Worker (void)multi_timeout(multi, &expire_time, &timeout_internal);
1351*6236dae4SAndroid Build Coastguard Worker if((timeout_internal >= 0) && (timeout_internal < (long)timeout_ms))
1352*6236dae4SAndroid Build Coastguard Worker timeout_ms = (int)timeout_internal;
1353*6236dae4SAndroid Build Coastguard Worker
1354*6236dae4SAndroid Build Coastguard Worker #if defined(ENABLE_WAKEUP) && defined(USE_WINSOCK)
1355*6236dae4SAndroid Build Coastguard Worker if(cpfds.n || use_wakeup) {
1356*6236dae4SAndroid Build Coastguard Worker #else
1357*6236dae4SAndroid Build Coastguard Worker if(cpfds.n) {
1358*6236dae4SAndroid Build Coastguard Worker #endif
1359*6236dae4SAndroid Build Coastguard Worker int pollrc;
1360*6236dae4SAndroid Build Coastguard Worker #ifdef USE_WINSOCK
1361*6236dae4SAndroid Build Coastguard Worker if(cpfds.n) /* just pre-check with Winsock */
1362*6236dae4SAndroid Build Coastguard Worker pollrc = Curl_poll(cpfds.pfds, cpfds.n, 0);
1363*6236dae4SAndroid Build Coastguard Worker else
1364*6236dae4SAndroid Build Coastguard Worker pollrc = 0;
1365*6236dae4SAndroid Build Coastguard Worker #else
1366*6236dae4SAndroid Build Coastguard Worker pollrc = Curl_poll(cpfds.pfds, cpfds.n, timeout_ms); /* wait... */
1367*6236dae4SAndroid Build Coastguard Worker #endif
1368*6236dae4SAndroid Build Coastguard Worker if(pollrc < 0) {
1369*6236dae4SAndroid Build Coastguard Worker result = CURLM_UNRECOVERABLE_POLL;
1370*6236dae4SAndroid Build Coastguard Worker goto out;
1371*6236dae4SAndroid Build Coastguard Worker }
1372*6236dae4SAndroid Build Coastguard Worker
1373*6236dae4SAndroid Build Coastguard Worker if(pollrc > 0) {
1374*6236dae4SAndroid Build Coastguard Worker retcode = pollrc;
1375*6236dae4SAndroid Build Coastguard Worker #ifdef USE_WINSOCK
1376*6236dae4SAndroid Build Coastguard Worker }
1377*6236dae4SAndroid Build Coastguard Worker else { /* now wait... if not ready during the pre-check (pollrc == 0) */
1378*6236dae4SAndroid Build Coastguard Worker WSAWaitForMultipleEvents(1, &multi->wsa_event, FALSE, (DWORD)timeout_ms,
1379*6236dae4SAndroid Build Coastguard Worker FALSE);
1380*6236dae4SAndroid Build Coastguard Worker }
1381*6236dae4SAndroid Build Coastguard Worker /* With Winsock, we have to run the following section unconditionally
1382*6236dae4SAndroid Build Coastguard Worker to call WSAEventSelect(fd, event, 0) on all the sockets */
1383*6236dae4SAndroid Build Coastguard Worker {
1384*6236dae4SAndroid Build Coastguard Worker #endif
1385*6236dae4SAndroid Build Coastguard Worker /* copy revents results from the poll to the curl_multi_wait poll
1386*6236dae4SAndroid Build Coastguard Worker struct, the bit values of the actual underlying poll() implementation
1387*6236dae4SAndroid Build Coastguard Worker may not be the same as the ones in the public libcurl API! */
1388*6236dae4SAndroid Build Coastguard Worker for(i = 0; i < extra_nfds; i++) {
1389*6236dae4SAndroid Build Coastguard Worker unsigned r = (unsigned)cpfds.pfds[curl_nfds + i].revents;
1390*6236dae4SAndroid Build Coastguard Worker unsigned short mask = 0;
1391*6236dae4SAndroid Build Coastguard Worker #ifdef USE_WINSOCK
1392*6236dae4SAndroid Build Coastguard Worker curl_socket_t s = extra_fds[i].fd;
1393*6236dae4SAndroid Build Coastguard Worker wsa_events.lNetworkEvents = 0;
1394*6236dae4SAndroid Build Coastguard Worker if(WSAEnumNetworkEvents(s, NULL, &wsa_events) == 0) {
1395*6236dae4SAndroid Build Coastguard Worker if(wsa_events.lNetworkEvents & (FD_READ|FD_ACCEPT|FD_CLOSE))
1396*6236dae4SAndroid Build Coastguard Worker mask |= CURL_WAIT_POLLIN;
1397*6236dae4SAndroid Build Coastguard Worker if(wsa_events.lNetworkEvents & (FD_WRITE|FD_CONNECT|FD_CLOSE))
1398*6236dae4SAndroid Build Coastguard Worker mask |= CURL_WAIT_POLLOUT;
1399*6236dae4SAndroid Build Coastguard Worker if(wsa_events.lNetworkEvents & FD_OOB)
1400*6236dae4SAndroid Build Coastguard Worker mask |= CURL_WAIT_POLLPRI;
1401*6236dae4SAndroid Build Coastguard Worker if(ret && !pollrc && wsa_events.lNetworkEvents)
1402*6236dae4SAndroid Build Coastguard Worker retcode++;
1403*6236dae4SAndroid Build Coastguard Worker }
1404*6236dae4SAndroid Build Coastguard Worker WSAEventSelect(s, multi->wsa_event, 0);
1405*6236dae4SAndroid Build Coastguard Worker if(!pollrc) {
1406*6236dae4SAndroid Build Coastguard Worker extra_fds[i].revents = (short)mask;
1407*6236dae4SAndroid Build Coastguard Worker continue;
1408*6236dae4SAndroid Build Coastguard Worker }
1409*6236dae4SAndroid Build Coastguard Worker #endif
1410*6236dae4SAndroid Build Coastguard Worker if(r & POLLIN)
1411*6236dae4SAndroid Build Coastguard Worker mask |= CURL_WAIT_POLLIN;
1412*6236dae4SAndroid Build Coastguard Worker if(r & POLLOUT)
1413*6236dae4SAndroid Build Coastguard Worker mask |= CURL_WAIT_POLLOUT;
1414*6236dae4SAndroid Build Coastguard Worker if(r & POLLPRI)
1415*6236dae4SAndroid Build Coastguard Worker mask |= CURL_WAIT_POLLPRI;
1416*6236dae4SAndroid Build Coastguard Worker extra_fds[i].revents = (short)mask;
1417*6236dae4SAndroid Build Coastguard Worker }
1418*6236dae4SAndroid Build Coastguard Worker
1419*6236dae4SAndroid Build Coastguard Worker #ifdef USE_WINSOCK
1420*6236dae4SAndroid Build Coastguard Worker /* Count up all our own sockets that had activity,
1421*6236dae4SAndroid Build Coastguard Worker and remove them from the event. */
1422*6236dae4SAndroid Build Coastguard Worker if(curl_nfds) {
1423*6236dae4SAndroid Build Coastguard Worker for(e = Curl_llist_head(&multi->process); e && !result;
1424*6236dae4SAndroid Build Coastguard Worker e = Curl_node_next(e)) {
1425*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data = Curl_node_elem(e);
1426*6236dae4SAndroid Build Coastguard Worker
1427*6236dae4SAndroid Build Coastguard Worker for(i = 0; i < data->last_poll.num; i++) {
1428*6236dae4SAndroid Build Coastguard Worker wsa_events.lNetworkEvents = 0;
1429*6236dae4SAndroid Build Coastguard Worker if(WSAEnumNetworkEvents(data->last_poll.sockets[i], NULL,
1430*6236dae4SAndroid Build Coastguard Worker &wsa_events) == 0) {
1431*6236dae4SAndroid Build Coastguard Worker if(ret && !pollrc && wsa_events.lNetworkEvents)
1432*6236dae4SAndroid Build Coastguard Worker retcode++;
1433*6236dae4SAndroid Build Coastguard Worker }
1434*6236dae4SAndroid Build Coastguard Worker WSAEventSelect(data->last_poll.sockets[i], multi->wsa_event, 0);
1435*6236dae4SAndroid Build Coastguard Worker }
1436*6236dae4SAndroid Build Coastguard Worker }
1437*6236dae4SAndroid Build Coastguard Worker }
1438*6236dae4SAndroid Build Coastguard Worker
1439*6236dae4SAndroid Build Coastguard Worker WSAResetEvent(multi->wsa_event);
1440*6236dae4SAndroid Build Coastguard Worker #else
1441*6236dae4SAndroid Build Coastguard Worker #ifdef ENABLE_WAKEUP
1442*6236dae4SAndroid Build Coastguard Worker if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) {
1443*6236dae4SAndroid Build Coastguard Worker if(cpfds.pfds[curl_nfds + extra_nfds].revents & POLLIN) {
1444*6236dae4SAndroid Build Coastguard Worker char buf[64];
1445*6236dae4SAndroid Build Coastguard Worker ssize_t nread;
1446*6236dae4SAndroid Build Coastguard Worker while(1) {
1447*6236dae4SAndroid Build Coastguard Worker /* the reading socket is non-blocking, try to read
1448*6236dae4SAndroid Build Coastguard Worker data from it until it receives an error (except EINTR).
1449*6236dae4SAndroid Build Coastguard Worker In normal cases it will get EAGAIN or EWOULDBLOCK
1450*6236dae4SAndroid Build Coastguard Worker when there is no more data, breaking the loop. */
1451*6236dae4SAndroid Build Coastguard Worker nread = wakeup_read(multi->wakeup_pair[0], buf, sizeof(buf));
1452*6236dae4SAndroid Build Coastguard Worker if(nread <= 0) {
1453*6236dae4SAndroid Build Coastguard Worker if(nread < 0 && EINTR == SOCKERRNO)
1454*6236dae4SAndroid Build Coastguard Worker continue;
1455*6236dae4SAndroid Build Coastguard Worker break;
1456*6236dae4SAndroid Build Coastguard Worker }
1457*6236dae4SAndroid Build Coastguard Worker }
1458*6236dae4SAndroid Build Coastguard Worker /* do not count the wakeup socket into the returned value */
1459*6236dae4SAndroid Build Coastguard Worker retcode--;
1460*6236dae4SAndroid Build Coastguard Worker }
1461*6236dae4SAndroid Build Coastguard Worker }
1462*6236dae4SAndroid Build Coastguard Worker #endif
1463*6236dae4SAndroid Build Coastguard Worker #endif
1464*6236dae4SAndroid Build Coastguard Worker }
1465*6236dae4SAndroid Build Coastguard Worker }
1466*6236dae4SAndroid Build Coastguard Worker
1467*6236dae4SAndroid Build Coastguard Worker if(ret)
1468*6236dae4SAndroid Build Coastguard Worker *ret = retcode;
1469*6236dae4SAndroid Build Coastguard Worker #if defined(ENABLE_WAKEUP) && defined(USE_WINSOCK)
1470*6236dae4SAndroid Build Coastguard Worker if(extrawait && !cpfds.n && !use_wakeup) {
1471*6236dae4SAndroid Build Coastguard Worker #else
1472*6236dae4SAndroid Build Coastguard Worker if(extrawait && !cpfds.n) {
1473*6236dae4SAndroid Build Coastguard Worker #endif
1474*6236dae4SAndroid Build Coastguard Worker long sleep_ms = 0;
1475*6236dae4SAndroid Build Coastguard Worker
1476*6236dae4SAndroid Build Coastguard Worker /* Avoid busy-looping when there is nothing particular to wait for */
1477*6236dae4SAndroid Build Coastguard Worker if(!curl_multi_timeout(multi, &sleep_ms) && sleep_ms) {
1478*6236dae4SAndroid Build Coastguard Worker if(sleep_ms > timeout_ms)
1479*6236dae4SAndroid Build Coastguard Worker sleep_ms = timeout_ms;
1480*6236dae4SAndroid Build Coastguard Worker /* when there are no easy handles in the multi, this holds a -1
1481*6236dae4SAndroid Build Coastguard Worker timeout */
1482*6236dae4SAndroid Build Coastguard Worker else if(sleep_ms < 0)
1483*6236dae4SAndroid Build Coastguard Worker sleep_ms = timeout_ms;
1484*6236dae4SAndroid Build Coastguard Worker Curl_wait_ms(sleep_ms);
1485*6236dae4SAndroid Build Coastguard Worker }
1486*6236dae4SAndroid Build Coastguard Worker }
1487*6236dae4SAndroid Build Coastguard Worker
1488*6236dae4SAndroid Build Coastguard Worker out:
1489*6236dae4SAndroid Build Coastguard Worker Curl_pollfds_cleanup(&cpfds);
1490*6236dae4SAndroid Build Coastguard Worker return result;
1491*6236dae4SAndroid Build Coastguard Worker }
1492*6236dae4SAndroid Build Coastguard Worker
1493*6236dae4SAndroid Build Coastguard Worker CURLMcode curl_multi_wait(CURLM *multi,
1494*6236dae4SAndroid Build Coastguard Worker struct curl_waitfd extra_fds[],
1495*6236dae4SAndroid Build Coastguard Worker unsigned int extra_nfds,
1496*6236dae4SAndroid Build Coastguard Worker int timeout_ms,
1497*6236dae4SAndroid Build Coastguard Worker int *ret)
1498*6236dae4SAndroid Build Coastguard Worker {
1499*6236dae4SAndroid Build Coastguard Worker return multi_wait(multi, extra_fds, extra_nfds, timeout_ms, ret, FALSE,
1500*6236dae4SAndroid Build Coastguard Worker FALSE);
1501*6236dae4SAndroid Build Coastguard Worker }
1502*6236dae4SAndroid Build Coastguard Worker
1503*6236dae4SAndroid Build Coastguard Worker CURLMcode curl_multi_poll(CURLM *multi,
1504*6236dae4SAndroid Build Coastguard Worker struct curl_waitfd extra_fds[],
1505*6236dae4SAndroid Build Coastguard Worker unsigned int extra_nfds,
1506*6236dae4SAndroid Build Coastguard Worker int timeout_ms,
1507*6236dae4SAndroid Build Coastguard Worker int *ret)
1508*6236dae4SAndroid Build Coastguard Worker {
1509*6236dae4SAndroid Build Coastguard Worker return multi_wait(multi, extra_fds, extra_nfds, timeout_ms, ret, TRUE,
1510*6236dae4SAndroid Build Coastguard Worker TRUE);
1511*6236dae4SAndroid Build Coastguard Worker }
1512*6236dae4SAndroid Build Coastguard Worker
1513*6236dae4SAndroid Build Coastguard Worker CURLMcode curl_multi_wakeup(CURLM *m)
1514*6236dae4SAndroid Build Coastguard Worker {
1515*6236dae4SAndroid Build Coastguard Worker /* this function is usually called from another thread,
1516*6236dae4SAndroid Build Coastguard Worker it has to be careful only to access parts of the
1517*6236dae4SAndroid Build Coastguard Worker Curl_multi struct that are constant */
1518*6236dae4SAndroid Build Coastguard Worker struct Curl_multi *multi = m;
1519*6236dae4SAndroid Build Coastguard Worker
1520*6236dae4SAndroid Build Coastguard Worker #if defined(ENABLE_WAKEUP) && !defined(USE_WINSOCK)
1521*6236dae4SAndroid Build Coastguard Worker #ifdef USE_EVENTFD
1522*6236dae4SAndroid Build Coastguard Worker const void *buf;
1523*6236dae4SAndroid Build Coastguard Worker const uint64_t val = 1;
1524*6236dae4SAndroid Build Coastguard Worker #else
1525*6236dae4SAndroid Build Coastguard Worker char buf[1];
1526*6236dae4SAndroid Build Coastguard Worker #endif
1527*6236dae4SAndroid Build Coastguard Worker #endif
1528*6236dae4SAndroid Build Coastguard Worker
1529*6236dae4SAndroid Build Coastguard Worker /* GOOD_MULTI_HANDLE can be safely called */
1530*6236dae4SAndroid Build Coastguard Worker if(!GOOD_MULTI_HANDLE(multi))
1531*6236dae4SAndroid Build Coastguard Worker return CURLM_BAD_HANDLE;
1532*6236dae4SAndroid Build Coastguard Worker
1533*6236dae4SAndroid Build Coastguard Worker #ifdef ENABLE_WAKEUP
1534*6236dae4SAndroid Build Coastguard Worker #ifdef USE_WINSOCK
1535*6236dae4SAndroid Build Coastguard Worker if(WSASetEvent(multi->wsa_event))
1536*6236dae4SAndroid Build Coastguard Worker return CURLM_OK;
1537*6236dae4SAndroid Build Coastguard Worker #else
1538*6236dae4SAndroid Build Coastguard Worker /* the wakeup_pair variable is only written during init and cleanup,
1539*6236dae4SAndroid Build Coastguard Worker making it safe to access from another thread after the init part
1540*6236dae4SAndroid Build Coastguard Worker and before cleanup */
1541*6236dae4SAndroid Build Coastguard Worker if(multi->wakeup_pair[1] != CURL_SOCKET_BAD) {
1542*6236dae4SAndroid Build Coastguard Worker #ifdef USE_EVENTFD
1543*6236dae4SAndroid Build Coastguard Worker buf = &val;
1544*6236dae4SAndroid Build Coastguard Worker #else
1545*6236dae4SAndroid Build Coastguard Worker buf[0] = 1;
1546*6236dae4SAndroid Build Coastguard Worker #endif
1547*6236dae4SAndroid Build Coastguard Worker while(1) {
1548*6236dae4SAndroid Build Coastguard Worker /* swrite() is not thread-safe in general, because concurrent calls
1549*6236dae4SAndroid Build Coastguard Worker can have their messages interleaved, but in this case the content
1550*6236dae4SAndroid Build Coastguard Worker of the messages does not matter, which makes it ok to call.
1551*6236dae4SAndroid Build Coastguard Worker
1552*6236dae4SAndroid Build Coastguard Worker The write socket is set to non-blocking, this way this function
1553*6236dae4SAndroid Build Coastguard Worker cannot block, making it safe to call even from the same thread
1554*6236dae4SAndroid Build Coastguard Worker that will call curl_multi_wait(). If swrite() returns that it
1555*6236dae4SAndroid Build Coastguard Worker would block, it is considered successful because it means that
1556*6236dae4SAndroid Build Coastguard Worker previous calls to this function will wake up the poll(). */
1557*6236dae4SAndroid Build Coastguard Worker if(wakeup_write(multi->wakeup_pair[1], buf, sizeof(buf)) < 0) {
1558*6236dae4SAndroid Build Coastguard Worker int err = SOCKERRNO;
1559*6236dae4SAndroid Build Coastguard Worker int return_success;
1560*6236dae4SAndroid Build Coastguard Worker #ifdef USE_WINSOCK
1561*6236dae4SAndroid Build Coastguard Worker return_success = WSAEWOULDBLOCK == err;
1562*6236dae4SAndroid Build Coastguard Worker #else
1563*6236dae4SAndroid Build Coastguard Worker if(EINTR == err)
1564*6236dae4SAndroid Build Coastguard Worker continue;
1565*6236dae4SAndroid Build Coastguard Worker return_success = EWOULDBLOCK == err || EAGAIN == err;
1566*6236dae4SAndroid Build Coastguard Worker #endif
1567*6236dae4SAndroid Build Coastguard Worker if(!return_success)
1568*6236dae4SAndroid Build Coastguard Worker return CURLM_WAKEUP_FAILURE;
1569*6236dae4SAndroid Build Coastguard Worker }
1570*6236dae4SAndroid Build Coastguard Worker return CURLM_OK;
1571*6236dae4SAndroid Build Coastguard Worker }
1572*6236dae4SAndroid Build Coastguard Worker }
1573*6236dae4SAndroid Build Coastguard Worker #endif
1574*6236dae4SAndroid Build Coastguard Worker #endif
1575*6236dae4SAndroid Build Coastguard Worker return CURLM_WAKEUP_FAILURE;
1576*6236dae4SAndroid Build Coastguard Worker }
1577*6236dae4SAndroid Build Coastguard Worker
1578*6236dae4SAndroid Build Coastguard Worker /*
1579*6236dae4SAndroid Build Coastguard Worker * multi_ischanged() is called
1580*6236dae4SAndroid Build Coastguard Worker *
1581*6236dae4SAndroid Build Coastguard Worker * Returns TRUE/FALSE whether the state is changed to trigger a CONNECT_PEND
1582*6236dae4SAndroid Build Coastguard Worker * => CONNECT action.
1583*6236dae4SAndroid Build Coastguard Worker *
1584*6236dae4SAndroid Build Coastguard Worker * Set 'clear' to TRUE to have it also clear the state variable.
1585*6236dae4SAndroid Build Coastguard Worker */
1586*6236dae4SAndroid Build Coastguard Worker static bool multi_ischanged(struct Curl_multi *multi, bool clear)
1587*6236dae4SAndroid Build Coastguard Worker {
1588*6236dae4SAndroid Build Coastguard Worker bool retval = multi->recheckstate;
1589*6236dae4SAndroid Build Coastguard Worker if(clear)
1590*6236dae4SAndroid Build Coastguard Worker multi->recheckstate = FALSE;
1591*6236dae4SAndroid Build Coastguard Worker return retval;
1592*6236dae4SAndroid Build Coastguard Worker }
1593*6236dae4SAndroid Build Coastguard Worker
1594*6236dae4SAndroid Build Coastguard Worker /*
1595*6236dae4SAndroid Build Coastguard Worker * Curl_multi_connchanged() is called to tell that there is a connection in
1596*6236dae4SAndroid Build Coastguard Worker * this multi handle that has changed state (multiplexing become possible, the
1597*6236dae4SAndroid Build Coastguard Worker * number of allowed streams changed or similar), and a subsequent use of this
1598*6236dae4SAndroid Build Coastguard Worker * multi handle should move CONNECT_PEND handles back to CONNECT to have them
1599*6236dae4SAndroid Build Coastguard Worker * retry.
1600*6236dae4SAndroid Build Coastguard Worker */
1601*6236dae4SAndroid Build Coastguard Worker void Curl_multi_connchanged(struct Curl_multi *multi)
1602*6236dae4SAndroid Build Coastguard Worker {
1603*6236dae4SAndroid Build Coastguard Worker multi->recheckstate = TRUE;
1604*6236dae4SAndroid Build Coastguard Worker }
1605*6236dae4SAndroid Build Coastguard Worker
1606*6236dae4SAndroid Build Coastguard Worker CURLMcode Curl_multi_add_perform(struct Curl_multi *multi,
1607*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data,
1608*6236dae4SAndroid Build Coastguard Worker struct connectdata *conn)
1609*6236dae4SAndroid Build Coastguard Worker {
1610*6236dae4SAndroid Build Coastguard Worker CURLMcode rc;
1611*6236dae4SAndroid Build Coastguard Worker
1612*6236dae4SAndroid Build Coastguard Worker if(multi->in_callback)
1613*6236dae4SAndroid Build Coastguard Worker return CURLM_RECURSIVE_API_CALL;
1614*6236dae4SAndroid Build Coastguard Worker
1615*6236dae4SAndroid Build Coastguard Worker rc = curl_multi_add_handle(multi, data);
1616*6236dae4SAndroid Build Coastguard Worker if(!rc) {
1617*6236dae4SAndroid Build Coastguard Worker struct SingleRequest *k = &data->req;
1618*6236dae4SAndroid Build Coastguard Worker
1619*6236dae4SAndroid Build Coastguard Worker /* pass in NULL for 'conn' here since we do not want to init the
1620*6236dae4SAndroid Build Coastguard Worker connection, only this transfer */
1621*6236dae4SAndroid Build Coastguard Worker Curl_init_do(data, NULL);
1622*6236dae4SAndroid Build Coastguard Worker
1623*6236dae4SAndroid Build Coastguard Worker /* take this handle to the perform state right away */
1624*6236dae4SAndroid Build Coastguard Worker multistate(data, MSTATE_PERFORMING);
1625*6236dae4SAndroid Build Coastguard Worker Curl_attach_connection(data, conn);
1626*6236dae4SAndroid Build Coastguard Worker k->keepon |= KEEP_RECV; /* setup to receive! */
1627*6236dae4SAndroid Build Coastguard Worker }
1628*6236dae4SAndroid Build Coastguard Worker return rc;
1629*6236dae4SAndroid Build Coastguard Worker }
1630*6236dae4SAndroid Build Coastguard Worker
1631*6236dae4SAndroid Build Coastguard Worker static CURLcode multi_do(struct Curl_easy *data, bool *done)
1632*6236dae4SAndroid Build Coastguard Worker {
1633*6236dae4SAndroid Build Coastguard Worker CURLcode result = CURLE_OK;
1634*6236dae4SAndroid Build Coastguard Worker struct connectdata *conn = data->conn;
1635*6236dae4SAndroid Build Coastguard Worker
1636*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(conn);
1637*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(conn->handler);
1638*6236dae4SAndroid Build Coastguard Worker
1639*6236dae4SAndroid Build Coastguard Worker if(conn->handler->do_it)
1640*6236dae4SAndroid Build Coastguard Worker result = conn->handler->do_it(data, done);
1641*6236dae4SAndroid Build Coastguard Worker
1642*6236dae4SAndroid Build Coastguard Worker return result;
1643*6236dae4SAndroid Build Coastguard Worker }
1644*6236dae4SAndroid Build Coastguard Worker
1645*6236dae4SAndroid Build Coastguard Worker /*
1646*6236dae4SAndroid Build Coastguard Worker * multi_do_more() is called during the DO_MORE multi state. It is basically a
1647*6236dae4SAndroid Build Coastguard Worker * second stage DO state which (wrongly) was introduced to support FTP's
1648*6236dae4SAndroid Build Coastguard Worker * second connection.
1649*6236dae4SAndroid Build Coastguard Worker *
1650*6236dae4SAndroid Build Coastguard Worker * 'complete' can return 0 for incomplete, 1 for done and -1 for go back to
1651*6236dae4SAndroid Build Coastguard Worker * DOING state there is more work to do!
1652*6236dae4SAndroid Build Coastguard Worker */
1653*6236dae4SAndroid Build Coastguard Worker
1654*6236dae4SAndroid Build Coastguard Worker static CURLcode multi_do_more(struct Curl_easy *data, int *complete)
1655*6236dae4SAndroid Build Coastguard Worker {
1656*6236dae4SAndroid Build Coastguard Worker CURLcode result = CURLE_OK;
1657*6236dae4SAndroid Build Coastguard Worker struct connectdata *conn = data->conn;
1658*6236dae4SAndroid Build Coastguard Worker
1659*6236dae4SAndroid Build Coastguard Worker *complete = 0;
1660*6236dae4SAndroid Build Coastguard Worker
1661*6236dae4SAndroid Build Coastguard Worker if(conn->handler->do_more)
1662*6236dae4SAndroid Build Coastguard Worker result = conn->handler->do_more(data, complete);
1663*6236dae4SAndroid Build Coastguard Worker
1664*6236dae4SAndroid Build Coastguard Worker return result;
1665*6236dae4SAndroid Build Coastguard Worker }
1666*6236dae4SAndroid Build Coastguard Worker
1667*6236dae4SAndroid Build Coastguard Worker /*
1668*6236dae4SAndroid Build Coastguard Worker * Check whether a timeout occurred, and handle it if it did
1669*6236dae4SAndroid Build Coastguard Worker */
1670*6236dae4SAndroid Build Coastguard Worker static bool multi_handle_timeout(struct Curl_easy *data,
1671*6236dae4SAndroid Build Coastguard Worker struct curltime *now,
1672*6236dae4SAndroid Build Coastguard Worker bool *stream_error,
1673*6236dae4SAndroid Build Coastguard Worker CURLcode *result)
1674*6236dae4SAndroid Build Coastguard Worker {
1675*6236dae4SAndroid Build Coastguard Worker bool connect_timeout = data->mstate < MSTATE_DO;
1676*6236dae4SAndroid Build Coastguard Worker timediff_t timeout_ms = Curl_timeleft(data, now, connect_timeout);
1677*6236dae4SAndroid Build Coastguard Worker if(timeout_ms < 0) {
1678*6236dae4SAndroid Build Coastguard Worker /* Handle timed out */
1679*6236dae4SAndroid Build Coastguard Worker struct curltime since;
1680*6236dae4SAndroid Build Coastguard Worker if(connect_timeout)
1681*6236dae4SAndroid Build Coastguard Worker since = data->progress.t_startsingle;
1682*6236dae4SAndroid Build Coastguard Worker else
1683*6236dae4SAndroid Build Coastguard Worker since = data->progress.t_startop;
1684*6236dae4SAndroid Build Coastguard Worker if(data->mstate == MSTATE_RESOLVING)
1685*6236dae4SAndroid Build Coastguard Worker failf(data, "Resolving timed out after %" FMT_TIMEDIFF_T
1686*6236dae4SAndroid Build Coastguard Worker " milliseconds", Curl_timediff(*now, since));
1687*6236dae4SAndroid Build Coastguard Worker else if(data->mstate == MSTATE_CONNECTING)
1688*6236dae4SAndroid Build Coastguard Worker failf(data, "Connection timed out after %" FMT_TIMEDIFF_T
1689*6236dae4SAndroid Build Coastguard Worker " milliseconds", Curl_timediff(*now, since));
1690*6236dae4SAndroid Build Coastguard Worker else {
1691*6236dae4SAndroid Build Coastguard Worker struct SingleRequest *k = &data->req;
1692*6236dae4SAndroid Build Coastguard Worker if(k->size != -1) {
1693*6236dae4SAndroid Build Coastguard Worker failf(data, "Operation timed out after %" FMT_TIMEDIFF_T
1694*6236dae4SAndroid Build Coastguard Worker " milliseconds with %" FMT_OFF_T " out of %"
1695*6236dae4SAndroid Build Coastguard Worker FMT_OFF_T " bytes received",
1696*6236dae4SAndroid Build Coastguard Worker Curl_timediff(*now, since), k->bytecount, k->size);
1697*6236dae4SAndroid Build Coastguard Worker }
1698*6236dae4SAndroid Build Coastguard Worker else {
1699*6236dae4SAndroid Build Coastguard Worker failf(data, "Operation timed out after %" FMT_TIMEDIFF_T
1700*6236dae4SAndroid Build Coastguard Worker " milliseconds with %" FMT_OFF_T " bytes received",
1701*6236dae4SAndroid Build Coastguard Worker Curl_timediff(*now, since), k->bytecount);
1702*6236dae4SAndroid Build Coastguard Worker }
1703*6236dae4SAndroid Build Coastguard Worker }
1704*6236dae4SAndroid Build Coastguard Worker *result = CURLE_OPERATION_TIMEDOUT;
1705*6236dae4SAndroid Build Coastguard Worker if(data->conn) {
1706*6236dae4SAndroid Build Coastguard Worker /* Force connection closed if the connection has indeed been used */
1707*6236dae4SAndroid Build Coastguard Worker if(data->mstate > MSTATE_DO) {
1708*6236dae4SAndroid Build Coastguard Worker streamclose(data->conn, "Disconnect due to timeout");
1709*6236dae4SAndroid Build Coastguard Worker *stream_error = TRUE;
1710*6236dae4SAndroid Build Coastguard Worker }
1711*6236dae4SAndroid Build Coastguard Worker (void)multi_done(data, *result, TRUE);
1712*6236dae4SAndroid Build Coastguard Worker }
1713*6236dae4SAndroid Build Coastguard Worker return TRUE;
1714*6236dae4SAndroid Build Coastguard Worker }
1715*6236dae4SAndroid Build Coastguard Worker
1716*6236dae4SAndroid Build Coastguard Worker return FALSE;
1717*6236dae4SAndroid Build Coastguard Worker }
1718*6236dae4SAndroid Build Coastguard Worker
1719*6236dae4SAndroid Build Coastguard Worker /*
1720*6236dae4SAndroid Build Coastguard Worker * We are doing protocol-specific connecting and this is being called over and
1721*6236dae4SAndroid Build Coastguard Worker * over from the multi interface until the connection phase is done on
1722*6236dae4SAndroid Build Coastguard Worker * protocol layer.
1723*6236dae4SAndroid Build Coastguard Worker */
1724*6236dae4SAndroid Build Coastguard Worker
1725*6236dae4SAndroid Build Coastguard Worker static CURLcode protocol_connecting(struct Curl_easy *data, bool *done)
1726*6236dae4SAndroid Build Coastguard Worker {
1727*6236dae4SAndroid Build Coastguard Worker CURLcode result = CURLE_OK;
1728*6236dae4SAndroid Build Coastguard Worker struct connectdata *conn = data->conn;
1729*6236dae4SAndroid Build Coastguard Worker
1730*6236dae4SAndroid Build Coastguard Worker if(conn && conn->handler->connecting) {
1731*6236dae4SAndroid Build Coastguard Worker *done = FALSE;
1732*6236dae4SAndroid Build Coastguard Worker result = conn->handler->connecting(data, done);
1733*6236dae4SAndroid Build Coastguard Worker }
1734*6236dae4SAndroid Build Coastguard Worker else
1735*6236dae4SAndroid Build Coastguard Worker *done = TRUE;
1736*6236dae4SAndroid Build Coastguard Worker
1737*6236dae4SAndroid Build Coastguard Worker return result;
1738*6236dae4SAndroid Build Coastguard Worker }
1739*6236dae4SAndroid Build Coastguard Worker
1740*6236dae4SAndroid Build Coastguard Worker /*
1741*6236dae4SAndroid Build Coastguard Worker * We are DOING this is being called over and over from the multi interface
1742*6236dae4SAndroid Build Coastguard Worker * until the DOING phase is done on protocol layer.
1743*6236dae4SAndroid Build Coastguard Worker */
1744*6236dae4SAndroid Build Coastguard Worker
1745*6236dae4SAndroid Build Coastguard Worker static CURLcode protocol_doing(struct Curl_easy *data, bool *done)
1746*6236dae4SAndroid Build Coastguard Worker {
1747*6236dae4SAndroid Build Coastguard Worker CURLcode result = CURLE_OK;
1748*6236dae4SAndroid Build Coastguard Worker struct connectdata *conn = data->conn;
1749*6236dae4SAndroid Build Coastguard Worker
1750*6236dae4SAndroid Build Coastguard Worker if(conn && conn->handler->doing) {
1751*6236dae4SAndroid Build Coastguard Worker *done = FALSE;
1752*6236dae4SAndroid Build Coastguard Worker result = conn->handler->doing(data, done);
1753*6236dae4SAndroid Build Coastguard Worker }
1754*6236dae4SAndroid Build Coastguard Worker else
1755*6236dae4SAndroid Build Coastguard Worker *done = TRUE;
1756*6236dae4SAndroid Build Coastguard Worker
1757*6236dae4SAndroid Build Coastguard Worker return result;
1758*6236dae4SAndroid Build Coastguard Worker }
1759*6236dae4SAndroid Build Coastguard Worker
1760*6236dae4SAndroid Build Coastguard Worker /*
1761*6236dae4SAndroid Build Coastguard Worker * We have discovered that the TCP connection has been successful, we can now
1762*6236dae4SAndroid Build Coastguard Worker * proceed with some action.
1763*6236dae4SAndroid Build Coastguard Worker *
1764*6236dae4SAndroid Build Coastguard Worker */
1765*6236dae4SAndroid Build Coastguard Worker static CURLcode protocol_connect(struct Curl_easy *data,
1766*6236dae4SAndroid Build Coastguard Worker bool *protocol_done)
1767*6236dae4SAndroid Build Coastguard Worker {
1768*6236dae4SAndroid Build Coastguard Worker CURLcode result = CURLE_OK;
1769*6236dae4SAndroid Build Coastguard Worker struct connectdata *conn = data->conn;
1770*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(conn);
1771*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(protocol_done);
1772*6236dae4SAndroid Build Coastguard Worker
1773*6236dae4SAndroid Build Coastguard Worker *protocol_done = FALSE;
1774*6236dae4SAndroid Build Coastguard Worker
1775*6236dae4SAndroid Build Coastguard Worker if(Curl_conn_is_connected(conn, FIRSTSOCKET)
1776*6236dae4SAndroid Build Coastguard Worker && conn->bits.protoconnstart) {
1777*6236dae4SAndroid Build Coastguard Worker /* We already are connected, get back. This may happen when the connect
1778*6236dae4SAndroid Build Coastguard Worker worked fine in the first call, like when we connect to a local server
1779*6236dae4SAndroid Build Coastguard Worker or proxy. Note that we do not know if the protocol is actually done.
1780*6236dae4SAndroid Build Coastguard Worker
1781*6236dae4SAndroid Build Coastguard Worker Unless this protocol does not have any protocol-connect callback, as
1782*6236dae4SAndroid Build Coastguard Worker then we know we are done. */
1783*6236dae4SAndroid Build Coastguard Worker if(!conn->handler->connecting)
1784*6236dae4SAndroid Build Coastguard Worker *protocol_done = TRUE;
1785*6236dae4SAndroid Build Coastguard Worker
1786*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
1787*6236dae4SAndroid Build Coastguard Worker }
1788*6236dae4SAndroid Build Coastguard Worker
1789*6236dae4SAndroid Build Coastguard Worker if(!conn->bits.protoconnstart) {
1790*6236dae4SAndroid Build Coastguard Worker if(conn->handler->connect_it) {
1791*6236dae4SAndroid Build Coastguard Worker /* is there a protocol-specific connect() procedure? */
1792*6236dae4SAndroid Build Coastguard Worker
1793*6236dae4SAndroid Build Coastguard Worker /* Call the protocol-specific connect function */
1794*6236dae4SAndroid Build Coastguard Worker result = conn->handler->connect_it(data, protocol_done);
1795*6236dae4SAndroid Build Coastguard Worker }
1796*6236dae4SAndroid Build Coastguard Worker else
1797*6236dae4SAndroid Build Coastguard Worker *protocol_done = TRUE;
1798*6236dae4SAndroid Build Coastguard Worker
1799*6236dae4SAndroid Build Coastguard Worker /* it has started, possibly even completed but that knowledge is not stored
1800*6236dae4SAndroid Build Coastguard Worker in this bit! */
1801*6236dae4SAndroid Build Coastguard Worker if(!result)
1802*6236dae4SAndroid Build Coastguard Worker conn->bits.protoconnstart = TRUE;
1803*6236dae4SAndroid Build Coastguard Worker }
1804*6236dae4SAndroid Build Coastguard Worker
1805*6236dae4SAndroid Build Coastguard Worker return result; /* pass back status */
1806*6236dae4SAndroid Build Coastguard Worker }
1807*6236dae4SAndroid Build Coastguard Worker
1808*6236dae4SAndroid Build Coastguard Worker static void set_in_callback(struct Curl_multi *multi, bool value)
1809*6236dae4SAndroid Build Coastguard Worker {
1810*6236dae4SAndroid Build Coastguard Worker multi->in_callback = value;
1811*6236dae4SAndroid Build Coastguard Worker }
1812*6236dae4SAndroid Build Coastguard Worker
1813*6236dae4SAndroid Build Coastguard Worker /*
1814*6236dae4SAndroid Build Coastguard Worker * posttransfer() is called immediately after a transfer ends
1815*6236dae4SAndroid Build Coastguard Worker */
1816*6236dae4SAndroid Build Coastguard Worker static void multi_posttransfer(struct Curl_easy *data)
1817*6236dae4SAndroid Build Coastguard Worker {
1818*6236dae4SAndroid Build Coastguard Worker #if defined(HAVE_SIGNAL) && defined(SIGPIPE) && !defined(HAVE_MSG_NOSIGNAL)
1819*6236dae4SAndroid Build Coastguard Worker /* restore the signal handler for SIGPIPE before we get back */
1820*6236dae4SAndroid Build Coastguard Worker if(!data->set.no_signal)
1821*6236dae4SAndroid Build Coastguard Worker signal(SIGPIPE, data->state.prev_signal);
1822*6236dae4SAndroid Build Coastguard Worker #else
1823*6236dae4SAndroid Build Coastguard Worker (void)data; /* unused parameter */
1824*6236dae4SAndroid Build Coastguard Worker #endif
1825*6236dae4SAndroid Build Coastguard Worker }
1826*6236dae4SAndroid Build Coastguard Worker
1827*6236dae4SAndroid Build Coastguard Worker /*
1828*6236dae4SAndroid Build Coastguard Worker * multi_follow() handles the URL redirect magic. Pass in the 'newurl' string
1829*6236dae4SAndroid Build Coastguard Worker * as given by the remote server and set up the new URL to request.
1830*6236dae4SAndroid Build Coastguard Worker *
1831*6236dae4SAndroid Build Coastguard Worker * This function DOES NOT FREE the given url.
1832*6236dae4SAndroid Build Coastguard Worker */
1833*6236dae4SAndroid Build Coastguard Worker static CURLcode multi_follow(struct Curl_easy *data,
1834*6236dae4SAndroid Build Coastguard Worker char *newurl, /* the Location: string */
1835*6236dae4SAndroid Build Coastguard Worker followtype type) /* see transfer.h */
1836*6236dae4SAndroid Build Coastguard Worker {
1837*6236dae4SAndroid Build Coastguard Worker #ifdef CURL_DISABLE_HTTP
1838*6236dae4SAndroid Build Coastguard Worker (void)data;
1839*6236dae4SAndroid Build Coastguard Worker (void)newurl;
1840*6236dae4SAndroid Build Coastguard Worker (void)type;
1841*6236dae4SAndroid Build Coastguard Worker /* Location: following will not happen when HTTP is disabled */
1842*6236dae4SAndroid Build Coastguard Worker return CURLE_TOO_MANY_REDIRECTS;
1843*6236dae4SAndroid Build Coastguard Worker #else
1844*6236dae4SAndroid Build Coastguard Worker
1845*6236dae4SAndroid Build Coastguard Worker /* Location: redirect */
1846*6236dae4SAndroid Build Coastguard Worker bool disallowport = FALSE;
1847*6236dae4SAndroid Build Coastguard Worker bool reachedmax = FALSE;
1848*6236dae4SAndroid Build Coastguard Worker CURLUcode uc;
1849*6236dae4SAndroid Build Coastguard Worker
1850*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(type != FOLLOW_NONE);
1851*6236dae4SAndroid Build Coastguard Worker
1852*6236dae4SAndroid Build Coastguard Worker if(type != FOLLOW_FAKE)
1853*6236dae4SAndroid Build Coastguard Worker data->state.requests++; /* count all real follows */
1854*6236dae4SAndroid Build Coastguard Worker if(type == FOLLOW_REDIR) {
1855*6236dae4SAndroid Build Coastguard Worker if((data->set.maxredirs != -1) &&
1856*6236dae4SAndroid Build Coastguard Worker (data->state.followlocation >= data->set.maxredirs)) {
1857*6236dae4SAndroid Build Coastguard Worker reachedmax = TRUE;
1858*6236dae4SAndroid Build Coastguard Worker type = FOLLOW_FAKE; /* switch to fake to store the would-be-redirected
1859*6236dae4SAndroid Build Coastguard Worker to URL */
1860*6236dae4SAndroid Build Coastguard Worker }
1861*6236dae4SAndroid Build Coastguard Worker else {
1862*6236dae4SAndroid Build Coastguard Worker data->state.followlocation++; /* count redirect-followings, including
1863*6236dae4SAndroid Build Coastguard Worker auth reloads */
1864*6236dae4SAndroid Build Coastguard Worker
1865*6236dae4SAndroid Build Coastguard Worker if(data->set.http_auto_referer) {
1866*6236dae4SAndroid Build Coastguard Worker CURLU *u;
1867*6236dae4SAndroid Build Coastguard Worker char *referer = NULL;
1868*6236dae4SAndroid Build Coastguard Worker
1869*6236dae4SAndroid Build Coastguard Worker /* We are asked to automatically set the previous URL as the referer
1870*6236dae4SAndroid Build Coastguard Worker when we get the next URL. We pick the ->url field, which may or may
1871*6236dae4SAndroid Build Coastguard Worker not be 100% correct */
1872*6236dae4SAndroid Build Coastguard Worker
1873*6236dae4SAndroid Build Coastguard Worker if(data->state.referer_alloc) {
1874*6236dae4SAndroid Build Coastguard Worker Curl_safefree(data->state.referer);
1875*6236dae4SAndroid Build Coastguard Worker data->state.referer_alloc = FALSE;
1876*6236dae4SAndroid Build Coastguard Worker }
1877*6236dae4SAndroid Build Coastguard Worker
1878*6236dae4SAndroid Build Coastguard Worker /* Make a copy of the URL without credentials and fragment */
1879*6236dae4SAndroid Build Coastguard Worker u = curl_url();
1880*6236dae4SAndroid Build Coastguard Worker if(!u)
1881*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
1882*6236dae4SAndroid Build Coastguard Worker
1883*6236dae4SAndroid Build Coastguard Worker uc = curl_url_set(u, CURLUPART_URL, data->state.url, 0);
1884*6236dae4SAndroid Build Coastguard Worker if(!uc)
1885*6236dae4SAndroid Build Coastguard Worker uc = curl_url_set(u, CURLUPART_FRAGMENT, NULL, 0);
1886*6236dae4SAndroid Build Coastguard Worker if(!uc)
1887*6236dae4SAndroid Build Coastguard Worker uc = curl_url_set(u, CURLUPART_USER, NULL, 0);
1888*6236dae4SAndroid Build Coastguard Worker if(!uc)
1889*6236dae4SAndroid Build Coastguard Worker uc = curl_url_set(u, CURLUPART_PASSWORD, NULL, 0);
1890*6236dae4SAndroid Build Coastguard Worker if(!uc)
1891*6236dae4SAndroid Build Coastguard Worker uc = curl_url_get(u, CURLUPART_URL, &referer, 0);
1892*6236dae4SAndroid Build Coastguard Worker
1893*6236dae4SAndroid Build Coastguard Worker curl_url_cleanup(u);
1894*6236dae4SAndroid Build Coastguard Worker
1895*6236dae4SAndroid Build Coastguard Worker if(uc || !referer)
1896*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
1897*6236dae4SAndroid Build Coastguard Worker
1898*6236dae4SAndroid Build Coastguard Worker data->state.referer = referer;
1899*6236dae4SAndroid Build Coastguard Worker data->state.referer_alloc = TRUE; /* yes, free this later */
1900*6236dae4SAndroid Build Coastguard Worker }
1901*6236dae4SAndroid Build Coastguard Worker }
1902*6236dae4SAndroid Build Coastguard Worker }
1903*6236dae4SAndroid Build Coastguard Worker
1904*6236dae4SAndroid Build Coastguard Worker if((type != FOLLOW_RETRY) &&
1905*6236dae4SAndroid Build Coastguard Worker (data->req.httpcode != 401) && (data->req.httpcode != 407) &&
1906*6236dae4SAndroid Build Coastguard Worker Curl_is_absolute_url(newurl, NULL, 0, FALSE)) {
1907*6236dae4SAndroid Build Coastguard Worker /* If this is not redirect due to a 401 or 407 response and an absolute
1908*6236dae4SAndroid Build Coastguard Worker URL: do not allow a custom port number */
1909*6236dae4SAndroid Build Coastguard Worker disallowport = TRUE;
1910*6236dae4SAndroid Build Coastguard Worker }
1911*6236dae4SAndroid Build Coastguard Worker
1912*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(data->state.uh);
1913*6236dae4SAndroid Build Coastguard Worker uc = curl_url_set(data->state.uh, CURLUPART_URL, newurl, (unsigned int)
1914*6236dae4SAndroid Build Coastguard Worker ((type == FOLLOW_FAKE) ? CURLU_NON_SUPPORT_SCHEME :
1915*6236dae4SAndroid Build Coastguard Worker ((type == FOLLOW_REDIR) ? CURLU_URLENCODE : 0) |
1916*6236dae4SAndroid Build Coastguard Worker CURLU_ALLOW_SPACE |
1917*6236dae4SAndroid Build Coastguard Worker (data->set.path_as_is ? CURLU_PATH_AS_IS : 0)));
1918*6236dae4SAndroid Build Coastguard Worker if(uc) {
1919*6236dae4SAndroid Build Coastguard Worker if(type != FOLLOW_FAKE) {
1920*6236dae4SAndroid Build Coastguard Worker failf(data, "The redirect target URL could not be parsed: %s",
1921*6236dae4SAndroid Build Coastguard Worker curl_url_strerror(uc));
1922*6236dae4SAndroid Build Coastguard Worker return Curl_uc_to_curlcode(uc);
1923*6236dae4SAndroid Build Coastguard Worker }
1924*6236dae4SAndroid Build Coastguard Worker
1925*6236dae4SAndroid Build Coastguard Worker /* the URL could not be parsed for some reason, but since this is FAKE
1926*6236dae4SAndroid Build Coastguard Worker mode, just duplicate the field as-is */
1927*6236dae4SAndroid Build Coastguard Worker newurl = strdup(newurl);
1928*6236dae4SAndroid Build Coastguard Worker if(!newurl)
1929*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
1930*6236dae4SAndroid Build Coastguard Worker }
1931*6236dae4SAndroid Build Coastguard Worker else {
1932*6236dae4SAndroid Build Coastguard Worker uc = curl_url_get(data->state.uh, CURLUPART_URL, &newurl, 0);
1933*6236dae4SAndroid Build Coastguard Worker if(uc)
1934*6236dae4SAndroid Build Coastguard Worker return Curl_uc_to_curlcode(uc);
1935*6236dae4SAndroid Build Coastguard Worker
1936*6236dae4SAndroid Build Coastguard Worker /* Clear auth if this redirects to a different port number or protocol,
1937*6236dae4SAndroid Build Coastguard Worker unless permitted */
1938*6236dae4SAndroid Build Coastguard Worker if(!data->set.allow_auth_to_other_hosts && (type != FOLLOW_FAKE)) {
1939*6236dae4SAndroid Build Coastguard Worker char *portnum;
1940*6236dae4SAndroid Build Coastguard Worker int port;
1941*6236dae4SAndroid Build Coastguard Worker bool clear = FALSE;
1942*6236dae4SAndroid Build Coastguard Worker
1943*6236dae4SAndroid Build Coastguard Worker if(data->set.use_port && data->state.allow_port)
1944*6236dae4SAndroid Build Coastguard Worker /* a custom port is used */
1945*6236dae4SAndroid Build Coastguard Worker port = (int)data->set.use_port;
1946*6236dae4SAndroid Build Coastguard Worker else {
1947*6236dae4SAndroid Build Coastguard Worker uc = curl_url_get(data->state.uh, CURLUPART_PORT, &portnum,
1948*6236dae4SAndroid Build Coastguard Worker CURLU_DEFAULT_PORT);
1949*6236dae4SAndroid Build Coastguard Worker if(uc) {
1950*6236dae4SAndroid Build Coastguard Worker free(newurl);
1951*6236dae4SAndroid Build Coastguard Worker return Curl_uc_to_curlcode(uc);
1952*6236dae4SAndroid Build Coastguard Worker }
1953*6236dae4SAndroid Build Coastguard Worker port = atoi(portnum);
1954*6236dae4SAndroid Build Coastguard Worker free(portnum);
1955*6236dae4SAndroid Build Coastguard Worker }
1956*6236dae4SAndroid Build Coastguard Worker if(port != data->info.conn_remote_port) {
1957*6236dae4SAndroid Build Coastguard Worker infof(data, "Clear auth, redirects to port from %u to %u",
1958*6236dae4SAndroid Build Coastguard Worker data->info.conn_remote_port, port);
1959*6236dae4SAndroid Build Coastguard Worker clear = TRUE;
1960*6236dae4SAndroid Build Coastguard Worker }
1961*6236dae4SAndroid Build Coastguard Worker else {
1962*6236dae4SAndroid Build Coastguard Worker char *scheme;
1963*6236dae4SAndroid Build Coastguard Worker const struct Curl_handler *p;
1964*6236dae4SAndroid Build Coastguard Worker uc = curl_url_get(data->state.uh, CURLUPART_SCHEME, &scheme, 0);
1965*6236dae4SAndroid Build Coastguard Worker if(uc) {
1966*6236dae4SAndroid Build Coastguard Worker free(newurl);
1967*6236dae4SAndroid Build Coastguard Worker return Curl_uc_to_curlcode(uc);
1968*6236dae4SAndroid Build Coastguard Worker }
1969*6236dae4SAndroid Build Coastguard Worker
1970*6236dae4SAndroid Build Coastguard Worker p = Curl_get_scheme_handler(scheme);
1971*6236dae4SAndroid Build Coastguard Worker if(p && (p->protocol != data->info.conn_protocol)) {
1972*6236dae4SAndroid Build Coastguard Worker infof(data, "Clear auth, redirects scheme from %s to %s",
1973*6236dae4SAndroid Build Coastguard Worker data->info.conn_scheme, scheme);
1974*6236dae4SAndroid Build Coastguard Worker clear = TRUE;
1975*6236dae4SAndroid Build Coastguard Worker }
1976*6236dae4SAndroid Build Coastguard Worker free(scheme);
1977*6236dae4SAndroid Build Coastguard Worker }
1978*6236dae4SAndroid Build Coastguard Worker if(clear) {
1979*6236dae4SAndroid Build Coastguard Worker Curl_safefree(data->state.aptr.user);
1980*6236dae4SAndroid Build Coastguard Worker Curl_safefree(data->state.aptr.passwd);
1981*6236dae4SAndroid Build Coastguard Worker }
1982*6236dae4SAndroid Build Coastguard Worker }
1983*6236dae4SAndroid Build Coastguard Worker }
1984*6236dae4SAndroid Build Coastguard Worker
1985*6236dae4SAndroid Build Coastguard Worker if(type == FOLLOW_FAKE) {
1986*6236dae4SAndroid Build Coastguard Worker /* we are only figuring out the new URL if we would have followed locations
1987*6236dae4SAndroid Build Coastguard Worker but now we are done so we can get out! */
1988*6236dae4SAndroid Build Coastguard Worker data->info.wouldredirect = newurl;
1989*6236dae4SAndroid Build Coastguard Worker
1990*6236dae4SAndroid Build Coastguard Worker if(reachedmax) {
1991*6236dae4SAndroid Build Coastguard Worker failf(data, "Maximum (%ld) redirects followed", data->set.maxredirs);
1992*6236dae4SAndroid Build Coastguard Worker return CURLE_TOO_MANY_REDIRECTS;
1993*6236dae4SAndroid Build Coastguard Worker }
1994*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
1995*6236dae4SAndroid Build Coastguard Worker }
1996*6236dae4SAndroid Build Coastguard Worker
1997*6236dae4SAndroid Build Coastguard Worker if(disallowport)
1998*6236dae4SAndroid Build Coastguard Worker data->state.allow_port = FALSE;
1999*6236dae4SAndroid Build Coastguard Worker
2000*6236dae4SAndroid Build Coastguard Worker if(data->state.url_alloc)
2001*6236dae4SAndroid Build Coastguard Worker Curl_safefree(data->state.url);
2002*6236dae4SAndroid Build Coastguard Worker
2003*6236dae4SAndroid Build Coastguard Worker data->state.url = newurl;
2004*6236dae4SAndroid Build Coastguard Worker data->state.url_alloc = TRUE;
2005*6236dae4SAndroid Build Coastguard Worker Curl_req_soft_reset(&data->req, data);
2006*6236dae4SAndroid Build Coastguard Worker infof(data, "Issue another request to this URL: '%s'", data->state.url);
2007*6236dae4SAndroid Build Coastguard Worker
2008*6236dae4SAndroid Build Coastguard Worker /*
2009*6236dae4SAndroid Build Coastguard Worker * We get here when the HTTP code is 300-399 (and 401). We need to perform
2010*6236dae4SAndroid Build Coastguard Worker * differently based on exactly what return code there was.
2011*6236dae4SAndroid Build Coastguard Worker *
2012*6236dae4SAndroid Build Coastguard Worker * News from 7.10.6: we can also get here on a 401 or 407, in case we act on
2013*6236dae4SAndroid Build Coastguard Worker * an HTTP (proxy-) authentication scheme other than Basic.
2014*6236dae4SAndroid Build Coastguard Worker */
2015*6236dae4SAndroid Build Coastguard Worker switch(data->info.httpcode) {
2016*6236dae4SAndroid Build Coastguard Worker /* 401 - Act on a WWW-Authenticate, we keep on moving and do the
2017*6236dae4SAndroid Build Coastguard Worker Authorization: XXXX header in the HTTP request code snippet */
2018*6236dae4SAndroid Build Coastguard Worker /* 407 - Act on a Proxy-Authenticate, we keep on moving and do the
2019*6236dae4SAndroid Build Coastguard Worker Proxy-Authorization: XXXX header in the HTTP request code snippet */
2020*6236dae4SAndroid Build Coastguard Worker /* 300 - Multiple Choices */
2021*6236dae4SAndroid Build Coastguard Worker /* 306 - Not used */
2022*6236dae4SAndroid Build Coastguard Worker /* 307 - Temporary Redirect */
2023*6236dae4SAndroid Build Coastguard Worker default: /* for all above (and the unknown ones) */
2024*6236dae4SAndroid Build Coastguard Worker /* Some codes are explicitly mentioned since I have checked RFC2616 and
2025*6236dae4SAndroid Build Coastguard Worker * they seem to be OK to POST to.
2026*6236dae4SAndroid Build Coastguard Worker */
2027*6236dae4SAndroid Build Coastguard Worker break;
2028*6236dae4SAndroid Build Coastguard Worker case 301: /* Moved Permanently */
2029*6236dae4SAndroid Build Coastguard Worker /* (quote from RFC7231, section 6.4.2)
2030*6236dae4SAndroid Build Coastguard Worker *
2031*6236dae4SAndroid Build Coastguard Worker * Note: For historical reasons, a user agent MAY change the request
2032*6236dae4SAndroid Build Coastguard Worker * method from POST to GET for the subsequent request. If this
2033*6236dae4SAndroid Build Coastguard Worker * behavior is undesired, the 307 (Temporary Redirect) status code
2034*6236dae4SAndroid Build Coastguard Worker * can be used instead.
2035*6236dae4SAndroid Build Coastguard Worker *
2036*6236dae4SAndroid Build Coastguard Worker * ----
2037*6236dae4SAndroid Build Coastguard Worker *
2038*6236dae4SAndroid Build Coastguard Worker * Many webservers expect this, so these servers often answers to a POST
2039*6236dae4SAndroid Build Coastguard Worker * request with an error page. To be sure that libcurl gets the page that
2040*6236dae4SAndroid Build Coastguard Worker * most user agents would get, libcurl has to force GET.
2041*6236dae4SAndroid Build Coastguard Worker *
2042*6236dae4SAndroid Build Coastguard Worker * This behavior is forbidden by RFC1945 and the obsolete RFC2616, and
2043*6236dae4SAndroid Build Coastguard Worker * can be overridden with CURLOPT_POSTREDIR.
2044*6236dae4SAndroid Build Coastguard Worker */
2045*6236dae4SAndroid Build Coastguard Worker if((data->state.httpreq == HTTPREQ_POST
2046*6236dae4SAndroid Build Coastguard Worker || data->state.httpreq == HTTPREQ_POST_FORM
2047*6236dae4SAndroid Build Coastguard Worker || data->state.httpreq == HTTPREQ_POST_MIME)
2048*6236dae4SAndroid Build Coastguard Worker && !(data->set.keep_post & CURL_REDIR_POST_301)) {
2049*6236dae4SAndroid Build Coastguard Worker infof(data, "Switch from POST to GET");
2050*6236dae4SAndroid Build Coastguard Worker data->state.httpreq = HTTPREQ_GET;
2051*6236dae4SAndroid Build Coastguard Worker Curl_creader_set_rewind(data, FALSE);
2052*6236dae4SAndroid Build Coastguard Worker }
2053*6236dae4SAndroid Build Coastguard Worker break;
2054*6236dae4SAndroid Build Coastguard Worker case 302: /* Found */
2055*6236dae4SAndroid Build Coastguard Worker /* (quote from RFC7231, section 6.4.3)
2056*6236dae4SAndroid Build Coastguard Worker *
2057*6236dae4SAndroid Build Coastguard Worker * Note: For historical reasons, a user agent MAY change the request
2058*6236dae4SAndroid Build Coastguard Worker * method from POST to GET for the subsequent request. If this
2059*6236dae4SAndroid Build Coastguard Worker * behavior is undesired, the 307 (Temporary Redirect) status code
2060*6236dae4SAndroid Build Coastguard Worker * can be used instead.
2061*6236dae4SAndroid Build Coastguard Worker *
2062*6236dae4SAndroid Build Coastguard Worker * ----
2063*6236dae4SAndroid Build Coastguard Worker *
2064*6236dae4SAndroid Build Coastguard Worker * Many webservers expect this, so these servers often answers to a POST
2065*6236dae4SAndroid Build Coastguard Worker * request with an error page. To be sure that libcurl gets the page that
2066*6236dae4SAndroid Build Coastguard Worker * most user agents would get, libcurl has to force GET.
2067*6236dae4SAndroid Build Coastguard Worker *
2068*6236dae4SAndroid Build Coastguard Worker * This behavior is forbidden by RFC1945 and the obsolete RFC2616, and
2069*6236dae4SAndroid Build Coastguard Worker * can be overridden with CURLOPT_POSTREDIR.
2070*6236dae4SAndroid Build Coastguard Worker */
2071*6236dae4SAndroid Build Coastguard Worker if((data->state.httpreq == HTTPREQ_POST
2072*6236dae4SAndroid Build Coastguard Worker || data->state.httpreq == HTTPREQ_POST_FORM
2073*6236dae4SAndroid Build Coastguard Worker || data->state.httpreq == HTTPREQ_POST_MIME)
2074*6236dae4SAndroid Build Coastguard Worker && !(data->set.keep_post & CURL_REDIR_POST_302)) {
2075*6236dae4SAndroid Build Coastguard Worker infof(data, "Switch from POST to GET");
2076*6236dae4SAndroid Build Coastguard Worker data->state.httpreq = HTTPREQ_GET;
2077*6236dae4SAndroid Build Coastguard Worker Curl_creader_set_rewind(data, FALSE);
2078*6236dae4SAndroid Build Coastguard Worker }
2079*6236dae4SAndroid Build Coastguard Worker break;
2080*6236dae4SAndroid Build Coastguard Worker
2081*6236dae4SAndroid Build Coastguard Worker case 303: /* See Other */
2082*6236dae4SAndroid Build Coastguard Worker /* 'See Other' location is not the resource but a substitute for the
2083*6236dae4SAndroid Build Coastguard Worker * resource. In this case we switch the method to GET/HEAD, unless the
2084*6236dae4SAndroid Build Coastguard Worker * method is POST and the user specified to keep it as POST.
2085*6236dae4SAndroid Build Coastguard Worker * https://github.com/curl/curl/issues/5237#issuecomment-614641049
2086*6236dae4SAndroid Build Coastguard Worker */
2087*6236dae4SAndroid Build Coastguard Worker if(data->state.httpreq != HTTPREQ_GET &&
2088*6236dae4SAndroid Build Coastguard Worker ((data->state.httpreq != HTTPREQ_POST &&
2089*6236dae4SAndroid Build Coastguard Worker data->state.httpreq != HTTPREQ_POST_FORM &&
2090*6236dae4SAndroid Build Coastguard Worker data->state.httpreq != HTTPREQ_POST_MIME) ||
2091*6236dae4SAndroid Build Coastguard Worker !(data->set.keep_post & CURL_REDIR_POST_303))) {
2092*6236dae4SAndroid Build Coastguard Worker data->state.httpreq = HTTPREQ_GET;
2093*6236dae4SAndroid Build Coastguard Worker infof(data, "Switch to %s",
2094*6236dae4SAndroid Build Coastguard Worker data->req.no_body ? "HEAD" : "GET");
2095*6236dae4SAndroid Build Coastguard Worker }
2096*6236dae4SAndroid Build Coastguard Worker break;
2097*6236dae4SAndroid Build Coastguard Worker case 304: /* Not Modified */
2098*6236dae4SAndroid Build Coastguard Worker /* 304 means we did a conditional request and it was "Not modified".
2099*6236dae4SAndroid Build Coastguard Worker * We should not get any Location: header in this response!
2100*6236dae4SAndroid Build Coastguard Worker */
2101*6236dae4SAndroid Build Coastguard Worker break;
2102*6236dae4SAndroid Build Coastguard Worker case 305: /* Use Proxy */
2103*6236dae4SAndroid Build Coastguard Worker /* (quote from RFC2616, section 10.3.6):
2104*6236dae4SAndroid Build Coastguard Worker * "The requested resource MUST be accessed through the proxy given
2105*6236dae4SAndroid Build Coastguard Worker * by the Location field. The Location field gives the URI of the
2106*6236dae4SAndroid Build Coastguard Worker * proxy. The recipient is expected to repeat this single request
2107*6236dae4SAndroid Build Coastguard Worker * via the proxy. 305 responses MUST only be generated by origin
2108*6236dae4SAndroid Build Coastguard Worker * servers."
2109*6236dae4SAndroid Build Coastguard Worker */
2110*6236dae4SAndroid Build Coastguard Worker break;
2111*6236dae4SAndroid Build Coastguard Worker }
2112*6236dae4SAndroid Build Coastguard Worker Curl_pgrsTime(data, TIMER_REDIRECT);
2113*6236dae4SAndroid Build Coastguard Worker Curl_pgrsResetTransferSizes(data);
2114*6236dae4SAndroid Build Coastguard Worker
2115*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
2116*6236dae4SAndroid Build Coastguard Worker #endif /* CURL_DISABLE_HTTP */
2117*6236dae4SAndroid Build Coastguard Worker }
2118*6236dae4SAndroid Build Coastguard Worker
2119*6236dae4SAndroid Build Coastguard Worker static CURLMcode state_performing(struct Curl_easy *data,
2120*6236dae4SAndroid Build Coastguard Worker struct curltime *nowp,
2121*6236dae4SAndroid Build Coastguard Worker bool *stream_errorp,
2122*6236dae4SAndroid Build Coastguard Worker CURLcode *resultp)
2123*6236dae4SAndroid Build Coastguard Worker {
2124*6236dae4SAndroid Build Coastguard Worker char *newurl = NULL;
2125*6236dae4SAndroid Build Coastguard Worker bool retry = FALSE;
2126*6236dae4SAndroid Build Coastguard Worker timediff_t recv_timeout_ms = 0;
2127*6236dae4SAndroid Build Coastguard Worker timediff_t send_timeout_ms = 0;
2128*6236dae4SAndroid Build Coastguard Worker CURLMcode rc = CURLM_OK;
2129*6236dae4SAndroid Build Coastguard Worker CURLcode result = *resultp = CURLE_OK;
2130*6236dae4SAndroid Build Coastguard Worker *stream_errorp = FALSE;
2131*6236dae4SAndroid Build Coastguard Worker
2132*6236dae4SAndroid Build Coastguard Worker /* check if over send speed */
2133*6236dae4SAndroid Build Coastguard Worker if(data->set.max_send_speed)
2134*6236dae4SAndroid Build Coastguard Worker send_timeout_ms = Curl_pgrsLimitWaitTime(&data->progress.ul,
2135*6236dae4SAndroid Build Coastguard Worker data->set.max_send_speed,
2136*6236dae4SAndroid Build Coastguard Worker *nowp);
2137*6236dae4SAndroid Build Coastguard Worker
2138*6236dae4SAndroid Build Coastguard Worker /* check if over recv speed */
2139*6236dae4SAndroid Build Coastguard Worker if(data->set.max_recv_speed)
2140*6236dae4SAndroid Build Coastguard Worker recv_timeout_ms = Curl_pgrsLimitWaitTime(&data->progress.dl,
2141*6236dae4SAndroid Build Coastguard Worker data->set.max_recv_speed,
2142*6236dae4SAndroid Build Coastguard Worker *nowp);
2143*6236dae4SAndroid Build Coastguard Worker
2144*6236dae4SAndroid Build Coastguard Worker if(send_timeout_ms || recv_timeout_ms) {
2145*6236dae4SAndroid Build Coastguard Worker Curl_ratelimit(data, *nowp);
2146*6236dae4SAndroid Build Coastguard Worker multistate(data, MSTATE_RATELIMITING);
2147*6236dae4SAndroid Build Coastguard Worker if(send_timeout_ms >= recv_timeout_ms)
2148*6236dae4SAndroid Build Coastguard Worker Curl_expire(data, send_timeout_ms, EXPIRE_TOOFAST);
2149*6236dae4SAndroid Build Coastguard Worker else
2150*6236dae4SAndroid Build Coastguard Worker Curl_expire(data, recv_timeout_ms, EXPIRE_TOOFAST);
2151*6236dae4SAndroid Build Coastguard Worker return CURLM_OK;
2152*6236dae4SAndroid Build Coastguard Worker }
2153*6236dae4SAndroid Build Coastguard Worker
2154*6236dae4SAndroid Build Coastguard Worker /* read/write data if it is ready to do so */
2155*6236dae4SAndroid Build Coastguard Worker result = Curl_sendrecv(data, nowp);
2156*6236dae4SAndroid Build Coastguard Worker
2157*6236dae4SAndroid Build Coastguard Worker if(data->req.done || (result == CURLE_RECV_ERROR)) {
2158*6236dae4SAndroid Build Coastguard Worker /* If CURLE_RECV_ERROR happens early enough, we assume it was a race
2159*6236dae4SAndroid Build Coastguard Worker * condition and the server closed the reused connection exactly when we
2160*6236dae4SAndroid Build Coastguard Worker * wanted to use it, so figure out if that is indeed the case.
2161*6236dae4SAndroid Build Coastguard Worker */
2162*6236dae4SAndroid Build Coastguard Worker CURLcode ret = Curl_retry_request(data, &newurl);
2163*6236dae4SAndroid Build Coastguard Worker if(!ret)
2164*6236dae4SAndroid Build Coastguard Worker retry = !!newurl;
2165*6236dae4SAndroid Build Coastguard Worker else if(!result)
2166*6236dae4SAndroid Build Coastguard Worker result = ret;
2167*6236dae4SAndroid Build Coastguard Worker
2168*6236dae4SAndroid Build Coastguard Worker if(retry) {
2169*6236dae4SAndroid Build Coastguard Worker /* if we are to retry, set the result to OK and consider the
2170*6236dae4SAndroid Build Coastguard Worker request as done */
2171*6236dae4SAndroid Build Coastguard Worker result = CURLE_OK;
2172*6236dae4SAndroid Build Coastguard Worker data->req.done = TRUE;
2173*6236dae4SAndroid Build Coastguard Worker }
2174*6236dae4SAndroid Build Coastguard Worker }
2175*6236dae4SAndroid Build Coastguard Worker else if((CURLE_HTTP2_STREAM == result) &&
2176*6236dae4SAndroid Build Coastguard Worker Curl_h2_http_1_1_error(data)) {
2177*6236dae4SAndroid Build Coastguard Worker CURLcode ret = Curl_retry_request(data, &newurl);
2178*6236dae4SAndroid Build Coastguard Worker
2179*6236dae4SAndroid Build Coastguard Worker if(!ret) {
2180*6236dae4SAndroid Build Coastguard Worker infof(data, "Downgrades to HTTP/1.1");
2181*6236dae4SAndroid Build Coastguard Worker streamclose(data->conn, "Disconnect HTTP/2 for HTTP/1");
2182*6236dae4SAndroid Build Coastguard Worker data->state.httpwant = CURL_HTTP_VERSION_1_1;
2183*6236dae4SAndroid Build Coastguard Worker /* clear the error message bit too as we ignore the one we got */
2184*6236dae4SAndroid Build Coastguard Worker data->state.errorbuf = FALSE;
2185*6236dae4SAndroid Build Coastguard Worker if(!newurl)
2186*6236dae4SAndroid Build Coastguard Worker /* typically for HTTP_1_1_REQUIRED error on first flight */
2187*6236dae4SAndroid Build Coastguard Worker newurl = strdup(data->state.url);
2188*6236dae4SAndroid Build Coastguard Worker /* if we are to retry, set the result to OK and consider the request
2189*6236dae4SAndroid Build Coastguard Worker as done */
2190*6236dae4SAndroid Build Coastguard Worker retry = TRUE;
2191*6236dae4SAndroid Build Coastguard Worker result = CURLE_OK;
2192*6236dae4SAndroid Build Coastguard Worker data->req.done = TRUE;
2193*6236dae4SAndroid Build Coastguard Worker }
2194*6236dae4SAndroid Build Coastguard Worker else
2195*6236dae4SAndroid Build Coastguard Worker result = ret;
2196*6236dae4SAndroid Build Coastguard Worker }
2197*6236dae4SAndroid Build Coastguard Worker
2198*6236dae4SAndroid Build Coastguard Worker if(result) {
2199*6236dae4SAndroid Build Coastguard Worker /*
2200*6236dae4SAndroid Build Coastguard Worker * The transfer phase returned error, we mark the connection to get closed
2201*6236dae4SAndroid Build Coastguard Worker * to prevent being reused. This is because we cannot possibly know if the
2202*6236dae4SAndroid Build Coastguard Worker * connection is in a good shape or not now. Unless it is a protocol which
2203*6236dae4SAndroid Build Coastguard Worker * uses two "channels" like FTP, as then the error happened in the data
2204*6236dae4SAndroid Build Coastguard Worker * connection.
2205*6236dae4SAndroid Build Coastguard Worker */
2206*6236dae4SAndroid Build Coastguard Worker
2207*6236dae4SAndroid Build Coastguard Worker if(!(data->conn->handler->flags & PROTOPT_DUAL) &&
2208*6236dae4SAndroid Build Coastguard Worker result != CURLE_HTTP2_STREAM)
2209*6236dae4SAndroid Build Coastguard Worker streamclose(data->conn, "Transfer returned error");
2210*6236dae4SAndroid Build Coastguard Worker
2211*6236dae4SAndroid Build Coastguard Worker multi_posttransfer(data);
2212*6236dae4SAndroid Build Coastguard Worker multi_done(data, result, TRUE);
2213*6236dae4SAndroid Build Coastguard Worker }
2214*6236dae4SAndroid Build Coastguard Worker else if(data->req.done && !Curl_cwriter_is_paused(data)) {
2215*6236dae4SAndroid Build Coastguard Worker
2216*6236dae4SAndroid Build Coastguard Worker /* call this even if the readwrite function returned error */
2217*6236dae4SAndroid Build Coastguard Worker multi_posttransfer(data);
2218*6236dae4SAndroid Build Coastguard Worker
2219*6236dae4SAndroid Build Coastguard Worker /* When we follow redirects or is set to retry the connection, we must to
2220*6236dae4SAndroid Build Coastguard Worker go back to the CONNECT state */
2221*6236dae4SAndroid Build Coastguard Worker if(data->req.newurl || retry) {
2222*6236dae4SAndroid Build Coastguard Worker followtype follow = FOLLOW_NONE;
2223*6236dae4SAndroid Build Coastguard Worker if(!retry) {
2224*6236dae4SAndroid Build Coastguard Worker /* if the URL is a follow-location and not just a retried request then
2225*6236dae4SAndroid Build Coastguard Worker figure out the URL here */
2226*6236dae4SAndroid Build Coastguard Worker free(newurl);
2227*6236dae4SAndroid Build Coastguard Worker newurl = data->req.newurl;
2228*6236dae4SAndroid Build Coastguard Worker data->req.newurl = NULL;
2229*6236dae4SAndroid Build Coastguard Worker follow = FOLLOW_REDIR;
2230*6236dae4SAndroid Build Coastguard Worker }
2231*6236dae4SAndroid Build Coastguard Worker else
2232*6236dae4SAndroid Build Coastguard Worker follow = FOLLOW_RETRY;
2233*6236dae4SAndroid Build Coastguard Worker (void)multi_done(data, CURLE_OK, FALSE);
2234*6236dae4SAndroid Build Coastguard Worker /* multi_done() might return CURLE_GOT_NOTHING */
2235*6236dae4SAndroid Build Coastguard Worker result = multi_follow(data, newurl, follow);
2236*6236dae4SAndroid Build Coastguard Worker if(!result) {
2237*6236dae4SAndroid Build Coastguard Worker multistate(data, MSTATE_SETUP);
2238*6236dae4SAndroid Build Coastguard Worker rc = CURLM_CALL_MULTI_PERFORM;
2239*6236dae4SAndroid Build Coastguard Worker }
2240*6236dae4SAndroid Build Coastguard Worker }
2241*6236dae4SAndroid Build Coastguard Worker else {
2242*6236dae4SAndroid Build Coastguard Worker /* after the transfer is done, go DONE */
2243*6236dae4SAndroid Build Coastguard Worker
2244*6236dae4SAndroid Build Coastguard Worker /* but first check to see if we got a location info even though we are
2245*6236dae4SAndroid Build Coastguard Worker not following redirects */
2246*6236dae4SAndroid Build Coastguard Worker if(data->req.location) {
2247*6236dae4SAndroid Build Coastguard Worker free(newurl);
2248*6236dae4SAndroid Build Coastguard Worker newurl = data->req.location;
2249*6236dae4SAndroid Build Coastguard Worker data->req.location = NULL;
2250*6236dae4SAndroid Build Coastguard Worker result = multi_follow(data, newurl, FOLLOW_FAKE);
2251*6236dae4SAndroid Build Coastguard Worker if(result) {
2252*6236dae4SAndroid Build Coastguard Worker *stream_errorp = TRUE;
2253*6236dae4SAndroid Build Coastguard Worker result = multi_done(data, result, TRUE);
2254*6236dae4SAndroid Build Coastguard Worker }
2255*6236dae4SAndroid Build Coastguard Worker }
2256*6236dae4SAndroid Build Coastguard Worker
2257*6236dae4SAndroid Build Coastguard Worker if(!result) {
2258*6236dae4SAndroid Build Coastguard Worker multistate(data, MSTATE_DONE);
2259*6236dae4SAndroid Build Coastguard Worker rc = CURLM_CALL_MULTI_PERFORM;
2260*6236dae4SAndroid Build Coastguard Worker }
2261*6236dae4SAndroid Build Coastguard Worker }
2262*6236dae4SAndroid Build Coastguard Worker }
2263*6236dae4SAndroid Build Coastguard Worker else if(data->state.select_bits && !Curl_xfer_is_blocked(data)) {
2264*6236dae4SAndroid Build Coastguard Worker /* This avoids CURLM_CALL_MULTI_PERFORM so that a very fast transfer does
2265*6236dae4SAndroid Build Coastguard Worker not get stuck on this transfer at the expense of other concurrent
2266*6236dae4SAndroid Build Coastguard Worker transfers */
2267*6236dae4SAndroid Build Coastguard Worker Curl_expire(data, 0, EXPIRE_RUN_NOW);
2268*6236dae4SAndroid Build Coastguard Worker }
2269*6236dae4SAndroid Build Coastguard Worker free(newurl);
2270*6236dae4SAndroid Build Coastguard Worker *resultp = result;
2271*6236dae4SAndroid Build Coastguard Worker return rc;
2272*6236dae4SAndroid Build Coastguard Worker }
2273*6236dae4SAndroid Build Coastguard Worker
2274*6236dae4SAndroid Build Coastguard Worker static CURLMcode state_do(struct Curl_easy *data,
2275*6236dae4SAndroid Build Coastguard Worker bool *stream_errorp,
2276*6236dae4SAndroid Build Coastguard Worker CURLcode *resultp)
2277*6236dae4SAndroid Build Coastguard Worker {
2278*6236dae4SAndroid Build Coastguard Worker CURLMcode rc = CURLM_OK;
2279*6236dae4SAndroid Build Coastguard Worker CURLcode result = CURLE_OK;
2280*6236dae4SAndroid Build Coastguard Worker if(data->set.fprereq) {
2281*6236dae4SAndroid Build Coastguard Worker int prereq_rc;
2282*6236dae4SAndroid Build Coastguard Worker
2283*6236dae4SAndroid Build Coastguard Worker /* call the prerequest callback function */
2284*6236dae4SAndroid Build Coastguard Worker Curl_set_in_callback(data, TRUE);
2285*6236dae4SAndroid Build Coastguard Worker prereq_rc = data->set.fprereq(data->set.prereq_userp,
2286*6236dae4SAndroid Build Coastguard Worker data->info.primary.remote_ip,
2287*6236dae4SAndroid Build Coastguard Worker data->info.primary.local_ip,
2288*6236dae4SAndroid Build Coastguard Worker data->info.primary.remote_port,
2289*6236dae4SAndroid Build Coastguard Worker data->info.primary.local_port);
2290*6236dae4SAndroid Build Coastguard Worker Curl_set_in_callback(data, FALSE);
2291*6236dae4SAndroid Build Coastguard Worker if(prereq_rc != CURL_PREREQFUNC_OK) {
2292*6236dae4SAndroid Build Coastguard Worker failf(data, "operation aborted by pre-request callback");
2293*6236dae4SAndroid Build Coastguard Worker /* failure in pre-request callback - do not do any other processing */
2294*6236dae4SAndroid Build Coastguard Worker result = CURLE_ABORTED_BY_CALLBACK;
2295*6236dae4SAndroid Build Coastguard Worker multi_posttransfer(data);
2296*6236dae4SAndroid Build Coastguard Worker multi_done(data, result, FALSE);
2297*6236dae4SAndroid Build Coastguard Worker *stream_errorp = TRUE;
2298*6236dae4SAndroid Build Coastguard Worker goto end;
2299*6236dae4SAndroid Build Coastguard Worker }
2300*6236dae4SAndroid Build Coastguard Worker }
2301*6236dae4SAndroid Build Coastguard Worker
2302*6236dae4SAndroid Build Coastguard Worker if(data->set.connect_only == 1) {
2303*6236dae4SAndroid Build Coastguard Worker /* keep connection open for application to use the socket */
2304*6236dae4SAndroid Build Coastguard Worker connkeep(data->conn, "CONNECT_ONLY");
2305*6236dae4SAndroid Build Coastguard Worker multistate(data, MSTATE_DONE);
2306*6236dae4SAndroid Build Coastguard Worker rc = CURLM_CALL_MULTI_PERFORM;
2307*6236dae4SAndroid Build Coastguard Worker }
2308*6236dae4SAndroid Build Coastguard Worker else {
2309*6236dae4SAndroid Build Coastguard Worker bool dophase_done = FALSE;
2310*6236dae4SAndroid Build Coastguard Worker /* Perform the protocol's DO action */
2311*6236dae4SAndroid Build Coastguard Worker result = multi_do(data, &dophase_done);
2312*6236dae4SAndroid Build Coastguard Worker
2313*6236dae4SAndroid Build Coastguard Worker /* When multi_do() returns failure, data->conn might be NULL! */
2314*6236dae4SAndroid Build Coastguard Worker
2315*6236dae4SAndroid Build Coastguard Worker if(!result) {
2316*6236dae4SAndroid Build Coastguard Worker if(!dophase_done) {
2317*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_FTP
2318*6236dae4SAndroid Build Coastguard Worker /* some steps needed for wildcard matching */
2319*6236dae4SAndroid Build Coastguard Worker if(data->state.wildcardmatch) {
2320*6236dae4SAndroid Build Coastguard Worker struct WildcardData *wc = data->wildcard;
2321*6236dae4SAndroid Build Coastguard Worker if(wc->state == CURLWC_DONE || wc->state == CURLWC_SKIP) {
2322*6236dae4SAndroid Build Coastguard Worker /* skip some states if it is important */
2323*6236dae4SAndroid Build Coastguard Worker multi_done(data, CURLE_OK, FALSE);
2324*6236dae4SAndroid Build Coastguard Worker
2325*6236dae4SAndroid Build Coastguard Worker /* if there is no connection left, skip the DONE state */
2326*6236dae4SAndroid Build Coastguard Worker multistate(data, data->conn ?
2327*6236dae4SAndroid Build Coastguard Worker MSTATE_DONE : MSTATE_COMPLETED);
2328*6236dae4SAndroid Build Coastguard Worker rc = CURLM_CALL_MULTI_PERFORM;
2329*6236dae4SAndroid Build Coastguard Worker goto end;
2330*6236dae4SAndroid Build Coastguard Worker }
2331*6236dae4SAndroid Build Coastguard Worker }
2332*6236dae4SAndroid Build Coastguard Worker #endif
2333*6236dae4SAndroid Build Coastguard Worker /* DO was not completed in one function call, we must continue
2334*6236dae4SAndroid Build Coastguard Worker DOING... */
2335*6236dae4SAndroid Build Coastguard Worker multistate(data, MSTATE_DOING);
2336*6236dae4SAndroid Build Coastguard Worker rc = CURLM_CALL_MULTI_PERFORM;
2337*6236dae4SAndroid Build Coastguard Worker }
2338*6236dae4SAndroid Build Coastguard Worker
2339*6236dae4SAndroid Build Coastguard Worker /* after DO, go DO_DONE... or DO_MORE */
2340*6236dae4SAndroid Build Coastguard Worker else if(data->conn->bits.do_more) {
2341*6236dae4SAndroid Build Coastguard Worker /* we are supposed to do more, but we need to sit down, relax and wait
2342*6236dae4SAndroid Build Coastguard Worker a little while first */
2343*6236dae4SAndroid Build Coastguard Worker multistate(data, MSTATE_DOING_MORE);
2344*6236dae4SAndroid Build Coastguard Worker rc = CURLM_CALL_MULTI_PERFORM;
2345*6236dae4SAndroid Build Coastguard Worker }
2346*6236dae4SAndroid Build Coastguard Worker else {
2347*6236dae4SAndroid Build Coastguard Worker /* we are done with the DO, now DID */
2348*6236dae4SAndroid Build Coastguard Worker multistate(data, MSTATE_DID);
2349*6236dae4SAndroid Build Coastguard Worker rc = CURLM_CALL_MULTI_PERFORM;
2350*6236dae4SAndroid Build Coastguard Worker }
2351*6236dae4SAndroid Build Coastguard Worker }
2352*6236dae4SAndroid Build Coastguard Worker else if((CURLE_SEND_ERROR == result) &&
2353*6236dae4SAndroid Build Coastguard Worker data->conn->bits.reuse) {
2354*6236dae4SAndroid Build Coastguard Worker /*
2355*6236dae4SAndroid Build Coastguard Worker * In this situation, a connection that we were trying to use may have
2356*6236dae4SAndroid Build Coastguard Worker * unexpectedly died. If possible, send the connection back to the
2357*6236dae4SAndroid Build Coastguard Worker * CONNECT phase so we can try again.
2358*6236dae4SAndroid Build Coastguard Worker */
2359*6236dae4SAndroid Build Coastguard Worker char *newurl = NULL;
2360*6236dae4SAndroid Build Coastguard Worker followtype follow = FOLLOW_NONE;
2361*6236dae4SAndroid Build Coastguard Worker CURLcode drc;
2362*6236dae4SAndroid Build Coastguard Worker
2363*6236dae4SAndroid Build Coastguard Worker drc = Curl_retry_request(data, &newurl);
2364*6236dae4SAndroid Build Coastguard Worker if(drc) {
2365*6236dae4SAndroid Build Coastguard Worker /* a failure here pretty much implies an out of memory */
2366*6236dae4SAndroid Build Coastguard Worker result = drc;
2367*6236dae4SAndroid Build Coastguard Worker *stream_errorp = TRUE;
2368*6236dae4SAndroid Build Coastguard Worker }
2369*6236dae4SAndroid Build Coastguard Worker
2370*6236dae4SAndroid Build Coastguard Worker multi_posttransfer(data);
2371*6236dae4SAndroid Build Coastguard Worker drc = multi_done(data, result, FALSE);
2372*6236dae4SAndroid Build Coastguard Worker
2373*6236dae4SAndroid Build Coastguard Worker /* When set to retry the connection, we must go back to the CONNECT
2374*6236dae4SAndroid Build Coastguard Worker * state */
2375*6236dae4SAndroid Build Coastguard Worker if(newurl) {
2376*6236dae4SAndroid Build Coastguard Worker if(!drc || (drc == CURLE_SEND_ERROR)) {
2377*6236dae4SAndroid Build Coastguard Worker follow = FOLLOW_RETRY;
2378*6236dae4SAndroid Build Coastguard Worker drc = multi_follow(data, newurl, follow);
2379*6236dae4SAndroid Build Coastguard Worker if(!drc) {
2380*6236dae4SAndroid Build Coastguard Worker multistate(data, MSTATE_SETUP);
2381*6236dae4SAndroid Build Coastguard Worker rc = CURLM_CALL_MULTI_PERFORM;
2382*6236dae4SAndroid Build Coastguard Worker result = CURLE_OK;
2383*6236dae4SAndroid Build Coastguard Worker }
2384*6236dae4SAndroid Build Coastguard Worker else {
2385*6236dae4SAndroid Build Coastguard Worker /* Follow failed */
2386*6236dae4SAndroid Build Coastguard Worker result = drc;
2387*6236dae4SAndroid Build Coastguard Worker }
2388*6236dae4SAndroid Build Coastguard Worker }
2389*6236dae4SAndroid Build Coastguard Worker else {
2390*6236dae4SAndroid Build Coastguard Worker /* done did not return OK or SEND_ERROR */
2391*6236dae4SAndroid Build Coastguard Worker result = drc;
2392*6236dae4SAndroid Build Coastguard Worker }
2393*6236dae4SAndroid Build Coastguard Worker }
2394*6236dae4SAndroid Build Coastguard Worker else {
2395*6236dae4SAndroid Build Coastguard Worker /* Have error handler disconnect conn if we cannot retry */
2396*6236dae4SAndroid Build Coastguard Worker *stream_errorp = TRUE;
2397*6236dae4SAndroid Build Coastguard Worker }
2398*6236dae4SAndroid Build Coastguard Worker free(newurl);
2399*6236dae4SAndroid Build Coastguard Worker }
2400*6236dae4SAndroid Build Coastguard Worker else {
2401*6236dae4SAndroid Build Coastguard Worker /* failure detected */
2402*6236dae4SAndroid Build Coastguard Worker multi_posttransfer(data);
2403*6236dae4SAndroid Build Coastguard Worker if(data->conn)
2404*6236dae4SAndroid Build Coastguard Worker multi_done(data, result, FALSE);
2405*6236dae4SAndroid Build Coastguard Worker *stream_errorp = TRUE;
2406*6236dae4SAndroid Build Coastguard Worker }
2407*6236dae4SAndroid Build Coastguard Worker }
2408*6236dae4SAndroid Build Coastguard Worker end:
2409*6236dae4SAndroid Build Coastguard Worker *resultp = result;
2410*6236dae4SAndroid Build Coastguard Worker return rc;
2411*6236dae4SAndroid Build Coastguard Worker }
2412*6236dae4SAndroid Build Coastguard Worker
2413*6236dae4SAndroid Build Coastguard Worker static CURLMcode state_ratelimiting(struct Curl_easy *data,
2414*6236dae4SAndroid Build Coastguard Worker struct curltime *nowp,
2415*6236dae4SAndroid Build Coastguard Worker CURLcode *resultp)
2416*6236dae4SAndroid Build Coastguard Worker {
2417*6236dae4SAndroid Build Coastguard Worker CURLcode result = CURLE_OK;
2418*6236dae4SAndroid Build Coastguard Worker CURLMcode rc = CURLM_OK;
2419*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(data->conn);
2420*6236dae4SAndroid Build Coastguard Worker /* if both rates are within spec, resume transfer */
2421*6236dae4SAndroid Build Coastguard Worker if(Curl_pgrsUpdate(data))
2422*6236dae4SAndroid Build Coastguard Worker result = CURLE_ABORTED_BY_CALLBACK;
2423*6236dae4SAndroid Build Coastguard Worker else
2424*6236dae4SAndroid Build Coastguard Worker result = Curl_speedcheck(data, *nowp);
2425*6236dae4SAndroid Build Coastguard Worker
2426*6236dae4SAndroid Build Coastguard Worker if(result) {
2427*6236dae4SAndroid Build Coastguard Worker if(!(data->conn->handler->flags & PROTOPT_DUAL) &&
2428*6236dae4SAndroid Build Coastguard Worker result != CURLE_HTTP2_STREAM)
2429*6236dae4SAndroid Build Coastguard Worker streamclose(data->conn, "Transfer returned error");
2430*6236dae4SAndroid Build Coastguard Worker
2431*6236dae4SAndroid Build Coastguard Worker multi_posttransfer(data);
2432*6236dae4SAndroid Build Coastguard Worker multi_done(data, result, TRUE);
2433*6236dae4SAndroid Build Coastguard Worker }
2434*6236dae4SAndroid Build Coastguard Worker else {
2435*6236dae4SAndroid Build Coastguard Worker timediff_t recv_timeout_ms = 0;
2436*6236dae4SAndroid Build Coastguard Worker timediff_t send_timeout_ms = 0;
2437*6236dae4SAndroid Build Coastguard Worker if(data->set.max_send_speed)
2438*6236dae4SAndroid Build Coastguard Worker send_timeout_ms =
2439*6236dae4SAndroid Build Coastguard Worker Curl_pgrsLimitWaitTime(&data->progress.ul,
2440*6236dae4SAndroid Build Coastguard Worker data->set.max_send_speed,
2441*6236dae4SAndroid Build Coastguard Worker *nowp);
2442*6236dae4SAndroid Build Coastguard Worker
2443*6236dae4SAndroid Build Coastguard Worker if(data->set.max_recv_speed)
2444*6236dae4SAndroid Build Coastguard Worker recv_timeout_ms =
2445*6236dae4SAndroid Build Coastguard Worker Curl_pgrsLimitWaitTime(&data->progress.dl,
2446*6236dae4SAndroid Build Coastguard Worker data->set.max_recv_speed,
2447*6236dae4SAndroid Build Coastguard Worker *nowp);
2448*6236dae4SAndroid Build Coastguard Worker
2449*6236dae4SAndroid Build Coastguard Worker if(!send_timeout_ms && !recv_timeout_ms) {
2450*6236dae4SAndroid Build Coastguard Worker multistate(data, MSTATE_PERFORMING);
2451*6236dae4SAndroid Build Coastguard Worker Curl_ratelimit(data, *nowp);
2452*6236dae4SAndroid Build Coastguard Worker /* start performing again right away */
2453*6236dae4SAndroid Build Coastguard Worker rc = CURLM_CALL_MULTI_PERFORM;
2454*6236dae4SAndroid Build Coastguard Worker }
2455*6236dae4SAndroid Build Coastguard Worker else if(send_timeout_ms >= recv_timeout_ms)
2456*6236dae4SAndroid Build Coastguard Worker Curl_expire(data, send_timeout_ms, EXPIRE_TOOFAST);
2457*6236dae4SAndroid Build Coastguard Worker else
2458*6236dae4SAndroid Build Coastguard Worker Curl_expire(data, recv_timeout_ms, EXPIRE_TOOFAST);
2459*6236dae4SAndroid Build Coastguard Worker }
2460*6236dae4SAndroid Build Coastguard Worker *resultp = result;
2461*6236dae4SAndroid Build Coastguard Worker return rc;
2462*6236dae4SAndroid Build Coastguard Worker }
2463*6236dae4SAndroid Build Coastguard Worker
2464*6236dae4SAndroid Build Coastguard Worker static CURLMcode state_resolving(struct Curl_multi *multi,
2465*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data,
2466*6236dae4SAndroid Build Coastguard Worker bool *stream_errorp,
2467*6236dae4SAndroid Build Coastguard Worker CURLcode *resultp)
2468*6236dae4SAndroid Build Coastguard Worker {
2469*6236dae4SAndroid Build Coastguard Worker struct Curl_dns_entry *dns = NULL;
2470*6236dae4SAndroid Build Coastguard Worker struct connectdata *conn = data->conn;
2471*6236dae4SAndroid Build Coastguard Worker const char *hostname;
2472*6236dae4SAndroid Build Coastguard Worker CURLcode result = CURLE_OK;
2473*6236dae4SAndroid Build Coastguard Worker CURLMcode rc = CURLM_OK;
2474*6236dae4SAndroid Build Coastguard Worker
2475*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(conn);
2476*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_PROXY
2477*6236dae4SAndroid Build Coastguard Worker if(conn->bits.httpproxy)
2478*6236dae4SAndroid Build Coastguard Worker hostname = conn->http_proxy.host.name;
2479*6236dae4SAndroid Build Coastguard Worker else
2480*6236dae4SAndroid Build Coastguard Worker #endif
2481*6236dae4SAndroid Build Coastguard Worker if(conn->bits.conn_to_host)
2482*6236dae4SAndroid Build Coastguard Worker hostname = conn->conn_to_host.name;
2483*6236dae4SAndroid Build Coastguard Worker else
2484*6236dae4SAndroid Build Coastguard Worker hostname = conn->host.name;
2485*6236dae4SAndroid Build Coastguard Worker
2486*6236dae4SAndroid Build Coastguard Worker /* check if we have the name resolved by now */
2487*6236dae4SAndroid Build Coastguard Worker dns = Curl_fetch_addr(data, hostname, conn->primary.remote_port);
2488*6236dae4SAndroid Build Coastguard Worker
2489*6236dae4SAndroid Build Coastguard Worker if(dns) {
2490*6236dae4SAndroid Build Coastguard Worker #ifdef CURLRES_ASYNCH
2491*6236dae4SAndroid Build Coastguard Worker data->state.async.dns = dns;
2492*6236dae4SAndroid Build Coastguard Worker data->state.async.done = TRUE;
2493*6236dae4SAndroid Build Coastguard Worker #endif
2494*6236dae4SAndroid Build Coastguard Worker result = CURLE_OK;
2495*6236dae4SAndroid Build Coastguard Worker infof(data, "Hostname '%s' was found in DNS cache", hostname);
2496*6236dae4SAndroid Build Coastguard Worker }
2497*6236dae4SAndroid Build Coastguard Worker
2498*6236dae4SAndroid Build Coastguard Worker if(!dns)
2499*6236dae4SAndroid Build Coastguard Worker result = Curl_resolv_check(data, &dns);
2500*6236dae4SAndroid Build Coastguard Worker
2501*6236dae4SAndroid Build Coastguard Worker /* Update sockets here, because the socket(s) may have been closed and the
2502*6236dae4SAndroid Build Coastguard Worker application thus needs to be told, even if it is likely that the same
2503*6236dae4SAndroid Build Coastguard Worker socket(s) will again be used further down. If the name has not yet been
2504*6236dae4SAndroid Build Coastguard Worker resolved, it is likely that new sockets have been opened in an attempt to
2505*6236dae4SAndroid Build Coastguard Worker contact another resolver. */
2506*6236dae4SAndroid Build Coastguard Worker rc = singlesocket(multi, data);
2507*6236dae4SAndroid Build Coastguard Worker if(rc)
2508*6236dae4SAndroid Build Coastguard Worker return rc;
2509*6236dae4SAndroid Build Coastguard Worker
2510*6236dae4SAndroid Build Coastguard Worker if(dns) {
2511*6236dae4SAndroid Build Coastguard Worker bool connected;
2512*6236dae4SAndroid Build Coastguard Worker /* Perform the next step in the connection phase, and then move on to the
2513*6236dae4SAndroid Build Coastguard Worker WAITCONNECT state */
2514*6236dae4SAndroid Build Coastguard Worker result = Curl_once_resolved(data, &connected);
2515*6236dae4SAndroid Build Coastguard Worker
2516*6236dae4SAndroid Build Coastguard Worker if(result)
2517*6236dae4SAndroid Build Coastguard Worker /* if Curl_once_resolved() returns failure, the connection struct is
2518*6236dae4SAndroid Build Coastguard Worker already freed and gone */
2519*6236dae4SAndroid Build Coastguard Worker data->conn = NULL; /* no more connection */
2520*6236dae4SAndroid Build Coastguard Worker else {
2521*6236dae4SAndroid Build Coastguard Worker /* call again please so that we get the next socket setup */
2522*6236dae4SAndroid Build Coastguard Worker rc = CURLM_CALL_MULTI_PERFORM;
2523*6236dae4SAndroid Build Coastguard Worker if(connected)
2524*6236dae4SAndroid Build Coastguard Worker multistate(data, MSTATE_PROTOCONNECT);
2525*6236dae4SAndroid Build Coastguard Worker else {
2526*6236dae4SAndroid Build Coastguard Worker multistate(data, MSTATE_CONNECTING);
2527*6236dae4SAndroid Build Coastguard Worker }
2528*6236dae4SAndroid Build Coastguard Worker }
2529*6236dae4SAndroid Build Coastguard Worker }
2530*6236dae4SAndroid Build Coastguard Worker
2531*6236dae4SAndroid Build Coastguard Worker if(result)
2532*6236dae4SAndroid Build Coastguard Worker /* failure detected */
2533*6236dae4SAndroid Build Coastguard Worker *stream_errorp = TRUE;
2534*6236dae4SAndroid Build Coastguard Worker
2535*6236dae4SAndroid Build Coastguard Worker *resultp = result;
2536*6236dae4SAndroid Build Coastguard Worker return rc;
2537*6236dae4SAndroid Build Coastguard Worker }
2538*6236dae4SAndroid Build Coastguard Worker
2539*6236dae4SAndroid Build Coastguard Worker static CURLMcode state_connect(struct Curl_multi *multi,
2540*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data,
2541*6236dae4SAndroid Build Coastguard Worker struct curltime *nowp,
2542*6236dae4SAndroid Build Coastguard Worker CURLcode *resultp)
2543*6236dae4SAndroid Build Coastguard Worker {
2544*6236dae4SAndroid Build Coastguard Worker /* Connect. We want to get a connection identifier filled in. This state can
2545*6236dae4SAndroid Build Coastguard Worker be entered from SETUP and from PENDING. */
2546*6236dae4SAndroid Build Coastguard Worker bool connected;
2547*6236dae4SAndroid Build Coastguard Worker bool async;
2548*6236dae4SAndroid Build Coastguard Worker CURLMcode rc = CURLM_OK;
2549*6236dae4SAndroid Build Coastguard Worker CURLcode result = Curl_connect(data, &async, &connected);
2550*6236dae4SAndroid Build Coastguard Worker if(CURLE_NO_CONNECTION_AVAILABLE == result) {
2551*6236dae4SAndroid Build Coastguard Worker /* There was no connection available. We will go to the pending state and
2552*6236dae4SAndroid Build Coastguard Worker wait for an available connection. */
2553*6236dae4SAndroid Build Coastguard Worker multistate(data, MSTATE_PENDING);
2554*6236dae4SAndroid Build Coastguard Worker /* unlink from process list */
2555*6236dae4SAndroid Build Coastguard Worker Curl_node_remove(&data->multi_queue);
2556*6236dae4SAndroid Build Coastguard Worker /* add handle to pending list */
2557*6236dae4SAndroid Build Coastguard Worker Curl_llist_append(&multi->pending, data, &data->multi_queue);
2558*6236dae4SAndroid Build Coastguard Worker *resultp = CURLE_OK;
2559*6236dae4SAndroid Build Coastguard Worker return rc;
2560*6236dae4SAndroid Build Coastguard Worker }
2561*6236dae4SAndroid Build Coastguard Worker else
2562*6236dae4SAndroid Build Coastguard Worker process_pending_handles(data->multi);
2563*6236dae4SAndroid Build Coastguard Worker
2564*6236dae4SAndroid Build Coastguard Worker if(!result) {
2565*6236dae4SAndroid Build Coastguard Worker *nowp = Curl_pgrsTime(data, TIMER_POSTQUEUE);
2566*6236dae4SAndroid Build Coastguard Worker if(async)
2567*6236dae4SAndroid Build Coastguard Worker /* We are now waiting for an asynchronous name lookup */
2568*6236dae4SAndroid Build Coastguard Worker multistate(data, MSTATE_RESOLVING);
2569*6236dae4SAndroid Build Coastguard Worker else {
2570*6236dae4SAndroid Build Coastguard Worker /* after the connect has been sent off, go WAITCONNECT unless the
2571*6236dae4SAndroid Build Coastguard Worker protocol connect is already done and we can go directly to WAITDO or
2572*6236dae4SAndroid Build Coastguard Worker DO! */
2573*6236dae4SAndroid Build Coastguard Worker rc = CURLM_CALL_MULTI_PERFORM;
2574*6236dae4SAndroid Build Coastguard Worker
2575*6236dae4SAndroid Build Coastguard Worker if(connected) {
2576*6236dae4SAndroid Build Coastguard Worker if(!data->conn->bits.reuse &&
2577*6236dae4SAndroid Build Coastguard Worker Curl_conn_is_multiplex(data->conn, FIRSTSOCKET)) {
2578*6236dae4SAndroid Build Coastguard Worker /* new connection, can multiplex, wake pending handles */
2579*6236dae4SAndroid Build Coastguard Worker process_pending_handles(data->multi);
2580*6236dae4SAndroid Build Coastguard Worker }
2581*6236dae4SAndroid Build Coastguard Worker multistate(data, MSTATE_PROTOCONNECT);
2582*6236dae4SAndroid Build Coastguard Worker }
2583*6236dae4SAndroid Build Coastguard Worker else {
2584*6236dae4SAndroid Build Coastguard Worker multistate(data, MSTATE_CONNECTING);
2585*6236dae4SAndroid Build Coastguard Worker }
2586*6236dae4SAndroid Build Coastguard Worker }
2587*6236dae4SAndroid Build Coastguard Worker }
2588*6236dae4SAndroid Build Coastguard Worker *resultp = result;
2589*6236dae4SAndroid Build Coastguard Worker return rc;
2590*6236dae4SAndroid Build Coastguard Worker }
2591*6236dae4SAndroid Build Coastguard Worker
2592*6236dae4SAndroid Build Coastguard Worker static CURLMcode multi_runsingle(struct Curl_multi *multi,
2593*6236dae4SAndroid Build Coastguard Worker struct curltime *nowp,
2594*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data)
2595*6236dae4SAndroid Build Coastguard Worker {
2596*6236dae4SAndroid Build Coastguard Worker struct Curl_message *msg = NULL;
2597*6236dae4SAndroid Build Coastguard Worker bool connected;
2598*6236dae4SAndroid Build Coastguard Worker bool protocol_connected = FALSE;
2599*6236dae4SAndroid Build Coastguard Worker bool dophase_done = FALSE;
2600*6236dae4SAndroid Build Coastguard Worker CURLMcode rc;
2601*6236dae4SAndroid Build Coastguard Worker CURLcode result = CURLE_OK;
2602*6236dae4SAndroid Build Coastguard Worker int control;
2603*6236dae4SAndroid Build Coastguard Worker
2604*6236dae4SAndroid Build Coastguard Worker if(!GOOD_EASY_HANDLE(data))
2605*6236dae4SAndroid Build Coastguard Worker return CURLM_BAD_EASY_HANDLE;
2606*6236dae4SAndroid Build Coastguard Worker
2607*6236dae4SAndroid Build Coastguard Worker if(multi->dead) {
2608*6236dae4SAndroid Build Coastguard Worker /* a multi-level callback returned error before, meaning every individual
2609*6236dae4SAndroid Build Coastguard Worker transfer now has failed */
2610*6236dae4SAndroid Build Coastguard Worker result = CURLE_ABORTED_BY_CALLBACK;
2611*6236dae4SAndroid Build Coastguard Worker multi_posttransfer(data);
2612*6236dae4SAndroid Build Coastguard Worker multi_done(data, result, FALSE);
2613*6236dae4SAndroid Build Coastguard Worker multistate(data, MSTATE_COMPLETED);
2614*6236dae4SAndroid Build Coastguard Worker }
2615*6236dae4SAndroid Build Coastguard Worker
2616*6236dae4SAndroid Build Coastguard Worker multi_warn_debug(multi, data);
2617*6236dae4SAndroid Build Coastguard Worker
2618*6236dae4SAndroid Build Coastguard Worker do {
2619*6236dae4SAndroid Build Coastguard Worker /* A "stream" here is a logical stream if the protocol can handle that
2620*6236dae4SAndroid Build Coastguard Worker (HTTP/2), or the full connection for older protocols */
2621*6236dae4SAndroid Build Coastguard Worker bool stream_error = FALSE;
2622*6236dae4SAndroid Build Coastguard Worker rc = CURLM_OK;
2623*6236dae4SAndroid Build Coastguard Worker
2624*6236dae4SAndroid Build Coastguard Worker if(multi_ischanged(multi, TRUE)) {
2625*6236dae4SAndroid Build Coastguard Worker DEBUGF(infof(data, "multi changed, check CONNECT_PEND queue"));
2626*6236dae4SAndroid Build Coastguard Worker process_pending_handles(multi); /* multiplexed */
2627*6236dae4SAndroid Build Coastguard Worker }
2628*6236dae4SAndroid Build Coastguard Worker
2629*6236dae4SAndroid Build Coastguard Worker if(data->mstate > MSTATE_CONNECT &&
2630*6236dae4SAndroid Build Coastguard Worker data->mstate < MSTATE_COMPLETED) {
2631*6236dae4SAndroid Build Coastguard Worker /* Make sure we set the connection's current owner */
2632*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(data->conn);
2633*6236dae4SAndroid Build Coastguard Worker if(!data->conn)
2634*6236dae4SAndroid Build Coastguard Worker return CURLM_INTERNAL_ERROR;
2635*6236dae4SAndroid Build Coastguard Worker }
2636*6236dae4SAndroid Build Coastguard Worker
2637*6236dae4SAndroid Build Coastguard Worker /* Wait for the connect state as only then is the start time stored, but
2638*6236dae4SAndroid Build Coastguard Worker we must not check already completed handles */
2639*6236dae4SAndroid Build Coastguard Worker if((data->mstate >= MSTATE_CONNECT) && (data->mstate < MSTATE_COMPLETED) &&
2640*6236dae4SAndroid Build Coastguard Worker multi_handle_timeout(data, nowp, &stream_error, &result))
2641*6236dae4SAndroid Build Coastguard Worker /* Skip the statemachine and go directly to error handling section. */
2642*6236dae4SAndroid Build Coastguard Worker goto statemachine_end;
2643*6236dae4SAndroid Build Coastguard Worker
2644*6236dae4SAndroid Build Coastguard Worker switch(data->mstate) {
2645*6236dae4SAndroid Build Coastguard Worker case MSTATE_INIT:
2646*6236dae4SAndroid Build Coastguard Worker /* Transitional state. init this transfer. A handle never comes back to
2647*6236dae4SAndroid Build Coastguard Worker this state. */
2648*6236dae4SAndroid Build Coastguard Worker result = Curl_pretransfer(data);
2649*6236dae4SAndroid Build Coastguard Worker if(result)
2650*6236dae4SAndroid Build Coastguard Worker break;
2651*6236dae4SAndroid Build Coastguard Worker
2652*6236dae4SAndroid Build Coastguard Worker /* after init, go SETUP */
2653*6236dae4SAndroid Build Coastguard Worker multistate(data, MSTATE_SETUP);
2654*6236dae4SAndroid Build Coastguard Worker (void)Curl_pgrsTime(data, TIMER_STARTOP);
2655*6236dae4SAndroid Build Coastguard Worker FALLTHROUGH();
2656*6236dae4SAndroid Build Coastguard Worker
2657*6236dae4SAndroid Build Coastguard Worker case MSTATE_SETUP:
2658*6236dae4SAndroid Build Coastguard Worker /* Transitional state. Setup things for a new transfer. The handle
2659*6236dae4SAndroid Build Coastguard Worker can come back to this state on a redirect. */
2660*6236dae4SAndroid Build Coastguard Worker *nowp = Curl_pgrsTime(data, TIMER_STARTSINGLE);
2661*6236dae4SAndroid Build Coastguard Worker if(data->set.timeout)
2662*6236dae4SAndroid Build Coastguard Worker Curl_expire(data, data->set.timeout, EXPIRE_TIMEOUT);
2663*6236dae4SAndroid Build Coastguard Worker if(data->set.connecttimeout)
2664*6236dae4SAndroid Build Coastguard Worker /* Since a connection might go to pending and back to CONNECT several
2665*6236dae4SAndroid Build Coastguard Worker times before it actually takes off, we need to set the timeout once
2666*6236dae4SAndroid Build Coastguard Worker in SETUP before we enter CONNECT the first time. */
2667*6236dae4SAndroid Build Coastguard Worker Curl_expire(data, data->set.connecttimeout, EXPIRE_CONNECTTIMEOUT);
2668*6236dae4SAndroid Build Coastguard Worker
2669*6236dae4SAndroid Build Coastguard Worker multistate(data, MSTATE_CONNECT);
2670*6236dae4SAndroid Build Coastguard Worker FALLTHROUGH();
2671*6236dae4SAndroid Build Coastguard Worker
2672*6236dae4SAndroid Build Coastguard Worker case MSTATE_CONNECT:
2673*6236dae4SAndroid Build Coastguard Worker rc = state_connect(multi, data, nowp, &result);
2674*6236dae4SAndroid Build Coastguard Worker break;
2675*6236dae4SAndroid Build Coastguard Worker
2676*6236dae4SAndroid Build Coastguard Worker case MSTATE_RESOLVING:
2677*6236dae4SAndroid Build Coastguard Worker /* awaiting an asynch name resolve to complete */
2678*6236dae4SAndroid Build Coastguard Worker rc = state_resolving(multi, data, &stream_error, &result);
2679*6236dae4SAndroid Build Coastguard Worker break;
2680*6236dae4SAndroid Build Coastguard Worker
2681*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_HTTP
2682*6236dae4SAndroid Build Coastguard Worker case MSTATE_TUNNELING:
2683*6236dae4SAndroid Build Coastguard Worker /* this is HTTP-specific, but sending CONNECT to a proxy is HTTP... */
2684*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(data->conn);
2685*6236dae4SAndroid Build Coastguard Worker result = Curl_http_connect(data, &protocol_connected);
2686*6236dae4SAndroid Build Coastguard Worker if(!result) {
2687*6236dae4SAndroid Build Coastguard Worker rc = CURLM_CALL_MULTI_PERFORM;
2688*6236dae4SAndroid Build Coastguard Worker /* initiate protocol connect phase */
2689*6236dae4SAndroid Build Coastguard Worker multistate(data, MSTATE_PROTOCONNECT);
2690*6236dae4SAndroid Build Coastguard Worker }
2691*6236dae4SAndroid Build Coastguard Worker else
2692*6236dae4SAndroid Build Coastguard Worker stream_error = TRUE;
2693*6236dae4SAndroid Build Coastguard Worker break;
2694*6236dae4SAndroid Build Coastguard Worker #endif
2695*6236dae4SAndroid Build Coastguard Worker
2696*6236dae4SAndroid Build Coastguard Worker case MSTATE_CONNECTING:
2697*6236dae4SAndroid Build Coastguard Worker /* awaiting a completion of an asynch TCP connect */
2698*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(data->conn);
2699*6236dae4SAndroid Build Coastguard Worker result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &connected);
2700*6236dae4SAndroid Build Coastguard Worker if(connected && !result) {
2701*6236dae4SAndroid Build Coastguard Worker if(!data->conn->bits.reuse &&
2702*6236dae4SAndroid Build Coastguard Worker Curl_conn_is_multiplex(data->conn, FIRSTSOCKET)) {
2703*6236dae4SAndroid Build Coastguard Worker /* new connection, can multiplex, wake pending handles */
2704*6236dae4SAndroid Build Coastguard Worker process_pending_handles(data->multi);
2705*6236dae4SAndroid Build Coastguard Worker }
2706*6236dae4SAndroid Build Coastguard Worker rc = CURLM_CALL_MULTI_PERFORM;
2707*6236dae4SAndroid Build Coastguard Worker multistate(data, MSTATE_PROTOCONNECT);
2708*6236dae4SAndroid Build Coastguard Worker }
2709*6236dae4SAndroid Build Coastguard Worker else if(result) {
2710*6236dae4SAndroid Build Coastguard Worker /* failure detected */
2711*6236dae4SAndroid Build Coastguard Worker multi_posttransfer(data);
2712*6236dae4SAndroid Build Coastguard Worker multi_done(data, result, TRUE);
2713*6236dae4SAndroid Build Coastguard Worker stream_error = TRUE;
2714*6236dae4SAndroid Build Coastguard Worker break;
2715*6236dae4SAndroid Build Coastguard Worker }
2716*6236dae4SAndroid Build Coastguard Worker break;
2717*6236dae4SAndroid Build Coastguard Worker
2718*6236dae4SAndroid Build Coastguard Worker case MSTATE_PROTOCONNECT:
2719*6236dae4SAndroid Build Coastguard Worker if(!result && data->conn->bits.reuse) {
2720*6236dae4SAndroid Build Coastguard Worker /* ftp seems to hang when protoconnect on reused connection since we
2721*6236dae4SAndroid Build Coastguard Worker * handle PROTOCONNECT in general inside the filers, it seems wrong to
2722*6236dae4SAndroid Build Coastguard Worker * restart this on a reused connection.
2723*6236dae4SAndroid Build Coastguard Worker */
2724*6236dae4SAndroid Build Coastguard Worker multistate(data, MSTATE_DO);
2725*6236dae4SAndroid Build Coastguard Worker rc = CURLM_CALL_MULTI_PERFORM;
2726*6236dae4SAndroid Build Coastguard Worker break;
2727*6236dae4SAndroid Build Coastguard Worker }
2728*6236dae4SAndroid Build Coastguard Worker if(!result)
2729*6236dae4SAndroid Build Coastguard Worker result = protocol_connect(data, &protocol_connected);
2730*6236dae4SAndroid Build Coastguard Worker if(!result && !protocol_connected) {
2731*6236dae4SAndroid Build Coastguard Worker /* switch to waiting state */
2732*6236dae4SAndroid Build Coastguard Worker multistate(data, MSTATE_PROTOCONNECTING);
2733*6236dae4SAndroid Build Coastguard Worker rc = CURLM_CALL_MULTI_PERFORM;
2734*6236dae4SAndroid Build Coastguard Worker }
2735*6236dae4SAndroid Build Coastguard Worker else if(!result) {
2736*6236dae4SAndroid Build Coastguard Worker /* protocol connect has completed, go WAITDO or DO */
2737*6236dae4SAndroid Build Coastguard Worker multistate(data, MSTATE_DO);
2738*6236dae4SAndroid Build Coastguard Worker rc = CURLM_CALL_MULTI_PERFORM;
2739*6236dae4SAndroid Build Coastguard Worker }
2740*6236dae4SAndroid Build Coastguard Worker else {
2741*6236dae4SAndroid Build Coastguard Worker /* failure detected */
2742*6236dae4SAndroid Build Coastguard Worker multi_posttransfer(data);
2743*6236dae4SAndroid Build Coastguard Worker multi_done(data, result, TRUE);
2744*6236dae4SAndroid Build Coastguard Worker stream_error = TRUE;
2745*6236dae4SAndroid Build Coastguard Worker }
2746*6236dae4SAndroid Build Coastguard Worker break;
2747*6236dae4SAndroid Build Coastguard Worker
2748*6236dae4SAndroid Build Coastguard Worker case MSTATE_PROTOCONNECTING:
2749*6236dae4SAndroid Build Coastguard Worker /* protocol-specific connect phase */
2750*6236dae4SAndroid Build Coastguard Worker result = protocol_connecting(data, &protocol_connected);
2751*6236dae4SAndroid Build Coastguard Worker if(!result && protocol_connected) {
2752*6236dae4SAndroid Build Coastguard Worker /* after the connect has completed, go WAITDO or DO */
2753*6236dae4SAndroid Build Coastguard Worker multistate(data, MSTATE_DO);
2754*6236dae4SAndroid Build Coastguard Worker rc = CURLM_CALL_MULTI_PERFORM;
2755*6236dae4SAndroid Build Coastguard Worker }
2756*6236dae4SAndroid Build Coastguard Worker else if(result) {
2757*6236dae4SAndroid Build Coastguard Worker /* failure detected */
2758*6236dae4SAndroid Build Coastguard Worker multi_posttransfer(data);
2759*6236dae4SAndroid Build Coastguard Worker multi_done(data, result, TRUE);
2760*6236dae4SAndroid Build Coastguard Worker stream_error = TRUE;
2761*6236dae4SAndroid Build Coastguard Worker }
2762*6236dae4SAndroid Build Coastguard Worker break;
2763*6236dae4SAndroid Build Coastguard Worker
2764*6236dae4SAndroid Build Coastguard Worker case MSTATE_DO:
2765*6236dae4SAndroid Build Coastguard Worker rc = state_do(data, &stream_error, &result);
2766*6236dae4SAndroid Build Coastguard Worker break;
2767*6236dae4SAndroid Build Coastguard Worker
2768*6236dae4SAndroid Build Coastguard Worker case MSTATE_DOING:
2769*6236dae4SAndroid Build Coastguard Worker /* we continue DOING until the DO phase is complete */
2770*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(data->conn);
2771*6236dae4SAndroid Build Coastguard Worker result = protocol_doing(data, &dophase_done);
2772*6236dae4SAndroid Build Coastguard Worker if(!result) {
2773*6236dae4SAndroid Build Coastguard Worker if(dophase_done) {
2774*6236dae4SAndroid Build Coastguard Worker /* after DO, go DO_DONE or DO_MORE */
2775*6236dae4SAndroid Build Coastguard Worker multistate(data, data->conn->bits.do_more ?
2776*6236dae4SAndroid Build Coastguard Worker MSTATE_DOING_MORE : MSTATE_DID);
2777*6236dae4SAndroid Build Coastguard Worker rc = CURLM_CALL_MULTI_PERFORM;
2778*6236dae4SAndroid Build Coastguard Worker } /* dophase_done */
2779*6236dae4SAndroid Build Coastguard Worker }
2780*6236dae4SAndroid Build Coastguard Worker else {
2781*6236dae4SAndroid Build Coastguard Worker /* failure detected */
2782*6236dae4SAndroid Build Coastguard Worker multi_posttransfer(data);
2783*6236dae4SAndroid Build Coastguard Worker multi_done(data, result, FALSE);
2784*6236dae4SAndroid Build Coastguard Worker stream_error = TRUE;
2785*6236dae4SAndroid Build Coastguard Worker }
2786*6236dae4SAndroid Build Coastguard Worker break;
2787*6236dae4SAndroid Build Coastguard Worker
2788*6236dae4SAndroid Build Coastguard Worker case MSTATE_DOING_MORE:
2789*6236dae4SAndroid Build Coastguard Worker /*
2790*6236dae4SAndroid Build Coastguard Worker * When we are connected, DOING MORE and then go DID
2791*6236dae4SAndroid Build Coastguard Worker */
2792*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(data->conn);
2793*6236dae4SAndroid Build Coastguard Worker result = multi_do_more(data, &control);
2794*6236dae4SAndroid Build Coastguard Worker
2795*6236dae4SAndroid Build Coastguard Worker if(!result) {
2796*6236dae4SAndroid Build Coastguard Worker if(control) {
2797*6236dae4SAndroid Build Coastguard Worker /* if positive, advance to DO_DONE
2798*6236dae4SAndroid Build Coastguard Worker if negative, go back to DOING */
2799*6236dae4SAndroid Build Coastguard Worker multistate(data, control == 1 ?
2800*6236dae4SAndroid Build Coastguard Worker MSTATE_DID : MSTATE_DOING);
2801*6236dae4SAndroid Build Coastguard Worker rc = CURLM_CALL_MULTI_PERFORM;
2802*6236dae4SAndroid Build Coastguard Worker }
2803*6236dae4SAndroid Build Coastguard Worker /* else
2804*6236dae4SAndroid Build Coastguard Worker stay in DO_MORE */
2805*6236dae4SAndroid Build Coastguard Worker }
2806*6236dae4SAndroid Build Coastguard Worker else {
2807*6236dae4SAndroid Build Coastguard Worker /* failure detected */
2808*6236dae4SAndroid Build Coastguard Worker multi_posttransfer(data);
2809*6236dae4SAndroid Build Coastguard Worker multi_done(data, result, FALSE);
2810*6236dae4SAndroid Build Coastguard Worker stream_error = TRUE;
2811*6236dae4SAndroid Build Coastguard Worker }
2812*6236dae4SAndroid Build Coastguard Worker break;
2813*6236dae4SAndroid Build Coastguard Worker
2814*6236dae4SAndroid Build Coastguard Worker case MSTATE_DID:
2815*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(data->conn);
2816*6236dae4SAndroid Build Coastguard Worker if(data->conn->bits.multiplex)
2817*6236dae4SAndroid Build Coastguard Worker /* Check if we can move pending requests to send pipe */
2818*6236dae4SAndroid Build Coastguard Worker process_pending_handles(multi); /* multiplexed */
2819*6236dae4SAndroid Build Coastguard Worker
2820*6236dae4SAndroid Build Coastguard Worker /* Only perform the transfer if there is a good socket to work with.
2821*6236dae4SAndroid Build Coastguard Worker Having both BAD is a signal to skip immediately to DONE */
2822*6236dae4SAndroid Build Coastguard Worker if((data->conn->sockfd != CURL_SOCKET_BAD) ||
2823*6236dae4SAndroid Build Coastguard Worker (data->conn->writesockfd != CURL_SOCKET_BAD))
2824*6236dae4SAndroid Build Coastguard Worker multistate(data, MSTATE_PERFORMING);
2825*6236dae4SAndroid Build Coastguard Worker else {
2826*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_FTP
2827*6236dae4SAndroid Build Coastguard Worker if(data->state.wildcardmatch &&
2828*6236dae4SAndroid Build Coastguard Worker ((data->conn->handler->flags & PROTOPT_WILDCARD) == 0)) {
2829*6236dae4SAndroid Build Coastguard Worker data->wildcard->state = CURLWC_DONE;
2830*6236dae4SAndroid Build Coastguard Worker }
2831*6236dae4SAndroid Build Coastguard Worker #endif
2832*6236dae4SAndroid Build Coastguard Worker multistate(data, MSTATE_DONE);
2833*6236dae4SAndroid Build Coastguard Worker }
2834*6236dae4SAndroid Build Coastguard Worker rc = CURLM_CALL_MULTI_PERFORM;
2835*6236dae4SAndroid Build Coastguard Worker break;
2836*6236dae4SAndroid Build Coastguard Worker
2837*6236dae4SAndroid Build Coastguard Worker case MSTATE_RATELIMITING: /* limit-rate exceeded in either direction */
2838*6236dae4SAndroid Build Coastguard Worker rc = state_ratelimiting(data, nowp, &result);
2839*6236dae4SAndroid Build Coastguard Worker break;
2840*6236dae4SAndroid Build Coastguard Worker
2841*6236dae4SAndroid Build Coastguard Worker case MSTATE_PERFORMING:
2842*6236dae4SAndroid Build Coastguard Worker rc = state_performing(data, nowp, &stream_error, &result);
2843*6236dae4SAndroid Build Coastguard Worker break;
2844*6236dae4SAndroid Build Coastguard Worker
2845*6236dae4SAndroid Build Coastguard Worker case MSTATE_DONE:
2846*6236dae4SAndroid Build Coastguard Worker /* this state is highly transient, so run another loop after this */
2847*6236dae4SAndroid Build Coastguard Worker rc = CURLM_CALL_MULTI_PERFORM;
2848*6236dae4SAndroid Build Coastguard Worker
2849*6236dae4SAndroid Build Coastguard Worker if(data->conn) {
2850*6236dae4SAndroid Build Coastguard Worker CURLcode res;
2851*6236dae4SAndroid Build Coastguard Worker
2852*6236dae4SAndroid Build Coastguard Worker /* post-transfer command */
2853*6236dae4SAndroid Build Coastguard Worker res = multi_done(data, result, FALSE);
2854*6236dae4SAndroid Build Coastguard Worker
2855*6236dae4SAndroid Build Coastguard Worker /* allow a previously set error code take precedence */
2856*6236dae4SAndroid Build Coastguard Worker if(!result)
2857*6236dae4SAndroid Build Coastguard Worker result = res;
2858*6236dae4SAndroid Build Coastguard Worker }
2859*6236dae4SAndroid Build Coastguard Worker
2860*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_FTP
2861*6236dae4SAndroid Build Coastguard Worker if(data->state.wildcardmatch) {
2862*6236dae4SAndroid Build Coastguard Worker if(data->wildcard->state != CURLWC_DONE) {
2863*6236dae4SAndroid Build Coastguard Worker /* if a wildcard is set and we are not ending -> lets start again
2864*6236dae4SAndroid Build Coastguard Worker with MSTATE_INIT */
2865*6236dae4SAndroid Build Coastguard Worker multistate(data, MSTATE_INIT);
2866*6236dae4SAndroid Build Coastguard Worker break;
2867*6236dae4SAndroid Build Coastguard Worker }
2868*6236dae4SAndroid Build Coastguard Worker }
2869*6236dae4SAndroid Build Coastguard Worker #endif
2870*6236dae4SAndroid Build Coastguard Worker /* after we have DONE what we are supposed to do, go COMPLETED, and
2871*6236dae4SAndroid Build Coastguard Worker it does not matter what the multi_done() returned! */
2872*6236dae4SAndroid Build Coastguard Worker multistate(data, MSTATE_COMPLETED);
2873*6236dae4SAndroid Build Coastguard Worker break;
2874*6236dae4SAndroid Build Coastguard Worker
2875*6236dae4SAndroid Build Coastguard Worker case MSTATE_COMPLETED:
2876*6236dae4SAndroid Build Coastguard Worker break;
2877*6236dae4SAndroid Build Coastguard Worker
2878*6236dae4SAndroid Build Coastguard Worker case MSTATE_PENDING:
2879*6236dae4SAndroid Build Coastguard Worker case MSTATE_MSGSENT:
2880*6236dae4SAndroid Build Coastguard Worker /* handles in these states should NOT be in this list */
2881*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(0);
2882*6236dae4SAndroid Build Coastguard Worker break;
2883*6236dae4SAndroid Build Coastguard Worker
2884*6236dae4SAndroid Build Coastguard Worker default:
2885*6236dae4SAndroid Build Coastguard Worker return CURLM_INTERNAL_ERROR;
2886*6236dae4SAndroid Build Coastguard Worker }
2887*6236dae4SAndroid Build Coastguard Worker
2888*6236dae4SAndroid Build Coastguard Worker if(data->mstate >= MSTATE_CONNECT &&
2889*6236dae4SAndroid Build Coastguard Worker data->mstate < MSTATE_DO &&
2890*6236dae4SAndroid Build Coastguard Worker rc != CURLM_CALL_MULTI_PERFORM &&
2891*6236dae4SAndroid Build Coastguard Worker !multi_ischanged(multi, FALSE)) {
2892*6236dae4SAndroid Build Coastguard Worker /* We now handle stream timeouts if and only if this will be the last
2893*6236dae4SAndroid Build Coastguard Worker * loop iteration. We only check this on the last iteration to ensure
2894*6236dae4SAndroid Build Coastguard Worker * that if we know we have additional work to do immediately
2895*6236dae4SAndroid Build Coastguard Worker * (i.e. CURLM_CALL_MULTI_PERFORM == TRUE) then we should do that before
2896*6236dae4SAndroid Build Coastguard Worker * declaring the connection timed out as we may almost have a completed
2897*6236dae4SAndroid Build Coastguard Worker * connection. */
2898*6236dae4SAndroid Build Coastguard Worker multi_handle_timeout(data, nowp, &stream_error, &result);
2899*6236dae4SAndroid Build Coastguard Worker }
2900*6236dae4SAndroid Build Coastguard Worker
2901*6236dae4SAndroid Build Coastguard Worker statemachine_end:
2902*6236dae4SAndroid Build Coastguard Worker
2903*6236dae4SAndroid Build Coastguard Worker if(data->mstate < MSTATE_COMPLETED) {
2904*6236dae4SAndroid Build Coastguard Worker if(result) {
2905*6236dae4SAndroid Build Coastguard Worker /*
2906*6236dae4SAndroid Build Coastguard Worker * If an error was returned, and we are not in completed state now,
2907*6236dae4SAndroid Build Coastguard Worker * then we go to completed and consider this transfer aborted.
2908*6236dae4SAndroid Build Coastguard Worker */
2909*6236dae4SAndroid Build Coastguard Worker
2910*6236dae4SAndroid Build Coastguard Worker /* NOTE: no attempt to disconnect connections must be made
2911*6236dae4SAndroid Build Coastguard Worker in the case blocks above - cleanup happens only here */
2912*6236dae4SAndroid Build Coastguard Worker
2913*6236dae4SAndroid Build Coastguard Worker /* Check if we can move pending requests to send pipe */
2914*6236dae4SAndroid Build Coastguard Worker process_pending_handles(multi); /* connection */
2915*6236dae4SAndroid Build Coastguard Worker
2916*6236dae4SAndroid Build Coastguard Worker if(data->conn) {
2917*6236dae4SAndroid Build Coastguard Worker if(stream_error) {
2918*6236dae4SAndroid Build Coastguard Worker /* Do not attempt to send data over a connection that timed out */
2919*6236dae4SAndroid Build Coastguard Worker bool dead_connection = result == CURLE_OPERATION_TIMEDOUT;
2920*6236dae4SAndroid Build Coastguard Worker struct connectdata *conn = data->conn;
2921*6236dae4SAndroid Build Coastguard Worker
2922*6236dae4SAndroid Build Coastguard Worker /* This is where we make sure that the conn pointer is reset.
2923*6236dae4SAndroid Build Coastguard Worker We do not have to do this in every case block above where a
2924*6236dae4SAndroid Build Coastguard Worker failure is detected */
2925*6236dae4SAndroid Build Coastguard Worker Curl_detach_connection(data);
2926*6236dae4SAndroid Build Coastguard Worker Curl_cpool_disconnect(data, conn, dead_connection);
2927*6236dae4SAndroid Build Coastguard Worker }
2928*6236dae4SAndroid Build Coastguard Worker }
2929*6236dae4SAndroid Build Coastguard Worker else if(data->mstate == MSTATE_CONNECT) {
2930*6236dae4SAndroid Build Coastguard Worker /* Curl_connect() failed */
2931*6236dae4SAndroid Build Coastguard Worker multi_posttransfer(data);
2932*6236dae4SAndroid Build Coastguard Worker Curl_pgrsUpdate_nometer(data);
2933*6236dae4SAndroid Build Coastguard Worker }
2934*6236dae4SAndroid Build Coastguard Worker
2935*6236dae4SAndroid Build Coastguard Worker multistate(data, MSTATE_COMPLETED);
2936*6236dae4SAndroid Build Coastguard Worker rc = CURLM_CALL_MULTI_PERFORM;
2937*6236dae4SAndroid Build Coastguard Worker }
2938*6236dae4SAndroid Build Coastguard Worker /* if there is still a connection to use, call the progress function */
2939*6236dae4SAndroid Build Coastguard Worker else if(data->conn && Curl_pgrsUpdate(data)) {
2940*6236dae4SAndroid Build Coastguard Worker /* aborted due to progress callback return code must close the
2941*6236dae4SAndroid Build Coastguard Worker connection */
2942*6236dae4SAndroid Build Coastguard Worker result = CURLE_ABORTED_BY_CALLBACK;
2943*6236dae4SAndroid Build Coastguard Worker streamclose(data->conn, "Aborted by callback");
2944*6236dae4SAndroid Build Coastguard Worker
2945*6236dae4SAndroid Build Coastguard Worker /* if not yet in DONE state, go there, otherwise COMPLETED */
2946*6236dae4SAndroid Build Coastguard Worker multistate(data, (data->mstate < MSTATE_DONE) ?
2947*6236dae4SAndroid Build Coastguard Worker MSTATE_DONE : MSTATE_COMPLETED);
2948*6236dae4SAndroid Build Coastguard Worker rc = CURLM_CALL_MULTI_PERFORM;
2949*6236dae4SAndroid Build Coastguard Worker }
2950*6236dae4SAndroid Build Coastguard Worker }
2951*6236dae4SAndroid Build Coastguard Worker
2952*6236dae4SAndroid Build Coastguard Worker if(MSTATE_COMPLETED == data->mstate) {
2953*6236dae4SAndroid Build Coastguard Worker if(data->set.fmultidone) {
2954*6236dae4SAndroid Build Coastguard Worker /* signal via callback instead */
2955*6236dae4SAndroid Build Coastguard Worker data->set.fmultidone(data, result);
2956*6236dae4SAndroid Build Coastguard Worker }
2957*6236dae4SAndroid Build Coastguard Worker else {
2958*6236dae4SAndroid Build Coastguard Worker /* now fill in the Curl_message with this info */
2959*6236dae4SAndroid Build Coastguard Worker msg = &data->msg;
2960*6236dae4SAndroid Build Coastguard Worker
2961*6236dae4SAndroid Build Coastguard Worker msg->extmsg.msg = CURLMSG_DONE;
2962*6236dae4SAndroid Build Coastguard Worker msg->extmsg.easy_handle = data;
2963*6236dae4SAndroid Build Coastguard Worker msg->extmsg.data.result = result;
2964*6236dae4SAndroid Build Coastguard Worker
2965*6236dae4SAndroid Build Coastguard Worker multi_addmsg(multi, msg);
2966*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(!data->conn);
2967*6236dae4SAndroid Build Coastguard Worker }
2968*6236dae4SAndroid Build Coastguard Worker multistate(data, MSTATE_MSGSENT);
2969*6236dae4SAndroid Build Coastguard Worker
2970*6236dae4SAndroid Build Coastguard Worker /* unlink from the process list */
2971*6236dae4SAndroid Build Coastguard Worker Curl_node_remove(&data->multi_queue);
2972*6236dae4SAndroid Build Coastguard Worker /* add this handle msgsent list */
2973*6236dae4SAndroid Build Coastguard Worker Curl_llist_append(&multi->msgsent, data, &data->multi_queue);
2974*6236dae4SAndroid Build Coastguard Worker return CURLM_OK;
2975*6236dae4SAndroid Build Coastguard Worker }
2976*6236dae4SAndroid Build Coastguard Worker } while((rc == CURLM_CALL_MULTI_PERFORM) || multi_ischanged(multi, FALSE));
2977*6236dae4SAndroid Build Coastguard Worker
2978*6236dae4SAndroid Build Coastguard Worker data->result = result;
2979*6236dae4SAndroid Build Coastguard Worker return rc;
2980*6236dae4SAndroid Build Coastguard Worker }
2981*6236dae4SAndroid Build Coastguard Worker
2982*6236dae4SAndroid Build Coastguard Worker
2983*6236dae4SAndroid Build Coastguard Worker CURLMcode curl_multi_perform(CURLM *m, int *running_handles)
2984*6236dae4SAndroid Build Coastguard Worker {
2985*6236dae4SAndroid Build Coastguard Worker CURLMcode returncode = CURLM_OK;
2986*6236dae4SAndroid Build Coastguard Worker struct Curl_tree *t = NULL;
2987*6236dae4SAndroid Build Coastguard Worker struct curltime now = Curl_now();
2988*6236dae4SAndroid Build Coastguard Worker struct Curl_llist_node *e;
2989*6236dae4SAndroid Build Coastguard Worker struct Curl_llist_node *n = NULL;
2990*6236dae4SAndroid Build Coastguard Worker struct Curl_multi *multi = m;
2991*6236dae4SAndroid Build Coastguard Worker SIGPIPE_VARIABLE(pipe_st);
2992*6236dae4SAndroid Build Coastguard Worker
2993*6236dae4SAndroid Build Coastguard Worker if(!GOOD_MULTI_HANDLE(multi))
2994*6236dae4SAndroid Build Coastguard Worker return CURLM_BAD_HANDLE;
2995*6236dae4SAndroid Build Coastguard Worker
2996*6236dae4SAndroid Build Coastguard Worker if(multi->in_callback)
2997*6236dae4SAndroid Build Coastguard Worker return CURLM_RECURSIVE_API_CALL;
2998*6236dae4SAndroid Build Coastguard Worker
2999*6236dae4SAndroid Build Coastguard Worker sigpipe_init(&pipe_st);
3000*6236dae4SAndroid Build Coastguard Worker for(e = Curl_llist_head(&multi->process); e; e = n) {
3001*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data = Curl_node_elem(e);
3002*6236dae4SAndroid Build Coastguard Worker CURLMcode result;
3003*6236dae4SAndroid Build Coastguard Worker /* Do the loop and only alter the signal ignore state if the next handle
3004*6236dae4SAndroid Build Coastguard Worker has a different NO_SIGNAL state than the previous */
3005*6236dae4SAndroid Build Coastguard Worker
3006*6236dae4SAndroid Build Coastguard Worker /* the current node might be unlinked in multi_runsingle(), get the next
3007*6236dae4SAndroid Build Coastguard Worker pointer now */
3008*6236dae4SAndroid Build Coastguard Worker n = Curl_node_next(e);
3009*6236dae4SAndroid Build Coastguard Worker
3010*6236dae4SAndroid Build Coastguard Worker if(data != multi->cpool.idata) {
3011*6236dae4SAndroid Build Coastguard Worker /* connection pool handle is processed below */
3012*6236dae4SAndroid Build Coastguard Worker sigpipe_apply(data, &pipe_st);
3013*6236dae4SAndroid Build Coastguard Worker result = multi_runsingle(multi, &now, data);
3014*6236dae4SAndroid Build Coastguard Worker if(result)
3015*6236dae4SAndroid Build Coastguard Worker returncode = result;
3016*6236dae4SAndroid Build Coastguard Worker }
3017*6236dae4SAndroid Build Coastguard Worker }
3018*6236dae4SAndroid Build Coastguard Worker
3019*6236dae4SAndroid Build Coastguard Worker sigpipe_apply(multi->cpool.idata, &pipe_st);
3020*6236dae4SAndroid Build Coastguard Worker Curl_cpool_multi_perform(multi);
3021*6236dae4SAndroid Build Coastguard Worker
3022*6236dae4SAndroid Build Coastguard Worker sigpipe_restore(&pipe_st);
3023*6236dae4SAndroid Build Coastguard Worker
3024*6236dae4SAndroid Build Coastguard Worker /*
3025*6236dae4SAndroid Build Coastguard Worker * Simply remove all expired timers from the splay since handles are dealt
3026*6236dae4SAndroid Build Coastguard Worker * with unconditionally by this function and curl_multi_timeout() requires
3027*6236dae4SAndroid Build Coastguard Worker * that already passed/handled expire times are removed from the splay.
3028*6236dae4SAndroid Build Coastguard Worker *
3029*6236dae4SAndroid Build Coastguard Worker * It is important that the 'now' value is set at the entry of this function
3030*6236dae4SAndroid Build Coastguard Worker * and not for the current time as it may have ticked a little while since
3031*6236dae4SAndroid Build Coastguard Worker * then and then we risk this loop to remove timers that actually have not
3032*6236dae4SAndroid Build Coastguard Worker * been handled!
3033*6236dae4SAndroid Build Coastguard Worker */
3034*6236dae4SAndroid Build Coastguard Worker do {
3035*6236dae4SAndroid Build Coastguard Worker multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
3036*6236dae4SAndroid Build Coastguard Worker if(t) {
3037*6236dae4SAndroid Build Coastguard Worker /* the removed may have another timeout in queue */
3038*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data = Curl_splayget(t);
3039*6236dae4SAndroid Build Coastguard Worker if(data->mstate == MSTATE_PENDING) {
3040*6236dae4SAndroid Build Coastguard Worker bool stream_unused;
3041*6236dae4SAndroid Build Coastguard Worker CURLcode result_unused;
3042*6236dae4SAndroid Build Coastguard Worker if(multi_handle_timeout(data, &now, &stream_unused, &result_unused)) {
3043*6236dae4SAndroid Build Coastguard Worker infof(data, "PENDING handle timeout");
3044*6236dae4SAndroid Build Coastguard Worker move_pending_to_connect(multi, data);
3045*6236dae4SAndroid Build Coastguard Worker }
3046*6236dae4SAndroid Build Coastguard Worker }
3047*6236dae4SAndroid Build Coastguard Worker (void)add_next_timeout(now, multi, Curl_splayget(t));
3048*6236dae4SAndroid Build Coastguard Worker }
3049*6236dae4SAndroid Build Coastguard Worker } while(t);
3050*6236dae4SAndroid Build Coastguard Worker
3051*6236dae4SAndroid Build Coastguard Worker if(running_handles)
3052*6236dae4SAndroid Build Coastguard Worker *running_handles = (int)multi->num_alive;
3053*6236dae4SAndroid Build Coastguard Worker
3054*6236dae4SAndroid Build Coastguard Worker if(CURLM_OK >= returncode)
3055*6236dae4SAndroid Build Coastguard Worker returncode = Curl_update_timer(multi);
3056*6236dae4SAndroid Build Coastguard Worker
3057*6236dae4SAndroid Build Coastguard Worker return returncode;
3058*6236dae4SAndroid Build Coastguard Worker }
3059*6236dae4SAndroid Build Coastguard Worker
3060*6236dae4SAndroid Build Coastguard Worker /* unlink_all_msgsent_handles() moves all nodes back from the msgsent list to
3061*6236dae4SAndroid Build Coastguard Worker the process list */
3062*6236dae4SAndroid Build Coastguard Worker static void unlink_all_msgsent_handles(struct Curl_multi *multi)
3063*6236dae4SAndroid Build Coastguard Worker {
3064*6236dae4SAndroid Build Coastguard Worker struct Curl_llist_node *e;
3065*6236dae4SAndroid Build Coastguard Worker for(e = Curl_llist_head(&multi->msgsent); e; e = Curl_node_next(e)) {
3066*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data = Curl_node_elem(e);
3067*6236dae4SAndroid Build Coastguard Worker if(data) {
3068*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(data->mstate == MSTATE_MSGSENT);
3069*6236dae4SAndroid Build Coastguard Worker Curl_node_remove(&data->multi_queue);
3070*6236dae4SAndroid Build Coastguard Worker /* put it into the process list */
3071*6236dae4SAndroid Build Coastguard Worker Curl_llist_append(&multi->process, data, &data->multi_queue);
3072*6236dae4SAndroid Build Coastguard Worker }
3073*6236dae4SAndroid Build Coastguard Worker }
3074*6236dae4SAndroid Build Coastguard Worker }
3075*6236dae4SAndroid Build Coastguard Worker
3076*6236dae4SAndroid Build Coastguard Worker CURLMcode curl_multi_cleanup(CURLM *m)
3077*6236dae4SAndroid Build Coastguard Worker {
3078*6236dae4SAndroid Build Coastguard Worker struct Curl_multi *multi = m;
3079*6236dae4SAndroid Build Coastguard Worker if(GOOD_MULTI_HANDLE(multi)) {
3080*6236dae4SAndroid Build Coastguard Worker struct Curl_llist_node *e;
3081*6236dae4SAndroid Build Coastguard Worker struct Curl_llist_node *n;
3082*6236dae4SAndroid Build Coastguard Worker if(multi->in_callback)
3083*6236dae4SAndroid Build Coastguard Worker return CURLM_RECURSIVE_API_CALL;
3084*6236dae4SAndroid Build Coastguard Worker
3085*6236dae4SAndroid Build Coastguard Worker /* move the pending and msgsent entries back to process
3086*6236dae4SAndroid Build Coastguard Worker so that there is just one list to iterate over */
3087*6236dae4SAndroid Build Coastguard Worker unlink_all_msgsent_handles(multi);
3088*6236dae4SAndroid Build Coastguard Worker process_pending_handles(multi);
3089*6236dae4SAndroid Build Coastguard Worker
3090*6236dae4SAndroid Build Coastguard Worker /* First remove all remaining easy handles */
3091*6236dae4SAndroid Build Coastguard Worker for(e = Curl_llist_head(&multi->process); e; e = n) {
3092*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data = Curl_node_elem(e);
3093*6236dae4SAndroid Build Coastguard Worker
3094*6236dae4SAndroid Build Coastguard Worker if(!GOOD_EASY_HANDLE(data))
3095*6236dae4SAndroid Build Coastguard Worker return CURLM_BAD_HANDLE;
3096*6236dae4SAndroid Build Coastguard Worker
3097*6236dae4SAndroid Build Coastguard Worker n = Curl_node_next(e);
3098*6236dae4SAndroid Build Coastguard Worker if(!data->state.done && data->conn)
3099*6236dae4SAndroid Build Coastguard Worker /* if DONE was never called for this handle */
3100*6236dae4SAndroid Build Coastguard Worker (void)multi_done(data, CURLE_OK, TRUE);
3101*6236dae4SAndroid Build Coastguard Worker if(data->dns.hostcachetype == HCACHE_MULTI) {
3102*6236dae4SAndroid Build Coastguard Worker /* clear out the usage of the shared DNS cache */
3103*6236dae4SAndroid Build Coastguard Worker Curl_hostcache_clean(data, data->dns.hostcache);
3104*6236dae4SAndroid Build Coastguard Worker data->dns.hostcache = NULL;
3105*6236dae4SAndroid Build Coastguard Worker data->dns.hostcachetype = HCACHE_NONE;
3106*6236dae4SAndroid Build Coastguard Worker }
3107*6236dae4SAndroid Build Coastguard Worker
3108*6236dae4SAndroid Build Coastguard Worker data->multi = NULL; /* clear the association */
3109*6236dae4SAndroid Build Coastguard Worker
3110*6236dae4SAndroid Build Coastguard Worker #ifdef USE_LIBPSL
3111*6236dae4SAndroid Build Coastguard Worker if(data->psl == &multi->psl)
3112*6236dae4SAndroid Build Coastguard Worker data->psl = NULL;
3113*6236dae4SAndroid Build Coastguard Worker #endif
3114*6236dae4SAndroid Build Coastguard Worker }
3115*6236dae4SAndroid Build Coastguard Worker
3116*6236dae4SAndroid Build Coastguard Worker Curl_cpool_destroy(&multi->cpool);
3117*6236dae4SAndroid Build Coastguard Worker
3118*6236dae4SAndroid Build Coastguard Worker multi->magic = 0; /* not good anymore */
3119*6236dae4SAndroid Build Coastguard Worker
3120*6236dae4SAndroid Build Coastguard Worker sockhash_destroy(&multi->sockhash);
3121*6236dae4SAndroid Build Coastguard Worker Curl_hash_destroy(&multi->proto_hash);
3122*6236dae4SAndroid Build Coastguard Worker Curl_hash_destroy(&multi->hostcache);
3123*6236dae4SAndroid Build Coastguard Worker Curl_psl_destroy(&multi->psl);
3124*6236dae4SAndroid Build Coastguard Worker
3125*6236dae4SAndroid Build Coastguard Worker #ifdef USE_WINSOCK
3126*6236dae4SAndroid Build Coastguard Worker WSACloseEvent(multi->wsa_event);
3127*6236dae4SAndroid Build Coastguard Worker #else
3128*6236dae4SAndroid Build Coastguard Worker #ifdef ENABLE_WAKEUP
3129*6236dae4SAndroid Build Coastguard Worker wakeup_close(multi->wakeup_pair[0]);
3130*6236dae4SAndroid Build Coastguard Worker #ifndef USE_EVENTFD
3131*6236dae4SAndroid Build Coastguard Worker wakeup_close(multi->wakeup_pair[1]);
3132*6236dae4SAndroid Build Coastguard Worker #endif
3133*6236dae4SAndroid Build Coastguard Worker #endif
3134*6236dae4SAndroid Build Coastguard Worker #endif
3135*6236dae4SAndroid Build Coastguard Worker
3136*6236dae4SAndroid Build Coastguard Worker multi_xfer_bufs_free(multi);
3137*6236dae4SAndroid Build Coastguard Worker free(multi);
3138*6236dae4SAndroid Build Coastguard Worker
3139*6236dae4SAndroid Build Coastguard Worker return CURLM_OK;
3140*6236dae4SAndroid Build Coastguard Worker }
3141*6236dae4SAndroid Build Coastguard Worker return CURLM_BAD_HANDLE;
3142*6236dae4SAndroid Build Coastguard Worker }
3143*6236dae4SAndroid Build Coastguard Worker
3144*6236dae4SAndroid Build Coastguard Worker /*
3145*6236dae4SAndroid Build Coastguard Worker * curl_multi_info_read()
3146*6236dae4SAndroid Build Coastguard Worker *
3147*6236dae4SAndroid Build Coastguard Worker * This function is the primary way for a multi/multi_socket application to
3148*6236dae4SAndroid Build Coastguard Worker * figure out if a transfer has ended. We MUST make this function as fast as
3149*6236dae4SAndroid Build Coastguard Worker * possible as it will be polled frequently and we MUST NOT scan any lists in
3150*6236dae4SAndroid Build Coastguard Worker * here to figure out things. We must scale fine to thousands of handles and
3151*6236dae4SAndroid Build Coastguard Worker * beyond. The current design is fully O(1).
3152*6236dae4SAndroid Build Coastguard Worker */
3153*6236dae4SAndroid Build Coastguard Worker
3154*6236dae4SAndroid Build Coastguard Worker CURLMsg *curl_multi_info_read(CURLM *m, int *msgs_in_queue)
3155*6236dae4SAndroid Build Coastguard Worker {
3156*6236dae4SAndroid Build Coastguard Worker struct Curl_message *msg;
3157*6236dae4SAndroid Build Coastguard Worker struct Curl_multi *multi = m;
3158*6236dae4SAndroid Build Coastguard Worker
3159*6236dae4SAndroid Build Coastguard Worker *msgs_in_queue = 0; /* default to none */
3160*6236dae4SAndroid Build Coastguard Worker
3161*6236dae4SAndroid Build Coastguard Worker if(GOOD_MULTI_HANDLE(multi) &&
3162*6236dae4SAndroid Build Coastguard Worker !multi->in_callback &&
3163*6236dae4SAndroid Build Coastguard Worker Curl_llist_count(&multi->msglist)) {
3164*6236dae4SAndroid Build Coastguard Worker /* there is one or more messages in the list */
3165*6236dae4SAndroid Build Coastguard Worker struct Curl_llist_node *e;
3166*6236dae4SAndroid Build Coastguard Worker
3167*6236dae4SAndroid Build Coastguard Worker /* extract the head of the list to return */
3168*6236dae4SAndroid Build Coastguard Worker e = Curl_llist_head(&multi->msglist);
3169*6236dae4SAndroid Build Coastguard Worker
3170*6236dae4SAndroid Build Coastguard Worker msg = Curl_node_elem(e);
3171*6236dae4SAndroid Build Coastguard Worker
3172*6236dae4SAndroid Build Coastguard Worker /* remove the extracted entry */
3173*6236dae4SAndroid Build Coastguard Worker Curl_node_remove(e);
3174*6236dae4SAndroid Build Coastguard Worker
3175*6236dae4SAndroid Build Coastguard Worker *msgs_in_queue = curlx_uztosi(Curl_llist_count(&multi->msglist));
3176*6236dae4SAndroid Build Coastguard Worker
3177*6236dae4SAndroid Build Coastguard Worker return &msg->extmsg;
3178*6236dae4SAndroid Build Coastguard Worker }
3179*6236dae4SAndroid Build Coastguard Worker return NULL;
3180*6236dae4SAndroid Build Coastguard Worker }
3181*6236dae4SAndroid Build Coastguard Worker
3182*6236dae4SAndroid Build Coastguard Worker /*
3183*6236dae4SAndroid Build Coastguard Worker * singlesocket() checks what sockets we deal with and their "action state"
3184*6236dae4SAndroid Build Coastguard Worker * and if we have a different state in any of those sockets from last time we
3185*6236dae4SAndroid Build Coastguard Worker * call the callback accordingly.
3186*6236dae4SAndroid Build Coastguard Worker */
3187*6236dae4SAndroid Build Coastguard Worker static CURLMcode singlesocket(struct Curl_multi *multi,
3188*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data)
3189*6236dae4SAndroid Build Coastguard Worker {
3190*6236dae4SAndroid Build Coastguard Worker struct easy_pollset cur_poll;
3191*6236dae4SAndroid Build Coastguard Worker CURLMcode mresult;
3192*6236dae4SAndroid Build Coastguard Worker
3193*6236dae4SAndroid Build Coastguard Worker /* Fill in the 'current' struct with the state as it is now: what sockets to
3194*6236dae4SAndroid Build Coastguard Worker supervise and for what actions */
3195*6236dae4SAndroid Build Coastguard Worker multi_getsock(data, &cur_poll);
3196*6236dae4SAndroid Build Coastguard Worker mresult = Curl_multi_pollset_ev(multi, data, &cur_poll, &data->last_poll);
3197*6236dae4SAndroid Build Coastguard Worker
3198*6236dae4SAndroid Build Coastguard Worker if(!mresult) /* Remember for next time */
3199*6236dae4SAndroid Build Coastguard Worker memcpy(&data->last_poll, &cur_poll, sizeof(cur_poll));
3200*6236dae4SAndroid Build Coastguard Worker return mresult;
3201*6236dae4SAndroid Build Coastguard Worker }
3202*6236dae4SAndroid Build Coastguard Worker
3203*6236dae4SAndroid Build Coastguard Worker CURLMcode Curl_multi_pollset_ev(struct Curl_multi *multi,
3204*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data,
3205*6236dae4SAndroid Build Coastguard Worker struct easy_pollset *ps,
3206*6236dae4SAndroid Build Coastguard Worker struct easy_pollset *last_ps)
3207*6236dae4SAndroid Build Coastguard Worker {
3208*6236dae4SAndroid Build Coastguard Worker unsigned int i;
3209*6236dae4SAndroid Build Coastguard Worker struct Curl_sh_entry *entry;
3210*6236dae4SAndroid Build Coastguard Worker curl_socket_t s;
3211*6236dae4SAndroid Build Coastguard Worker int rc;
3212*6236dae4SAndroid Build Coastguard Worker
3213*6236dae4SAndroid Build Coastguard Worker /* We have 0 .. N sockets already and we get to know about the 0 .. M
3214*6236dae4SAndroid Build Coastguard Worker sockets we should have from now on. Detect the differences, remove no
3215*6236dae4SAndroid Build Coastguard Worker longer supervised ones and add new ones */
3216*6236dae4SAndroid Build Coastguard Worker
3217*6236dae4SAndroid Build Coastguard Worker /* walk over the sockets we got right now */
3218*6236dae4SAndroid Build Coastguard Worker for(i = 0; i < ps->num; i++) {
3219*6236dae4SAndroid Build Coastguard Worker unsigned char cur_action = ps->actions[i];
3220*6236dae4SAndroid Build Coastguard Worker unsigned char last_action = 0;
3221*6236dae4SAndroid Build Coastguard Worker int comboaction;
3222*6236dae4SAndroid Build Coastguard Worker
3223*6236dae4SAndroid Build Coastguard Worker s = ps->sockets[i];
3224*6236dae4SAndroid Build Coastguard Worker
3225*6236dae4SAndroid Build Coastguard Worker /* get it from the hash */
3226*6236dae4SAndroid Build Coastguard Worker entry = sh_getentry(&multi->sockhash, s);
3227*6236dae4SAndroid Build Coastguard Worker if(entry) {
3228*6236dae4SAndroid Build Coastguard Worker /* check if new for this transfer */
3229*6236dae4SAndroid Build Coastguard Worker unsigned int j;
3230*6236dae4SAndroid Build Coastguard Worker for(j = 0; j < last_ps->num; j++) {
3231*6236dae4SAndroid Build Coastguard Worker if(s == last_ps->sockets[j]) {
3232*6236dae4SAndroid Build Coastguard Worker last_action = last_ps->actions[j];
3233*6236dae4SAndroid Build Coastguard Worker break;
3234*6236dae4SAndroid Build Coastguard Worker }
3235*6236dae4SAndroid Build Coastguard Worker }
3236*6236dae4SAndroid Build Coastguard Worker }
3237*6236dae4SAndroid Build Coastguard Worker else {
3238*6236dae4SAndroid Build Coastguard Worker /* this is a socket we did not have before, add it to the hash! */
3239*6236dae4SAndroid Build Coastguard Worker entry = sh_addentry(&multi->sockhash, s);
3240*6236dae4SAndroid Build Coastguard Worker if(!entry)
3241*6236dae4SAndroid Build Coastguard Worker /* fatal */
3242*6236dae4SAndroid Build Coastguard Worker return CURLM_OUT_OF_MEMORY;
3243*6236dae4SAndroid Build Coastguard Worker }
3244*6236dae4SAndroid Build Coastguard Worker if(last_action && (last_action != cur_action)) {
3245*6236dae4SAndroid Build Coastguard Worker /* Socket was used already, but different action now */
3246*6236dae4SAndroid Build Coastguard Worker if(last_action & CURL_POLL_IN) {
3247*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(entry->readers);
3248*6236dae4SAndroid Build Coastguard Worker entry->readers--;
3249*6236dae4SAndroid Build Coastguard Worker }
3250*6236dae4SAndroid Build Coastguard Worker if(last_action & CURL_POLL_OUT) {
3251*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(entry->writers);
3252*6236dae4SAndroid Build Coastguard Worker entry->writers--;
3253*6236dae4SAndroid Build Coastguard Worker }
3254*6236dae4SAndroid Build Coastguard Worker if(cur_action & CURL_POLL_IN) {
3255*6236dae4SAndroid Build Coastguard Worker entry->readers++;
3256*6236dae4SAndroid Build Coastguard Worker }
3257*6236dae4SAndroid Build Coastguard Worker if(cur_action & CURL_POLL_OUT)
3258*6236dae4SAndroid Build Coastguard Worker entry->writers++;
3259*6236dae4SAndroid Build Coastguard Worker }
3260*6236dae4SAndroid Build Coastguard Worker else if(!last_action &&
3261*6236dae4SAndroid Build Coastguard Worker !Curl_hash_pick(&entry->transfers, (char *)&data, /* hash key */
3262*6236dae4SAndroid Build Coastguard Worker sizeof(struct Curl_easy *))) {
3263*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(entry->users < 100000); /* detect weird values */
3264*6236dae4SAndroid Build Coastguard Worker /* a new transfer using this socket */
3265*6236dae4SAndroid Build Coastguard Worker entry->users++;
3266*6236dae4SAndroid Build Coastguard Worker if(cur_action & CURL_POLL_IN)
3267*6236dae4SAndroid Build Coastguard Worker entry->readers++;
3268*6236dae4SAndroid Build Coastguard Worker if(cur_action & CURL_POLL_OUT)
3269*6236dae4SAndroid Build Coastguard Worker entry->writers++;
3270*6236dae4SAndroid Build Coastguard Worker /* add 'data' to the transfer hash on this socket! */
3271*6236dae4SAndroid Build Coastguard Worker if(!Curl_hash_add(&entry->transfers, (char *)&data, /* hash key */
3272*6236dae4SAndroid Build Coastguard Worker sizeof(struct Curl_easy *), data)) {
3273*6236dae4SAndroid Build Coastguard Worker Curl_hash_destroy(&entry->transfers);
3274*6236dae4SAndroid Build Coastguard Worker return CURLM_OUT_OF_MEMORY;
3275*6236dae4SAndroid Build Coastguard Worker }
3276*6236dae4SAndroid Build Coastguard Worker }
3277*6236dae4SAndroid Build Coastguard Worker
3278*6236dae4SAndroid Build Coastguard Worker comboaction = (entry->writers ? CURL_POLL_OUT : 0) |
3279*6236dae4SAndroid Build Coastguard Worker (entry->readers ? CURL_POLL_IN : 0);
3280*6236dae4SAndroid Build Coastguard Worker
3281*6236dae4SAndroid Build Coastguard Worker /* socket existed before and has the same action set as before */
3282*6236dae4SAndroid Build Coastguard Worker if(last_action && ((int)entry->action == comboaction))
3283*6236dae4SAndroid Build Coastguard Worker /* same, continue */
3284*6236dae4SAndroid Build Coastguard Worker continue;
3285*6236dae4SAndroid Build Coastguard Worker
3286*6236dae4SAndroid Build Coastguard Worker if(multi->socket_cb) {
3287*6236dae4SAndroid Build Coastguard Worker set_in_callback(multi, TRUE);
3288*6236dae4SAndroid Build Coastguard Worker rc = multi->socket_cb(data, s, comboaction, multi->socket_userp,
3289*6236dae4SAndroid Build Coastguard Worker entry->socketp);
3290*6236dae4SAndroid Build Coastguard Worker
3291*6236dae4SAndroid Build Coastguard Worker set_in_callback(multi, FALSE);
3292*6236dae4SAndroid Build Coastguard Worker if(rc == -1) {
3293*6236dae4SAndroid Build Coastguard Worker multi->dead = TRUE;
3294*6236dae4SAndroid Build Coastguard Worker return CURLM_ABORTED_BY_CALLBACK;
3295*6236dae4SAndroid Build Coastguard Worker }
3296*6236dae4SAndroid Build Coastguard Worker }
3297*6236dae4SAndroid Build Coastguard Worker
3298*6236dae4SAndroid Build Coastguard Worker /* store the current action state */
3299*6236dae4SAndroid Build Coastguard Worker entry->action = (unsigned int)comboaction;
3300*6236dae4SAndroid Build Coastguard Worker }
3301*6236dae4SAndroid Build Coastguard Worker
3302*6236dae4SAndroid Build Coastguard Worker /* Check for last_poll.sockets that no longer appear in ps->sockets.
3303*6236dae4SAndroid Build Coastguard Worker * Need to remove the easy handle from the multi->sockhash->transfers and
3304*6236dae4SAndroid Build Coastguard Worker * remove multi->sockhash entry when this was the last transfer */
3305*6236dae4SAndroid Build Coastguard Worker for(i = 0; i < last_ps->num; i++) {
3306*6236dae4SAndroid Build Coastguard Worker unsigned int j;
3307*6236dae4SAndroid Build Coastguard Worker bool stillused = FALSE;
3308*6236dae4SAndroid Build Coastguard Worker s = last_ps->sockets[i];
3309*6236dae4SAndroid Build Coastguard Worker for(j = 0; j < ps->num; j++) {
3310*6236dae4SAndroid Build Coastguard Worker if(s == ps->sockets[j]) {
3311*6236dae4SAndroid Build Coastguard Worker /* this is still supervised */
3312*6236dae4SAndroid Build Coastguard Worker stillused = TRUE;
3313*6236dae4SAndroid Build Coastguard Worker break;
3314*6236dae4SAndroid Build Coastguard Worker }
3315*6236dae4SAndroid Build Coastguard Worker }
3316*6236dae4SAndroid Build Coastguard Worker if(stillused)
3317*6236dae4SAndroid Build Coastguard Worker continue;
3318*6236dae4SAndroid Build Coastguard Worker
3319*6236dae4SAndroid Build Coastguard Worker entry = sh_getentry(&multi->sockhash, s);
3320*6236dae4SAndroid Build Coastguard Worker /* if this is NULL here, the socket has been closed and notified so
3321*6236dae4SAndroid Build Coastguard Worker already by Curl_multi_closed() */
3322*6236dae4SAndroid Build Coastguard Worker if(entry) {
3323*6236dae4SAndroid Build Coastguard Worker unsigned char oldactions = last_ps->actions[i];
3324*6236dae4SAndroid Build Coastguard Worker /* this socket has been removed. Decrease user count */
3325*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(entry->users);
3326*6236dae4SAndroid Build Coastguard Worker entry->users--;
3327*6236dae4SAndroid Build Coastguard Worker if(oldactions & CURL_POLL_OUT)
3328*6236dae4SAndroid Build Coastguard Worker entry->writers--;
3329*6236dae4SAndroid Build Coastguard Worker if(oldactions & CURL_POLL_IN)
3330*6236dae4SAndroid Build Coastguard Worker entry->readers--;
3331*6236dae4SAndroid Build Coastguard Worker if(!entry->users) {
3332*6236dae4SAndroid Build Coastguard Worker bool dead = FALSE;
3333*6236dae4SAndroid Build Coastguard Worker if(multi->socket_cb) {
3334*6236dae4SAndroid Build Coastguard Worker set_in_callback(multi, TRUE);
3335*6236dae4SAndroid Build Coastguard Worker rc = multi->socket_cb(data, s, CURL_POLL_REMOVE,
3336*6236dae4SAndroid Build Coastguard Worker multi->socket_userp, entry->socketp);
3337*6236dae4SAndroid Build Coastguard Worker set_in_callback(multi, FALSE);
3338*6236dae4SAndroid Build Coastguard Worker if(rc == -1)
3339*6236dae4SAndroid Build Coastguard Worker dead = TRUE;
3340*6236dae4SAndroid Build Coastguard Worker }
3341*6236dae4SAndroid Build Coastguard Worker sh_delentry(entry, &multi->sockhash, s);
3342*6236dae4SAndroid Build Coastguard Worker if(dead) {
3343*6236dae4SAndroid Build Coastguard Worker multi->dead = TRUE;
3344*6236dae4SAndroid Build Coastguard Worker return CURLM_ABORTED_BY_CALLBACK;
3345*6236dae4SAndroid Build Coastguard Worker }
3346*6236dae4SAndroid Build Coastguard Worker }
3347*6236dae4SAndroid Build Coastguard Worker else {
3348*6236dae4SAndroid Build Coastguard Worker /* still users, but remove this handle as a user of this socket */
3349*6236dae4SAndroid Build Coastguard Worker if(Curl_hash_delete(&entry->transfers, (char *)&data,
3350*6236dae4SAndroid Build Coastguard Worker sizeof(struct Curl_easy *))) {
3351*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(NULL);
3352*6236dae4SAndroid Build Coastguard Worker }
3353*6236dae4SAndroid Build Coastguard Worker }
3354*6236dae4SAndroid Build Coastguard Worker }
3355*6236dae4SAndroid Build Coastguard Worker } /* for loop over num */
3356*6236dae4SAndroid Build Coastguard Worker
3357*6236dae4SAndroid Build Coastguard Worker return CURLM_OK;
3358*6236dae4SAndroid Build Coastguard Worker }
3359*6236dae4SAndroid Build Coastguard Worker
3360*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_updatesocket(struct Curl_easy *data)
3361*6236dae4SAndroid Build Coastguard Worker {
3362*6236dae4SAndroid Build Coastguard Worker if(singlesocket(data->multi, data))
3363*6236dae4SAndroid Build Coastguard Worker return CURLE_ABORTED_BY_CALLBACK;
3364*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
3365*6236dae4SAndroid Build Coastguard Worker }
3366*6236dae4SAndroid Build Coastguard Worker
3367*6236dae4SAndroid Build Coastguard Worker
3368*6236dae4SAndroid Build Coastguard Worker /*
3369*6236dae4SAndroid Build Coastguard Worker * Curl_multi_closed()
3370*6236dae4SAndroid Build Coastguard Worker *
3371*6236dae4SAndroid Build Coastguard Worker * Used by the connect code to tell the multi_socket code that one of the
3372*6236dae4SAndroid Build Coastguard Worker * sockets we were using is about to be closed. This function will then
3373*6236dae4SAndroid Build Coastguard Worker * remove it from the sockethash for this handle to make the multi_socket API
3374*6236dae4SAndroid Build Coastguard Worker * behave properly, especially for the case when libcurl will create another
3375*6236dae4SAndroid Build Coastguard Worker * socket again and it gets the same file descriptor number.
3376*6236dae4SAndroid Build Coastguard Worker */
3377*6236dae4SAndroid Build Coastguard Worker
3378*6236dae4SAndroid Build Coastguard Worker void Curl_multi_closed(struct Curl_easy *data, curl_socket_t s)
3379*6236dae4SAndroid Build Coastguard Worker {
3380*6236dae4SAndroid Build Coastguard Worker if(data) {
3381*6236dae4SAndroid Build Coastguard Worker /* if there is still an easy handle associated with this connection */
3382*6236dae4SAndroid Build Coastguard Worker struct Curl_multi *multi = data->multi;
3383*6236dae4SAndroid Build Coastguard Worker DEBUGF(infof(data, "Curl_multi_closed, fd=%" FMT_SOCKET_T
3384*6236dae4SAndroid Build Coastguard Worker " multi is %p", s, (void *)multi));
3385*6236dae4SAndroid Build Coastguard Worker if(multi) {
3386*6236dae4SAndroid Build Coastguard Worker /* this is set if this connection is part of a handle that is added to
3387*6236dae4SAndroid Build Coastguard Worker a multi handle, and only then this is necessary */
3388*6236dae4SAndroid Build Coastguard Worker struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s);
3389*6236dae4SAndroid Build Coastguard Worker
3390*6236dae4SAndroid Build Coastguard Worker DEBUGF(infof(data, "Curl_multi_closed, fd=%" FMT_SOCKET_T
3391*6236dae4SAndroid Build Coastguard Worker " entry is %p", s, (void *)entry));
3392*6236dae4SAndroid Build Coastguard Worker if(entry) {
3393*6236dae4SAndroid Build Coastguard Worker int rc = 0;
3394*6236dae4SAndroid Build Coastguard Worker if(multi->socket_cb) {
3395*6236dae4SAndroid Build Coastguard Worker set_in_callback(multi, TRUE);
3396*6236dae4SAndroid Build Coastguard Worker rc = multi->socket_cb(data, s, CURL_POLL_REMOVE,
3397*6236dae4SAndroid Build Coastguard Worker multi->socket_userp, entry->socketp);
3398*6236dae4SAndroid Build Coastguard Worker set_in_callback(multi, FALSE);
3399*6236dae4SAndroid Build Coastguard Worker }
3400*6236dae4SAndroid Build Coastguard Worker
3401*6236dae4SAndroid Build Coastguard Worker /* now remove it from the socket hash */
3402*6236dae4SAndroid Build Coastguard Worker sh_delentry(entry, &multi->sockhash, s);
3403*6236dae4SAndroid Build Coastguard Worker if(rc == -1)
3404*6236dae4SAndroid Build Coastguard Worker /* This just marks the multi handle as "dead" without returning an
3405*6236dae4SAndroid Build Coastguard Worker error code primarily because this function is used from many
3406*6236dae4SAndroid Build Coastguard Worker places where propagating an error back is tricky. */
3407*6236dae4SAndroid Build Coastguard Worker multi->dead = TRUE;
3408*6236dae4SAndroid Build Coastguard Worker }
3409*6236dae4SAndroid Build Coastguard Worker }
3410*6236dae4SAndroid Build Coastguard Worker }
3411*6236dae4SAndroid Build Coastguard Worker }
3412*6236dae4SAndroid Build Coastguard Worker
3413*6236dae4SAndroid Build Coastguard Worker /*
3414*6236dae4SAndroid Build Coastguard Worker * add_next_timeout()
3415*6236dae4SAndroid Build Coastguard Worker *
3416*6236dae4SAndroid Build Coastguard Worker * Each Curl_easy has a list of timeouts. The add_next_timeout() is called
3417*6236dae4SAndroid Build Coastguard Worker * when it has just been removed from the splay tree because the timeout has
3418*6236dae4SAndroid Build Coastguard Worker * expired. This function is then to advance in the list to pick the next
3419*6236dae4SAndroid Build Coastguard Worker * timeout to use (skip the already expired ones) and add this node back to
3420*6236dae4SAndroid Build Coastguard Worker * the splay tree again.
3421*6236dae4SAndroid Build Coastguard Worker *
3422*6236dae4SAndroid Build Coastguard Worker * The splay tree only has each sessionhandle as a single node and the nearest
3423*6236dae4SAndroid Build Coastguard Worker * timeout is used to sort it on.
3424*6236dae4SAndroid Build Coastguard Worker */
3425*6236dae4SAndroid Build Coastguard Worker static CURLMcode add_next_timeout(struct curltime now,
3426*6236dae4SAndroid Build Coastguard Worker struct Curl_multi *multi,
3427*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *d)
3428*6236dae4SAndroid Build Coastguard Worker {
3429*6236dae4SAndroid Build Coastguard Worker struct curltime *tv = &d->state.expiretime;
3430*6236dae4SAndroid Build Coastguard Worker struct Curl_llist *list = &d->state.timeoutlist;
3431*6236dae4SAndroid Build Coastguard Worker struct Curl_llist_node *e;
3432*6236dae4SAndroid Build Coastguard Worker
3433*6236dae4SAndroid Build Coastguard Worker /* move over the timeout list for this specific handle and remove all
3434*6236dae4SAndroid Build Coastguard Worker timeouts that are now passed tense and store the next pending
3435*6236dae4SAndroid Build Coastguard Worker timeout in *tv */
3436*6236dae4SAndroid Build Coastguard Worker for(e = Curl_llist_head(list); e;) {
3437*6236dae4SAndroid Build Coastguard Worker struct Curl_llist_node *n = Curl_node_next(e);
3438*6236dae4SAndroid Build Coastguard Worker struct time_node *node = Curl_node_elem(e);
3439*6236dae4SAndroid Build Coastguard Worker timediff_t diff = Curl_timediff_us(node->time, now);
3440*6236dae4SAndroid Build Coastguard Worker if(diff <= 0)
3441*6236dae4SAndroid Build Coastguard Worker /* remove outdated entry */
3442*6236dae4SAndroid Build Coastguard Worker Curl_node_remove(e);
3443*6236dae4SAndroid Build Coastguard Worker else
3444*6236dae4SAndroid Build Coastguard Worker /* the list is sorted so get out on the first mismatch */
3445*6236dae4SAndroid Build Coastguard Worker break;
3446*6236dae4SAndroid Build Coastguard Worker e = n;
3447*6236dae4SAndroid Build Coastguard Worker }
3448*6236dae4SAndroid Build Coastguard Worker e = Curl_llist_head(list);
3449*6236dae4SAndroid Build Coastguard Worker if(!e) {
3450*6236dae4SAndroid Build Coastguard Worker /* clear the expire times within the handles that we remove from the
3451*6236dae4SAndroid Build Coastguard Worker splay tree */
3452*6236dae4SAndroid Build Coastguard Worker tv->tv_sec = 0;
3453*6236dae4SAndroid Build Coastguard Worker tv->tv_usec = 0;
3454*6236dae4SAndroid Build Coastguard Worker }
3455*6236dae4SAndroid Build Coastguard Worker else {
3456*6236dae4SAndroid Build Coastguard Worker struct time_node *node = Curl_node_elem(e);
3457*6236dae4SAndroid Build Coastguard Worker /* copy the first entry to 'tv' */
3458*6236dae4SAndroid Build Coastguard Worker memcpy(tv, &node->time, sizeof(*tv));
3459*6236dae4SAndroid Build Coastguard Worker
3460*6236dae4SAndroid Build Coastguard Worker /* Insert this node again into the splay. Keep the timer in the list in
3461*6236dae4SAndroid Build Coastguard Worker case we need to recompute future timers. */
3462*6236dae4SAndroid Build Coastguard Worker multi->timetree = Curl_splayinsert(*tv, multi->timetree,
3463*6236dae4SAndroid Build Coastguard Worker &d->state.timenode);
3464*6236dae4SAndroid Build Coastguard Worker }
3465*6236dae4SAndroid Build Coastguard Worker return CURLM_OK;
3466*6236dae4SAndroid Build Coastguard Worker }
3467*6236dae4SAndroid Build Coastguard Worker
3468*6236dae4SAndroid Build Coastguard Worker struct multi_run_ctx {
3469*6236dae4SAndroid Build Coastguard Worker struct Curl_multi *multi;
3470*6236dae4SAndroid Build Coastguard Worker struct curltime now;
3471*6236dae4SAndroid Build Coastguard Worker size_t run_xfers;
3472*6236dae4SAndroid Build Coastguard Worker SIGPIPE_MEMBER(pipe_st);
3473*6236dae4SAndroid Build Coastguard Worker bool run_cpool;
3474*6236dae4SAndroid Build Coastguard Worker };
3475*6236dae4SAndroid Build Coastguard Worker
3476*6236dae4SAndroid Build Coastguard Worker static CURLMcode multi_run_expired(struct multi_run_ctx *mrc)
3477*6236dae4SAndroid Build Coastguard Worker {
3478*6236dae4SAndroid Build Coastguard Worker struct Curl_multi *multi = mrc->multi;
3479*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data = NULL;
3480*6236dae4SAndroid Build Coastguard Worker struct Curl_tree *t = NULL;
3481*6236dae4SAndroid Build Coastguard Worker CURLMcode result = CURLM_OK;
3482*6236dae4SAndroid Build Coastguard Worker
3483*6236dae4SAndroid Build Coastguard Worker /*
3484*6236dae4SAndroid Build Coastguard Worker * The loop following here will go on as long as there are expire-times left
3485*6236dae4SAndroid Build Coastguard Worker * to process (compared to mrc->now) in the splay and 'data' will be
3486*6236dae4SAndroid Build Coastguard Worker * re-assigned for every expired handle we deal with.
3487*6236dae4SAndroid Build Coastguard Worker */
3488*6236dae4SAndroid Build Coastguard Worker while(1) {
3489*6236dae4SAndroid Build Coastguard Worker /* Check if there is one (more) expired timer to deal with! This function
3490*6236dae4SAndroid Build Coastguard Worker extracts a matching node if there is one */
3491*6236dae4SAndroid Build Coastguard Worker multi->timetree = Curl_splaygetbest(mrc->now, multi->timetree, &t);
3492*6236dae4SAndroid Build Coastguard Worker if(!t)
3493*6236dae4SAndroid Build Coastguard Worker goto out;
3494*6236dae4SAndroid Build Coastguard Worker
3495*6236dae4SAndroid Build Coastguard Worker data = Curl_splayget(t); /* assign this for next loop */
3496*6236dae4SAndroid Build Coastguard Worker if(!data)
3497*6236dae4SAndroid Build Coastguard Worker continue;
3498*6236dae4SAndroid Build Coastguard Worker
3499*6236dae4SAndroid Build Coastguard Worker (void)add_next_timeout(mrc->now, multi, data);
3500*6236dae4SAndroid Build Coastguard Worker if(data == multi->cpool.idata) {
3501*6236dae4SAndroid Build Coastguard Worker mrc->run_cpool = TRUE;
3502*6236dae4SAndroid Build Coastguard Worker continue;
3503*6236dae4SAndroid Build Coastguard Worker }
3504*6236dae4SAndroid Build Coastguard Worker
3505*6236dae4SAndroid Build Coastguard Worker mrc->run_xfers++;
3506*6236dae4SAndroid Build Coastguard Worker sigpipe_apply(data, &mrc->pipe_st);
3507*6236dae4SAndroid Build Coastguard Worker result = multi_runsingle(multi, &mrc->now, data);
3508*6236dae4SAndroid Build Coastguard Worker
3509*6236dae4SAndroid Build Coastguard Worker if(CURLM_OK >= result) {
3510*6236dae4SAndroid Build Coastguard Worker /* get the socket(s) and check if the state has been changed since
3511*6236dae4SAndroid Build Coastguard Worker last */
3512*6236dae4SAndroid Build Coastguard Worker result = singlesocket(multi, data);
3513*6236dae4SAndroid Build Coastguard Worker if(result)
3514*6236dae4SAndroid Build Coastguard Worker goto out;
3515*6236dae4SAndroid Build Coastguard Worker }
3516*6236dae4SAndroid Build Coastguard Worker }
3517*6236dae4SAndroid Build Coastguard Worker
3518*6236dae4SAndroid Build Coastguard Worker out:
3519*6236dae4SAndroid Build Coastguard Worker return result;
3520*6236dae4SAndroid Build Coastguard Worker }
3521*6236dae4SAndroid Build Coastguard Worker static CURLMcode multi_socket(struct Curl_multi *multi,
3522*6236dae4SAndroid Build Coastguard Worker bool checkall,
3523*6236dae4SAndroid Build Coastguard Worker curl_socket_t s,
3524*6236dae4SAndroid Build Coastguard Worker int ev_bitmask,
3525*6236dae4SAndroid Build Coastguard Worker int *running_handles)
3526*6236dae4SAndroid Build Coastguard Worker {
3527*6236dae4SAndroid Build Coastguard Worker CURLMcode result = CURLM_OK;
3528*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data = NULL;
3529*6236dae4SAndroid Build Coastguard Worker struct multi_run_ctx mrc;
3530*6236dae4SAndroid Build Coastguard Worker
3531*6236dae4SAndroid Build Coastguard Worker (void)ev_bitmask;
3532*6236dae4SAndroid Build Coastguard Worker memset(&mrc, 0, sizeof(mrc));
3533*6236dae4SAndroid Build Coastguard Worker mrc.multi = multi;
3534*6236dae4SAndroid Build Coastguard Worker mrc.now = Curl_now();
3535*6236dae4SAndroid Build Coastguard Worker sigpipe_init(&mrc.pipe_st);
3536*6236dae4SAndroid Build Coastguard Worker
3537*6236dae4SAndroid Build Coastguard Worker if(checkall) {
3538*6236dae4SAndroid Build Coastguard Worker struct Curl_llist_node *e;
3539*6236dae4SAndroid Build Coastguard Worker /* *perform() deals with running_handles on its own */
3540*6236dae4SAndroid Build Coastguard Worker result = curl_multi_perform(multi, running_handles);
3541*6236dae4SAndroid Build Coastguard Worker
3542*6236dae4SAndroid Build Coastguard Worker /* walk through each easy handle and do the socket state change magic
3543*6236dae4SAndroid Build Coastguard Worker and callbacks */
3544*6236dae4SAndroid Build Coastguard Worker if(result != CURLM_BAD_HANDLE) {
3545*6236dae4SAndroid Build Coastguard Worker for(e = Curl_llist_head(&multi->process); e && !result;
3546*6236dae4SAndroid Build Coastguard Worker e = Curl_node_next(e)) {
3547*6236dae4SAndroid Build Coastguard Worker result = singlesocket(multi, Curl_node_elem(e));
3548*6236dae4SAndroid Build Coastguard Worker }
3549*6236dae4SAndroid Build Coastguard Worker }
3550*6236dae4SAndroid Build Coastguard Worker mrc.run_cpool = TRUE;
3551*6236dae4SAndroid Build Coastguard Worker goto out;
3552*6236dae4SAndroid Build Coastguard Worker }
3553*6236dae4SAndroid Build Coastguard Worker
3554*6236dae4SAndroid Build Coastguard Worker if(s != CURL_SOCKET_TIMEOUT) {
3555*6236dae4SAndroid Build Coastguard Worker struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s);
3556*6236dae4SAndroid Build Coastguard Worker
3557*6236dae4SAndroid Build Coastguard Worker if(!entry) {
3558*6236dae4SAndroid Build Coastguard Worker /* Unmatched socket, we cannot act on it but we ignore this fact. In
3559*6236dae4SAndroid Build Coastguard Worker real-world tests it has been proved that libevent can in fact give
3560*6236dae4SAndroid Build Coastguard Worker the application actions even though the socket was just previously
3561*6236dae4SAndroid Build Coastguard Worker asked to get removed, so thus we better survive stray socket actions
3562*6236dae4SAndroid Build Coastguard Worker and just move on. */
3563*6236dae4SAndroid Build Coastguard Worker /* The socket might come from a connection that is being shut down
3564*6236dae4SAndroid Build Coastguard Worker * by the multi's connection pool. */
3565*6236dae4SAndroid Build Coastguard Worker Curl_cpool_multi_socket(multi, s, ev_bitmask);
3566*6236dae4SAndroid Build Coastguard Worker }
3567*6236dae4SAndroid Build Coastguard Worker else {
3568*6236dae4SAndroid Build Coastguard Worker struct Curl_hash_iterator iter;
3569*6236dae4SAndroid Build Coastguard Worker struct Curl_hash_element *he;
3570*6236dae4SAndroid Build Coastguard Worker
3571*6236dae4SAndroid Build Coastguard Worker /* the socket can be shared by many transfers, iterate */
3572*6236dae4SAndroid Build Coastguard Worker Curl_hash_start_iterate(&entry->transfers, &iter);
3573*6236dae4SAndroid Build Coastguard Worker for(he = Curl_hash_next_element(&iter); he;
3574*6236dae4SAndroid Build Coastguard Worker he = Curl_hash_next_element(&iter)) {
3575*6236dae4SAndroid Build Coastguard Worker data = (struct Curl_easy *)he->ptr;
3576*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(data);
3577*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(data->magic == CURLEASY_MAGIC_NUMBER);
3578*6236dae4SAndroid Build Coastguard Worker
3579*6236dae4SAndroid Build Coastguard Worker if(data == multi->cpool.idata)
3580*6236dae4SAndroid Build Coastguard Worker mrc.run_cpool = TRUE;
3581*6236dae4SAndroid Build Coastguard Worker else {
3582*6236dae4SAndroid Build Coastguard Worker /* Expire with out current now, so we will get it below when
3583*6236dae4SAndroid Build Coastguard Worker * asking the splaytree for expired transfers. */
3584*6236dae4SAndroid Build Coastguard Worker expire_ex(data, &mrc.now, 0, EXPIRE_RUN_NOW);
3585*6236dae4SAndroid Build Coastguard Worker }
3586*6236dae4SAndroid Build Coastguard Worker }
3587*6236dae4SAndroid Build Coastguard Worker }
3588*6236dae4SAndroid Build Coastguard Worker }
3589*6236dae4SAndroid Build Coastguard Worker
3590*6236dae4SAndroid Build Coastguard Worker result = multi_run_expired(&mrc);
3591*6236dae4SAndroid Build Coastguard Worker if(result)
3592*6236dae4SAndroid Build Coastguard Worker goto out;
3593*6236dae4SAndroid Build Coastguard Worker
3594*6236dae4SAndroid Build Coastguard Worker if(mrc.run_xfers) {
3595*6236dae4SAndroid Build Coastguard Worker /* Running transfers takes time. With a new timestamp, we might catch
3596*6236dae4SAndroid Build Coastguard Worker * other expires which are due now. Instead of telling the application
3597*6236dae4SAndroid Build Coastguard Worker * to set a 0 timeout and call us again, we run them here.
3598*6236dae4SAndroid Build Coastguard Worker * Do that only once or it might be unfair to transfers on other
3599*6236dae4SAndroid Build Coastguard Worker * sockets. */
3600*6236dae4SAndroid Build Coastguard Worker mrc.now = Curl_now();
3601*6236dae4SAndroid Build Coastguard Worker result = multi_run_expired(&mrc);
3602*6236dae4SAndroid Build Coastguard Worker }
3603*6236dae4SAndroid Build Coastguard Worker
3604*6236dae4SAndroid Build Coastguard Worker out:
3605*6236dae4SAndroid Build Coastguard Worker if(mrc.run_cpool) {
3606*6236dae4SAndroid Build Coastguard Worker sigpipe_apply(multi->cpool.idata, &mrc.pipe_st);
3607*6236dae4SAndroid Build Coastguard Worker Curl_cpool_multi_perform(multi);
3608*6236dae4SAndroid Build Coastguard Worker }
3609*6236dae4SAndroid Build Coastguard Worker sigpipe_restore(&mrc.pipe_st);
3610*6236dae4SAndroid Build Coastguard Worker
3611*6236dae4SAndroid Build Coastguard Worker if(running_handles)
3612*6236dae4SAndroid Build Coastguard Worker *running_handles = (int)multi->num_alive;
3613*6236dae4SAndroid Build Coastguard Worker
3614*6236dae4SAndroid Build Coastguard Worker if(CURLM_OK >= result)
3615*6236dae4SAndroid Build Coastguard Worker result = Curl_update_timer(multi);
3616*6236dae4SAndroid Build Coastguard Worker return result;
3617*6236dae4SAndroid Build Coastguard Worker }
3618*6236dae4SAndroid Build Coastguard Worker
3619*6236dae4SAndroid Build Coastguard Worker #undef curl_multi_setopt
3620*6236dae4SAndroid Build Coastguard Worker CURLMcode curl_multi_setopt(CURLM *m,
3621*6236dae4SAndroid Build Coastguard Worker CURLMoption option, ...)
3622*6236dae4SAndroid Build Coastguard Worker {
3623*6236dae4SAndroid Build Coastguard Worker CURLMcode res = CURLM_OK;
3624*6236dae4SAndroid Build Coastguard Worker va_list param;
3625*6236dae4SAndroid Build Coastguard Worker unsigned long uarg;
3626*6236dae4SAndroid Build Coastguard Worker struct Curl_multi *multi = m;
3627*6236dae4SAndroid Build Coastguard Worker
3628*6236dae4SAndroid Build Coastguard Worker if(!GOOD_MULTI_HANDLE(multi))
3629*6236dae4SAndroid Build Coastguard Worker return CURLM_BAD_HANDLE;
3630*6236dae4SAndroid Build Coastguard Worker
3631*6236dae4SAndroid Build Coastguard Worker if(multi->in_callback)
3632*6236dae4SAndroid Build Coastguard Worker return CURLM_RECURSIVE_API_CALL;
3633*6236dae4SAndroid Build Coastguard Worker
3634*6236dae4SAndroid Build Coastguard Worker va_start(param, option);
3635*6236dae4SAndroid Build Coastguard Worker
3636*6236dae4SAndroid Build Coastguard Worker switch(option) {
3637*6236dae4SAndroid Build Coastguard Worker case CURLMOPT_SOCKETFUNCTION:
3638*6236dae4SAndroid Build Coastguard Worker multi->socket_cb = va_arg(param, curl_socket_callback);
3639*6236dae4SAndroid Build Coastguard Worker break;
3640*6236dae4SAndroid Build Coastguard Worker case CURLMOPT_SOCKETDATA:
3641*6236dae4SAndroid Build Coastguard Worker multi->socket_userp = va_arg(param, void *);
3642*6236dae4SAndroid Build Coastguard Worker break;
3643*6236dae4SAndroid Build Coastguard Worker case CURLMOPT_PUSHFUNCTION:
3644*6236dae4SAndroid Build Coastguard Worker multi->push_cb = va_arg(param, curl_push_callback);
3645*6236dae4SAndroid Build Coastguard Worker break;
3646*6236dae4SAndroid Build Coastguard Worker case CURLMOPT_PUSHDATA:
3647*6236dae4SAndroid Build Coastguard Worker multi->push_userp = va_arg(param, void *);
3648*6236dae4SAndroid Build Coastguard Worker break;
3649*6236dae4SAndroid Build Coastguard Worker case CURLMOPT_PIPELINING:
3650*6236dae4SAndroid Build Coastguard Worker multi->multiplexing = va_arg(param, long) & CURLPIPE_MULTIPLEX ? 1 : 0;
3651*6236dae4SAndroid Build Coastguard Worker break;
3652*6236dae4SAndroid Build Coastguard Worker case CURLMOPT_TIMERFUNCTION:
3653*6236dae4SAndroid Build Coastguard Worker multi->timer_cb = va_arg(param, curl_multi_timer_callback);
3654*6236dae4SAndroid Build Coastguard Worker break;
3655*6236dae4SAndroid Build Coastguard Worker case CURLMOPT_TIMERDATA:
3656*6236dae4SAndroid Build Coastguard Worker multi->timer_userp = va_arg(param, void *);
3657*6236dae4SAndroid Build Coastguard Worker break;
3658*6236dae4SAndroid Build Coastguard Worker case CURLMOPT_MAXCONNECTS:
3659*6236dae4SAndroid Build Coastguard Worker uarg = va_arg(param, unsigned long);
3660*6236dae4SAndroid Build Coastguard Worker if(uarg <= UINT_MAX)
3661*6236dae4SAndroid Build Coastguard Worker multi->maxconnects = (unsigned int)uarg;
3662*6236dae4SAndroid Build Coastguard Worker break;
3663*6236dae4SAndroid Build Coastguard Worker case CURLMOPT_MAX_HOST_CONNECTIONS:
3664*6236dae4SAndroid Build Coastguard Worker multi->max_host_connections = va_arg(param, long);
3665*6236dae4SAndroid Build Coastguard Worker break;
3666*6236dae4SAndroid Build Coastguard Worker case CURLMOPT_MAX_TOTAL_CONNECTIONS:
3667*6236dae4SAndroid Build Coastguard Worker multi->max_total_connections = va_arg(param, long);
3668*6236dae4SAndroid Build Coastguard Worker /* for now, let this also decide the max number of connections
3669*6236dae4SAndroid Build Coastguard Worker * in shutdown handling */
3670*6236dae4SAndroid Build Coastguard Worker multi->max_shutdown_connections = va_arg(param, long);
3671*6236dae4SAndroid Build Coastguard Worker break;
3672*6236dae4SAndroid Build Coastguard Worker /* options formerly used for pipelining */
3673*6236dae4SAndroid Build Coastguard Worker case CURLMOPT_MAX_PIPELINE_LENGTH:
3674*6236dae4SAndroid Build Coastguard Worker break;
3675*6236dae4SAndroid Build Coastguard Worker case CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE:
3676*6236dae4SAndroid Build Coastguard Worker break;
3677*6236dae4SAndroid Build Coastguard Worker case CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE:
3678*6236dae4SAndroid Build Coastguard Worker break;
3679*6236dae4SAndroid Build Coastguard Worker case CURLMOPT_PIPELINING_SITE_BL:
3680*6236dae4SAndroid Build Coastguard Worker break;
3681*6236dae4SAndroid Build Coastguard Worker case CURLMOPT_PIPELINING_SERVER_BL:
3682*6236dae4SAndroid Build Coastguard Worker break;
3683*6236dae4SAndroid Build Coastguard Worker case CURLMOPT_MAX_CONCURRENT_STREAMS:
3684*6236dae4SAndroid Build Coastguard Worker {
3685*6236dae4SAndroid Build Coastguard Worker long streams = va_arg(param, long);
3686*6236dae4SAndroid Build Coastguard Worker if((streams < 1) || (streams > INT_MAX))
3687*6236dae4SAndroid Build Coastguard Worker streams = 100;
3688*6236dae4SAndroid Build Coastguard Worker multi->max_concurrent_streams = (unsigned int)streams;
3689*6236dae4SAndroid Build Coastguard Worker }
3690*6236dae4SAndroid Build Coastguard Worker break;
3691*6236dae4SAndroid Build Coastguard Worker default:
3692*6236dae4SAndroid Build Coastguard Worker res = CURLM_UNKNOWN_OPTION;
3693*6236dae4SAndroid Build Coastguard Worker break;
3694*6236dae4SAndroid Build Coastguard Worker }
3695*6236dae4SAndroid Build Coastguard Worker va_end(param);
3696*6236dae4SAndroid Build Coastguard Worker return res;
3697*6236dae4SAndroid Build Coastguard Worker }
3698*6236dae4SAndroid Build Coastguard Worker
3699*6236dae4SAndroid Build Coastguard Worker /* we define curl_multi_socket() in the public multi.h header */
3700*6236dae4SAndroid Build Coastguard Worker #undef curl_multi_socket
3701*6236dae4SAndroid Build Coastguard Worker
3702*6236dae4SAndroid Build Coastguard Worker CURLMcode curl_multi_socket(CURLM *m, curl_socket_t s, int *running_handles)
3703*6236dae4SAndroid Build Coastguard Worker {
3704*6236dae4SAndroid Build Coastguard Worker struct Curl_multi *multi = m;
3705*6236dae4SAndroid Build Coastguard Worker if(multi->in_callback)
3706*6236dae4SAndroid Build Coastguard Worker return CURLM_RECURSIVE_API_CALL;
3707*6236dae4SAndroid Build Coastguard Worker return multi_socket(multi, FALSE, s, 0, running_handles);
3708*6236dae4SAndroid Build Coastguard Worker }
3709*6236dae4SAndroid Build Coastguard Worker
3710*6236dae4SAndroid Build Coastguard Worker CURLMcode curl_multi_socket_action(CURLM *m, curl_socket_t s,
3711*6236dae4SAndroid Build Coastguard Worker int ev_bitmask, int *running_handles)
3712*6236dae4SAndroid Build Coastguard Worker {
3713*6236dae4SAndroid Build Coastguard Worker struct Curl_multi *multi = m;
3714*6236dae4SAndroid Build Coastguard Worker if(multi->in_callback)
3715*6236dae4SAndroid Build Coastguard Worker return CURLM_RECURSIVE_API_CALL;
3716*6236dae4SAndroid Build Coastguard Worker return multi_socket(multi, FALSE, s, ev_bitmask, running_handles);
3717*6236dae4SAndroid Build Coastguard Worker }
3718*6236dae4SAndroid Build Coastguard Worker
3719*6236dae4SAndroid Build Coastguard Worker CURLMcode curl_multi_socket_all(CURLM *m, int *running_handles)
3720*6236dae4SAndroid Build Coastguard Worker {
3721*6236dae4SAndroid Build Coastguard Worker struct Curl_multi *multi = m;
3722*6236dae4SAndroid Build Coastguard Worker if(multi->in_callback)
3723*6236dae4SAndroid Build Coastguard Worker return CURLM_RECURSIVE_API_CALL;
3724*6236dae4SAndroid Build Coastguard Worker return multi_socket(multi, TRUE, CURL_SOCKET_BAD, 0, running_handles);
3725*6236dae4SAndroid Build Coastguard Worker }
3726*6236dae4SAndroid Build Coastguard Worker
3727*6236dae4SAndroid Build Coastguard Worker static CURLMcode multi_timeout(struct Curl_multi *multi,
3728*6236dae4SAndroid Build Coastguard Worker struct curltime *expire_time,
3729*6236dae4SAndroid Build Coastguard Worker long *timeout_ms)
3730*6236dae4SAndroid Build Coastguard Worker {
3731*6236dae4SAndroid Build Coastguard Worker static const struct curltime tv_zero = {0, 0};
3732*6236dae4SAndroid Build Coastguard Worker
3733*6236dae4SAndroid Build Coastguard Worker if(multi->dead) {
3734*6236dae4SAndroid Build Coastguard Worker *timeout_ms = 0;
3735*6236dae4SAndroid Build Coastguard Worker return CURLM_OK;
3736*6236dae4SAndroid Build Coastguard Worker }
3737*6236dae4SAndroid Build Coastguard Worker
3738*6236dae4SAndroid Build Coastguard Worker if(multi->timetree) {
3739*6236dae4SAndroid Build Coastguard Worker /* we have a tree of expire times */
3740*6236dae4SAndroid Build Coastguard Worker struct curltime now = Curl_now();
3741*6236dae4SAndroid Build Coastguard Worker
3742*6236dae4SAndroid Build Coastguard Worker /* splay the lowest to the bottom */
3743*6236dae4SAndroid Build Coastguard Worker multi->timetree = Curl_splay(tv_zero, multi->timetree);
3744*6236dae4SAndroid Build Coastguard Worker /* this will not return NULL from a non-emtpy tree, but some compilers
3745*6236dae4SAndroid Build Coastguard Worker * are not convinced of that. Analyzers are hard. */
3746*6236dae4SAndroid Build Coastguard Worker *expire_time = multi->timetree ? multi->timetree->key : tv_zero;
3747*6236dae4SAndroid Build Coastguard Worker
3748*6236dae4SAndroid Build Coastguard Worker /* 'multi->timetree' will be non-NULL here but the compilers sometimes
3749*6236dae4SAndroid Build Coastguard Worker yell at us if we assume so */
3750*6236dae4SAndroid Build Coastguard Worker if(multi->timetree &&
3751*6236dae4SAndroid Build Coastguard Worker Curl_timediff_us(multi->timetree->key, now) > 0) {
3752*6236dae4SAndroid Build Coastguard Worker /* some time left before expiration */
3753*6236dae4SAndroid Build Coastguard Worker timediff_t diff = Curl_timediff_ceil(multi->timetree->key, now);
3754*6236dae4SAndroid Build Coastguard Worker /* this should be safe even on 32-bit archs, as we do not use that
3755*6236dae4SAndroid Build Coastguard Worker overly long timeouts */
3756*6236dae4SAndroid Build Coastguard Worker *timeout_ms = (long)diff;
3757*6236dae4SAndroid Build Coastguard Worker }
3758*6236dae4SAndroid Build Coastguard Worker else {
3759*6236dae4SAndroid Build Coastguard Worker /* 0 means immediately */
3760*6236dae4SAndroid Build Coastguard Worker *timeout_ms = 0;
3761*6236dae4SAndroid Build Coastguard Worker }
3762*6236dae4SAndroid Build Coastguard Worker }
3763*6236dae4SAndroid Build Coastguard Worker else {
3764*6236dae4SAndroid Build Coastguard Worker *expire_time = tv_zero;
3765*6236dae4SAndroid Build Coastguard Worker *timeout_ms = -1;
3766*6236dae4SAndroid Build Coastguard Worker }
3767*6236dae4SAndroid Build Coastguard Worker
3768*6236dae4SAndroid Build Coastguard Worker return CURLM_OK;
3769*6236dae4SAndroid Build Coastguard Worker }
3770*6236dae4SAndroid Build Coastguard Worker
3771*6236dae4SAndroid Build Coastguard Worker CURLMcode curl_multi_timeout(CURLM *m,
3772*6236dae4SAndroid Build Coastguard Worker long *timeout_ms)
3773*6236dae4SAndroid Build Coastguard Worker {
3774*6236dae4SAndroid Build Coastguard Worker struct curltime expire_time;
3775*6236dae4SAndroid Build Coastguard Worker struct Curl_multi *multi = m;
3776*6236dae4SAndroid Build Coastguard Worker
3777*6236dae4SAndroid Build Coastguard Worker /* First, make some basic checks that the CURLM handle is a good handle */
3778*6236dae4SAndroid Build Coastguard Worker if(!GOOD_MULTI_HANDLE(multi))
3779*6236dae4SAndroid Build Coastguard Worker return CURLM_BAD_HANDLE;
3780*6236dae4SAndroid Build Coastguard Worker
3781*6236dae4SAndroid Build Coastguard Worker if(multi->in_callback)
3782*6236dae4SAndroid Build Coastguard Worker return CURLM_RECURSIVE_API_CALL;
3783*6236dae4SAndroid Build Coastguard Worker
3784*6236dae4SAndroid Build Coastguard Worker return multi_timeout(multi, &expire_time, timeout_ms);
3785*6236dae4SAndroid Build Coastguard Worker }
3786*6236dae4SAndroid Build Coastguard Worker
3787*6236dae4SAndroid Build Coastguard Worker #define DEBUG_UPDATE_TIMER 0
3788*6236dae4SAndroid Build Coastguard Worker
3789*6236dae4SAndroid Build Coastguard Worker /*
3790*6236dae4SAndroid Build Coastguard Worker * Tell the application it should update its timers, if it subscribes to the
3791*6236dae4SAndroid Build Coastguard Worker * update timer callback.
3792*6236dae4SAndroid Build Coastguard Worker */
3793*6236dae4SAndroid Build Coastguard Worker CURLMcode Curl_update_timer(struct Curl_multi *multi)
3794*6236dae4SAndroid Build Coastguard Worker {
3795*6236dae4SAndroid Build Coastguard Worker struct curltime expire_ts;
3796*6236dae4SAndroid Build Coastguard Worker long timeout_ms;
3797*6236dae4SAndroid Build Coastguard Worker int rc;
3798*6236dae4SAndroid Build Coastguard Worker bool set_value = FALSE;
3799*6236dae4SAndroid Build Coastguard Worker
3800*6236dae4SAndroid Build Coastguard Worker if(!multi->timer_cb || multi->dead)
3801*6236dae4SAndroid Build Coastguard Worker return CURLM_OK;
3802*6236dae4SAndroid Build Coastguard Worker if(multi_timeout(multi, &expire_ts, &timeout_ms)) {
3803*6236dae4SAndroid Build Coastguard Worker return CURLM_OK;
3804*6236dae4SAndroid Build Coastguard Worker }
3805*6236dae4SAndroid Build Coastguard Worker
3806*6236dae4SAndroid Build Coastguard Worker if(timeout_ms < 0 && multi->last_timeout_ms < 0) {
3807*6236dae4SAndroid Build Coastguard Worker #if DEBUG_UPDATE_TIMER
3808*6236dae4SAndroid Build Coastguard Worker fprintf(stderr, "Curl_update_timer(), still no timeout, no change\n");
3809*6236dae4SAndroid Build Coastguard Worker #endif
3810*6236dae4SAndroid Build Coastguard Worker }
3811*6236dae4SAndroid Build Coastguard Worker else if(timeout_ms < 0) {
3812*6236dae4SAndroid Build Coastguard Worker /* there is no timeout now but there was one previously */
3813*6236dae4SAndroid Build Coastguard Worker #if DEBUG_UPDATE_TIMER
3814*6236dae4SAndroid Build Coastguard Worker fprintf(stderr, "Curl_update_timer(), remove timeout, "
3815*6236dae4SAndroid Build Coastguard Worker " last_timeout=%ldms\n", multi->last_timeout_ms);
3816*6236dae4SAndroid Build Coastguard Worker #endif
3817*6236dae4SAndroid Build Coastguard Worker timeout_ms = -1; /* normalize */
3818*6236dae4SAndroid Build Coastguard Worker set_value = TRUE;
3819*6236dae4SAndroid Build Coastguard Worker }
3820*6236dae4SAndroid Build Coastguard Worker else if(multi->last_timeout_ms < 0) {
3821*6236dae4SAndroid Build Coastguard Worker #if DEBUG_UPDATE_TIMER
3822*6236dae4SAndroid Build Coastguard Worker fprintf(stderr, "Curl_update_timer(), had no timeout, set now\n");
3823*6236dae4SAndroid Build Coastguard Worker #endif
3824*6236dae4SAndroid Build Coastguard Worker set_value = TRUE;
3825*6236dae4SAndroid Build Coastguard Worker }
3826*6236dae4SAndroid Build Coastguard Worker else if(Curl_timediff_us(multi->last_expire_ts, expire_ts)) {
3827*6236dae4SAndroid Build Coastguard Worker /* We had a timeout before and have one now, the absolute timestamp
3828*6236dae4SAndroid Build Coastguard Worker * differs. The relative timeout_ms may be the same, but the starting
3829*6236dae4SAndroid Build Coastguard Worker * point differs. Let the application restart its timer. */
3830*6236dae4SAndroid Build Coastguard Worker #if DEBUG_UPDATE_TIMER
3831*6236dae4SAndroid Build Coastguard Worker fprintf(stderr, "Curl_update_timer(), expire timestamp changed\n");
3832*6236dae4SAndroid Build Coastguard Worker #endif
3833*6236dae4SAndroid Build Coastguard Worker set_value = TRUE;
3834*6236dae4SAndroid Build Coastguard Worker }
3835*6236dae4SAndroid Build Coastguard Worker else {
3836*6236dae4SAndroid Build Coastguard Worker /* We have same expire time as previously. Our relative 'timeout_ms'
3837*6236dae4SAndroid Build Coastguard Worker * may be different now, but the application has the timer running
3838*6236dae4SAndroid Build Coastguard Worker * and we do not to tell it to start this again. */
3839*6236dae4SAndroid Build Coastguard Worker #if DEBUG_UPDATE_TIMER
3840*6236dae4SAndroid Build Coastguard Worker fprintf(stderr, "Curl_update_timer(), same expire timestamp, no change\n");
3841*6236dae4SAndroid Build Coastguard Worker #endif
3842*6236dae4SAndroid Build Coastguard Worker }
3843*6236dae4SAndroid Build Coastguard Worker
3844*6236dae4SAndroid Build Coastguard Worker if(set_value) {
3845*6236dae4SAndroid Build Coastguard Worker #if DEBUG_UPDATE_TIMER
3846*6236dae4SAndroid Build Coastguard Worker fprintf(stderr, "Curl_update_timer(), set timeout %ldms\n", timeout_ms);
3847*6236dae4SAndroid Build Coastguard Worker #endif
3848*6236dae4SAndroid Build Coastguard Worker multi->last_expire_ts = expire_ts;
3849*6236dae4SAndroid Build Coastguard Worker multi->last_timeout_ms = timeout_ms;
3850*6236dae4SAndroid Build Coastguard Worker set_in_callback(multi, TRUE);
3851*6236dae4SAndroid Build Coastguard Worker rc = multi->timer_cb(multi, timeout_ms, multi->timer_userp);
3852*6236dae4SAndroid Build Coastguard Worker set_in_callback(multi, FALSE);
3853*6236dae4SAndroid Build Coastguard Worker if(rc == -1) {
3854*6236dae4SAndroid Build Coastguard Worker multi->dead = TRUE;
3855*6236dae4SAndroid Build Coastguard Worker return CURLM_ABORTED_BY_CALLBACK;
3856*6236dae4SAndroid Build Coastguard Worker }
3857*6236dae4SAndroid Build Coastguard Worker }
3858*6236dae4SAndroid Build Coastguard Worker return CURLM_OK;
3859*6236dae4SAndroid Build Coastguard Worker }
3860*6236dae4SAndroid Build Coastguard Worker
3861*6236dae4SAndroid Build Coastguard Worker /*
3862*6236dae4SAndroid Build Coastguard Worker * multi_deltimeout()
3863*6236dae4SAndroid Build Coastguard Worker *
3864*6236dae4SAndroid Build Coastguard Worker * Remove a given timestamp from the list of timeouts.
3865*6236dae4SAndroid Build Coastguard Worker */
3866*6236dae4SAndroid Build Coastguard Worker static void
3867*6236dae4SAndroid Build Coastguard Worker multi_deltimeout(struct Curl_easy *data, expire_id eid)
3868*6236dae4SAndroid Build Coastguard Worker {
3869*6236dae4SAndroid Build Coastguard Worker struct Curl_llist_node *e;
3870*6236dae4SAndroid Build Coastguard Worker struct Curl_llist *timeoutlist = &data->state.timeoutlist;
3871*6236dae4SAndroid Build Coastguard Worker /* find and remove the specific node from the list */
3872*6236dae4SAndroid Build Coastguard Worker for(e = Curl_llist_head(timeoutlist); e; e = Curl_node_next(e)) {
3873*6236dae4SAndroid Build Coastguard Worker struct time_node *n = Curl_node_elem(e);
3874*6236dae4SAndroid Build Coastguard Worker if(n->eid == eid) {
3875*6236dae4SAndroid Build Coastguard Worker Curl_node_remove(e);
3876*6236dae4SAndroid Build Coastguard Worker return;
3877*6236dae4SAndroid Build Coastguard Worker }
3878*6236dae4SAndroid Build Coastguard Worker }
3879*6236dae4SAndroid Build Coastguard Worker }
3880*6236dae4SAndroid Build Coastguard Worker
3881*6236dae4SAndroid Build Coastguard Worker /*
3882*6236dae4SAndroid Build Coastguard Worker * multi_addtimeout()
3883*6236dae4SAndroid Build Coastguard Worker *
3884*6236dae4SAndroid Build Coastguard Worker * Add a timestamp to the list of timeouts. Keep the list sorted so that head
3885*6236dae4SAndroid Build Coastguard Worker * of list is always the timeout nearest in time.
3886*6236dae4SAndroid Build Coastguard Worker *
3887*6236dae4SAndroid Build Coastguard Worker */
3888*6236dae4SAndroid Build Coastguard Worker static CURLMcode
3889*6236dae4SAndroid Build Coastguard Worker multi_addtimeout(struct Curl_easy *data,
3890*6236dae4SAndroid Build Coastguard Worker struct curltime *stamp,
3891*6236dae4SAndroid Build Coastguard Worker expire_id eid)
3892*6236dae4SAndroid Build Coastguard Worker {
3893*6236dae4SAndroid Build Coastguard Worker struct Curl_llist_node *e;
3894*6236dae4SAndroid Build Coastguard Worker struct time_node *node;
3895*6236dae4SAndroid Build Coastguard Worker struct Curl_llist_node *prev = NULL;
3896*6236dae4SAndroid Build Coastguard Worker size_t n;
3897*6236dae4SAndroid Build Coastguard Worker struct Curl_llist *timeoutlist = &data->state.timeoutlist;
3898*6236dae4SAndroid Build Coastguard Worker
3899*6236dae4SAndroid Build Coastguard Worker node = &data->state.expires[eid];
3900*6236dae4SAndroid Build Coastguard Worker
3901*6236dae4SAndroid Build Coastguard Worker /* copy the timestamp and id */
3902*6236dae4SAndroid Build Coastguard Worker memcpy(&node->time, stamp, sizeof(*stamp));
3903*6236dae4SAndroid Build Coastguard Worker node->eid = eid; /* also marks it as in use */
3904*6236dae4SAndroid Build Coastguard Worker
3905*6236dae4SAndroid Build Coastguard Worker n = Curl_llist_count(timeoutlist);
3906*6236dae4SAndroid Build Coastguard Worker if(n) {
3907*6236dae4SAndroid Build Coastguard Worker /* find the correct spot in the list */
3908*6236dae4SAndroid Build Coastguard Worker for(e = Curl_llist_head(timeoutlist); e; e = Curl_node_next(e)) {
3909*6236dae4SAndroid Build Coastguard Worker struct time_node *check = Curl_node_elem(e);
3910*6236dae4SAndroid Build Coastguard Worker timediff_t diff = Curl_timediff(check->time, node->time);
3911*6236dae4SAndroid Build Coastguard Worker if(diff > 0)
3912*6236dae4SAndroid Build Coastguard Worker break;
3913*6236dae4SAndroid Build Coastguard Worker prev = e;
3914*6236dae4SAndroid Build Coastguard Worker }
3915*6236dae4SAndroid Build Coastguard Worker
3916*6236dae4SAndroid Build Coastguard Worker }
3917*6236dae4SAndroid Build Coastguard Worker /* else
3918*6236dae4SAndroid Build Coastguard Worker this is the first timeout on the list */
3919*6236dae4SAndroid Build Coastguard Worker
3920*6236dae4SAndroid Build Coastguard Worker Curl_llist_insert_next(timeoutlist, prev, node, &node->list);
3921*6236dae4SAndroid Build Coastguard Worker return CURLM_OK;
3922*6236dae4SAndroid Build Coastguard Worker }
3923*6236dae4SAndroid Build Coastguard Worker
3924*6236dae4SAndroid Build Coastguard Worker static void expire_ex(struct Curl_easy *data,
3925*6236dae4SAndroid Build Coastguard Worker const struct curltime *nowp,
3926*6236dae4SAndroid Build Coastguard Worker timediff_t milli, expire_id id)
3927*6236dae4SAndroid Build Coastguard Worker {
3928*6236dae4SAndroid Build Coastguard Worker struct Curl_multi *multi = data->multi;
3929*6236dae4SAndroid Build Coastguard Worker struct curltime *curr_expire = &data->state.expiretime;
3930*6236dae4SAndroid Build Coastguard Worker struct curltime set;
3931*6236dae4SAndroid Build Coastguard Worker
3932*6236dae4SAndroid Build Coastguard Worker /* this is only interesting while there is still an associated multi struct
3933*6236dae4SAndroid Build Coastguard Worker remaining! */
3934*6236dae4SAndroid Build Coastguard Worker if(!multi)
3935*6236dae4SAndroid Build Coastguard Worker return;
3936*6236dae4SAndroid Build Coastguard Worker
3937*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(id < EXPIRE_LAST);
3938*6236dae4SAndroid Build Coastguard Worker
3939*6236dae4SAndroid Build Coastguard Worker set = *nowp;
3940*6236dae4SAndroid Build Coastguard Worker set.tv_sec += (time_t)(milli/1000); /* might be a 64 to 32 bits conversion */
3941*6236dae4SAndroid Build Coastguard Worker set.tv_usec += (int)(milli%1000)*1000;
3942*6236dae4SAndroid Build Coastguard Worker
3943*6236dae4SAndroid Build Coastguard Worker if(set.tv_usec >= 1000000) {
3944*6236dae4SAndroid Build Coastguard Worker set.tv_sec++;
3945*6236dae4SAndroid Build Coastguard Worker set.tv_usec -= 1000000;
3946*6236dae4SAndroid Build Coastguard Worker }
3947*6236dae4SAndroid Build Coastguard Worker
3948*6236dae4SAndroid Build Coastguard Worker /* Remove any timer with the same id just in case. */
3949*6236dae4SAndroid Build Coastguard Worker multi_deltimeout(data, id);
3950*6236dae4SAndroid Build Coastguard Worker
3951*6236dae4SAndroid Build Coastguard Worker /* Add it to the timer list. It must stay in the list until it has expired
3952*6236dae4SAndroid Build Coastguard Worker in case we need to recompute the minimum timer later. */
3953*6236dae4SAndroid Build Coastguard Worker multi_addtimeout(data, &set, id);
3954*6236dae4SAndroid Build Coastguard Worker
3955*6236dae4SAndroid Build Coastguard Worker if(curr_expire->tv_sec || curr_expire->tv_usec) {
3956*6236dae4SAndroid Build Coastguard Worker /* This means that the struct is added as a node in the splay tree.
3957*6236dae4SAndroid Build Coastguard Worker Compare if the new time is earlier, and only remove-old/add-new if it
3958*6236dae4SAndroid Build Coastguard Worker is. */
3959*6236dae4SAndroid Build Coastguard Worker timediff_t diff = Curl_timediff(set, *curr_expire);
3960*6236dae4SAndroid Build Coastguard Worker int rc;
3961*6236dae4SAndroid Build Coastguard Worker
3962*6236dae4SAndroid Build Coastguard Worker if(diff > 0) {
3963*6236dae4SAndroid Build Coastguard Worker /* The current splay tree entry is sooner than this new expiry time.
3964*6236dae4SAndroid Build Coastguard Worker We do not need to update our splay tree entry. */
3965*6236dae4SAndroid Build Coastguard Worker return;
3966*6236dae4SAndroid Build Coastguard Worker }
3967*6236dae4SAndroid Build Coastguard Worker
3968*6236dae4SAndroid Build Coastguard Worker /* Since this is an updated time, we must remove the previous entry from
3969*6236dae4SAndroid Build Coastguard Worker the splay tree first and then re-add the new value */
3970*6236dae4SAndroid Build Coastguard Worker rc = Curl_splayremove(multi->timetree, &data->state.timenode,
3971*6236dae4SAndroid Build Coastguard Worker &multi->timetree);
3972*6236dae4SAndroid Build Coastguard Worker if(rc)
3973*6236dae4SAndroid Build Coastguard Worker infof(data, "Internal error removing splay node = %d", rc);
3974*6236dae4SAndroid Build Coastguard Worker }
3975*6236dae4SAndroid Build Coastguard Worker
3976*6236dae4SAndroid Build Coastguard Worker /* Indicate that we are in the splay tree and insert the new timer expiry
3977*6236dae4SAndroid Build Coastguard Worker value since it is our local minimum. */
3978*6236dae4SAndroid Build Coastguard Worker *curr_expire = set;
3979*6236dae4SAndroid Build Coastguard Worker Curl_splayset(&data->state.timenode, data);
3980*6236dae4SAndroid Build Coastguard Worker multi->timetree = Curl_splayinsert(*curr_expire, multi->timetree,
3981*6236dae4SAndroid Build Coastguard Worker &data->state.timenode);
3982*6236dae4SAndroid Build Coastguard Worker }
3983*6236dae4SAndroid Build Coastguard Worker
3984*6236dae4SAndroid Build Coastguard Worker /*
3985*6236dae4SAndroid Build Coastguard Worker * Curl_expire()
3986*6236dae4SAndroid Build Coastguard Worker *
3987*6236dae4SAndroid Build Coastguard Worker * given a number of milliseconds from now to use to set the 'act before
3988*6236dae4SAndroid Build Coastguard Worker * this'-time for the transfer, to be extracted by curl_multi_timeout()
3989*6236dae4SAndroid Build Coastguard Worker *
3990*6236dae4SAndroid Build Coastguard Worker * The timeout will be added to a queue of timeouts if it defines a moment in
3991*6236dae4SAndroid Build Coastguard Worker * time that is later than the current head of queue.
3992*6236dae4SAndroid Build Coastguard Worker *
3993*6236dae4SAndroid Build Coastguard Worker * Expire replaces a former timeout using the same id if already set.
3994*6236dae4SAndroid Build Coastguard Worker */
3995*6236dae4SAndroid Build Coastguard Worker void Curl_expire(struct Curl_easy *data, timediff_t milli, expire_id id)
3996*6236dae4SAndroid Build Coastguard Worker {
3997*6236dae4SAndroid Build Coastguard Worker struct curltime now = Curl_now();
3998*6236dae4SAndroid Build Coastguard Worker expire_ex(data, &now, milli, id);
3999*6236dae4SAndroid Build Coastguard Worker }
4000*6236dae4SAndroid Build Coastguard Worker
4001*6236dae4SAndroid Build Coastguard Worker /*
4002*6236dae4SAndroid Build Coastguard Worker * Curl_expire_done()
4003*6236dae4SAndroid Build Coastguard Worker *
4004*6236dae4SAndroid Build Coastguard Worker * Removes the expire timer. Marks it as done.
4005*6236dae4SAndroid Build Coastguard Worker *
4006*6236dae4SAndroid Build Coastguard Worker */
4007*6236dae4SAndroid Build Coastguard Worker void Curl_expire_done(struct Curl_easy *data, expire_id id)
4008*6236dae4SAndroid Build Coastguard Worker {
4009*6236dae4SAndroid Build Coastguard Worker /* remove the timer, if there */
4010*6236dae4SAndroid Build Coastguard Worker multi_deltimeout(data, id);
4011*6236dae4SAndroid Build Coastguard Worker }
4012*6236dae4SAndroid Build Coastguard Worker
4013*6236dae4SAndroid Build Coastguard Worker /*
4014*6236dae4SAndroid Build Coastguard Worker * Curl_expire_clear()
4015*6236dae4SAndroid Build Coastguard Worker *
4016*6236dae4SAndroid Build Coastguard Worker * Clear ALL timeout values for this handle.
4017*6236dae4SAndroid Build Coastguard Worker */
4018*6236dae4SAndroid Build Coastguard Worker bool Curl_expire_clear(struct Curl_easy *data)
4019*6236dae4SAndroid Build Coastguard Worker {
4020*6236dae4SAndroid Build Coastguard Worker struct Curl_multi *multi = data->multi;
4021*6236dae4SAndroid Build Coastguard Worker struct curltime *nowp = &data->state.expiretime;
4022*6236dae4SAndroid Build Coastguard Worker
4023*6236dae4SAndroid Build Coastguard Worker /* this is only interesting while there is still an associated multi struct
4024*6236dae4SAndroid Build Coastguard Worker remaining! */
4025*6236dae4SAndroid Build Coastguard Worker if(!multi)
4026*6236dae4SAndroid Build Coastguard Worker return FALSE;
4027*6236dae4SAndroid Build Coastguard Worker
4028*6236dae4SAndroid Build Coastguard Worker if(nowp->tv_sec || nowp->tv_usec) {
4029*6236dae4SAndroid Build Coastguard Worker /* Since this is an cleared time, we must remove the previous entry from
4030*6236dae4SAndroid Build Coastguard Worker the splay tree */
4031*6236dae4SAndroid Build Coastguard Worker struct Curl_llist *list = &data->state.timeoutlist;
4032*6236dae4SAndroid Build Coastguard Worker int rc;
4033*6236dae4SAndroid Build Coastguard Worker
4034*6236dae4SAndroid Build Coastguard Worker rc = Curl_splayremove(multi->timetree, &data->state.timenode,
4035*6236dae4SAndroid Build Coastguard Worker &multi->timetree);
4036*6236dae4SAndroid Build Coastguard Worker if(rc)
4037*6236dae4SAndroid Build Coastguard Worker infof(data, "Internal error clearing splay node = %d", rc);
4038*6236dae4SAndroid Build Coastguard Worker
4039*6236dae4SAndroid Build Coastguard Worker /* clear the timeout list too */
4040*6236dae4SAndroid Build Coastguard Worker Curl_llist_destroy(list, NULL);
4041*6236dae4SAndroid Build Coastguard Worker
4042*6236dae4SAndroid Build Coastguard Worker #ifdef DEBUGBUILD
4043*6236dae4SAndroid Build Coastguard Worker infof(data, "Expire cleared");
4044*6236dae4SAndroid Build Coastguard Worker #endif
4045*6236dae4SAndroid Build Coastguard Worker nowp->tv_sec = 0;
4046*6236dae4SAndroid Build Coastguard Worker nowp->tv_usec = 0;
4047*6236dae4SAndroid Build Coastguard Worker return TRUE;
4048*6236dae4SAndroid Build Coastguard Worker }
4049*6236dae4SAndroid Build Coastguard Worker return FALSE;
4050*6236dae4SAndroid Build Coastguard Worker }
4051*6236dae4SAndroid Build Coastguard Worker
4052*6236dae4SAndroid Build Coastguard Worker CURLMcode curl_multi_assign(CURLM *m, curl_socket_t s,
4053*6236dae4SAndroid Build Coastguard Worker void *hashp)
4054*6236dae4SAndroid Build Coastguard Worker {
4055*6236dae4SAndroid Build Coastguard Worker struct Curl_sh_entry *there = NULL;
4056*6236dae4SAndroid Build Coastguard Worker struct Curl_multi *multi = m;
4057*6236dae4SAndroid Build Coastguard Worker if(!GOOD_MULTI_HANDLE(multi))
4058*6236dae4SAndroid Build Coastguard Worker return CURLM_BAD_HANDLE;
4059*6236dae4SAndroid Build Coastguard Worker
4060*6236dae4SAndroid Build Coastguard Worker there = sh_getentry(&multi->sockhash, s);
4061*6236dae4SAndroid Build Coastguard Worker
4062*6236dae4SAndroid Build Coastguard Worker if(!there)
4063*6236dae4SAndroid Build Coastguard Worker return CURLM_BAD_SOCKET;
4064*6236dae4SAndroid Build Coastguard Worker
4065*6236dae4SAndroid Build Coastguard Worker there->socketp = hashp;
4066*6236dae4SAndroid Build Coastguard Worker
4067*6236dae4SAndroid Build Coastguard Worker return CURLM_OK;
4068*6236dae4SAndroid Build Coastguard Worker }
4069*6236dae4SAndroid Build Coastguard Worker
4070*6236dae4SAndroid Build Coastguard Worker static void move_pending_to_connect(struct Curl_multi *multi,
4071*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data)
4072*6236dae4SAndroid Build Coastguard Worker {
4073*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(data->mstate == MSTATE_PENDING);
4074*6236dae4SAndroid Build Coastguard Worker
4075*6236dae4SAndroid Build Coastguard Worker /* Remove this node from the pending list */
4076*6236dae4SAndroid Build Coastguard Worker Curl_node_remove(&data->multi_queue);
4077*6236dae4SAndroid Build Coastguard Worker
4078*6236dae4SAndroid Build Coastguard Worker /* put it into the process list */
4079*6236dae4SAndroid Build Coastguard Worker Curl_llist_append(&multi->process, data, &data->multi_queue);
4080*6236dae4SAndroid Build Coastguard Worker
4081*6236dae4SAndroid Build Coastguard Worker multistate(data, MSTATE_CONNECT);
4082*6236dae4SAndroid Build Coastguard Worker
4083*6236dae4SAndroid Build Coastguard Worker /* Make sure that the handle will be processed soonish. */
4084*6236dae4SAndroid Build Coastguard Worker Curl_expire(data, 0, EXPIRE_RUN_NOW);
4085*6236dae4SAndroid Build Coastguard Worker }
4086*6236dae4SAndroid Build Coastguard Worker
4087*6236dae4SAndroid Build Coastguard Worker /* process_pending_handles() moves a handle from PENDING back into the process
4088*6236dae4SAndroid Build Coastguard Worker list and change state to CONNECT.
4089*6236dae4SAndroid Build Coastguard Worker
4090*6236dae4SAndroid Build Coastguard Worker We do not move all transfers because that can be a significant amount.
4091*6236dae4SAndroid Build Coastguard Worker Since this is tried every now and then doing too many too often becomes a
4092*6236dae4SAndroid Build Coastguard Worker performance problem.
4093*6236dae4SAndroid Build Coastguard Worker
4094*6236dae4SAndroid Build Coastguard Worker When there is a change for connection limits like max host connections etc,
4095*6236dae4SAndroid Build Coastguard Worker this likely only allows one new transfer. When there is a pipewait change,
4096*6236dae4SAndroid Build Coastguard Worker it can potentially allow hundreds of new transfers.
4097*6236dae4SAndroid Build Coastguard Worker
4098*6236dae4SAndroid Build Coastguard Worker We could consider an improvement where we store the queue reason and allow
4099*6236dae4SAndroid Build Coastguard Worker more pipewait rechecks than others.
4100*6236dae4SAndroid Build Coastguard Worker */
4101*6236dae4SAndroid Build Coastguard Worker static void process_pending_handles(struct Curl_multi *multi)
4102*6236dae4SAndroid Build Coastguard Worker {
4103*6236dae4SAndroid Build Coastguard Worker struct Curl_llist_node *e = Curl_llist_head(&multi->pending);
4104*6236dae4SAndroid Build Coastguard Worker if(e) {
4105*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data = Curl_node_elem(e);
4106*6236dae4SAndroid Build Coastguard Worker move_pending_to_connect(multi, data);
4107*6236dae4SAndroid Build Coastguard Worker }
4108*6236dae4SAndroid Build Coastguard Worker }
4109*6236dae4SAndroid Build Coastguard Worker
4110*6236dae4SAndroid Build Coastguard Worker void Curl_set_in_callback(struct Curl_easy *data, bool value)
4111*6236dae4SAndroid Build Coastguard Worker {
4112*6236dae4SAndroid Build Coastguard Worker if(data && data->multi)
4113*6236dae4SAndroid Build Coastguard Worker data->multi->in_callback = value;
4114*6236dae4SAndroid Build Coastguard Worker }
4115*6236dae4SAndroid Build Coastguard Worker
4116*6236dae4SAndroid Build Coastguard Worker bool Curl_is_in_callback(struct Curl_easy *data)
4117*6236dae4SAndroid Build Coastguard Worker {
4118*6236dae4SAndroid Build Coastguard Worker return (data && data->multi && data->multi->in_callback);
4119*6236dae4SAndroid Build Coastguard Worker }
4120*6236dae4SAndroid Build Coastguard Worker
4121*6236dae4SAndroid Build Coastguard Worker unsigned int Curl_multi_max_concurrent_streams(struct Curl_multi *multi)
4122*6236dae4SAndroid Build Coastguard Worker {
4123*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(multi);
4124*6236dae4SAndroid Build Coastguard Worker return multi->max_concurrent_streams;
4125*6236dae4SAndroid Build Coastguard Worker }
4126*6236dae4SAndroid Build Coastguard Worker
4127*6236dae4SAndroid Build Coastguard Worker CURL **curl_multi_get_handles(CURLM *m)
4128*6236dae4SAndroid Build Coastguard Worker {
4129*6236dae4SAndroid Build Coastguard Worker struct Curl_multi *multi = m;
4130*6236dae4SAndroid Build Coastguard Worker CURL **a = malloc(sizeof(struct Curl_easy *) * (multi->num_easy + 1));
4131*6236dae4SAndroid Build Coastguard Worker if(a) {
4132*6236dae4SAndroid Build Coastguard Worker unsigned int i = 0;
4133*6236dae4SAndroid Build Coastguard Worker struct Curl_llist_node *e;
4134*6236dae4SAndroid Build Coastguard Worker for(e = Curl_llist_head(&multi->process); e; e = Curl_node_next(e)) {
4135*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data = Curl_node_elem(e);
4136*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(i < multi->num_easy);
4137*6236dae4SAndroid Build Coastguard Worker if(!data->state.internal)
4138*6236dae4SAndroid Build Coastguard Worker a[i++] = data;
4139*6236dae4SAndroid Build Coastguard Worker }
4140*6236dae4SAndroid Build Coastguard Worker a[i] = NULL; /* last entry is a NULL */
4141*6236dae4SAndroid Build Coastguard Worker }
4142*6236dae4SAndroid Build Coastguard Worker return a;
4143*6236dae4SAndroid Build Coastguard Worker }
4144*6236dae4SAndroid Build Coastguard Worker
4145*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_multi_xfer_buf_borrow(struct Curl_easy *data,
4146*6236dae4SAndroid Build Coastguard Worker char **pbuf, size_t *pbuflen)
4147*6236dae4SAndroid Build Coastguard Worker {
4148*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(data);
4149*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(data->multi);
4150*6236dae4SAndroid Build Coastguard Worker *pbuf = NULL;
4151*6236dae4SAndroid Build Coastguard Worker *pbuflen = 0;
4152*6236dae4SAndroid Build Coastguard Worker if(!data->multi) {
4153*6236dae4SAndroid Build Coastguard Worker failf(data, "transfer has no multi handle");
4154*6236dae4SAndroid Build Coastguard Worker return CURLE_FAILED_INIT;
4155*6236dae4SAndroid Build Coastguard Worker }
4156*6236dae4SAndroid Build Coastguard Worker if(!data->set.buffer_size) {
4157*6236dae4SAndroid Build Coastguard Worker failf(data, "transfer buffer size is 0");
4158*6236dae4SAndroid Build Coastguard Worker return CURLE_FAILED_INIT;
4159*6236dae4SAndroid Build Coastguard Worker }
4160*6236dae4SAndroid Build Coastguard Worker if(data->multi->xfer_buf_borrowed) {
4161*6236dae4SAndroid Build Coastguard Worker failf(data, "attempt to borrow xfer_buf when already borrowed");
4162*6236dae4SAndroid Build Coastguard Worker return CURLE_AGAIN;
4163*6236dae4SAndroid Build Coastguard Worker }
4164*6236dae4SAndroid Build Coastguard Worker
4165*6236dae4SAndroid Build Coastguard Worker if(data->multi->xfer_buf &&
4166*6236dae4SAndroid Build Coastguard Worker data->set.buffer_size > data->multi->xfer_buf_len) {
4167*6236dae4SAndroid Build Coastguard Worker /* not large enough, get a new one */
4168*6236dae4SAndroid Build Coastguard Worker free(data->multi->xfer_buf);
4169*6236dae4SAndroid Build Coastguard Worker data->multi->xfer_buf = NULL;
4170*6236dae4SAndroid Build Coastguard Worker data->multi->xfer_buf_len = 0;
4171*6236dae4SAndroid Build Coastguard Worker }
4172*6236dae4SAndroid Build Coastguard Worker
4173*6236dae4SAndroid Build Coastguard Worker if(!data->multi->xfer_buf) {
4174*6236dae4SAndroid Build Coastguard Worker data->multi->xfer_buf = malloc((size_t)data->set.buffer_size);
4175*6236dae4SAndroid Build Coastguard Worker if(!data->multi->xfer_buf) {
4176*6236dae4SAndroid Build Coastguard Worker failf(data, "could not allocate xfer_buf of %zu bytes",
4177*6236dae4SAndroid Build Coastguard Worker (size_t)data->set.buffer_size);
4178*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
4179*6236dae4SAndroid Build Coastguard Worker }
4180*6236dae4SAndroid Build Coastguard Worker data->multi->xfer_buf_len = data->set.buffer_size;
4181*6236dae4SAndroid Build Coastguard Worker }
4182*6236dae4SAndroid Build Coastguard Worker
4183*6236dae4SAndroid Build Coastguard Worker data->multi->xfer_buf_borrowed = TRUE;
4184*6236dae4SAndroid Build Coastguard Worker *pbuf = data->multi->xfer_buf;
4185*6236dae4SAndroid Build Coastguard Worker *pbuflen = data->multi->xfer_buf_len;
4186*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
4187*6236dae4SAndroid Build Coastguard Worker }
4188*6236dae4SAndroid Build Coastguard Worker
4189*6236dae4SAndroid Build Coastguard Worker void Curl_multi_xfer_buf_release(struct Curl_easy *data, char *buf)
4190*6236dae4SAndroid Build Coastguard Worker {
4191*6236dae4SAndroid Build Coastguard Worker (void)buf;
4192*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(data);
4193*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(data->multi);
4194*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(!buf || data->multi->xfer_buf == buf);
4195*6236dae4SAndroid Build Coastguard Worker data->multi->xfer_buf_borrowed = FALSE;
4196*6236dae4SAndroid Build Coastguard Worker }
4197*6236dae4SAndroid Build Coastguard Worker
4198*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_multi_xfer_ulbuf_borrow(struct Curl_easy *data,
4199*6236dae4SAndroid Build Coastguard Worker char **pbuf, size_t *pbuflen)
4200*6236dae4SAndroid Build Coastguard Worker {
4201*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(data);
4202*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(data->multi);
4203*6236dae4SAndroid Build Coastguard Worker *pbuf = NULL;
4204*6236dae4SAndroid Build Coastguard Worker *pbuflen = 0;
4205*6236dae4SAndroid Build Coastguard Worker if(!data->multi) {
4206*6236dae4SAndroid Build Coastguard Worker failf(data, "transfer has no multi handle");
4207*6236dae4SAndroid Build Coastguard Worker return CURLE_FAILED_INIT;
4208*6236dae4SAndroid Build Coastguard Worker }
4209*6236dae4SAndroid Build Coastguard Worker if(!data->set.upload_buffer_size) {
4210*6236dae4SAndroid Build Coastguard Worker failf(data, "transfer upload buffer size is 0");
4211*6236dae4SAndroid Build Coastguard Worker return CURLE_FAILED_INIT;
4212*6236dae4SAndroid Build Coastguard Worker }
4213*6236dae4SAndroid Build Coastguard Worker if(data->multi->xfer_ulbuf_borrowed) {
4214*6236dae4SAndroid Build Coastguard Worker failf(data, "attempt to borrow xfer_ulbuf when already borrowed");
4215*6236dae4SAndroid Build Coastguard Worker return CURLE_AGAIN;
4216*6236dae4SAndroid Build Coastguard Worker }
4217*6236dae4SAndroid Build Coastguard Worker
4218*6236dae4SAndroid Build Coastguard Worker if(data->multi->xfer_ulbuf &&
4219*6236dae4SAndroid Build Coastguard Worker data->set.upload_buffer_size > data->multi->xfer_ulbuf_len) {
4220*6236dae4SAndroid Build Coastguard Worker /* not large enough, get a new one */
4221*6236dae4SAndroid Build Coastguard Worker free(data->multi->xfer_ulbuf);
4222*6236dae4SAndroid Build Coastguard Worker data->multi->xfer_ulbuf = NULL;
4223*6236dae4SAndroid Build Coastguard Worker data->multi->xfer_ulbuf_len = 0;
4224*6236dae4SAndroid Build Coastguard Worker }
4225*6236dae4SAndroid Build Coastguard Worker
4226*6236dae4SAndroid Build Coastguard Worker if(!data->multi->xfer_ulbuf) {
4227*6236dae4SAndroid Build Coastguard Worker data->multi->xfer_ulbuf = malloc((size_t)data->set.upload_buffer_size);
4228*6236dae4SAndroid Build Coastguard Worker if(!data->multi->xfer_ulbuf) {
4229*6236dae4SAndroid Build Coastguard Worker failf(data, "could not allocate xfer_ulbuf of %zu bytes",
4230*6236dae4SAndroid Build Coastguard Worker (size_t)data->set.upload_buffer_size);
4231*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
4232*6236dae4SAndroid Build Coastguard Worker }
4233*6236dae4SAndroid Build Coastguard Worker data->multi->xfer_ulbuf_len = data->set.upload_buffer_size;
4234*6236dae4SAndroid Build Coastguard Worker }
4235*6236dae4SAndroid Build Coastguard Worker
4236*6236dae4SAndroid Build Coastguard Worker data->multi->xfer_ulbuf_borrowed = TRUE;
4237*6236dae4SAndroid Build Coastguard Worker *pbuf = data->multi->xfer_ulbuf;
4238*6236dae4SAndroid Build Coastguard Worker *pbuflen = data->multi->xfer_ulbuf_len;
4239*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
4240*6236dae4SAndroid Build Coastguard Worker }
4241*6236dae4SAndroid Build Coastguard Worker
4242*6236dae4SAndroid Build Coastguard Worker void Curl_multi_xfer_ulbuf_release(struct Curl_easy *data, char *buf)
4243*6236dae4SAndroid Build Coastguard Worker {
4244*6236dae4SAndroid Build Coastguard Worker (void)buf;
4245*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(data);
4246*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(data->multi);
4247*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(!buf || data->multi->xfer_ulbuf == buf);
4248*6236dae4SAndroid Build Coastguard Worker data->multi->xfer_ulbuf_borrowed = FALSE;
4249*6236dae4SAndroid Build Coastguard Worker }
4250*6236dae4SAndroid Build Coastguard Worker
4251*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_multi_xfer_sockbuf_borrow(struct Curl_easy *data,
4252*6236dae4SAndroid Build Coastguard Worker size_t blen, char **pbuf)
4253*6236dae4SAndroid Build Coastguard Worker {
4254*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(data);
4255*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(data->multi);
4256*6236dae4SAndroid Build Coastguard Worker *pbuf = NULL;
4257*6236dae4SAndroid Build Coastguard Worker if(!data->multi) {
4258*6236dae4SAndroid Build Coastguard Worker failf(data, "transfer has no multi handle");
4259*6236dae4SAndroid Build Coastguard Worker return CURLE_FAILED_INIT;
4260*6236dae4SAndroid Build Coastguard Worker }
4261*6236dae4SAndroid Build Coastguard Worker if(data->multi->xfer_sockbuf_borrowed) {
4262*6236dae4SAndroid Build Coastguard Worker failf(data, "attempt to borrow xfer_sockbuf when already borrowed");
4263*6236dae4SAndroid Build Coastguard Worker return CURLE_AGAIN;
4264*6236dae4SAndroid Build Coastguard Worker }
4265*6236dae4SAndroid Build Coastguard Worker
4266*6236dae4SAndroid Build Coastguard Worker if(data->multi->xfer_sockbuf && blen > data->multi->xfer_sockbuf_len) {
4267*6236dae4SAndroid Build Coastguard Worker /* not large enough, get a new one */
4268*6236dae4SAndroid Build Coastguard Worker free(data->multi->xfer_sockbuf);
4269*6236dae4SAndroid Build Coastguard Worker data->multi->xfer_sockbuf = NULL;
4270*6236dae4SAndroid Build Coastguard Worker data->multi->xfer_sockbuf_len = 0;
4271*6236dae4SAndroid Build Coastguard Worker }
4272*6236dae4SAndroid Build Coastguard Worker
4273*6236dae4SAndroid Build Coastguard Worker if(!data->multi->xfer_sockbuf) {
4274*6236dae4SAndroid Build Coastguard Worker data->multi->xfer_sockbuf = malloc(blen);
4275*6236dae4SAndroid Build Coastguard Worker if(!data->multi->xfer_sockbuf) {
4276*6236dae4SAndroid Build Coastguard Worker failf(data, "could not allocate xfer_sockbuf of %zu bytes", blen);
4277*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
4278*6236dae4SAndroid Build Coastguard Worker }
4279*6236dae4SAndroid Build Coastguard Worker data->multi->xfer_sockbuf_len = blen;
4280*6236dae4SAndroid Build Coastguard Worker }
4281*6236dae4SAndroid Build Coastguard Worker
4282*6236dae4SAndroid Build Coastguard Worker data->multi->xfer_sockbuf_borrowed = TRUE;
4283*6236dae4SAndroid Build Coastguard Worker *pbuf = data->multi->xfer_sockbuf;
4284*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
4285*6236dae4SAndroid Build Coastguard Worker }
4286*6236dae4SAndroid Build Coastguard Worker
4287*6236dae4SAndroid Build Coastguard Worker void Curl_multi_xfer_sockbuf_release(struct Curl_easy *data, char *buf)
4288*6236dae4SAndroid Build Coastguard Worker {
4289*6236dae4SAndroid Build Coastguard Worker (void)buf;
4290*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(data);
4291*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(data->multi);
4292*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(!buf || data->multi->xfer_sockbuf == buf);
4293*6236dae4SAndroid Build Coastguard Worker data->multi->xfer_sockbuf_borrowed = FALSE;
4294*6236dae4SAndroid Build Coastguard Worker }
4295*6236dae4SAndroid Build Coastguard Worker
4296*6236dae4SAndroid Build Coastguard Worker static void multi_xfer_bufs_free(struct Curl_multi *multi)
4297*6236dae4SAndroid Build Coastguard Worker {
4298*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(multi);
4299*6236dae4SAndroid Build Coastguard Worker Curl_safefree(multi->xfer_buf);
4300*6236dae4SAndroid Build Coastguard Worker multi->xfer_buf_len = 0;
4301*6236dae4SAndroid Build Coastguard Worker multi->xfer_buf_borrowed = FALSE;
4302*6236dae4SAndroid Build Coastguard Worker Curl_safefree(multi->xfer_ulbuf);
4303*6236dae4SAndroid Build Coastguard Worker multi->xfer_ulbuf_len = 0;
4304*6236dae4SAndroid Build Coastguard Worker multi->xfer_ulbuf_borrowed = FALSE;
4305*6236dae4SAndroid Build Coastguard Worker Curl_safefree(multi->xfer_sockbuf);
4306*6236dae4SAndroid Build Coastguard Worker multi->xfer_sockbuf_len = 0;
4307*6236dae4SAndroid Build Coastguard Worker multi->xfer_sockbuf_borrowed = FALSE;
4308*6236dae4SAndroid Build Coastguard Worker }
4309*6236dae4SAndroid Build Coastguard Worker
4310*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *Curl_multi_get_handle(struct Curl_multi *multi,
4311*6236dae4SAndroid Build Coastguard Worker curl_off_t mid)
4312*6236dae4SAndroid Build Coastguard Worker {
4313*6236dae4SAndroid Build Coastguard Worker
4314*6236dae4SAndroid Build Coastguard Worker if(mid >= 0) {
4315*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data;
4316*6236dae4SAndroid Build Coastguard Worker struct Curl_llist_node *e;
4317*6236dae4SAndroid Build Coastguard Worker
4318*6236dae4SAndroid Build Coastguard Worker for(e = Curl_llist_head(&multi->process); e; e = Curl_node_next(e)) {
4319*6236dae4SAndroid Build Coastguard Worker data = Curl_node_elem(e);
4320*6236dae4SAndroid Build Coastguard Worker if(data->mid == mid)
4321*6236dae4SAndroid Build Coastguard Worker return data;
4322*6236dae4SAndroid Build Coastguard Worker }
4323*6236dae4SAndroid Build Coastguard Worker /* may be in msgsent queue */
4324*6236dae4SAndroid Build Coastguard Worker for(e = Curl_llist_head(&multi->msgsent); e; e = Curl_node_next(e)) {
4325*6236dae4SAndroid Build Coastguard Worker data = Curl_node_elem(e);
4326*6236dae4SAndroid Build Coastguard Worker if(data->mid == mid)
4327*6236dae4SAndroid Build Coastguard Worker return data;
4328*6236dae4SAndroid Build Coastguard Worker }
4329*6236dae4SAndroid Build Coastguard Worker /* may be in pending queue */
4330*6236dae4SAndroid Build Coastguard Worker for(e = Curl_llist_head(&multi->pending); e; e = Curl_node_next(e)) {
4331*6236dae4SAndroid Build Coastguard Worker data = Curl_node_elem(e);
4332*6236dae4SAndroid Build Coastguard Worker if(data->mid == mid)
4333*6236dae4SAndroid Build Coastguard Worker return data;
4334*6236dae4SAndroid Build Coastguard Worker }
4335*6236dae4SAndroid Build Coastguard Worker }
4336*6236dae4SAndroid Build Coastguard Worker return NULL;
4337*6236dae4SAndroid Build Coastguard Worker }
4338