xref: /aosp_15_r20/external/curl/lib/conncache.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) Linus Nielsen Feltzing, <[email protected]>
9*6236dae4SAndroid Build Coastguard Worker  * Copyright (C) Daniel Stenberg, <[email protected]>, et al.
10*6236dae4SAndroid Build Coastguard Worker  *
11*6236dae4SAndroid Build Coastguard Worker  * This software is licensed as described in the file COPYING, which
12*6236dae4SAndroid Build Coastguard Worker  * you should have received as part of this distribution. The terms
13*6236dae4SAndroid Build Coastguard Worker  * are also available at https://curl.se/docs/copyright.html.
14*6236dae4SAndroid Build Coastguard Worker  *
15*6236dae4SAndroid Build Coastguard Worker  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
16*6236dae4SAndroid Build Coastguard Worker  * copies of the Software, and permit persons to whom the Software is
17*6236dae4SAndroid Build Coastguard Worker  * furnished to do so, under the terms of the COPYING file.
18*6236dae4SAndroid Build Coastguard Worker  *
19*6236dae4SAndroid Build Coastguard Worker  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20*6236dae4SAndroid Build Coastguard Worker  * KIND, either express or implied.
21*6236dae4SAndroid Build Coastguard Worker  *
22*6236dae4SAndroid Build Coastguard Worker  * SPDX-License-Identifier: curl
23*6236dae4SAndroid Build Coastguard Worker  *
24*6236dae4SAndroid Build Coastguard Worker  ***************************************************************************/
25*6236dae4SAndroid Build Coastguard Worker 
26*6236dae4SAndroid Build Coastguard Worker #include "curl_setup.h"
27*6236dae4SAndroid Build Coastguard Worker 
28*6236dae4SAndroid Build Coastguard Worker #include <curl/curl.h>
29*6236dae4SAndroid Build Coastguard Worker 
30*6236dae4SAndroid Build Coastguard Worker #include "urldata.h"
31*6236dae4SAndroid Build Coastguard Worker #include "url.h"
32*6236dae4SAndroid Build Coastguard Worker #include "cfilters.h"
33*6236dae4SAndroid Build Coastguard Worker #include "progress.h"
34*6236dae4SAndroid Build Coastguard Worker #include "multiif.h"
35*6236dae4SAndroid Build Coastguard Worker #include "sendf.h"
36*6236dae4SAndroid Build Coastguard Worker #include "conncache.h"
37*6236dae4SAndroid Build Coastguard Worker #include "http_negotiate.h"
38*6236dae4SAndroid Build Coastguard Worker #include "http_ntlm.h"
39*6236dae4SAndroid Build Coastguard Worker #include "share.h"
40*6236dae4SAndroid Build Coastguard Worker #include "sigpipe.h"
41*6236dae4SAndroid Build Coastguard Worker #include "connect.h"
42*6236dae4SAndroid Build Coastguard Worker #include "select.h"
43*6236dae4SAndroid Build Coastguard Worker #include "strcase.h"
44*6236dae4SAndroid Build Coastguard Worker 
45*6236dae4SAndroid Build Coastguard Worker /* The last 3 #include files should be in this order */
46*6236dae4SAndroid Build Coastguard Worker #include "curl_printf.h"
47*6236dae4SAndroid Build Coastguard Worker #include "curl_memory.h"
48*6236dae4SAndroid Build Coastguard Worker #include "memdebug.h"
49*6236dae4SAndroid Build Coastguard Worker 
50*6236dae4SAndroid Build Coastguard Worker 
51*6236dae4SAndroid Build Coastguard Worker #define CPOOL_IS_LOCKED(c)    ((c) && (c)->locked)
52*6236dae4SAndroid Build Coastguard Worker 
53*6236dae4SAndroid Build Coastguard Worker #define CPOOL_LOCK(c)                                                   \
54*6236dae4SAndroid Build Coastguard Worker   do {                                                                  \
55*6236dae4SAndroid Build Coastguard Worker     if((c)) {                                                           \
56*6236dae4SAndroid Build Coastguard Worker       if(CURL_SHARE_KEEP_CONNECT((c)->share))                           \
57*6236dae4SAndroid Build Coastguard Worker         Curl_share_lock(((c)->idata), CURL_LOCK_DATA_CONNECT,           \
58*6236dae4SAndroid Build Coastguard Worker                         CURL_LOCK_ACCESS_SINGLE);                       \
59*6236dae4SAndroid Build Coastguard Worker       DEBUGASSERT(!(c)->locked);                                        \
60*6236dae4SAndroid Build Coastguard Worker       (c)->locked = TRUE;                                               \
61*6236dae4SAndroid Build Coastguard Worker     }                                                                   \
62*6236dae4SAndroid Build Coastguard Worker   } while(0)
63*6236dae4SAndroid Build Coastguard Worker 
64*6236dae4SAndroid Build Coastguard Worker #define CPOOL_UNLOCK(c)                                                 \
65*6236dae4SAndroid Build Coastguard Worker   do {                                                                  \
66*6236dae4SAndroid Build Coastguard Worker     if((c)) {                                                           \
67*6236dae4SAndroid Build Coastguard Worker       DEBUGASSERT((c)->locked);                                         \
68*6236dae4SAndroid Build Coastguard Worker       (c)->locked = FALSE;                                              \
69*6236dae4SAndroid Build Coastguard Worker       if(CURL_SHARE_KEEP_CONNECT((c)->share))                           \
70*6236dae4SAndroid Build Coastguard Worker         Curl_share_unlock((c)->idata, CURL_LOCK_DATA_CONNECT);          \
71*6236dae4SAndroid Build Coastguard Worker     }                                                                   \
72*6236dae4SAndroid Build Coastguard Worker   } while(0)
73*6236dae4SAndroid Build Coastguard Worker 
74*6236dae4SAndroid Build Coastguard Worker 
75*6236dae4SAndroid Build Coastguard Worker /* A list of connections to the same destination. */
76*6236dae4SAndroid Build Coastguard Worker struct cpool_bundle {
77*6236dae4SAndroid Build Coastguard Worker   struct Curl_llist conns; /* connections in the bundle */
78*6236dae4SAndroid Build Coastguard Worker   size_t dest_len; /* total length of destination, including NUL */
79*6236dae4SAndroid Build Coastguard Worker   char *dest[1]; /* destination of bundle, allocated to keep dest_len bytes */
80*6236dae4SAndroid Build Coastguard Worker };
81*6236dae4SAndroid Build Coastguard Worker 
82*6236dae4SAndroid Build Coastguard Worker 
83*6236dae4SAndroid Build Coastguard Worker static void cpool_discard_conn(struct cpool *cpool,
84*6236dae4SAndroid Build Coastguard Worker                                struct Curl_easy *data,
85*6236dae4SAndroid Build Coastguard Worker                                struct connectdata *conn,
86*6236dae4SAndroid Build Coastguard Worker                                bool aborted);
87*6236dae4SAndroid Build Coastguard Worker static void cpool_close_and_destroy(struct cpool *cpool,
88*6236dae4SAndroid Build Coastguard Worker                                     struct connectdata *conn,
89*6236dae4SAndroid Build Coastguard Worker                                     struct Curl_easy *data,
90*6236dae4SAndroid Build Coastguard Worker                                     bool do_shutdown);
91*6236dae4SAndroid Build Coastguard Worker static void cpool_run_conn_shutdown(struct Curl_easy *data,
92*6236dae4SAndroid Build Coastguard Worker                                     struct connectdata *conn,
93*6236dae4SAndroid Build Coastguard Worker                                     bool *done);
94*6236dae4SAndroid Build Coastguard Worker static void cpool_run_conn_shutdown_handler(struct Curl_easy *data,
95*6236dae4SAndroid Build Coastguard Worker                                             struct connectdata *conn);
96*6236dae4SAndroid Build Coastguard Worker static CURLMcode cpool_update_shutdown_ev(struct Curl_multi *multi,
97*6236dae4SAndroid Build Coastguard Worker                                           struct Curl_easy *data,
98*6236dae4SAndroid Build Coastguard Worker                                           struct connectdata *conn);
99*6236dae4SAndroid Build Coastguard Worker static void cpool_shutdown_all(struct cpool *cpool,
100*6236dae4SAndroid Build Coastguard Worker                                struct Curl_easy *data, int timeout_ms);
101*6236dae4SAndroid Build Coastguard Worker static void cpool_close_and_destroy_all(struct cpool *cpool);
102*6236dae4SAndroid Build Coastguard Worker static struct connectdata *cpool_get_oldest_idle(struct cpool *cpool);
103*6236dae4SAndroid Build Coastguard Worker 
cpool_bundle_create(const char * dest,size_t dest_len)104*6236dae4SAndroid Build Coastguard Worker static struct cpool_bundle *cpool_bundle_create(const char *dest,
105*6236dae4SAndroid Build Coastguard Worker                                                 size_t dest_len)
106*6236dae4SAndroid Build Coastguard Worker {
107*6236dae4SAndroid Build Coastguard Worker   struct cpool_bundle *bundle;
108*6236dae4SAndroid Build Coastguard Worker   bundle = calloc(1, sizeof(*bundle) + dest_len);
109*6236dae4SAndroid Build Coastguard Worker   if(!bundle)
110*6236dae4SAndroid Build Coastguard Worker     return NULL;
111*6236dae4SAndroid Build Coastguard Worker   Curl_llist_init(&bundle->conns, NULL);
112*6236dae4SAndroid Build Coastguard Worker   bundle->dest_len = dest_len;
113*6236dae4SAndroid Build Coastguard Worker   memcpy(bundle->dest, dest, dest_len);
114*6236dae4SAndroid Build Coastguard Worker   return bundle;
115*6236dae4SAndroid Build Coastguard Worker }
116*6236dae4SAndroid Build Coastguard Worker 
cpool_bundle_destroy(struct cpool_bundle * bundle)117*6236dae4SAndroid Build Coastguard Worker static void cpool_bundle_destroy(struct cpool_bundle *bundle)
118*6236dae4SAndroid Build Coastguard Worker {
119*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(!Curl_llist_count(&bundle->conns));
120*6236dae4SAndroid Build Coastguard Worker   free(bundle);
121*6236dae4SAndroid Build Coastguard Worker }
122*6236dae4SAndroid Build Coastguard Worker 
123*6236dae4SAndroid Build Coastguard Worker /* Add a connection to a bundle */
cpool_bundle_add(struct cpool_bundle * bundle,struct connectdata * conn)124*6236dae4SAndroid Build Coastguard Worker static void cpool_bundle_add(struct cpool_bundle *bundle,
125*6236dae4SAndroid Build Coastguard Worker                              struct connectdata *conn)
126*6236dae4SAndroid Build Coastguard Worker {
127*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(!Curl_node_llist(&conn->cpool_node));
128*6236dae4SAndroid Build Coastguard Worker   Curl_llist_append(&bundle->conns, conn, &conn->cpool_node);
129*6236dae4SAndroid Build Coastguard Worker   conn->bits.in_cpool = TRUE;
130*6236dae4SAndroid Build Coastguard Worker }
131*6236dae4SAndroid Build Coastguard Worker 
132*6236dae4SAndroid Build Coastguard Worker /* Remove a connection from a bundle */
cpool_bundle_remove(struct cpool_bundle * bundle,struct connectdata * conn)133*6236dae4SAndroid Build Coastguard Worker static void cpool_bundle_remove(struct cpool_bundle *bundle,
134*6236dae4SAndroid Build Coastguard Worker                                 struct connectdata *conn)
135*6236dae4SAndroid Build Coastguard Worker {
136*6236dae4SAndroid Build Coastguard Worker   (void)bundle;
137*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(Curl_node_llist(&conn->cpool_node) == &bundle->conns);
138*6236dae4SAndroid Build Coastguard Worker   Curl_node_remove(&conn->cpool_node);
139*6236dae4SAndroid Build Coastguard Worker   conn->bits.in_cpool = FALSE;
140*6236dae4SAndroid Build Coastguard Worker }
141*6236dae4SAndroid Build Coastguard Worker 
cpool_bundle_free_entry(void * freethis)142*6236dae4SAndroid Build Coastguard Worker static void cpool_bundle_free_entry(void *freethis)
143*6236dae4SAndroid Build Coastguard Worker {
144*6236dae4SAndroid Build Coastguard Worker   cpool_bundle_destroy((struct cpool_bundle *)freethis);
145*6236dae4SAndroid Build Coastguard Worker }
146*6236dae4SAndroid Build Coastguard Worker 
Curl_cpool_init(struct cpool * cpool,Curl_cpool_disconnect_cb * disconnect_cb,struct Curl_multi * multi,struct Curl_share * share,size_t size)147*6236dae4SAndroid Build Coastguard Worker int Curl_cpool_init(struct cpool *cpool,
148*6236dae4SAndroid Build Coastguard Worker                         Curl_cpool_disconnect_cb *disconnect_cb,
149*6236dae4SAndroid Build Coastguard Worker                         struct Curl_multi *multi,
150*6236dae4SAndroid Build Coastguard Worker                         struct Curl_share *share,
151*6236dae4SAndroid Build Coastguard Worker                         size_t size)
152*6236dae4SAndroid Build Coastguard Worker {
153*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(!!multi != !!share); /* either one */
154*6236dae4SAndroid Build Coastguard Worker   Curl_hash_init(&cpool->dest2bundle, size, Curl_hash_str,
155*6236dae4SAndroid Build Coastguard Worker                  Curl_str_key_compare, cpool_bundle_free_entry);
156*6236dae4SAndroid Build Coastguard Worker   Curl_llist_init(&cpool->shutdowns, NULL);
157*6236dae4SAndroid Build Coastguard Worker 
158*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(disconnect_cb);
159*6236dae4SAndroid Build Coastguard Worker   if(!disconnect_cb)
160*6236dae4SAndroid Build Coastguard Worker     return 1;
161*6236dae4SAndroid Build Coastguard Worker 
162*6236dae4SAndroid Build Coastguard Worker   /* allocate a new easy handle to use when closing cached connections */
163*6236dae4SAndroid Build Coastguard Worker   cpool->idata = curl_easy_init();
164*6236dae4SAndroid Build Coastguard Worker   if(!cpool->idata)
165*6236dae4SAndroid Build Coastguard Worker     return 1; /* bad */
166*6236dae4SAndroid Build Coastguard Worker   cpool->idata->state.internal = TRUE;
167*6236dae4SAndroid Build Coastguard Worker   /* TODO: this is quirky. We need an internal handle for certain
168*6236dae4SAndroid Build Coastguard Worker    * operations, but we do not add it to the multi (if there is one).
169*6236dae4SAndroid Build Coastguard Worker    * But we give it the multi so that socket event operations can work.
170*6236dae4SAndroid Build Coastguard Worker    * Probably better to have an internal handle owned by the multi that
171*6236dae4SAndroid Build Coastguard Worker    * can be used for cpool operations. */
172*6236dae4SAndroid Build Coastguard Worker   cpool->idata->multi = multi;
173*6236dae4SAndroid Build Coastguard Worker #ifdef DEBUGBUILD
174*6236dae4SAndroid Build Coastguard Worker   if(getenv("CURL_DEBUG"))
175*6236dae4SAndroid Build Coastguard Worker     cpool->idata->set.verbose = TRUE;
176*6236dae4SAndroid Build Coastguard Worker #endif
177*6236dae4SAndroid Build Coastguard Worker 
178*6236dae4SAndroid Build Coastguard Worker   cpool->disconnect_cb = disconnect_cb;
179*6236dae4SAndroid Build Coastguard Worker   cpool->idata->multi = cpool->multi = multi;
180*6236dae4SAndroid Build Coastguard Worker   cpool->idata->share = cpool->share = share;
181*6236dae4SAndroid Build Coastguard Worker 
182*6236dae4SAndroid Build Coastguard Worker   return 0; /* good */
183*6236dae4SAndroid Build Coastguard Worker }
184*6236dae4SAndroid Build Coastguard Worker 
Curl_cpool_destroy(struct cpool * cpool)185*6236dae4SAndroid Build Coastguard Worker void Curl_cpool_destroy(struct cpool *cpool)
186*6236dae4SAndroid Build Coastguard Worker {
187*6236dae4SAndroid Build Coastguard Worker   if(cpool) {
188*6236dae4SAndroid Build Coastguard Worker     if(cpool->idata) {
189*6236dae4SAndroid Build Coastguard Worker       cpool_close_and_destroy_all(cpool);
190*6236dae4SAndroid Build Coastguard Worker       /* The internal closure handle is special and we need to
191*6236dae4SAndroid Build Coastguard Worker        * disconnect it from multi/share before closing it down. */
192*6236dae4SAndroid Build Coastguard Worker       cpool->idata->multi = NULL;
193*6236dae4SAndroid Build Coastguard Worker       cpool->idata->share = NULL;
194*6236dae4SAndroid Build Coastguard Worker       Curl_close(&cpool->idata);
195*6236dae4SAndroid Build Coastguard Worker     }
196*6236dae4SAndroid Build Coastguard Worker     Curl_hash_destroy(&cpool->dest2bundle);
197*6236dae4SAndroid Build Coastguard Worker     cpool->multi = NULL;
198*6236dae4SAndroid Build Coastguard Worker   }
199*6236dae4SAndroid Build Coastguard Worker }
200*6236dae4SAndroid Build Coastguard Worker 
cpool_get_instance(struct Curl_easy * data)201*6236dae4SAndroid Build Coastguard Worker static struct cpool *cpool_get_instance(struct Curl_easy *data)
202*6236dae4SAndroid Build Coastguard Worker {
203*6236dae4SAndroid Build Coastguard Worker   if(data) {
204*6236dae4SAndroid Build Coastguard Worker     if(CURL_SHARE_KEEP_CONNECT(data->share))
205*6236dae4SAndroid Build Coastguard Worker       return &data->share->cpool;
206*6236dae4SAndroid Build Coastguard Worker     else if(data->multi_easy)
207*6236dae4SAndroid Build Coastguard Worker       return &data->multi_easy->cpool;
208*6236dae4SAndroid Build Coastguard Worker     else if(data->multi)
209*6236dae4SAndroid Build Coastguard Worker       return &data->multi->cpool;
210*6236dae4SAndroid Build Coastguard Worker   }
211*6236dae4SAndroid Build Coastguard Worker   return NULL;
212*6236dae4SAndroid Build Coastguard Worker }
213*6236dae4SAndroid Build Coastguard Worker 
Curl_cpool_xfer_init(struct Curl_easy * data)214*6236dae4SAndroid Build Coastguard Worker void Curl_cpool_xfer_init(struct Curl_easy *data)
215*6236dae4SAndroid Build Coastguard Worker {
216*6236dae4SAndroid Build Coastguard Worker   struct cpool *cpool = cpool_get_instance(data);
217*6236dae4SAndroid Build Coastguard Worker 
218*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(cpool);
219*6236dae4SAndroid Build Coastguard Worker   if(cpool) {
220*6236dae4SAndroid Build Coastguard Worker     CPOOL_LOCK(cpool);
221*6236dae4SAndroid Build Coastguard Worker     /* the identifier inside the connection cache */
222*6236dae4SAndroid Build Coastguard Worker     data->id = cpool->next_easy_id++;
223*6236dae4SAndroid Build Coastguard Worker     if(cpool->next_easy_id <= 0)
224*6236dae4SAndroid Build Coastguard Worker       cpool->next_easy_id = 0;
225*6236dae4SAndroid Build Coastguard Worker     data->state.lastconnect_id = -1;
226*6236dae4SAndroid Build Coastguard Worker 
227*6236dae4SAndroid Build Coastguard Worker     /* The closure handle only ever has default timeouts set. To improve the
228*6236dae4SAndroid Build Coastguard Worker        state somewhat we clone the timeouts from each added handle so that the
229*6236dae4SAndroid Build Coastguard Worker        closure handle always has the same timeouts as the most recently added
230*6236dae4SAndroid Build Coastguard Worker        easy handle. */
231*6236dae4SAndroid Build Coastguard Worker     cpool->idata->set.timeout = data->set.timeout;
232*6236dae4SAndroid Build Coastguard Worker     cpool->idata->set.server_response_timeout =
233*6236dae4SAndroid Build Coastguard Worker       data->set.server_response_timeout;
234*6236dae4SAndroid Build Coastguard Worker     cpool->idata->set.no_signal = data->set.no_signal;
235*6236dae4SAndroid Build Coastguard Worker 
236*6236dae4SAndroid Build Coastguard Worker     CPOOL_UNLOCK(cpool);
237*6236dae4SAndroid Build Coastguard Worker   }
238*6236dae4SAndroid Build Coastguard Worker   else {
239*6236dae4SAndroid Build Coastguard Worker     /* We should not get here, but in a non-debug build, do something */
240*6236dae4SAndroid Build Coastguard Worker     data->id = 0;
241*6236dae4SAndroid Build Coastguard Worker     data->state.lastconnect_id = -1;
242*6236dae4SAndroid Build Coastguard Worker   }
243*6236dae4SAndroid Build Coastguard Worker }
244*6236dae4SAndroid Build Coastguard Worker 
cpool_find_bundle(struct cpool * cpool,struct connectdata * conn)245*6236dae4SAndroid Build Coastguard Worker static struct cpool_bundle *cpool_find_bundle(struct cpool *cpool,
246*6236dae4SAndroid Build Coastguard Worker                                               struct connectdata *conn)
247*6236dae4SAndroid Build Coastguard Worker {
248*6236dae4SAndroid Build Coastguard Worker   return Curl_hash_pick(&cpool->dest2bundle,
249*6236dae4SAndroid Build Coastguard Worker                         conn->destination, conn->destination_len);
250*6236dae4SAndroid Build Coastguard Worker }
251*6236dae4SAndroid Build Coastguard Worker 
252*6236dae4SAndroid Build Coastguard Worker static struct cpool_bundle *
cpool_add_bundle(struct cpool * cpool,struct connectdata * conn)253*6236dae4SAndroid Build Coastguard Worker cpool_add_bundle(struct cpool *cpool, struct connectdata *conn)
254*6236dae4SAndroid Build Coastguard Worker {
255*6236dae4SAndroid Build Coastguard Worker   struct cpool_bundle *bundle;
256*6236dae4SAndroid Build Coastguard Worker 
257*6236dae4SAndroid Build Coastguard Worker   bundle = cpool_bundle_create(conn->destination, conn->destination_len);
258*6236dae4SAndroid Build Coastguard Worker   if(!bundle)
259*6236dae4SAndroid Build Coastguard Worker     return NULL;
260*6236dae4SAndroid Build Coastguard Worker 
261*6236dae4SAndroid Build Coastguard Worker   if(!Curl_hash_add(&cpool->dest2bundle,
262*6236dae4SAndroid Build Coastguard Worker                     bundle->dest, bundle->dest_len, bundle)) {
263*6236dae4SAndroid Build Coastguard Worker     cpool_bundle_destroy(bundle);
264*6236dae4SAndroid Build Coastguard Worker     return NULL;
265*6236dae4SAndroid Build Coastguard Worker   }
266*6236dae4SAndroid Build Coastguard Worker   return bundle;
267*6236dae4SAndroid Build Coastguard Worker }
268*6236dae4SAndroid Build Coastguard Worker 
cpool_remove_bundle(struct cpool * cpool,struct cpool_bundle * bundle)269*6236dae4SAndroid Build Coastguard Worker static void cpool_remove_bundle(struct cpool *cpool,
270*6236dae4SAndroid Build Coastguard Worker                                 struct cpool_bundle *bundle)
271*6236dae4SAndroid Build Coastguard Worker {
272*6236dae4SAndroid Build Coastguard Worker   if(!cpool)
273*6236dae4SAndroid Build Coastguard Worker     return;
274*6236dae4SAndroid Build Coastguard Worker 
275*6236dae4SAndroid Build Coastguard Worker   Curl_hash_delete(&cpool->dest2bundle, bundle->dest, bundle->dest_len);
276*6236dae4SAndroid Build Coastguard Worker }
277*6236dae4SAndroid Build Coastguard Worker 
278*6236dae4SAndroid Build Coastguard Worker static struct connectdata *
279*6236dae4SAndroid Build Coastguard Worker cpool_bundle_get_oldest_idle(struct cpool_bundle *bundle);
280*6236dae4SAndroid Build Coastguard Worker 
Curl_cpool_check_limits(struct Curl_easy * data,struct connectdata * conn)281*6236dae4SAndroid Build Coastguard Worker int Curl_cpool_check_limits(struct Curl_easy *data,
282*6236dae4SAndroid Build Coastguard Worker                             struct connectdata *conn)
283*6236dae4SAndroid Build Coastguard Worker {
284*6236dae4SAndroid Build Coastguard Worker   struct cpool *cpool = cpool_get_instance(data);
285*6236dae4SAndroid Build Coastguard Worker   struct cpool_bundle *bundle;
286*6236dae4SAndroid Build Coastguard Worker   size_t dest_limit = 0;
287*6236dae4SAndroid Build Coastguard Worker   size_t total_limit = 0;
288*6236dae4SAndroid Build Coastguard Worker   int result = CPOOL_LIMIT_OK;
289*6236dae4SAndroid Build Coastguard Worker 
290*6236dae4SAndroid Build Coastguard Worker   if(!cpool)
291*6236dae4SAndroid Build Coastguard Worker     return CPOOL_LIMIT_OK;
292*6236dae4SAndroid Build Coastguard Worker 
293*6236dae4SAndroid Build Coastguard Worker   if(data && data->multi) {
294*6236dae4SAndroid Build Coastguard Worker     dest_limit = data->multi->max_host_connections;
295*6236dae4SAndroid Build Coastguard Worker     total_limit = data->multi->max_total_connections;
296*6236dae4SAndroid Build Coastguard Worker   }
297*6236dae4SAndroid Build Coastguard Worker 
298*6236dae4SAndroid Build Coastguard Worker   if(!dest_limit && !total_limit)
299*6236dae4SAndroid Build Coastguard Worker     return CPOOL_LIMIT_OK;
300*6236dae4SAndroid Build Coastguard Worker 
301*6236dae4SAndroid Build Coastguard Worker   CPOOL_LOCK(cpool);
302*6236dae4SAndroid Build Coastguard Worker   if(dest_limit) {
303*6236dae4SAndroid Build Coastguard Worker     bundle = cpool_find_bundle(cpool, conn);
304*6236dae4SAndroid Build Coastguard Worker     while(bundle && (Curl_llist_count(&bundle->conns) >= dest_limit)) {
305*6236dae4SAndroid Build Coastguard Worker       struct connectdata *oldest_idle = NULL;
306*6236dae4SAndroid Build Coastguard Worker       /* The bundle is full. Extract the oldest connection that may
307*6236dae4SAndroid Build Coastguard Worker        * be removed now, if there is one. */
308*6236dae4SAndroid Build Coastguard Worker       oldest_idle = cpool_bundle_get_oldest_idle(bundle);
309*6236dae4SAndroid Build Coastguard Worker       if(!oldest_idle)
310*6236dae4SAndroid Build Coastguard Worker         break;
311*6236dae4SAndroid Build Coastguard Worker       /* disconnect the old conn and continue */
312*6236dae4SAndroid Build Coastguard Worker       DEBUGF(infof(data, "Discarding connection #%"
313*6236dae4SAndroid Build Coastguard Worker                    FMT_OFF_T " from %zu to reach destination "
314*6236dae4SAndroid Build Coastguard Worker                    "limit of %zu", oldest_idle->connection_id,
315*6236dae4SAndroid Build Coastguard Worker                    Curl_llist_count(&bundle->conns), dest_limit));
316*6236dae4SAndroid Build Coastguard Worker       Curl_cpool_disconnect(data, oldest_idle, FALSE);
317*6236dae4SAndroid Build Coastguard Worker 
318*6236dae4SAndroid Build Coastguard Worker       /* in case the bundle was destroyed in disconnect, look it up again */
319*6236dae4SAndroid Build Coastguard Worker       bundle = cpool_find_bundle(cpool, conn);
320*6236dae4SAndroid Build Coastguard Worker     }
321*6236dae4SAndroid Build Coastguard Worker     if(bundle && (Curl_llist_count(&bundle->conns) >= dest_limit)) {
322*6236dae4SAndroid Build Coastguard Worker       result = CPOOL_LIMIT_DEST;
323*6236dae4SAndroid Build Coastguard Worker       goto out;
324*6236dae4SAndroid Build Coastguard Worker     }
325*6236dae4SAndroid Build Coastguard Worker   }
326*6236dae4SAndroid Build Coastguard Worker 
327*6236dae4SAndroid Build Coastguard Worker   if(total_limit) {
328*6236dae4SAndroid Build Coastguard Worker     while(cpool->num_conn >= total_limit) {
329*6236dae4SAndroid Build Coastguard Worker       struct connectdata *oldest_idle = cpool_get_oldest_idle(cpool);
330*6236dae4SAndroid Build Coastguard Worker       if(!oldest_idle)
331*6236dae4SAndroid Build Coastguard Worker         break;
332*6236dae4SAndroid Build Coastguard Worker       /* disconnect the old conn and continue */
333*6236dae4SAndroid Build Coastguard Worker       DEBUGF(infof(data, "Discarding connection #%"
334*6236dae4SAndroid Build Coastguard Worker                    FMT_OFF_T " from %zu to reach total "
335*6236dae4SAndroid Build Coastguard Worker                    "limit of %zu",
336*6236dae4SAndroid Build Coastguard Worker                    oldest_idle->connection_id, cpool->num_conn, total_limit));
337*6236dae4SAndroid Build Coastguard Worker       Curl_cpool_disconnect(data, oldest_idle, FALSE);
338*6236dae4SAndroid Build Coastguard Worker     }
339*6236dae4SAndroid Build Coastguard Worker     if(cpool->num_conn >= total_limit) {
340*6236dae4SAndroid Build Coastguard Worker       result = CPOOL_LIMIT_TOTAL;
341*6236dae4SAndroid Build Coastguard Worker       goto out;
342*6236dae4SAndroid Build Coastguard Worker     }
343*6236dae4SAndroid Build Coastguard Worker   }
344*6236dae4SAndroid Build Coastguard Worker 
345*6236dae4SAndroid Build Coastguard Worker out:
346*6236dae4SAndroid Build Coastguard Worker   CPOOL_UNLOCK(cpool);
347*6236dae4SAndroid Build Coastguard Worker   return result;
348*6236dae4SAndroid Build Coastguard Worker }
349*6236dae4SAndroid Build Coastguard Worker 
Curl_cpool_add_conn(struct Curl_easy * data,struct connectdata * conn)350*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_cpool_add_conn(struct Curl_easy *data,
351*6236dae4SAndroid Build Coastguard Worker                              struct connectdata *conn)
352*6236dae4SAndroid Build Coastguard Worker {
353*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OK;
354*6236dae4SAndroid Build Coastguard Worker   struct cpool_bundle *bundle = NULL;
355*6236dae4SAndroid Build Coastguard Worker   struct cpool *cpool = cpool_get_instance(data);
356*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(conn);
357*6236dae4SAndroid Build Coastguard Worker 
358*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(cpool);
359*6236dae4SAndroid Build Coastguard Worker   if(!cpool)
360*6236dae4SAndroid Build Coastguard Worker     return CURLE_FAILED_INIT;
361*6236dae4SAndroid Build Coastguard Worker 
362*6236dae4SAndroid Build Coastguard Worker   CPOOL_LOCK(cpool);
363*6236dae4SAndroid Build Coastguard Worker   bundle = cpool_find_bundle(cpool, conn);
364*6236dae4SAndroid Build Coastguard Worker   if(!bundle) {
365*6236dae4SAndroid Build Coastguard Worker     bundle = cpool_add_bundle(cpool, conn);
366*6236dae4SAndroid Build Coastguard Worker     if(!bundle) {
367*6236dae4SAndroid Build Coastguard Worker       result = CURLE_OUT_OF_MEMORY;
368*6236dae4SAndroid Build Coastguard Worker       goto out;
369*6236dae4SAndroid Build Coastguard Worker     }
370*6236dae4SAndroid Build Coastguard Worker   }
371*6236dae4SAndroid Build Coastguard Worker 
372*6236dae4SAndroid Build Coastguard Worker   cpool_bundle_add(bundle, conn);
373*6236dae4SAndroid Build Coastguard Worker   conn->connection_id = cpool->next_connection_id++;
374*6236dae4SAndroid Build Coastguard Worker   cpool->num_conn++;
375*6236dae4SAndroid Build Coastguard Worker   DEBUGF(infof(data, "Added connection %" FMT_OFF_T ". "
376*6236dae4SAndroid Build Coastguard Worker                "The cache now contains %zu members",
377*6236dae4SAndroid Build Coastguard Worker                conn->connection_id, cpool->num_conn));
378*6236dae4SAndroid Build Coastguard Worker out:
379*6236dae4SAndroid Build Coastguard Worker   CPOOL_UNLOCK(cpool);
380*6236dae4SAndroid Build Coastguard Worker 
381*6236dae4SAndroid Build Coastguard Worker   return result;
382*6236dae4SAndroid Build Coastguard Worker }
383*6236dae4SAndroid Build Coastguard Worker 
cpool_remove_conn(struct cpool * cpool,struct connectdata * conn)384*6236dae4SAndroid Build Coastguard Worker static void cpool_remove_conn(struct cpool *cpool,
385*6236dae4SAndroid Build Coastguard Worker                               struct connectdata *conn)
386*6236dae4SAndroid Build Coastguard Worker {
387*6236dae4SAndroid Build Coastguard Worker   struct Curl_llist *list = Curl_node_llist(&conn->cpool_node);
388*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(cpool);
389*6236dae4SAndroid Build Coastguard Worker   if(list) {
390*6236dae4SAndroid Build Coastguard Worker     /* The connection is certainly in the pool, but where? */
391*6236dae4SAndroid Build Coastguard Worker     struct cpool_bundle *bundle = cpool_find_bundle(cpool, conn);
392*6236dae4SAndroid Build Coastguard Worker     if(bundle && (list == &bundle->conns)) {
393*6236dae4SAndroid Build Coastguard Worker       cpool_bundle_remove(bundle, conn);
394*6236dae4SAndroid Build Coastguard Worker       if(!Curl_llist_count(&bundle->conns))
395*6236dae4SAndroid Build Coastguard Worker         cpool_remove_bundle(cpool, bundle);
396*6236dae4SAndroid Build Coastguard Worker       conn->bits.in_cpool = FALSE;
397*6236dae4SAndroid Build Coastguard Worker       cpool->num_conn--;
398*6236dae4SAndroid Build Coastguard Worker     }
399*6236dae4SAndroid Build Coastguard Worker     else {
400*6236dae4SAndroid Build Coastguard Worker       /* Not in a bundle, already in the shutdown list? */
401*6236dae4SAndroid Build Coastguard Worker       DEBUGASSERT(list == &cpool->shutdowns);
402*6236dae4SAndroid Build Coastguard Worker     }
403*6236dae4SAndroid Build Coastguard Worker   }
404*6236dae4SAndroid Build Coastguard Worker }
405*6236dae4SAndroid Build Coastguard Worker 
406*6236dae4SAndroid Build Coastguard Worker /* This function iterates the entire connection pool and calls the function
407*6236dae4SAndroid Build Coastguard Worker    func() with the connection pointer as the first argument and the supplied
408*6236dae4SAndroid Build Coastguard Worker    'param' argument as the other.
409*6236dae4SAndroid Build Coastguard Worker 
410*6236dae4SAndroid Build Coastguard Worker    The cpool lock is still held when the callback is called. It needs it,
411*6236dae4SAndroid Build Coastguard Worker    so that it can safely continue traversing the lists once the callback
412*6236dae4SAndroid Build Coastguard Worker    returns.
413*6236dae4SAndroid Build Coastguard Worker 
414*6236dae4SAndroid Build Coastguard Worker    Returns TRUE if the loop was aborted due to the callback's return code.
415*6236dae4SAndroid Build Coastguard Worker 
416*6236dae4SAndroid Build Coastguard Worker    Return 0 from func() to continue the loop, return 1 to abort it.
417*6236dae4SAndroid Build Coastguard Worker  */
cpool_foreach(struct Curl_easy * data,struct cpool * cpool,void * param,int (* func)(struct Curl_easy * data,struct connectdata * conn,void * param))418*6236dae4SAndroid Build Coastguard Worker static bool cpool_foreach(struct Curl_easy *data,
419*6236dae4SAndroid Build Coastguard Worker                           struct cpool *cpool,
420*6236dae4SAndroid Build Coastguard Worker                           void *param,
421*6236dae4SAndroid Build Coastguard Worker                           int (*func)(struct Curl_easy *data,
422*6236dae4SAndroid Build Coastguard Worker                                       struct connectdata *conn, void *param))
423*6236dae4SAndroid Build Coastguard Worker {
424*6236dae4SAndroid Build Coastguard Worker   struct Curl_hash_iterator iter;
425*6236dae4SAndroid Build Coastguard Worker   struct Curl_hash_element *he;
426*6236dae4SAndroid Build Coastguard Worker 
427*6236dae4SAndroid Build Coastguard Worker   if(!cpool)
428*6236dae4SAndroid Build Coastguard Worker     return FALSE;
429*6236dae4SAndroid Build Coastguard Worker 
430*6236dae4SAndroid Build Coastguard Worker   Curl_hash_start_iterate(&cpool->dest2bundle, &iter);
431*6236dae4SAndroid Build Coastguard Worker 
432*6236dae4SAndroid Build Coastguard Worker   he = Curl_hash_next_element(&iter);
433*6236dae4SAndroid Build Coastguard Worker   while(he) {
434*6236dae4SAndroid Build Coastguard Worker     struct Curl_llist_node *curr;
435*6236dae4SAndroid Build Coastguard Worker     struct cpool_bundle *bundle = he->ptr;
436*6236dae4SAndroid Build Coastguard Worker     he = Curl_hash_next_element(&iter);
437*6236dae4SAndroid Build Coastguard Worker 
438*6236dae4SAndroid Build Coastguard Worker     curr = Curl_llist_head(&bundle->conns);
439*6236dae4SAndroid Build Coastguard Worker     while(curr) {
440*6236dae4SAndroid Build Coastguard Worker       /* Yes, we need to update curr before calling func(), because func()
441*6236dae4SAndroid Build Coastguard Worker          might decide to remove the connection */
442*6236dae4SAndroid Build Coastguard Worker       struct connectdata *conn = Curl_node_elem(curr);
443*6236dae4SAndroid Build Coastguard Worker       curr = Curl_node_next(curr);
444*6236dae4SAndroid Build Coastguard Worker 
445*6236dae4SAndroid Build Coastguard Worker       if(1 == func(data, conn, param)) {
446*6236dae4SAndroid Build Coastguard Worker         return TRUE;
447*6236dae4SAndroid Build Coastguard Worker       }
448*6236dae4SAndroid Build Coastguard Worker     }
449*6236dae4SAndroid Build Coastguard Worker   }
450*6236dae4SAndroid Build Coastguard Worker   return FALSE;
451*6236dae4SAndroid Build Coastguard Worker }
452*6236dae4SAndroid Build Coastguard Worker 
453*6236dae4SAndroid Build Coastguard Worker /* Return a live connection in the pool or NULL. */
cpool_get_live_conn(struct cpool * cpool)454*6236dae4SAndroid Build Coastguard Worker static struct connectdata *cpool_get_live_conn(struct cpool *cpool)
455*6236dae4SAndroid Build Coastguard Worker {
456*6236dae4SAndroid Build Coastguard Worker   struct Curl_hash_iterator iter;
457*6236dae4SAndroid Build Coastguard Worker   struct Curl_hash_element *he;
458*6236dae4SAndroid Build Coastguard Worker   struct cpool_bundle *bundle;
459*6236dae4SAndroid Build Coastguard Worker   struct Curl_llist_node *conn_node;
460*6236dae4SAndroid Build Coastguard Worker 
461*6236dae4SAndroid Build Coastguard Worker   Curl_hash_start_iterate(&cpool->dest2bundle, &iter);
462*6236dae4SAndroid Build Coastguard Worker   for(he = Curl_hash_next_element(&iter); he;
463*6236dae4SAndroid Build Coastguard Worker       he = Curl_hash_next_element(&iter)) {
464*6236dae4SAndroid Build Coastguard Worker     bundle = he->ptr;
465*6236dae4SAndroid Build Coastguard Worker     conn_node = Curl_llist_head(&bundle->conns);
466*6236dae4SAndroid Build Coastguard Worker     if(conn_node)
467*6236dae4SAndroid Build Coastguard Worker       return Curl_node_elem(conn_node);
468*6236dae4SAndroid Build Coastguard Worker   }
469*6236dae4SAndroid Build Coastguard Worker   return NULL;
470*6236dae4SAndroid Build Coastguard Worker }
471*6236dae4SAndroid Build Coastguard Worker 
472*6236dae4SAndroid Build Coastguard Worker /*
473*6236dae4SAndroid Build Coastguard Worker  * A connection (already in the pool) has become idle. Do any
474*6236dae4SAndroid Build Coastguard Worker  * cleanups in regard to the pool's limits.
475*6236dae4SAndroid Build Coastguard Worker  *
476*6236dae4SAndroid Build Coastguard Worker  * Return TRUE if idle connection kept in pool, FALSE if closed.
477*6236dae4SAndroid Build Coastguard Worker  */
Curl_cpool_conn_now_idle(struct Curl_easy * data,struct connectdata * conn)478*6236dae4SAndroid Build Coastguard Worker bool Curl_cpool_conn_now_idle(struct Curl_easy *data,
479*6236dae4SAndroid Build Coastguard Worker                               struct connectdata *conn)
480*6236dae4SAndroid Build Coastguard Worker {
481*6236dae4SAndroid Build Coastguard Worker   unsigned int maxconnects = !data->multi->maxconnects ?
482*6236dae4SAndroid Build Coastguard Worker     data->multi->num_easy * 4 : data->multi->maxconnects;
483*6236dae4SAndroid Build Coastguard Worker   struct connectdata *oldest_idle = NULL;
484*6236dae4SAndroid Build Coastguard Worker   struct cpool *cpool = cpool_get_instance(data);
485*6236dae4SAndroid Build Coastguard Worker   bool kept = TRUE;
486*6236dae4SAndroid Build Coastguard Worker 
487*6236dae4SAndroid Build Coastguard Worker   conn->lastused = Curl_now(); /* it was used up until now */
488*6236dae4SAndroid Build Coastguard Worker   if(cpool && maxconnects) {
489*6236dae4SAndroid Build Coastguard Worker     /* may be called form a callback already under lock */
490*6236dae4SAndroid Build Coastguard Worker     bool do_lock = !CPOOL_IS_LOCKED(cpool);
491*6236dae4SAndroid Build Coastguard Worker     if(do_lock)
492*6236dae4SAndroid Build Coastguard Worker       CPOOL_LOCK(cpool);
493*6236dae4SAndroid Build Coastguard Worker     if(cpool->num_conn > maxconnects) {
494*6236dae4SAndroid Build Coastguard Worker       infof(data, "Connection pool is full, closing the oldest one");
495*6236dae4SAndroid Build Coastguard Worker 
496*6236dae4SAndroid Build Coastguard Worker       oldest_idle = cpool_get_oldest_idle(cpool);
497*6236dae4SAndroid Build Coastguard Worker       kept = (oldest_idle != conn);
498*6236dae4SAndroid Build Coastguard Worker       if(oldest_idle) {
499*6236dae4SAndroid Build Coastguard Worker         Curl_cpool_disconnect(cpool->idata, oldest_idle, FALSE);
500*6236dae4SAndroid Build Coastguard Worker       }
501*6236dae4SAndroid Build Coastguard Worker     }
502*6236dae4SAndroid Build Coastguard Worker     if(do_lock)
503*6236dae4SAndroid Build Coastguard Worker       CPOOL_UNLOCK(cpool);
504*6236dae4SAndroid Build Coastguard Worker   }
505*6236dae4SAndroid Build Coastguard Worker 
506*6236dae4SAndroid Build Coastguard Worker   return kept;
507*6236dae4SAndroid Build Coastguard Worker }
508*6236dae4SAndroid Build Coastguard Worker 
509*6236dae4SAndroid Build Coastguard Worker /*
510*6236dae4SAndroid Build Coastguard Worker  * This function finds the connection in the connection bundle that has been
511*6236dae4SAndroid Build Coastguard Worker  * unused for the longest time.
512*6236dae4SAndroid Build Coastguard Worker  */
513*6236dae4SAndroid Build Coastguard Worker static struct connectdata *
cpool_bundle_get_oldest_idle(struct cpool_bundle * bundle)514*6236dae4SAndroid Build Coastguard Worker cpool_bundle_get_oldest_idle(struct cpool_bundle *bundle)
515*6236dae4SAndroid Build Coastguard Worker {
516*6236dae4SAndroid Build Coastguard Worker   struct Curl_llist_node *curr;
517*6236dae4SAndroid Build Coastguard Worker   timediff_t highscore = -1;
518*6236dae4SAndroid Build Coastguard Worker   timediff_t score;
519*6236dae4SAndroid Build Coastguard Worker   struct curltime now;
520*6236dae4SAndroid Build Coastguard Worker   struct connectdata *oldest_idle = NULL;
521*6236dae4SAndroid Build Coastguard Worker   struct connectdata *conn;
522*6236dae4SAndroid Build Coastguard Worker 
523*6236dae4SAndroid Build Coastguard Worker   now = Curl_now();
524*6236dae4SAndroid Build Coastguard Worker   curr = Curl_llist_head(&bundle->conns);
525*6236dae4SAndroid Build Coastguard Worker   while(curr) {
526*6236dae4SAndroid Build Coastguard Worker     conn = Curl_node_elem(curr);
527*6236dae4SAndroid Build Coastguard Worker 
528*6236dae4SAndroid Build Coastguard Worker     if(!CONN_INUSE(conn)) {
529*6236dae4SAndroid Build Coastguard Worker       /* Set higher score for the age passed since the connection was used */
530*6236dae4SAndroid Build Coastguard Worker       score = Curl_timediff(now, conn->lastused);
531*6236dae4SAndroid Build Coastguard Worker 
532*6236dae4SAndroid Build Coastguard Worker       if(score > highscore) {
533*6236dae4SAndroid Build Coastguard Worker         highscore = score;
534*6236dae4SAndroid Build Coastguard Worker         oldest_idle = conn;
535*6236dae4SAndroid Build Coastguard Worker       }
536*6236dae4SAndroid Build Coastguard Worker     }
537*6236dae4SAndroid Build Coastguard Worker     curr = Curl_node_next(curr);
538*6236dae4SAndroid Build Coastguard Worker   }
539*6236dae4SAndroid Build Coastguard Worker   return oldest_idle;
540*6236dae4SAndroid Build Coastguard Worker }
541*6236dae4SAndroid Build Coastguard Worker 
cpool_get_oldest_idle(struct cpool * cpool)542*6236dae4SAndroid Build Coastguard Worker static struct connectdata *cpool_get_oldest_idle(struct cpool *cpool)
543*6236dae4SAndroid Build Coastguard Worker {
544*6236dae4SAndroid Build Coastguard Worker   struct Curl_hash_iterator iter;
545*6236dae4SAndroid Build Coastguard Worker   struct Curl_llist_node *curr;
546*6236dae4SAndroid Build Coastguard Worker   struct Curl_hash_element *he;
547*6236dae4SAndroid Build Coastguard Worker   struct connectdata *oldest_idle = NULL;
548*6236dae4SAndroid Build Coastguard Worker   struct cpool_bundle *bundle;
549*6236dae4SAndroid Build Coastguard Worker   struct curltime now;
550*6236dae4SAndroid Build Coastguard Worker   timediff_t highscore =- 1;
551*6236dae4SAndroid Build Coastguard Worker   timediff_t score;
552*6236dae4SAndroid Build Coastguard Worker 
553*6236dae4SAndroid Build Coastguard Worker   now = Curl_now();
554*6236dae4SAndroid Build Coastguard Worker   Curl_hash_start_iterate(&cpool->dest2bundle, &iter);
555*6236dae4SAndroid Build Coastguard Worker 
556*6236dae4SAndroid Build Coastguard Worker   for(he = Curl_hash_next_element(&iter); he;
557*6236dae4SAndroid Build Coastguard Worker       he = Curl_hash_next_element(&iter)) {
558*6236dae4SAndroid Build Coastguard Worker     struct connectdata *conn;
559*6236dae4SAndroid Build Coastguard Worker     bundle = he->ptr;
560*6236dae4SAndroid Build Coastguard Worker 
561*6236dae4SAndroid Build Coastguard Worker     for(curr = Curl_llist_head(&bundle->conns); curr;
562*6236dae4SAndroid Build Coastguard Worker         curr = Curl_node_next(curr)) {
563*6236dae4SAndroid Build Coastguard Worker       conn = Curl_node_elem(curr);
564*6236dae4SAndroid Build Coastguard Worker       if(CONN_INUSE(conn) || conn->bits.close || conn->connect_only)
565*6236dae4SAndroid Build Coastguard Worker         continue;
566*6236dae4SAndroid Build Coastguard Worker       /* Set higher score for the age passed since the connection was used */
567*6236dae4SAndroid Build Coastguard Worker       score = Curl_timediff(now, conn->lastused);
568*6236dae4SAndroid Build Coastguard Worker       if(score > highscore) {
569*6236dae4SAndroid Build Coastguard Worker         highscore = score;
570*6236dae4SAndroid Build Coastguard Worker         oldest_idle = conn;
571*6236dae4SAndroid Build Coastguard Worker       }
572*6236dae4SAndroid Build Coastguard Worker     }
573*6236dae4SAndroid Build Coastguard Worker   }
574*6236dae4SAndroid Build Coastguard Worker   return oldest_idle;
575*6236dae4SAndroid Build Coastguard Worker }
576*6236dae4SAndroid Build Coastguard Worker 
Curl_cpool_find(struct Curl_easy * data,const char * destination,size_t dest_len,Curl_cpool_conn_match_cb * conn_cb,Curl_cpool_done_match_cb * done_cb,void * userdata)577*6236dae4SAndroid Build Coastguard Worker bool Curl_cpool_find(struct Curl_easy *data,
578*6236dae4SAndroid Build Coastguard Worker                      const char *destination, size_t dest_len,
579*6236dae4SAndroid Build Coastguard Worker                      Curl_cpool_conn_match_cb *conn_cb,
580*6236dae4SAndroid Build Coastguard Worker                      Curl_cpool_done_match_cb *done_cb,
581*6236dae4SAndroid Build Coastguard Worker                      void *userdata)
582*6236dae4SAndroid Build Coastguard Worker {
583*6236dae4SAndroid Build Coastguard Worker   struct cpool *cpool = cpool_get_instance(data);
584*6236dae4SAndroid Build Coastguard Worker   struct cpool_bundle *bundle;
585*6236dae4SAndroid Build Coastguard Worker   bool result = FALSE;
586*6236dae4SAndroid Build Coastguard Worker 
587*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(cpool);
588*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(conn_cb);
589*6236dae4SAndroid Build Coastguard Worker   if(!cpool)
590*6236dae4SAndroid Build Coastguard Worker     return FALSE;
591*6236dae4SAndroid Build Coastguard Worker 
592*6236dae4SAndroid Build Coastguard Worker   CPOOL_LOCK(cpool);
593*6236dae4SAndroid Build Coastguard Worker   bundle = Curl_hash_pick(&cpool->dest2bundle, (void *)destination, dest_len);
594*6236dae4SAndroid Build Coastguard Worker   if(bundle) {
595*6236dae4SAndroid Build Coastguard Worker     struct Curl_llist_node *curr = Curl_llist_head(&bundle->conns);
596*6236dae4SAndroid Build Coastguard Worker     while(curr) {
597*6236dae4SAndroid Build Coastguard Worker       struct connectdata *conn = Curl_node_elem(curr);
598*6236dae4SAndroid Build Coastguard Worker       /* Get next node now. callback might discard current */
599*6236dae4SAndroid Build Coastguard Worker       curr = Curl_node_next(curr);
600*6236dae4SAndroid Build Coastguard Worker 
601*6236dae4SAndroid Build Coastguard Worker       if(conn_cb(conn, userdata)) {
602*6236dae4SAndroid Build Coastguard Worker         result = TRUE;
603*6236dae4SAndroid Build Coastguard Worker         break;
604*6236dae4SAndroid Build Coastguard Worker       }
605*6236dae4SAndroid Build Coastguard Worker     }
606*6236dae4SAndroid Build Coastguard Worker   }
607*6236dae4SAndroid Build Coastguard Worker 
608*6236dae4SAndroid Build Coastguard Worker   if(done_cb) {
609*6236dae4SAndroid Build Coastguard Worker     result = done_cb(result, userdata);
610*6236dae4SAndroid Build Coastguard Worker   }
611*6236dae4SAndroid Build Coastguard Worker   CPOOL_UNLOCK(cpool);
612*6236dae4SAndroid Build Coastguard Worker   return result;
613*6236dae4SAndroid Build Coastguard Worker }
614*6236dae4SAndroid Build Coastguard Worker 
cpool_shutdown_discard_all(struct cpool * cpool)615*6236dae4SAndroid Build Coastguard Worker static void cpool_shutdown_discard_all(struct cpool *cpool)
616*6236dae4SAndroid Build Coastguard Worker {
617*6236dae4SAndroid Build Coastguard Worker   struct Curl_llist_node *e = Curl_llist_head(&cpool->shutdowns);
618*6236dae4SAndroid Build Coastguard Worker   struct connectdata *conn;
619*6236dae4SAndroid Build Coastguard Worker 
620*6236dae4SAndroid Build Coastguard Worker   if(!e)
621*6236dae4SAndroid Build Coastguard Worker     return;
622*6236dae4SAndroid Build Coastguard Worker 
623*6236dae4SAndroid Build Coastguard Worker   DEBUGF(infof(cpool->idata, "cpool_shutdown_discard_all"));
624*6236dae4SAndroid Build Coastguard Worker   while(e) {
625*6236dae4SAndroid Build Coastguard Worker     conn = Curl_node_elem(e);
626*6236dae4SAndroid Build Coastguard Worker     Curl_node_remove(e);
627*6236dae4SAndroid Build Coastguard Worker     DEBUGF(infof(cpool->idata, "discard connection #%" FMT_OFF_T,
628*6236dae4SAndroid Build Coastguard Worker                  conn->connection_id));
629*6236dae4SAndroid Build Coastguard Worker     cpool_close_and_destroy(cpool, conn, NULL, FALSE);
630*6236dae4SAndroid Build Coastguard Worker     e = Curl_llist_head(&cpool->shutdowns);
631*6236dae4SAndroid Build Coastguard Worker   }
632*6236dae4SAndroid Build Coastguard Worker }
633*6236dae4SAndroid Build Coastguard Worker 
cpool_close_and_destroy_all(struct cpool * cpool)634*6236dae4SAndroid Build Coastguard Worker static void cpool_close_and_destroy_all(struct cpool *cpool)
635*6236dae4SAndroid Build Coastguard Worker {
636*6236dae4SAndroid Build Coastguard Worker   struct connectdata *conn;
637*6236dae4SAndroid Build Coastguard Worker   int timeout_ms = 0;
638*6236dae4SAndroid Build Coastguard Worker   SIGPIPE_VARIABLE(pipe_st);
639*6236dae4SAndroid Build Coastguard Worker 
640*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(cpool);
641*6236dae4SAndroid Build Coastguard Worker   /* Move all connections to the shutdown list */
642*6236dae4SAndroid Build Coastguard Worker   sigpipe_init(&pipe_st);
643*6236dae4SAndroid Build Coastguard Worker   CPOOL_LOCK(cpool);
644*6236dae4SAndroid Build Coastguard Worker   conn = cpool_get_live_conn(cpool);
645*6236dae4SAndroid Build Coastguard Worker   while(conn) {
646*6236dae4SAndroid Build Coastguard Worker     cpool_remove_conn(cpool, conn);
647*6236dae4SAndroid Build Coastguard Worker     sigpipe_apply(cpool->idata, &pipe_st);
648*6236dae4SAndroid Build Coastguard Worker     connclose(conn, "kill all");
649*6236dae4SAndroid Build Coastguard Worker     cpool_discard_conn(cpool, cpool->idata, conn, FALSE);
650*6236dae4SAndroid Build Coastguard Worker 
651*6236dae4SAndroid Build Coastguard Worker     conn = cpool_get_live_conn(cpool);
652*6236dae4SAndroid Build Coastguard Worker   }
653*6236dae4SAndroid Build Coastguard Worker   CPOOL_UNLOCK(cpool);
654*6236dae4SAndroid Build Coastguard Worker 
655*6236dae4SAndroid Build Coastguard Worker     /* Just for testing, run graceful shutdown */
656*6236dae4SAndroid Build Coastguard Worker #ifdef DEBUGBUILD
657*6236dae4SAndroid Build Coastguard Worker   {
658*6236dae4SAndroid Build Coastguard Worker     char *p = getenv("CURL_GRACEFUL_SHUTDOWN");
659*6236dae4SAndroid Build Coastguard Worker     if(p) {
660*6236dae4SAndroid Build Coastguard Worker       long l = strtol(p, NULL, 10);
661*6236dae4SAndroid Build Coastguard Worker       if(l > 0 && l < INT_MAX)
662*6236dae4SAndroid Build Coastguard Worker         timeout_ms = (int)l;
663*6236dae4SAndroid Build Coastguard Worker     }
664*6236dae4SAndroid Build Coastguard Worker   }
665*6236dae4SAndroid Build Coastguard Worker #endif
666*6236dae4SAndroid Build Coastguard Worker   sigpipe_apply(cpool->idata, &pipe_st);
667*6236dae4SAndroid Build Coastguard Worker   cpool_shutdown_all(cpool, cpool->idata, timeout_ms);
668*6236dae4SAndroid Build Coastguard Worker 
669*6236dae4SAndroid Build Coastguard Worker   /* discard all connections in the shutdown list */
670*6236dae4SAndroid Build Coastguard Worker   cpool_shutdown_discard_all(cpool);
671*6236dae4SAndroid Build Coastguard Worker 
672*6236dae4SAndroid Build Coastguard Worker   Curl_hostcache_clean(cpool->idata, cpool->idata->dns.hostcache);
673*6236dae4SAndroid Build Coastguard Worker   sigpipe_restore(&pipe_st);
674*6236dae4SAndroid Build Coastguard Worker }
675*6236dae4SAndroid Build Coastguard Worker 
676*6236dae4SAndroid Build Coastguard Worker 
cpool_shutdown_destroy_oldest(struct cpool * cpool)677*6236dae4SAndroid Build Coastguard Worker static void cpool_shutdown_destroy_oldest(struct cpool *cpool)
678*6236dae4SAndroid Build Coastguard Worker {
679*6236dae4SAndroid Build Coastguard Worker   struct Curl_llist_node *e;
680*6236dae4SAndroid Build Coastguard Worker   struct connectdata *conn;
681*6236dae4SAndroid Build Coastguard Worker 
682*6236dae4SAndroid Build Coastguard Worker   e = Curl_llist_head(&cpool->shutdowns);
683*6236dae4SAndroid Build Coastguard Worker   if(e) {
684*6236dae4SAndroid Build Coastguard Worker     SIGPIPE_VARIABLE(pipe_st);
685*6236dae4SAndroid Build Coastguard Worker     conn = Curl_node_elem(e);
686*6236dae4SAndroid Build Coastguard Worker     Curl_node_remove(e);
687*6236dae4SAndroid Build Coastguard Worker     sigpipe_init(&pipe_st);
688*6236dae4SAndroid Build Coastguard Worker     sigpipe_apply(cpool->idata, &pipe_st);
689*6236dae4SAndroid Build Coastguard Worker     cpool_close_and_destroy(cpool, conn, NULL, FALSE);
690*6236dae4SAndroid Build Coastguard Worker     sigpipe_restore(&pipe_st);
691*6236dae4SAndroid Build Coastguard Worker   }
692*6236dae4SAndroid Build Coastguard Worker }
693*6236dae4SAndroid Build Coastguard Worker 
cpool_discard_conn(struct cpool * cpool,struct Curl_easy * data,struct connectdata * conn,bool aborted)694*6236dae4SAndroid Build Coastguard Worker static void cpool_discard_conn(struct cpool *cpool,
695*6236dae4SAndroid Build Coastguard Worker                                struct Curl_easy *data,
696*6236dae4SAndroid Build Coastguard Worker                                struct connectdata *conn,
697*6236dae4SAndroid Build Coastguard Worker                                bool aborted)
698*6236dae4SAndroid Build Coastguard Worker {
699*6236dae4SAndroid Build Coastguard Worker   bool done = FALSE;
700*6236dae4SAndroid Build Coastguard Worker 
701*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(data);
702*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(cpool);
703*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(!conn->bits.in_cpool);
704*6236dae4SAndroid Build Coastguard Worker 
705*6236dae4SAndroid Build Coastguard Worker   /*
706*6236dae4SAndroid Build Coastguard Worker    * If this connection is not marked to force-close, leave it open if there
707*6236dae4SAndroid Build Coastguard Worker    * are other users of it
708*6236dae4SAndroid Build Coastguard Worker    */
709*6236dae4SAndroid Build Coastguard Worker   if(CONN_INUSE(conn) && !aborted) {
710*6236dae4SAndroid Build Coastguard Worker     DEBUGF(infof(data, "[CCACHE] not discarding #%" FMT_OFF_T
711*6236dae4SAndroid Build Coastguard Worker                  " still in use by %zu transfers", conn->connection_id,
712*6236dae4SAndroid Build Coastguard Worker                  CONN_INUSE(conn)));
713*6236dae4SAndroid Build Coastguard Worker     return;
714*6236dae4SAndroid Build Coastguard Worker   }
715*6236dae4SAndroid Build Coastguard Worker 
716*6236dae4SAndroid Build Coastguard Worker   /* treat the connection as aborted in CONNECT_ONLY situations, we do
717*6236dae4SAndroid Build Coastguard Worker    * not know what the APP did with it. */
718*6236dae4SAndroid Build Coastguard Worker   if(conn->connect_only)
719*6236dae4SAndroid Build Coastguard Worker     aborted = TRUE;
720*6236dae4SAndroid Build Coastguard Worker   conn->bits.aborted = aborted;
721*6236dae4SAndroid Build Coastguard Worker 
722*6236dae4SAndroid Build Coastguard Worker   /* We do not shutdown dead connections. The term 'dead' can be misleading
723*6236dae4SAndroid Build Coastguard Worker    * here, as we also mark errored connections/transfers as 'dead'.
724*6236dae4SAndroid Build Coastguard Worker    * If we do a shutdown for an aborted transfer, the server might think
725*6236dae4SAndroid Build Coastguard Worker    * it was successful otherwise (for example an ftps: upload). This is
726*6236dae4SAndroid Build Coastguard Worker    * not what we want. */
727*6236dae4SAndroid Build Coastguard Worker   if(aborted)
728*6236dae4SAndroid Build Coastguard Worker     done = TRUE;
729*6236dae4SAndroid Build Coastguard Worker   if(!done) {
730*6236dae4SAndroid Build Coastguard Worker     /* Attempt to shutdown the connection right away. */
731*6236dae4SAndroid Build Coastguard Worker     Curl_attach_connection(data, conn);
732*6236dae4SAndroid Build Coastguard Worker     cpool_run_conn_shutdown(data, conn, &done);
733*6236dae4SAndroid Build Coastguard Worker     DEBUGF(infof(data, "[CCACHE] shutdown #%" FMT_OFF_T ", done=%d",
734*6236dae4SAndroid Build Coastguard Worker                  conn->connection_id, done));
735*6236dae4SAndroid Build Coastguard Worker     Curl_detach_connection(data);
736*6236dae4SAndroid Build Coastguard Worker   }
737*6236dae4SAndroid Build Coastguard Worker 
738*6236dae4SAndroid Build Coastguard Worker   if(done) {
739*6236dae4SAndroid Build Coastguard Worker     cpool_close_and_destroy(cpool, conn, data, FALSE);
740*6236dae4SAndroid Build Coastguard Worker     return;
741*6236dae4SAndroid Build Coastguard Worker   }
742*6236dae4SAndroid Build Coastguard Worker 
743*6236dae4SAndroid Build Coastguard Worker   /* Add the connection to our shutdown list for non-blocking shutdown
744*6236dae4SAndroid Build Coastguard Worker    * during multi processing. */
745*6236dae4SAndroid Build Coastguard Worker   if(data->multi && data->multi->max_shutdown_connections > 0 &&
746*6236dae4SAndroid Build Coastguard Worker      (data->multi->max_shutdown_connections >=
747*6236dae4SAndroid Build Coastguard Worker       (long)Curl_llist_count(&cpool->shutdowns))) {
748*6236dae4SAndroid Build Coastguard Worker     DEBUGF(infof(data, "[CCACHE] discarding oldest shutdown connection "
749*6236dae4SAndroid Build Coastguard Worker                        "due to limit of %ld",
750*6236dae4SAndroid Build Coastguard Worker                        data->multi->max_shutdown_connections));
751*6236dae4SAndroid Build Coastguard Worker     cpool_shutdown_destroy_oldest(cpool);
752*6236dae4SAndroid Build Coastguard Worker   }
753*6236dae4SAndroid Build Coastguard Worker 
754*6236dae4SAndroid Build Coastguard Worker   if(data->multi && data->multi->socket_cb) {
755*6236dae4SAndroid Build Coastguard Worker     DEBUGASSERT(cpool == &data->multi->cpool);
756*6236dae4SAndroid Build Coastguard Worker     /* Start with an empty shutdown pollset, so out internal closure handle
757*6236dae4SAndroid Build Coastguard Worker      * is added to the sockets. */
758*6236dae4SAndroid Build Coastguard Worker     memset(&conn->shutdown_poll, 0, sizeof(conn->shutdown_poll));
759*6236dae4SAndroid Build Coastguard Worker     if(cpool_update_shutdown_ev(data->multi, cpool->idata, conn)) {
760*6236dae4SAndroid Build Coastguard Worker       DEBUGF(infof(data, "[CCACHE] update events for shutdown failed, "
761*6236dae4SAndroid Build Coastguard Worker                    "discarding #%" FMT_OFF_T,
762*6236dae4SAndroid Build Coastguard Worker                    conn->connection_id));
763*6236dae4SAndroid Build Coastguard Worker       cpool_close_and_destroy(cpool, conn, data, FALSE);
764*6236dae4SAndroid Build Coastguard Worker       return;
765*6236dae4SAndroid Build Coastguard Worker     }
766*6236dae4SAndroid Build Coastguard Worker   }
767*6236dae4SAndroid Build Coastguard Worker 
768*6236dae4SAndroid Build Coastguard Worker   Curl_llist_append(&cpool->shutdowns, conn, &conn->cpool_node);
769*6236dae4SAndroid Build Coastguard Worker   DEBUGF(infof(data, "[CCACHE] added #%" FMT_OFF_T
770*6236dae4SAndroid Build Coastguard Worker                " to shutdown list of length %zu", conn->connection_id,
771*6236dae4SAndroid Build Coastguard Worker                Curl_llist_count(&cpool->shutdowns)));
772*6236dae4SAndroid Build Coastguard Worker }
773*6236dae4SAndroid Build Coastguard Worker 
Curl_cpool_disconnect(struct Curl_easy * data,struct connectdata * conn,bool aborted)774*6236dae4SAndroid Build Coastguard Worker void Curl_cpool_disconnect(struct Curl_easy *data,
775*6236dae4SAndroid Build Coastguard Worker                            struct connectdata *conn,
776*6236dae4SAndroid Build Coastguard Worker                            bool aborted)
777*6236dae4SAndroid Build Coastguard Worker {
778*6236dae4SAndroid Build Coastguard Worker   struct cpool *cpool = cpool_get_instance(data);
779*6236dae4SAndroid Build Coastguard Worker   bool do_lock;
780*6236dae4SAndroid Build Coastguard Worker 
781*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(cpool);
782*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(data && !data->conn);
783*6236dae4SAndroid Build Coastguard Worker   if(!cpool)
784*6236dae4SAndroid Build Coastguard Worker     return;
785*6236dae4SAndroid Build Coastguard Worker 
786*6236dae4SAndroid Build Coastguard Worker   /* If this connection is not marked to force-close, leave it open if there
787*6236dae4SAndroid Build Coastguard Worker    * are other users of it */
788*6236dae4SAndroid Build Coastguard Worker   if(CONN_INUSE(conn) && !aborted) {
789*6236dae4SAndroid Build Coastguard Worker     DEBUGASSERT(0); /* does this ever happen? */
790*6236dae4SAndroid Build Coastguard Worker     DEBUGF(infof(data, "Curl_disconnect when inuse: %zu", CONN_INUSE(conn)));
791*6236dae4SAndroid Build Coastguard Worker     return;
792*6236dae4SAndroid Build Coastguard Worker   }
793*6236dae4SAndroid Build Coastguard Worker 
794*6236dae4SAndroid Build Coastguard Worker   /* This method may be called while we are under lock, e.g. from a
795*6236dae4SAndroid Build Coastguard Worker    * user callback in find. */
796*6236dae4SAndroid Build Coastguard Worker   do_lock = !CPOOL_IS_LOCKED(cpool);
797*6236dae4SAndroid Build Coastguard Worker   if(do_lock)
798*6236dae4SAndroid Build Coastguard Worker     CPOOL_LOCK(cpool);
799*6236dae4SAndroid Build Coastguard Worker 
800*6236dae4SAndroid Build Coastguard Worker   if(conn->bits.in_cpool) {
801*6236dae4SAndroid Build Coastguard Worker     cpool_remove_conn(cpool, conn);
802*6236dae4SAndroid Build Coastguard Worker     DEBUGASSERT(!conn->bits.in_cpool);
803*6236dae4SAndroid Build Coastguard Worker   }
804*6236dae4SAndroid Build Coastguard Worker 
805*6236dae4SAndroid Build Coastguard Worker   /* Run the callback to let it clean up anything it wants to. */
806*6236dae4SAndroid Build Coastguard Worker   aborted = cpool->disconnect_cb(data, conn, aborted);
807*6236dae4SAndroid Build Coastguard Worker 
808*6236dae4SAndroid Build Coastguard Worker   if(data->multi) {
809*6236dae4SAndroid Build Coastguard Worker     /* Add it to the multi's cpool for shutdown handling */
810*6236dae4SAndroid Build Coastguard Worker     infof(data, "%s connection #%" FMT_OFF_T,
811*6236dae4SAndroid Build Coastguard Worker           aborted ? "closing" : "shutting down", conn->connection_id);
812*6236dae4SAndroid Build Coastguard Worker     cpool_discard_conn(&data->multi->cpool, data, conn, aborted);
813*6236dae4SAndroid Build Coastguard Worker   }
814*6236dae4SAndroid Build Coastguard Worker   else {
815*6236dae4SAndroid Build Coastguard Worker     /* No multi available. Make a best-effort shutdown + close */
816*6236dae4SAndroid Build Coastguard Worker     infof(data, "closing connection #%" FMT_OFF_T, conn->connection_id);
817*6236dae4SAndroid Build Coastguard Worker     cpool_close_and_destroy(NULL, conn, data, !aborted);
818*6236dae4SAndroid Build Coastguard Worker   }
819*6236dae4SAndroid Build Coastguard Worker 
820*6236dae4SAndroid Build Coastguard Worker   if(do_lock)
821*6236dae4SAndroid Build Coastguard Worker     CPOOL_UNLOCK(cpool);
822*6236dae4SAndroid Build Coastguard Worker }
823*6236dae4SAndroid Build Coastguard Worker 
cpool_run_conn_shutdown_handler(struct Curl_easy * data,struct connectdata * conn)824*6236dae4SAndroid Build Coastguard Worker static void cpool_run_conn_shutdown_handler(struct Curl_easy *data,
825*6236dae4SAndroid Build Coastguard Worker                                             struct connectdata *conn)
826*6236dae4SAndroid Build Coastguard Worker {
827*6236dae4SAndroid Build Coastguard Worker   if(!conn->bits.shutdown_handler) {
828*6236dae4SAndroid Build Coastguard Worker     if(conn->dns_entry)
829*6236dae4SAndroid Build Coastguard Worker       Curl_resolv_unlink(data, &conn->dns_entry);
830*6236dae4SAndroid Build Coastguard Worker 
831*6236dae4SAndroid Build Coastguard Worker     /* Cleanup NTLM connection-related data */
832*6236dae4SAndroid Build Coastguard Worker     Curl_http_auth_cleanup_ntlm(conn);
833*6236dae4SAndroid Build Coastguard Worker 
834*6236dae4SAndroid Build Coastguard Worker     /* Cleanup NEGOTIATE connection-related data */
835*6236dae4SAndroid Build Coastguard Worker     Curl_http_auth_cleanup_negotiate(conn);
836*6236dae4SAndroid Build Coastguard Worker 
837*6236dae4SAndroid Build Coastguard Worker     if(conn->handler && conn->handler->disconnect) {
838*6236dae4SAndroid Build Coastguard Worker       /* This is set if protocol-specific cleanups should be made */
839*6236dae4SAndroid Build Coastguard Worker       DEBUGF(infof(data, "connection #%" FMT_OFF_T
840*6236dae4SAndroid Build Coastguard Worker                    ", shutdown protocol handler (aborted=%d)",
841*6236dae4SAndroid Build Coastguard Worker                    conn->connection_id, conn->bits.aborted));
842*6236dae4SAndroid Build Coastguard Worker 
843*6236dae4SAndroid Build Coastguard Worker       conn->handler->disconnect(data, conn, conn->bits.aborted);
844*6236dae4SAndroid Build Coastguard Worker     }
845*6236dae4SAndroid Build Coastguard Worker 
846*6236dae4SAndroid Build Coastguard Worker     /* possible left-overs from the async name resolvers */
847*6236dae4SAndroid Build Coastguard Worker     Curl_resolver_cancel(data);
848*6236dae4SAndroid Build Coastguard Worker 
849*6236dae4SAndroid Build Coastguard Worker     conn->bits.shutdown_handler = TRUE;
850*6236dae4SAndroid Build Coastguard Worker   }
851*6236dae4SAndroid Build Coastguard Worker }
852*6236dae4SAndroid Build Coastguard Worker 
cpool_run_conn_shutdown(struct Curl_easy * data,struct connectdata * conn,bool * done)853*6236dae4SAndroid Build Coastguard Worker static void cpool_run_conn_shutdown(struct Curl_easy *data,
854*6236dae4SAndroid Build Coastguard Worker                                     struct connectdata *conn,
855*6236dae4SAndroid Build Coastguard Worker                                     bool *done)
856*6236dae4SAndroid Build Coastguard Worker {
857*6236dae4SAndroid Build Coastguard Worker   CURLcode r1, r2;
858*6236dae4SAndroid Build Coastguard Worker   bool done1, done2;
859*6236dae4SAndroid Build Coastguard Worker 
860*6236dae4SAndroid Build Coastguard Worker   /* We expect to be attached when called */
861*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(data->conn == conn);
862*6236dae4SAndroid Build Coastguard Worker 
863*6236dae4SAndroid Build Coastguard Worker   cpool_run_conn_shutdown_handler(data, conn);
864*6236dae4SAndroid Build Coastguard Worker 
865*6236dae4SAndroid Build Coastguard Worker   if(conn->bits.shutdown_filters) {
866*6236dae4SAndroid Build Coastguard Worker     *done = TRUE;
867*6236dae4SAndroid Build Coastguard Worker     return;
868*6236dae4SAndroid Build Coastguard Worker   }
869*6236dae4SAndroid Build Coastguard Worker 
870*6236dae4SAndroid Build Coastguard Worker   if(!conn->connect_only && Curl_conn_is_connected(conn, FIRSTSOCKET))
871*6236dae4SAndroid Build Coastguard Worker     r1 = Curl_conn_shutdown(data, FIRSTSOCKET, &done1);
872*6236dae4SAndroid Build Coastguard Worker   else {
873*6236dae4SAndroid Build Coastguard Worker     r1 = CURLE_OK;
874*6236dae4SAndroid Build Coastguard Worker     done1 = TRUE;
875*6236dae4SAndroid Build Coastguard Worker   }
876*6236dae4SAndroid Build Coastguard Worker 
877*6236dae4SAndroid Build Coastguard Worker   if(!conn->connect_only && Curl_conn_is_connected(conn, SECONDARYSOCKET))
878*6236dae4SAndroid Build Coastguard Worker     r2 = Curl_conn_shutdown(data, SECONDARYSOCKET, &done2);
879*6236dae4SAndroid Build Coastguard Worker   else {
880*6236dae4SAndroid Build Coastguard Worker     r2 = CURLE_OK;
881*6236dae4SAndroid Build Coastguard Worker     done2 = TRUE;
882*6236dae4SAndroid Build Coastguard Worker   }
883*6236dae4SAndroid Build Coastguard Worker 
884*6236dae4SAndroid Build Coastguard Worker   /* we are done when any failed or both report success */
885*6236dae4SAndroid Build Coastguard Worker   *done = (r1 || r2 || (done1 && done2));
886*6236dae4SAndroid Build Coastguard Worker   if(*done)
887*6236dae4SAndroid Build Coastguard Worker     conn->bits.shutdown_filters = TRUE;
888*6236dae4SAndroid Build Coastguard Worker }
889*6236dae4SAndroid Build Coastguard Worker 
cpool_add_pollfds(struct cpool * cpool,struct curl_pollfds * cpfds)890*6236dae4SAndroid Build Coastguard Worker static CURLcode cpool_add_pollfds(struct cpool *cpool,
891*6236dae4SAndroid Build Coastguard Worker                                   struct curl_pollfds *cpfds)
892*6236dae4SAndroid Build Coastguard Worker {
893*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OK;
894*6236dae4SAndroid Build Coastguard Worker 
895*6236dae4SAndroid Build Coastguard Worker   if(Curl_llist_head(&cpool->shutdowns)) {
896*6236dae4SAndroid Build Coastguard Worker     struct Curl_llist_node *e;
897*6236dae4SAndroid Build Coastguard Worker     struct easy_pollset ps;
898*6236dae4SAndroid Build Coastguard Worker     struct connectdata *conn;
899*6236dae4SAndroid Build Coastguard Worker 
900*6236dae4SAndroid Build Coastguard Worker     for(e = Curl_llist_head(&cpool->shutdowns); e;
901*6236dae4SAndroid Build Coastguard Worker         e = Curl_node_next(e)) {
902*6236dae4SAndroid Build Coastguard Worker       conn = Curl_node_elem(e);
903*6236dae4SAndroid Build Coastguard Worker       memset(&ps, 0, sizeof(ps));
904*6236dae4SAndroid Build Coastguard Worker       Curl_attach_connection(cpool->idata, conn);
905*6236dae4SAndroid Build Coastguard Worker       Curl_conn_adjust_pollset(cpool->idata, &ps);
906*6236dae4SAndroid Build Coastguard Worker       Curl_detach_connection(cpool->idata);
907*6236dae4SAndroid Build Coastguard Worker 
908*6236dae4SAndroid Build Coastguard Worker       result = Curl_pollfds_add_ps(cpfds, &ps);
909*6236dae4SAndroid Build Coastguard Worker       if(result) {
910*6236dae4SAndroid Build Coastguard Worker         Curl_pollfds_cleanup(cpfds);
911*6236dae4SAndroid Build Coastguard Worker         goto out;
912*6236dae4SAndroid Build Coastguard Worker       }
913*6236dae4SAndroid Build Coastguard Worker     }
914*6236dae4SAndroid Build Coastguard Worker   }
915*6236dae4SAndroid Build Coastguard Worker out:
916*6236dae4SAndroid Build Coastguard Worker   return result;
917*6236dae4SAndroid Build Coastguard Worker }
918*6236dae4SAndroid Build Coastguard Worker 
Curl_cpool_add_pollfds(struct cpool * cpool,struct curl_pollfds * cpfds)919*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_cpool_add_pollfds(struct cpool *cpool,
920*6236dae4SAndroid Build Coastguard Worker                                 struct curl_pollfds *cpfds)
921*6236dae4SAndroid Build Coastguard Worker {
922*6236dae4SAndroid Build Coastguard Worker   CURLcode result;
923*6236dae4SAndroid Build Coastguard Worker   CPOOL_LOCK(cpool);
924*6236dae4SAndroid Build Coastguard Worker   result = cpool_add_pollfds(cpool, cpfds);
925*6236dae4SAndroid Build Coastguard Worker   CPOOL_UNLOCK(cpool);
926*6236dae4SAndroid Build Coastguard Worker   return result;
927*6236dae4SAndroid Build Coastguard Worker }
928*6236dae4SAndroid Build Coastguard Worker 
Curl_cpool_add_waitfds(struct cpool * cpool,struct curl_waitfds * cwfds)929*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_cpool_add_waitfds(struct cpool *cpool,
930*6236dae4SAndroid Build Coastguard Worker                                 struct curl_waitfds *cwfds)
931*6236dae4SAndroid Build Coastguard Worker {
932*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OK;
933*6236dae4SAndroid Build Coastguard Worker 
934*6236dae4SAndroid Build Coastguard Worker   CPOOL_LOCK(cpool);
935*6236dae4SAndroid Build Coastguard Worker   if(Curl_llist_head(&cpool->shutdowns)) {
936*6236dae4SAndroid Build Coastguard Worker     struct Curl_llist_node *e;
937*6236dae4SAndroid Build Coastguard Worker     struct easy_pollset ps;
938*6236dae4SAndroid Build Coastguard Worker     struct connectdata *conn;
939*6236dae4SAndroid Build Coastguard Worker 
940*6236dae4SAndroid Build Coastguard Worker     for(e = Curl_llist_head(&cpool->shutdowns); e;
941*6236dae4SAndroid Build Coastguard Worker         e = Curl_node_next(e)) {
942*6236dae4SAndroid Build Coastguard Worker       conn = Curl_node_elem(e);
943*6236dae4SAndroid Build Coastguard Worker       memset(&ps, 0, sizeof(ps));
944*6236dae4SAndroid Build Coastguard Worker       Curl_attach_connection(cpool->idata, conn);
945*6236dae4SAndroid Build Coastguard Worker       Curl_conn_adjust_pollset(cpool->idata, &ps);
946*6236dae4SAndroid Build Coastguard Worker       Curl_detach_connection(cpool->idata);
947*6236dae4SAndroid Build Coastguard Worker 
948*6236dae4SAndroid Build Coastguard Worker       result = Curl_waitfds_add_ps(cwfds, &ps);
949*6236dae4SAndroid Build Coastguard Worker       if(result)
950*6236dae4SAndroid Build Coastguard Worker         goto out;
951*6236dae4SAndroid Build Coastguard Worker     }
952*6236dae4SAndroid Build Coastguard Worker   }
953*6236dae4SAndroid Build Coastguard Worker out:
954*6236dae4SAndroid Build Coastguard Worker   CPOOL_UNLOCK(cpool);
955*6236dae4SAndroid Build Coastguard Worker   return result;
956*6236dae4SAndroid Build Coastguard Worker }
957*6236dae4SAndroid Build Coastguard Worker 
cpool_perform(struct cpool * cpool)958*6236dae4SAndroid Build Coastguard Worker static void cpool_perform(struct cpool *cpool)
959*6236dae4SAndroid Build Coastguard Worker {
960*6236dae4SAndroid Build Coastguard Worker   struct Curl_easy *data = cpool->idata;
961*6236dae4SAndroid Build Coastguard Worker   struct Curl_llist_node *e = Curl_llist_head(&cpool->shutdowns);
962*6236dae4SAndroid Build Coastguard Worker   struct Curl_llist_node *enext;
963*6236dae4SAndroid Build Coastguard Worker   struct connectdata *conn;
964*6236dae4SAndroid Build Coastguard Worker   struct curltime *nowp = NULL;
965*6236dae4SAndroid Build Coastguard Worker   struct curltime now;
966*6236dae4SAndroid Build Coastguard Worker   timediff_t next_from_now_ms = 0, ms;
967*6236dae4SAndroid Build Coastguard Worker   bool done;
968*6236dae4SAndroid Build Coastguard Worker 
969*6236dae4SAndroid Build Coastguard Worker   if(!e)
970*6236dae4SAndroid Build Coastguard Worker     return;
971*6236dae4SAndroid Build Coastguard Worker 
972*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(data);
973*6236dae4SAndroid Build Coastguard Worker   DEBUGF(infof(data, "[CCACHE] perform, %zu connections being shutdown",
974*6236dae4SAndroid Build Coastguard Worker                Curl_llist_count(&cpool->shutdowns)));
975*6236dae4SAndroid Build Coastguard Worker   while(e) {
976*6236dae4SAndroid Build Coastguard Worker     enext = Curl_node_next(e);
977*6236dae4SAndroid Build Coastguard Worker     conn = Curl_node_elem(e);
978*6236dae4SAndroid Build Coastguard Worker     Curl_attach_connection(data, conn);
979*6236dae4SAndroid Build Coastguard Worker     cpool_run_conn_shutdown(data, conn, &done);
980*6236dae4SAndroid Build Coastguard Worker     DEBUGF(infof(data, "[CCACHE] shutdown #%" FMT_OFF_T ", done=%d",
981*6236dae4SAndroid Build Coastguard Worker                  conn->connection_id, done));
982*6236dae4SAndroid Build Coastguard Worker     Curl_detach_connection(data);
983*6236dae4SAndroid Build Coastguard Worker     if(done) {
984*6236dae4SAndroid Build Coastguard Worker       Curl_node_remove(e);
985*6236dae4SAndroid Build Coastguard Worker       cpool_close_and_destroy(cpool, conn, NULL, FALSE);
986*6236dae4SAndroid Build Coastguard Worker     }
987*6236dae4SAndroid Build Coastguard Worker     else {
988*6236dae4SAndroid Build Coastguard Worker       /* Not done, when does this connection time out? */
989*6236dae4SAndroid Build Coastguard Worker       if(!nowp) {
990*6236dae4SAndroid Build Coastguard Worker         now = Curl_now();
991*6236dae4SAndroid Build Coastguard Worker         nowp = &now;
992*6236dae4SAndroid Build Coastguard Worker       }
993*6236dae4SAndroid Build Coastguard Worker       ms = Curl_conn_shutdown_timeleft(conn, nowp);
994*6236dae4SAndroid Build Coastguard Worker       if(ms && ms < next_from_now_ms)
995*6236dae4SAndroid Build Coastguard Worker         next_from_now_ms = ms;
996*6236dae4SAndroid Build Coastguard Worker     }
997*6236dae4SAndroid Build Coastguard Worker     e = enext;
998*6236dae4SAndroid Build Coastguard Worker   }
999*6236dae4SAndroid Build Coastguard Worker 
1000*6236dae4SAndroid Build Coastguard Worker   if(next_from_now_ms)
1001*6236dae4SAndroid Build Coastguard Worker     Curl_expire(data, next_from_now_ms, EXPIRE_RUN_NOW);
1002*6236dae4SAndroid Build Coastguard Worker }
1003*6236dae4SAndroid Build Coastguard Worker 
Curl_cpool_multi_perform(struct Curl_multi * multi)1004*6236dae4SAndroid Build Coastguard Worker void Curl_cpool_multi_perform(struct Curl_multi *multi)
1005*6236dae4SAndroid Build Coastguard Worker {
1006*6236dae4SAndroid Build Coastguard Worker   CPOOL_LOCK(&multi->cpool);
1007*6236dae4SAndroid Build Coastguard Worker   cpool_perform(&multi->cpool);
1008*6236dae4SAndroid Build Coastguard Worker   CPOOL_UNLOCK(&multi->cpool);
1009*6236dae4SAndroid Build Coastguard Worker }
1010*6236dae4SAndroid Build Coastguard Worker 
1011*6236dae4SAndroid Build Coastguard Worker 
1012*6236dae4SAndroid Build Coastguard Worker /*
1013*6236dae4SAndroid Build Coastguard Worker  * Close and destroy the connection. Run the shutdown sequence once,
1014*6236dae4SAndroid Build Coastguard Worker  * of so requested.
1015*6236dae4SAndroid Build Coastguard Worker  */
cpool_close_and_destroy(struct cpool * cpool,struct connectdata * conn,struct Curl_easy * data,bool do_shutdown)1016*6236dae4SAndroid Build Coastguard Worker static void cpool_close_and_destroy(struct cpool *cpool,
1017*6236dae4SAndroid Build Coastguard Worker                                     struct connectdata *conn,
1018*6236dae4SAndroid Build Coastguard Worker                                     struct Curl_easy *data,
1019*6236dae4SAndroid Build Coastguard Worker                                     bool do_shutdown)
1020*6236dae4SAndroid Build Coastguard Worker {
1021*6236dae4SAndroid Build Coastguard Worker   bool done;
1022*6236dae4SAndroid Build Coastguard Worker 
1023*6236dae4SAndroid Build Coastguard Worker   /* there must be a connection to close */
1024*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(conn);
1025*6236dae4SAndroid Build Coastguard Worker   /* it must be removed from the connection pool */
1026*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(!conn->bits.in_cpool);
1027*6236dae4SAndroid Build Coastguard Worker   /* there must be an associated transfer */
1028*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(data || cpool);
1029*6236dae4SAndroid Build Coastguard Worker   if(!data)
1030*6236dae4SAndroid Build Coastguard Worker     data = cpool->idata;
1031*6236dae4SAndroid Build Coastguard Worker 
1032*6236dae4SAndroid Build Coastguard Worker   /* the transfer must be detached from the connection */
1033*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(data && !data->conn);
1034*6236dae4SAndroid Build Coastguard Worker 
1035*6236dae4SAndroid Build Coastguard Worker   Curl_attach_connection(data, conn);
1036*6236dae4SAndroid Build Coastguard Worker 
1037*6236dae4SAndroid Build Coastguard Worker   cpool_run_conn_shutdown_handler(data, conn);
1038*6236dae4SAndroid Build Coastguard Worker   if(do_shutdown) {
1039*6236dae4SAndroid Build Coastguard Worker     /* Make a last attempt to shutdown handlers and filters, if
1040*6236dae4SAndroid Build Coastguard Worker      * not done so already. */
1041*6236dae4SAndroid Build Coastguard Worker     cpool_run_conn_shutdown(data, conn, &done);
1042*6236dae4SAndroid Build Coastguard Worker   }
1043*6236dae4SAndroid Build Coastguard Worker 
1044*6236dae4SAndroid Build Coastguard Worker   if(cpool)
1045*6236dae4SAndroid Build Coastguard Worker     DEBUGF(infof(data, "[CCACHE] closing #%" FMT_OFF_T,
1046*6236dae4SAndroid Build Coastguard Worker                  conn->connection_id));
1047*6236dae4SAndroid Build Coastguard Worker   else
1048*6236dae4SAndroid Build Coastguard Worker     DEBUGF(infof(data, "closing connection #%" FMT_OFF_T,
1049*6236dae4SAndroid Build Coastguard Worker                  conn->connection_id));
1050*6236dae4SAndroid Build Coastguard Worker   Curl_conn_close(data, SECONDARYSOCKET);
1051*6236dae4SAndroid Build Coastguard Worker   Curl_conn_close(data, FIRSTSOCKET);
1052*6236dae4SAndroid Build Coastguard Worker   Curl_detach_connection(data);
1053*6236dae4SAndroid Build Coastguard Worker 
1054*6236dae4SAndroid Build Coastguard Worker   Curl_conn_free(data, conn);
1055*6236dae4SAndroid Build Coastguard Worker }
1056*6236dae4SAndroid Build Coastguard Worker 
1057*6236dae4SAndroid Build Coastguard Worker 
cpool_update_shutdown_ev(struct Curl_multi * multi,struct Curl_easy * data,struct connectdata * conn)1058*6236dae4SAndroid Build Coastguard Worker static CURLMcode cpool_update_shutdown_ev(struct Curl_multi *multi,
1059*6236dae4SAndroid Build Coastguard Worker                                           struct Curl_easy *data,
1060*6236dae4SAndroid Build Coastguard Worker                                           struct connectdata *conn)
1061*6236dae4SAndroid Build Coastguard Worker {
1062*6236dae4SAndroid Build Coastguard Worker   struct easy_pollset ps;
1063*6236dae4SAndroid Build Coastguard Worker   CURLMcode mresult;
1064*6236dae4SAndroid Build Coastguard Worker 
1065*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(data);
1066*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(multi);
1067*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(multi->socket_cb);
1068*6236dae4SAndroid Build Coastguard Worker 
1069*6236dae4SAndroid Build Coastguard Worker   memset(&ps, 0, sizeof(ps));
1070*6236dae4SAndroid Build Coastguard Worker   Curl_attach_connection(data, conn);
1071*6236dae4SAndroid Build Coastguard Worker   Curl_conn_adjust_pollset(data, &ps);
1072*6236dae4SAndroid Build Coastguard Worker   Curl_detach_connection(data);
1073*6236dae4SAndroid Build Coastguard Worker 
1074*6236dae4SAndroid Build Coastguard Worker   mresult = Curl_multi_pollset_ev(multi, data, &ps, &conn->shutdown_poll);
1075*6236dae4SAndroid Build Coastguard Worker 
1076*6236dae4SAndroid Build Coastguard Worker   if(!mresult) /* Remember for next time */
1077*6236dae4SAndroid Build Coastguard Worker     memcpy(&conn->shutdown_poll, &ps, sizeof(ps));
1078*6236dae4SAndroid Build Coastguard Worker   return mresult;
1079*6236dae4SAndroid Build Coastguard Worker }
1080*6236dae4SAndroid Build Coastguard Worker 
Curl_cpool_multi_socket(struct Curl_multi * multi,curl_socket_t s,int ev_bitmask)1081*6236dae4SAndroid Build Coastguard Worker void Curl_cpool_multi_socket(struct Curl_multi *multi,
1082*6236dae4SAndroid Build Coastguard Worker                              curl_socket_t s, int ev_bitmask)
1083*6236dae4SAndroid Build Coastguard Worker {
1084*6236dae4SAndroid Build Coastguard Worker   struct cpool *cpool = &multi->cpool;
1085*6236dae4SAndroid Build Coastguard Worker   struct Curl_easy *data = cpool->idata;
1086*6236dae4SAndroid Build Coastguard Worker   struct Curl_llist_node *e;
1087*6236dae4SAndroid Build Coastguard Worker   struct connectdata *conn;
1088*6236dae4SAndroid Build Coastguard Worker   bool done;
1089*6236dae4SAndroid Build Coastguard Worker 
1090*6236dae4SAndroid Build Coastguard Worker   (void)ev_bitmask;
1091*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(multi->socket_cb);
1092*6236dae4SAndroid Build Coastguard Worker   CPOOL_LOCK(cpool);
1093*6236dae4SAndroid Build Coastguard Worker   e = Curl_llist_head(&cpool->shutdowns);
1094*6236dae4SAndroid Build Coastguard Worker   while(e) {
1095*6236dae4SAndroid Build Coastguard Worker     conn = Curl_node_elem(e);
1096*6236dae4SAndroid Build Coastguard Worker     if(s == conn->sock[FIRSTSOCKET] || s == conn->sock[SECONDARYSOCKET]) {
1097*6236dae4SAndroid Build Coastguard Worker       Curl_attach_connection(data, conn);
1098*6236dae4SAndroid Build Coastguard Worker       cpool_run_conn_shutdown(data, conn, &done);
1099*6236dae4SAndroid Build Coastguard Worker       DEBUGF(infof(data, "[CCACHE] shutdown #%" FMT_OFF_T ", done=%d",
1100*6236dae4SAndroid Build Coastguard Worker                    conn->connection_id, done));
1101*6236dae4SAndroid Build Coastguard Worker       Curl_detach_connection(data);
1102*6236dae4SAndroid Build Coastguard Worker       if(done || cpool_update_shutdown_ev(multi, data, conn)) {
1103*6236dae4SAndroid Build Coastguard Worker         Curl_node_remove(e);
1104*6236dae4SAndroid Build Coastguard Worker         cpool_close_and_destroy(cpool, conn, NULL, FALSE);
1105*6236dae4SAndroid Build Coastguard Worker       }
1106*6236dae4SAndroid Build Coastguard Worker       break;
1107*6236dae4SAndroid Build Coastguard Worker     }
1108*6236dae4SAndroid Build Coastguard Worker     e = Curl_node_next(e);
1109*6236dae4SAndroid Build Coastguard Worker   }
1110*6236dae4SAndroid Build Coastguard Worker   CPOOL_UNLOCK(cpool);
1111*6236dae4SAndroid Build Coastguard Worker }
1112*6236dae4SAndroid Build Coastguard Worker 
1113*6236dae4SAndroid Build Coastguard Worker #define NUM_POLLS_ON_STACK 10
1114*6236dae4SAndroid Build Coastguard Worker 
cpool_shutdown_wait(struct cpool * cpool,int timeout_ms)1115*6236dae4SAndroid Build Coastguard Worker static CURLcode cpool_shutdown_wait(struct cpool *cpool, int timeout_ms)
1116*6236dae4SAndroid Build Coastguard Worker {
1117*6236dae4SAndroid Build Coastguard Worker   struct pollfd a_few_on_stack[NUM_POLLS_ON_STACK];
1118*6236dae4SAndroid Build Coastguard Worker   struct curl_pollfds cpfds;
1119*6236dae4SAndroid Build Coastguard Worker   CURLcode result;
1120*6236dae4SAndroid Build Coastguard Worker 
1121*6236dae4SAndroid Build Coastguard Worker   Curl_pollfds_init(&cpfds, a_few_on_stack, NUM_POLLS_ON_STACK);
1122*6236dae4SAndroid Build Coastguard Worker 
1123*6236dae4SAndroid Build Coastguard Worker   result = cpool_add_pollfds(cpool, &cpfds);
1124*6236dae4SAndroid Build Coastguard Worker   if(result)
1125*6236dae4SAndroid Build Coastguard Worker     goto out;
1126*6236dae4SAndroid Build Coastguard Worker 
1127*6236dae4SAndroid Build Coastguard Worker   Curl_poll(cpfds.pfds, cpfds.n, CURLMIN(timeout_ms, 1000));
1128*6236dae4SAndroid Build Coastguard Worker 
1129*6236dae4SAndroid Build Coastguard Worker out:
1130*6236dae4SAndroid Build Coastguard Worker   Curl_pollfds_cleanup(&cpfds);
1131*6236dae4SAndroid Build Coastguard Worker   return result;
1132*6236dae4SAndroid Build Coastguard Worker }
1133*6236dae4SAndroid Build Coastguard Worker 
cpool_shutdown_all(struct cpool * cpool,struct Curl_easy * data,int timeout_ms)1134*6236dae4SAndroid Build Coastguard Worker static void cpool_shutdown_all(struct cpool *cpool,
1135*6236dae4SAndroid Build Coastguard Worker                                struct Curl_easy *data, int timeout_ms)
1136*6236dae4SAndroid Build Coastguard Worker {
1137*6236dae4SAndroid Build Coastguard Worker   struct connectdata *conn;
1138*6236dae4SAndroid Build Coastguard Worker   struct curltime started = Curl_now();
1139*6236dae4SAndroid Build Coastguard Worker 
1140*6236dae4SAndroid Build Coastguard Worker   if(!data)
1141*6236dae4SAndroid Build Coastguard Worker     return;
1142*6236dae4SAndroid Build Coastguard Worker   (void)data;
1143*6236dae4SAndroid Build Coastguard Worker 
1144*6236dae4SAndroid Build Coastguard Worker   DEBUGF(infof(data, "cpool shutdown all"));
1145*6236dae4SAndroid Build Coastguard Worker 
1146*6236dae4SAndroid Build Coastguard Worker   /* Move all connections into the shutdown queue */
1147*6236dae4SAndroid Build Coastguard Worker   for(conn = cpool_get_live_conn(cpool); conn;
1148*6236dae4SAndroid Build Coastguard Worker       conn = cpool_get_live_conn(cpool)) {
1149*6236dae4SAndroid Build Coastguard Worker     /* Move conn from live set to shutdown or destroy right away */
1150*6236dae4SAndroid Build Coastguard Worker     DEBUGF(infof(data, "moving connection #%" FMT_OFF_T
1151*6236dae4SAndroid Build Coastguard Worker                  " to shutdown queue", conn->connection_id));
1152*6236dae4SAndroid Build Coastguard Worker     cpool_remove_conn(cpool, conn);
1153*6236dae4SAndroid Build Coastguard Worker     cpool_discard_conn(cpool, data, conn, FALSE);
1154*6236dae4SAndroid Build Coastguard Worker   }
1155*6236dae4SAndroid Build Coastguard Worker 
1156*6236dae4SAndroid Build Coastguard Worker   while(Curl_llist_head(&cpool->shutdowns)) {
1157*6236dae4SAndroid Build Coastguard Worker     timediff_t timespent;
1158*6236dae4SAndroid Build Coastguard Worker     int remain_ms;
1159*6236dae4SAndroid Build Coastguard Worker 
1160*6236dae4SAndroid Build Coastguard Worker     cpool_perform(cpool);
1161*6236dae4SAndroid Build Coastguard Worker 
1162*6236dae4SAndroid Build Coastguard Worker     if(!Curl_llist_head(&cpool->shutdowns)) {
1163*6236dae4SAndroid Build Coastguard Worker       DEBUGF(infof(data, "cpool shutdown ok"));
1164*6236dae4SAndroid Build Coastguard Worker       break;
1165*6236dae4SAndroid Build Coastguard Worker     }
1166*6236dae4SAndroid Build Coastguard Worker 
1167*6236dae4SAndroid Build Coastguard Worker     /* wait for activity, timeout or "nothing" */
1168*6236dae4SAndroid Build Coastguard Worker     timespent = Curl_timediff(Curl_now(), started);
1169*6236dae4SAndroid Build Coastguard Worker     if(timespent >= (timediff_t)timeout_ms) {
1170*6236dae4SAndroid Build Coastguard Worker       DEBUGF(infof(data, "cpool shutdown %s",
1171*6236dae4SAndroid Build Coastguard Worker                    (timeout_ms > 0) ? "timeout" : "best effort done"));
1172*6236dae4SAndroid Build Coastguard Worker       break;
1173*6236dae4SAndroid Build Coastguard Worker     }
1174*6236dae4SAndroid Build Coastguard Worker 
1175*6236dae4SAndroid Build Coastguard Worker     remain_ms = timeout_ms - (int)timespent;
1176*6236dae4SAndroid Build Coastguard Worker     if(cpool_shutdown_wait(cpool, remain_ms)) {
1177*6236dae4SAndroid Build Coastguard Worker       DEBUGF(infof(data, "cpool shutdown all, abort"));
1178*6236dae4SAndroid Build Coastguard Worker       break;
1179*6236dae4SAndroid Build Coastguard Worker     }
1180*6236dae4SAndroid Build Coastguard Worker   }
1181*6236dae4SAndroid Build Coastguard Worker 
1182*6236dae4SAndroid Build Coastguard Worker   /* Due to errors/timeout, we might come here without being done. */
1183*6236dae4SAndroid Build Coastguard Worker   cpool_shutdown_discard_all(cpool);
1184*6236dae4SAndroid Build Coastguard Worker }
1185*6236dae4SAndroid Build Coastguard Worker 
1186*6236dae4SAndroid Build Coastguard Worker struct cpool_reaper_ctx {
1187*6236dae4SAndroid Build Coastguard Worker   struct curltime now;
1188*6236dae4SAndroid Build Coastguard Worker };
1189*6236dae4SAndroid Build Coastguard Worker 
cpool_reap_dead_cb(struct Curl_easy * data,struct connectdata * conn,void * param)1190*6236dae4SAndroid Build Coastguard Worker static int cpool_reap_dead_cb(struct Curl_easy *data,
1191*6236dae4SAndroid Build Coastguard Worker                               struct connectdata *conn, void *param)
1192*6236dae4SAndroid Build Coastguard Worker {
1193*6236dae4SAndroid Build Coastguard Worker   struct cpool_reaper_ctx *rctx = param;
1194*6236dae4SAndroid Build Coastguard Worker   if(Curl_conn_seems_dead(conn, data, &rctx->now)) {
1195*6236dae4SAndroid Build Coastguard Worker     /* stop the iteration here, pass back the connection that was pruned */
1196*6236dae4SAndroid Build Coastguard Worker     Curl_cpool_disconnect(data, conn, FALSE);
1197*6236dae4SAndroid Build Coastguard Worker     return 1;
1198*6236dae4SAndroid Build Coastguard Worker   }
1199*6236dae4SAndroid Build Coastguard Worker   return 0; /* continue iteration */
1200*6236dae4SAndroid Build Coastguard Worker }
1201*6236dae4SAndroid Build Coastguard Worker 
1202*6236dae4SAndroid Build Coastguard Worker /*
1203*6236dae4SAndroid Build Coastguard Worker  * This function scans the data's connection pool for half-open/dead
1204*6236dae4SAndroid Build Coastguard Worker  * connections, closes and removes them.
1205*6236dae4SAndroid Build Coastguard Worker  * The cleanup is done at most once per second.
1206*6236dae4SAndroid Build Coastguard Worker  *
1207*6236dae4SAndroid Build Coastguard Worker  * When called, this transfer has no connection attached.
1208*6236dae4SAndroid Build Coastguard Worker  */
Curl_cpool_prune_dead(struct Curl_easy * data)1209*6236dae4SAndroid Build Coastguard Worker void Curl_cpool_prune_dead(struct Curl_easy *data)
1210*6236dae4SAndroid Build Coastguard Worker {
1211*6236dae4SAndroid Build Coastguard Worker   struct cpool *cpool = cpool_get_instance(data);
1212*6236dae4SAndroid Build Coastguard Worker   struct cpool_reaper_ctx rctx;
1213*6236dae4SAndroid Build Coastguard Worker   timediff_t elapsed;
1214*6236dae4SAndroid Build Coastguard Worker 
1215*6236dae4SAndroid Build Coastguard Worker   if(!cpool)
1216*6236dae4SAndroid Build Coastguard Worker     return;
1217*6236dae4SAndroid Build Coastguard Worker 
1218*6236dae4SAndroid Build Coastguard Worker   rctx.now = Curl_now();
1219*6236dae4SAndroid Build Coastguard Worker   CPOOL_LOCK(cpool);
1220*6236dae4SAndroid Build Coastguard Worker   elapsed = Curl_timediff(rctx.now, cpool->last_cleanup);
1221*6236dae4SAndroid Build Coastguard Worker 
1222*6236dae4SAndroid Build Coastguard Worker   if(elapsed >= 1000L) {
1223*6236dae4SAndroid Build Coastguard Worker     while(cpool_foreach(data, cpool, &rctx, cpool_reap_dead_cb))
1224*6236dae4SAndroid Build Coastguard Worker       ;
1225*6236dae4SAndroid Build Coastguard Worker     cpool->last_cleanup = rctx.now;
1226*6236dae4SAndroid Build Coastguard Worker   }
1227*6236dae4SAndroid Build Coastguard Worker   CPOOL_UNLOCK(cpool);
1228*6236dae4SAndroid Build Coastguard Worker }
1229*6236dae4SAndroid Build Coastguard Worker 
conn_upkeep(struct Curl_easy * data,struct connectdata * conn,void * param)1230*6236dae4SAndroid Build Coastguard Worker static int conn_upkeep(struct Curl_easy *data,
1231*6236dae4SAndroid Build Coastguard Worker                        struct connectdata *conn,
1232*6236dae4SAndroid Build Coastguard Worker                        void *param)
1233*6236dae4SAndroid Build Coastguard Worker {
1234*6236dae4SAndroid Build Coastguard Worker   struct curltime *now = param;
1235*6236dae4SAndroid Build Coastguard Worker   /* TODO, shall we reap connections that return an error here? */
1236*6236dae4SAndroid Build Coastguard Worker   Curl_conn_upkeep(data, conn, now);
1237*6236dae4SAndroid Build Coastguard Worker   return 0; /* continue iteration */
1238*6236dae4SAndroid Build Coastguard Worker }
1239*6236dae4SAndroid Build Coastguard Worker 
Curl_cpool_upkeep(void * data)1240*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_cpool_upkeep(void *data)
1241*6236dae4SAndroid Build Coastguard Worker {
1242*6236dae4SAndroid Build Coastguard Worker   struct cpool *cpool = cpool_get_instance(data);
1243*6236dae4SAndroid Build Coastguard Worker   struct curltime now = Curl_now();
1244*6236dae4SAndroid Build Coastguard Worker 
1245*6236dae4SAndroid Build Coastguard Worker   if(!cpool)
1246*6236dae4SAndroid Build Coastguard Worker     return CURLE_OK;
1247*6236dae4SAndroid Build Coastguard Worker 
1248*6236dae4SAndroid Build Coastguard Worker   CPOOL_LOCK(cpool);
1249*6236dae4SAndroid Build Coastguard Worker   cpool_foreach(data, cpool, &now, conn_upkeep);
1250*6236dae4SAndroid Build Coastguard Worker   CPOOL_UNLOCK(cpool);
1251*6236dae4SAndroid Build Coastguard Worker   return CURLE_OK;
1252*6236dae4SAndroid Build Coastguard Worker }
1253*6236dae4SAndroid Build Coastguard Worker 
1254*6236dae4SAndroid Build Coastguard Worker struct cpool_find_ctx {
1255*6236dae4SAndroid Build Coastguard Worker   curl_off_t id;
1256*6236dae4SAndroid Build Coastguard Worker   struct connectdata *conn;
1257*6236dae4SAndroid Build Coastguard Worker };
1258*6236dae4SAndroid Build Coastguard Worker 
cpool_find_conn(struct Curl_easy * data,struct connectdata * conn,void * param)1259*6236dae4SAndroid Build Coastguard Worker static int cpool_find_conn(struct Curl_easy *data,
1260*6236dae4SAndroid Build Coastguard Worker                            struct connectdata *conn, void *param)
1261*6236dae4SAndroid Build Coastguard Worker {
1262*6236dae4SAndroid Build Coastguard Worker   struct cpool_find_ctx *fctx = param;
1263*6236dae4SAndroid Build Coastguard Worker   (void)data;
1264*6236dae4SAndroid Build Coastguard Worker   if(conn->connection_id == fctx->id) {
1265*6236dae4SAndroid Build Coastguard Worker     fctx->conn = conn;
1266*6236dae4SAndroid Build Coastguard Worker     return 1;
1267*6236dae4SAndroid Build Coastguard Worker   }
1268*6236dae4SAndroid Build Coastguard Worker   return 0;
1269*6236dae4SAndroid Build Coastguard Worker }
1270*6236dae4SAndroid Build Coastguard Worker 
Curl_cpool_get_conn(struct Curl_easy * data,curl_off_t conn_id)1271*6236dae4SAndroid Build Coastguard Worker struct connectdata *Curl_cpool_get_conn(struct Curl_easy *data,
1272*6236dae4SAndroid Build Coastguard Worker                                         curl_off_t conn_id)
1273*6236dae4SAndroid Build Coastguard Worker {
1274*6236dae4SAndroid Build Coastguard Worker   struct cpool *cpool = cpool_get_instance(data);
1275*6236dae4SAndroid Build Coastguard Worker   struct cpool_find_ctx fctx;
1276*6236dae4SAndroid Build Coastguard Worker 
1277*6236dae4SAndroid Build Coastguard Worker   if(!cpool)
1278*6236dae4SAndroid Build Coastguard Worker     return NULL;
1279*6236dae4SAndroid Build Coastguard Worker   fctx.id = conn_id;
1280*6236dae4SAndroid Build Coastguard Worker   fctx.conn = NULL;
1281*6236dae4SAndroid Build Coastguard Worker   CPOOL_LOCK(cpool);
1282*6236dae4SAndroid Build Coastguard Worker   cpool_foreach(cpool->idata, cpool, &fctx, cpool_find_conn);
1283*6236dae4SAndroid Build Coastguard Worker   CPOOL_UNLOCK(cpool);
1284*6236dae4SAndroid Build Coastguard Worker   return fctx.conn;
1285*6236dae4SAndroid Build Coastguard Worker }
1286*6236dae4SAndroid Build Coastguard Worker 
1287*6236dae4SAndroid Build Coastguard Worker struct cpool_do_conn_ctx {
1288*6236dae4SAndroid Build Coastguard Worker   curl_off_t id;
1289*6236dae4SAndroid Build Coastguard Worker   Curl_cpool_conn_do_cb *cb;
1290*6236dae4SAndroid Build Coastguard Worker   void *cbdata;
1291*6236dae4SAndroid Build Coastguard Worker };
1292*6236dae4SAndroid Build Coastguard Worker 
cpool_do_conn(struct Curl_easy * data,struct connectdata * conn,void * param)1293*6236dae4SAndroid Build Coastguard Worker static int cpool_do_conn(struct Curl_easy *data,
1294*6236dae4SAndroid Build Coastguard Worker                          struct connectdata *conn, void *param)
1295*6236dae4SAndroid Build Coastguard Worker {
1296*6236dae4SAndroid Build Coastguard Worker   struct cpool_do_conn_ctx *dctx = param;
1297*6236dae4SAndroid Build Coastguard Worker   (void)data;
1298*6236dae4SAndroid Build Coastguard Worker   if(conn->connection_id == dctx->id) {
1299*6236dae4SAndroid Build Coastguard Worker     dctx->cb(conn, data, dctx->cbdata);
1300*6236dae4SAndroid Build Coastguard Worker     return 1;
1301*6236dae4SAndroid Build Coastguard Worker   }
1302*6236dae4SAndroid Build Coastguard Worker   return 0;
1303*6236dae4SAndroid Build Coastguard Worker }
1304*6236dae4SAndroid Build Coastguard Worker 
Curl_cpool_do_by_id(struct Curl_easy * data,curl_off_t conn_id,Curl_cpool_conn_do_cb * cb,void * cbdata)1305*6236dae4SAndroid Build Coastguard Worker void Curl_cpool_do_by_id(struct Curl_easy *data, curl_off_t conn_id,
1306*6236dae4SAndroid Build Coastguard Worker                          Curl_cpool_conn_do_cb *cb, void *cbdata)
1307*6236dae4SAndroid Build Coastguard Worker {
1308*6236dae4SAndroid Build Coastguard Worker   struct cpool *cpool = cpool_get_instance(data);
1309*6236dae4SAndroid Build Coastguard Worker   struct cpool_do_conn_ctx dctx;
1310*6236dae4SAndroid Build Coastguard Worker 
1311*6236dae4SAndroid Build Coastguard Worker   if(!cpool)
1312*6236dae4SAndroid Build Coastguard Worker     return;
1313*6236dae4SAndroid Build Coastguard Worker   dctx.id = conn_id;
1314*6236dae4SAndroid Build Coastguard Worker   dctx.cb = cb;
1315*6236dae4SAndroid Build Coastguard Worker   dctx.cbdata = cbdata;
1316*6236dae4SAndroid Build Coastguard Worker   CPOOL_LOCK(cpool);
1317*6236dae4SAndroid Build Coastguard Worker   cpool_foreach(data, cpool, &dctx, cpool_do_conn);
1318*6236dae4SAndroid Build Coastguard Worker   CPOOL_UNLOCK(cpool);
1319*6236dae4SAndroid Build Coastguard Worker }
1320*6236dae4SAndroid Build Coastguard Worker 
Curl_cpool_do_locked(struct Curl_easy * data,struct connectdata * conn,Curl_cpool_conn_do_cb * cb,void * cbdata)1321*6236dae4SAndroid Build Coastguard Worker void Curl_cpool_do_locked(struct Curl_easy *data,
1322*6236dae4SAndroid Build Coastguard Worker                           struct connectdata *conn,
1323*6236dae4SAndroid Build Coastguard Worker                           Curl_cpool_conn_do_cb *cb, void *cbdata)
1324*6236dae4SAndroid Build Coastguard Worker {
1325*6236dae4SAndroid Build Coastguard Worker   struct cpool *cpool = cpool_get_instance(data);
1326*6236dae4SAndroid Build Coastguard Worker   if(cpool) {
1327*6236dae4SAndroid Build Coastguard Worker     CPOOL_LOCK(cpool);
1328*6236dae4SAndroid Build Coastguard Worker     cb(conn, data, cbdata);
1329*6236dae4SAndroid Build Coastguard Worker     CPOOL_UNLOCK(cpool);
1330*6236dae4SAndroid Build Coastguard Worker   }
1331*6236dae4SAndroid Build Coastguard Worker   else
1332*6236dae4SAndroid Build Coastguard Worker     cb(conn, data, cbdata);
1333*6236dae4SAndroid Build Coastguard Worker }
1334*6236dae4SAndroid Build Coastguard Worker 
1335*6236dae4SAndroid Build Coastguard Worker #if 0
1336*6236dae4SAndroid Build Coastguard Worker /* Useful for debugging the connection pool */
1337*6236dae4SAndroid Build Coastguard Worker void Curl_cpool_print(struct cpool *cpool)
1338*6236dae4SAndroid Build Coastguard Worker {
1339*6236dae4SAndroid Build Coastguard Worker   struct Curl_hash_iterator iter;
1340*6236dae4SAndroid Build Coastguard Worker   struct Curl_llist_node *curr;
1341*6236dae4SAndroid Build Coastguard Worker   struct Curl_hash_element *he;
1342*6236dae4SAndroid Build Coastguard Worker 
1343*6236dae4SAndroid Build Coastguard Worker   if(!cpool)
1344*6236dae4SAndroid Build Coastguard Worker     return;
1345*6236dae4SAndroid Build Coastguard Worker 
1346*6236dae4SAndroid Build Coastguard Worker   fprintf(stderr, "=Bundle cache=\n");
1347*6236dae4SAndroid Build Coastguard Worker 
1348*6236dae4SAndroid Build Coastguard Worker   Curl_hash_start_iterate(cpool->dest2bundle, &iter);
1349*6236dae4SAndroid Build Coastguard Worker 
1350*6236dae4SAndroid Build Coastguard Worker   he = Curl_hash_next_element(&iter);
1351*6236dae4SAndroid Build Coastguard Worker   while(he) {
1352*6236dae4SAndroid Build Coastguard Worker     struct cpool_bundle *bundle;
1353*6236dae4SAndroid Build Coastguard Worker     struct connectdata *conn;
1354*6236dae4SAndroid Build Coastguard Worker 
1355*6236dae4SAndroid Build Coastguard Worker     bundle = he->ptr;
1356*6236dae4SAndroid Build Coastguard Worker 
1357*6236dae4SAndroid Build Coastguard Worker     fprintf(stderr, "%s -", he->key);
1358*6236dae4SAndroid Build Coastguard Worker     curr = Curl_llist_head(bundle->conns);
1359*6236dae4SAndroid Build Coastguard Worker     while(curr) {
1360*6236dae4SAndroid Build Coastguard Worker       conn = Curl_node_elem(curr);
1361*6236dae4SAndroid Build Coastguard Worker 
1362*6236dae4SAndroid Build Coastguard Worker       fprintf(stderr, " [%p %d]", (void *)conn, conn->refcount);
1363*6236dae4SAndroid Build Coastguard Worker       curr = Curl_node_next(curr);
1364*6236dae4SAndroid Build Coastguard Worker     }
1365*6236dae4SAndroid Build Coastguard Worker     fprintf(stderr, "\n");
1366*6236dae4SAndroid Build Coastguard Worker 
1367*6236dae4SAndroid Build Coastguard Worker     he = Curl_hash_next_element(&iter);
1368*6236dae4SAndroid Build Coastguard Worker   }
1369*6236dae4SAndroid Build Coastguard Worker }
1370*6236dae4SAndroid Build Coastguard Worker #endif
1371