xref: /aosp_15_r20/external/curl/lib/multi.c (revision 6236dae45794135f37c4eb022389c904c8b0090d)
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