1 /***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
9 *
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at http://curl.haxx.se/docs/copyright.html.
13 *
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ***************************************************************************/
22
23 #include "setup.h"
24
25 #ifdef HAVE_SYS_SOCKET_H
26 #include <sys/socket.h>
27 #endif
28 #ifdef HAVE_UNISTD_H
29 #include <unistd.h>
30 #endif
31
32 #include <curl/curl.h>
33
34 #include "urldata.h"
35 #include "transfer.h"
36 #include "url.h"
37 #include "connect.h"
38 #include "progress.h"
39 #include "easyif.h"
40 #include "multiif.h"
41 #include "sendf.h"
42 #include "timeval.h"
43 #include "http.h"
44 #include "warnless.h"
45
46 #define _MPRINTF_REPLACE /* use our functions only */
47 #include <curl/mprintf.h>
48
49 #include "curl_memory.h"
50 /* The last #include file should be: */
51 #include "memdebug.h"
52
53 /*
54 CURL_SOCKET_HASH_TABLE_SIZE should be a prime number. Increasing it from 97
55 to 911 takes on a 32-bit machine 4 x 804 = 3211 more bytes. Still, every
56 CURL handle takes 45-50 K memory, therefore this 3K are not significant.
57 */
58 #ifndef CURL_SOCKET_HASH_TABLE_SIZE
59 #define CURL_SOCKET_HASH_TABLE_SIZE 911
60 #endif
61
62 struct Curl_message {
63 /* the 'CURLMsg' is the part that is visible to the external user */
64 struct CURLMsg extmsg;
65 };
66
67 /* NOTE: if you add a state here, add the name to the statename[] array as
68 well!
69 */
70 typedef enum {
71 CURLM_STATE_INIT, /* 0 - start in this state */
72 CURLM_STATE_CONNECT, /* 1 - resolve/connect has been sent off */
73 CURLM_STATE_WAITRESOLVE, /* 2 - awaiting the resolve to finalize */
74 CURLM_STATE_WAITCONNECT, /* 3 - awaiting the connect to finalize */
75 CURLM_STATE_WAITPROXYCONNECT, /* 4 - awaiting proxy CONNECT to finalize */
76 CURLM_STATE_PROTOCONNECT, /* 5 - completing the protocol-specific connect
77 phase */
78 CURLM_STATE_WAITDO, /* 6 - wait for our turn to send the request */
79 CURLM_STATE_DO, /* 7 - start send off the request (part 1) */
80 CURLM_STATE_DOING, /* 8 - sending off the request (part 1) */
81 CURLM_STATE_DO_MORE, /* 9 - send off the request (part 2) */
82 CURLM_STATE_DO_DONE, /* 10 - done sending off request */
83 CURLM_STATE_WAITPERFORM, /* 11 - wait for our turn to read the response */
84 CURLM_STATE_PERFORM, /* 12 - transfer data */
85 CURLM_STATE_TOOFAST, /* 13 - wait because limit-rate exceeded */
86 CURLM_STATE_DONE, /* 14 - post data transfer operation */
87 CURLM_STATE_COMPLETED, /* 15 - operation complete */
88 CURLM_STATE_MSGSENT, /* 16 - the operation complete message is sent */
89 CURLM_STATE_LAST /* 17 - not a true state, never use this */
90 } CURLMstate;
91
92 /* we support N sockets per easy handle. Set the corresponding bit to what
93 action we should wait for */
94 #define MAX_SOCKSPEREASYHANDLE 5
95 #define GETSOCK_READABLE (0x00ff)
96 #define GETSOCK_WRITABLE (0xff00)
97
98 struct closure {
99 struct closure *next; /* a simple one-way list of structs */
100 struct SessionHandle *easy_handle;
101 };
102
103 struct Curl_one_easy {
104 /* first, two fields for the linked list of these */
105 struct Curl_one_easy *next;
106 struct Curl_one_easy *prev;
107
108 struct SessionHandle *easy_handle; /* the easy handle for this unit */
109 struct connectdata *easy_conn; /* the "unit's" connection */
110
111 CURLMstate state; /* the handle's state */
112 CURLcode result; /* previous result */
113
114 struct Curl_message msg; /* A single posted message. */
115
116 /* Array with the plain socket numbers this handle takes care of, in no
117 particular order. Note that all sockets are added to the sockhash, where
118 the state etc are also kept. This array is mostly used to detect when a
119 socket is to be removed from the hash. See singlesocket(). */
120 curl_socket_t sockets[MAX_SOCKSPEREASYHANDLE];
121 int numsocks;
122 };
123
124 #define CURL_MULTI_HANDLE 0x000bab1e
125
126 #define GOOD_MULTI_HANDLE(x) \
127 ((x)&&(((struct Curl_multi *)(x))->type == CURL_MULTI_HANDLE))
128 #define GOOD_EASY_HANDLE(x) \
129 (((struct SessionHandle *)(x))->magic == CURLEASY_MAGIC_NUMBER)
130
131 /* This is the struct known as CURLM on the outside */
132 struct Curl_multi {
133 /* First a simple identifier to easier detect if a user mix up
134 this multi handle with an easy handle. Set this to CURL_MULTI_HANDLE. */
135 long type;
136
137 /* We have a linked list with easy handles */
138 struct Curl_one_easy easy;
139
140 int num_easy; /* amount of entries in the linked list above. */
141 int num_alive; /* amount of easy handles that are added but have not yet
142 reached COMPLETE state */
143
144 struct curl_llist *msglist; /* a list of messages from completed transfers */
145
146 /* callback function and user data pointer for the *socket() API */
147 curl_socket_callback socket_cb;
148 void *socket_userp;
149
150 /* Hostname cache */
151 struct curl_hash *hostcache;
152
153 /* timetree points to the splay-tree of time nodes to figure out expire
154 times of all currently set timers */
155 struct Curl_tree *timetree;
156
157 /* 'sockhash' is the lookup hash for socket descriptor => easy handles (note
158 the pluralis form, there can be more than one easy handle waiting on the
159 same actual socket) */
160 struct curl_hash *sockhash;
161
162 /* Whether pipelining is enabled for this multi handle */
163 bool pipelining_enabled;
164
165 /* shared connection cache */
166 struct conncache *connc;
167 long maxconnects; /* if >0, a fixed limit of the maximum number of entries
168 we're allowed to grow the connection cache to */
169
170 /* list of easy handles kept around for doing nice connection closures */
171 struct closure *closure;
172
173 /* timer callback and user data pointer for the *socket() API */
174 curl_multi_timer_callback timer_cb;
175 void *timer_userp;
176 struct timeval timer_lastcall; /* the fixed time for the timeout for the
177 previous callback */
178 };
179
180 static void multi_connc_remove_handle(struct Curl_multi *multi,
181 struct SessionHandle *data);
182 static void singlesocket(struct Curl_multi *multi,
183 struct Curl_one_easy *easy);
184 static CURLMcode add_closure(struct Curl_multi *multi,
185 struct SessionHandle *data);
186 static int update_timer(struct Curl_multi *multi);
187
188 static CURLcode addHandleToSendOrPendPipeline(struct SessionHandle *handle,
189 struct connectdata *conn);
190 static int checkPendPipeline(struct connectdata *conn);
191 static void moveHandleFromSendToRecvPipeline(struct SessionHandle *handle,
192 struct connectdata *conn);
193 static void moveHandleFromRecvToDonePipeline(struct SessionHandle *handle,
194 struct connectdata *conn);
195 static bool isHandleAtHead(struct SessionHandle *handle,
196 struct curl_llist *pipeline);
197 static CURLMcode add_next_timeout(struct timeval now,
198 struct Curl_multi *multi,
199 struct SessionHandle *d);
200
201 #ifdef DEBUGBUILD
202 static const char * const statename[]={
203 "INIT",
204 "CONNECT",
205 "WAITRESOLVE",
206 "WAITCONNECT",
207 "WAITPROXYCONNECT",
208 "PROTOCONNECT",
209 "WAITDO",
210 "DO",
211 "DOING",
212 "DO_MORE",
213 "DO_DONE",
214 "WAITPERFORM",
215 "PERFORM",
216 "TOOFAST",
217 "DONE",
218 "COMPLETED",
219 "MSGSENT",
220 };
221 #endif
222
223 static void multi_freetimeout(void *a, void *b);
224
225 /* always use this function to change state, to make debugging easier */
multistate(struct Curl_one_easy * easy,CURLMstate state)226 static void multistate(struct Curl_one_easy *easy, CURLMstate state)
227 {
228 #ifdef DEBUGBUILD
229 long connectindex = -5000;
230 #endif
231 CURLMstate oldstate = easy->state;
232
233 if(oldstate == state)
234 /* don't bother when the new state is the same as the old state */
235 return;
236
237 easy->state = state;
238
239 #ifdef DEBUGBUILD
240 if(easy->easy_conn) {
241 if(easy->state > CURLM_STATE_CONNECT &&
242 easy->state < CURLM_STATE_COMPLETED)
243 connectindex = easy->easy_conn->connectindex;
244
245 infof(easy->easy_handle,
246 "STATE: %s => %s handle %p; (connection #%ld) \n",
247 statename[oldstate], statename[easy->state],
248 (char *)easy, connectindex);
249 }
250 #endif
251 if(state == CURLM_STATE_COMPLETED)
252 /* changing to COMPLETED means there's one less easy handle 'alive' */
253 easy->easy_handle->multi->num_alive--;
254 }
255
256 /*
257 * We add one of these structs to the sockhash for a particular socket
258 */
259
260 struct Curl_sh_entry {
261 struct SessionHandle *easy;
262 time_t timestamp;
263 int action; /* what action READ/WRITE this socket waits for */
264 curl_socket_t socket; /* mainly to ease debugging */
265 void *socketp; /* settable by users with curl_multi_assign() */
266 };
267 /* bits for 'action' having no bits means this socket is not expecting any
268 action */
269 #define SH_READ 1
270 #define SH_WRITE 2
271
272 /* make sure this socket is present in the hash for this handle */
sh_addentry(struct curl_hash * sh,curl_socket_t s,struct SessionHandle * data)273 static struct Curl_sh_entry *sh_addentry(struct curl_hash *sh,
274 curl_socket_t s,
275 struct SessionHandle *data)
276 {
277 struct Curl_sh_entry *there =
278 Curl_hash_pick(sh, (char *)&s, sizeof(curl_socket_t));
279 struct Curl_sh_entry *check;
280
281 if(there)
282 /* it is present, return fine */
283 return there;
284
285 /* not present, add it */
286 check = calloc(1, sizeof(struct Curl_sh_entry));
287 if(!check)
288 return NULL; /* major failure */
289 check->easy = data;
290 check->socket = s;
291
292 /* make/add new hash entry */
293 if(NULL == Curl_hash_add(sh, (char *)&s, sizeof(curl_socket_t), check)) {
294 free(check);
295 return NULL; /* major failure */
296 }
297
298 return check; /* things are good in sockhash land */
299 }
300
301
302 /* delete the given socket + handle from the hash */
sh_delentry(struct curl_hash * sh,curl_socket_t s)303 static void sh_delentry(struct curl_hash *sh, curl_socket_t s)
304 {
305 struct Curl_sh_entry *there =
306 Curl_hash_pick(sh, (char *)&s, sizeof(curl_socket_t));
307
308 if(there) {
309 /* this socket is in the hash */
310 /* We remove the hash entry. (This'll end up in a call to
311 sh_freeentry().) */
312 Curl_hash_delete(sh, (char *)&s, sizeof(curl_socket_t));
313 }
314 }
315
316 /*
317 * free a sockhash entry
318 */
sh_freeentry(void * freethis)319 static void sh_freeentry(void *freethis)
320 {
321 struct Curl_sh_entry *p = (struct Curl_sh_entry *) freethis;
322
323 if(p)
324 free(p);
325 }
326
fd_key_compare(void * k1,size_t k1_len,void * k2,size_t k2_len)327 static size_t fd_key_compare(void*k1, size_t k1_len, void*k2, size_t k2_len)
328 {
329 (void) k1_len; (void) k2_len;
330
331 return (*((int* ) k1)) == (*((int* ) k2));
332 }
333
hash_fd(void * key,size_t key_length,size_t slots_num)334 static size_t hash_fd(void* key, size_t key_length, size_t slots_num)
335 {
336 int fd = * ((int* ) key);
337 (void) key_length;
338
339 return (fd % (int)slots_num);
340 }
341
342 /*
343 * sh_init() creates a new socket hash and returns the handle for it.
344 *
345 * Quote from README.multi_socket:
346 *
347 * "Some tests at 7000 and 9000 connections showed that the socket hash lookup
348 * is somewhat of a bottle neck. Its current implementation may be a bit too
349 * limiting. It simply has a fixed-size array, and on each entry in the array
350 * it has a linked list with entries. So the hash only checks which list to
351 * scan through. The code I had used so for used a list with merely 7 slots
352 * (as that is what the DNS hash uses) but with 7000 connections that would
353 * make an average of 1000 nodes in each list to run through. I upped that to
354 * 97 slots (I believe a prime is suitable) and noticed a significant speed
355 * increase. I need to reconsider the hash implementation or use a rather
356 * large default value like this. At 9000 connections I was still below 10us
357 * per call."
358 *
359 */
sh_init(void)360 static struct curl_hash *sh_init(void)
361 {
362 return Curl_hash_alloc(CURL_SOCKET_HASH_TABLE_SIZE, hash_fd, fd_key_compare,
363 sh_freeentry);
364 }
365
366 /*
367 * multi_addmsg()
368 *
369 * Called when a transfer is completed. Adds the given msg pointer to
370 * the list kept in the multi handle.
371 */
multi_addmsg(struct Curl_multi * multi,struct Curl_message * msg)372 static CURLMcode multi_addmsg(struct Curl_multi *multi,
373 struct Curl_message *msg)
374 {
375 if(!Curl_llist_insert_next(multi->msglist, multi->msglist->tail, msg))
376 return CURLM_OUT_OF_MEMORY;
377
378 return CURLM_OK;
379 }
380
381 /*
382 * multi_freeamsg()
383 *
384 * Callback used by the llist system when a single list entry is destroyed.
385 */
multi_freeamsg(void * a,void * b)386 static void multi_freeamsg(void *a, void *b)
387 {
388 (void)a;
389 (void)b;
390 }
391
392
curl_multi_init(void)393 CURLM *curl_multi_init(void)
394 {
395 struct Curl_multi *multi = calloc(1, sizeof(struct Curl_multi));
396
397 if(!multi)
398 return NULL;
399
400 multi->type = CURL_MULTI_HANDLE;
401
402 multi->hostcache = Curl_mk_dnscache();
403 if(!multi->hostcache)
404 goto error;
405
406 multi->sockhash = sh_init();
407 if(!multi->sockhash)
408 goto error;
409
410 multi->connc = Curl_mk_connc(CONNCACHE_MULTI, -1L);
411 if(!multi->connc)
412 goto error;
413
414 multi->msglist = Curl_llist_alloc(multi_freeamsg);
415 if(!multi->msglist)
416 goto error;
417
418 /* Let's make the doubly-linked list a circular list. This makes
419 the linked list code simpler and allows inserting at the end
420 with less work (we didn't keep a tail pointer before). */
421 multi->easy.next = &multi->easy;
422 multi->easy.prev = &multi->easy;
423
424 return (CURLM *) multi;
425
426 error:
427 if(multi->sockhash)
428 Curl_hash_destroy(multi->sockhash);
429 if(multi->hostcache)
430 Curl_hash_destroy(multi->hostcache);
431 if(multi->connc)
432 Curl_rm_connc(multi->connc);
433
434 free(multi);
435 return NULL;
436 }
437
curl_multi_add_handle(CURLM * multi_handle,CURL * easy_handle)438 CURLMcode curl_multi_add_handle(CURLM *multi_handle,
439 CURL *easy_handle)
440 {
441 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
442 struct Curl_one_easy *easy;
443 struct closure *cl;
444 struct closure *prev=NULL;
445 struct SessionHandle *data = easy_handle;
446
447 /* First, make some basic checks that the CURLM handle is a good handle */
448 if(!GOOD_MULTI_HANDLE(multi))
449 return CURLM_BAD_HANDLE;
450
451 /* Verify that we got a somewhat good easy handle too */
452 if(!GOOD_EASY_HANDLE(easy_handle))
453 return CURLM_BAD_EASY_HANDLE;
454
455 /* Prevent users to add the same handle more than once! */
456 if(((struct SessionHandle *)easy_handle)->multi)
457 /* possibly we should create a new unique error code for this condition */
458 return CURLM_BAD_EASY_HANDLE;
459
460 data->state.timeoutlist = Curl_llist_alloc(multi_freetimeout);
461 if(!data->state.timeoutlist)
462 return CURLM_OUT_OF_MEMORY;
463
464 /* Now, time to add an easy handle to the multi stack */
465 easy = calloc(1, sizeof(struct Curl_one_easy));
466 if(!easy)
467 return CURLM_OUT_OF_MEMORY;
468
469 cl = multi->closure;
470 while(cl) {
471 struct closure *next = cl->next;
472 if(cl->easy_handle == (struct SessionHandle *)easy_handle) {
473 /* remove this handle from the closure list */
474 free(cl);
475 if(prev)
476 prev->next = next;
477 else
478 multi->closure = next;
479 break; /* no need to continue since this handle can only be present once
480 in the list */
481 }
482 prev = cl;
483 cl = next;
484 }
485
486 /* set the easy handle */
487 easy->easy_handle = easy_handle;
488 multistate(easy, CURLM_STATE_INIT);
489
490 /* set the back pointer to one_easy to assist in removal */
491 easy->easy_handle->multi_pos = easy;
492
493 /* for multi interface connections, we share DNS cache automatically if the
494 easy handle's one is currently private. */
495 if(easy->easy_handle->dns.hostcache &&
496 (easy->easy_handle->dns.hostcachetype == HCACHE_PRIVATE)) {
497 Curl_hash_destroy(easy->easy_handle->dns.hostcache);
498 easy->easy_handle->dns.hostcache = NULL;
499 easy->easy_handle->dns.hostcachetype = HCACHE_NONE;
500 }
501
502 if(!easy->easy_handle->dns.hostcache ||
503 (easy->easy_handle->dns.hostcachetype == HCACHE_NONE)) {
504 easy->easy_handle->dns.hostcache = multi->hostcache;
505 easy->easy_handle->dns.hostcachetype = HCACHE_MULTI;
506 }
507
508 if(easy->easy_handle->state.connc) {
509 if(easy->easy_handle->state.connc->type == CONNCACHE_PRIVATE) {
510 /* kill old private version */
511 Curl_rm_connc(easy->easy_handle->state.connc);
512 /* point out our shared one instead */
513 easy->easy_handle->state.connc = multi->connc;
514 }
515 /* else it is already using multi? */
516 }
517 else
518 /* point out our shared one */
519 easy->easy_handle->state.connc = multi->connc;
520
521 /* Make sure the type is setup correctly */
522 easy->easy_handle->state.connc->type = CONNCACHE_MULTI;
523
524 /* This adds the new entry at the back of the list
525 to try and maintain a FIFO queue so the pipelined
526 requests are in order. */
527
528 /* We add this new entry last in the list. We make our 'next' point to the
529 'first' struct and our 'prev' point to the previous 'prev' */
530 easy->next = &multi->easy;
531 easy->prev = multi->easy.prev;
532
533 /* make 'easy' the last node in the chain */
534 multi->easy.prev = easy;
535
536 /* if there was a prev node, make sure its 'next' pointer links to
537 the new node */
538 easy->prev->next = easy;
539
540 Curl_easy_addmulti(easy_handle, multi_handle);
541
542 /* make the SessionHandle struct refer back to this struct */
543 easy->easy_handle->set.one_easy = easy;
544
545 /* Set the timeout for this handle to expire really soon so that it will
546 be taken care of even when this handle is added in the midst of operation
547 when only the curl_multi_socket() API is used. During that flow, only
548 sockets that time-out or have actions will be dealt with. Since this
549 handle has no action yet, we make sure it times out to get things to
550 happen. */
551 Curl_expire(easy->easy_handle, 1);
552
553 /* increase the node-counter */
554 multi->num_easy++;
555
556 if((multi->num_easy * 4) > multi->connc->num) {
557 /* We want the connection cache to have plenty room. Before we supported
558 the shared cache every single easy handle had 5 entries in their cache
559 by default. */
560 long newmax = multi->num_easy * 4;
561
562 if(multi->maxconnects && (multi->maxconnects < newmax))
563 /* don't grow beyond the allowed size */
564 newmax = multi->maxconnects;
565
566 if(newmax > multi->connc->num) {
567 /* we only do this is we can in fact grow the cache */
568 CURLcode res = Curl_ch_connc(easy_handle, multi->connc, newmax);
569 if(res != CURLE_OK) {
570 /* FIXME: may need to do more cleanup here */
571 curl_multi_remove_handle(multi_handle, easy_handle);
572 return CURLM_OUT_OF_MEMORY;
573 }
574 }
575 }
576
577 /* increase the alive-counter */
578 multi->num_alive++;
579
580 /* A somewhat crude work-around for a little glitch in update_timer() that
581 happens if the lastcall time is set to the same time when the handle is
582 removed as when the next handle is added, as then the check in
583 update_timer() that prevents calling the application multiple times with
584 the same timer infor will not trigger and then the new handle's timeout
585 will not be notified to the app.
586
587 The work-around is thus simply to clear the 'lastcall' variable to force
588 update_timer() to always trigger a callback to the app when a new easy
589 handle is added */
590 memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall));
591
592 update_timer(multi);
593 return CURLM_OK;
594 }
595
596 #if 0
597 /* Debug-function, used like this:
598 *
599 * Curl_hash_print(multi->sockhash, debug_print_sock_hash);
600 *
601 * Enable the hash print function first by editing hash.c
602 */
603 static void debug_print_sock_hash(void *p)
604 {
605 struct Curl_sh_entry *sh = (struct Curl_sh_entry *)p;
606
607 fprintf(stderr, " [easy %p/magic %x/socket %d]",
608 (void *)sh->easy, sh->easy->magic, (int)sh->socket);
609 }
610 #endif
611
curl_multi_remove_handle(CURLM * multi_handle,CURL * curl_handle)612 CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
613 CURL *curl_handle)
614 {
615 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
616 struct Curl_one_easy *easy;
617 struct SessionHandle *data = curl_handle;
618
619 /* First, make some basic checks that the CURLM handle is a good handle */
620 if(!GOOD_MULTI_HANDLE(multi))
621 return CURLM_BAD_HANDLE;
622
623 /* Verify that we got a somewhat good easy handle too */
624 if(!GOOD_EASY_HANDLE(curl_handle))
625 return CURLM_BAD_EASY_HANDLE;
626
627 /* pick-up from the 'curl_handle' the kept position in the list */
628 easy = data->multi_pos;
629
630 if(easy) {
631 bool premature = (bool)(easy->state < CURLM_STATE_COMPLETED);
632 bool easy_owns_conn = (bool)(easy->easy_conn &&
633 (easy->easy_conn->data == easy->easy_handle));
634
635 /* If the 'state' is not INIT or COMPLETED, we might need to do something
636 nice to put the easy_handle in a good known state when this returns. */
637 if(premature)
638 /* this handle is "alive" so we need to count down the total number of
639 alive connections when this is removed */
640 multi->num_alive--;
641
642 if(easy->easy_conn &&
643 (easy->easy_conn->send_pipe->size +
644 easy->easy_conn->recv_pipe->size > 1) &&
645 easy->state > CURLM_STATE_WAITDO &&
646 easy->state < CURLM_STATE_COMPLETED) {
647 /* If the handle is in a pipeline and has started sending off its
648 request but not received its response yet, we need to close
649 connection. */
650 easy->easy_conn->bits.close = TRUE;
651 /* Set connection owner so that Curl_done() closes it.
652 We can sefely do this here since connection is killed. */
653 easy->easy_conn->data = easy->easy_handle;
654 }
655
656 /* The timer must be shut down before easy->multi is set to NULL,
657 else the timenode will remain in the splay tree after
658 curl_easy_cleanup is called. */
659 Curl_expire(easy->easy_handle, 0);
660
661 /* destroy the timeout list that is held in the easy handle */
662 if(data->state.timeoutlist) {
663 Curl_llist_destroy(data->state.timeoutlist, NULL);
664 data->state.timeoutlist = NULL;
665 }
666
667 if(easy->easy_handle->dns.hostcachetype == HCACHE_MULTI) {
668 /* clear out the usage of the shared DNS cache */
669 easy->easy_handle->dns.hostcache = NULL;
670 easy->easy_handle->dns.hostcachetype = HCACHE_NONE;
671 }
672
673 if(easy->easy_conn) {
674
675 /* we must call Curl_done() here (if we still "own it") so that we don't
676 leave a half-baked one around */
677 if (easy_owns_conn) {
678
679 /* Curl_done() clears the conn->data field to lose the association
680 between the easy handle and the connection
681
682 Note that this ignores the return code simply because there's
683 nothing really useful to do with it anyway! */
684 (void)Curl_done(&easy->easy_conn, easy->result, premature);
685
686 if(easy->easy_conn)
687 /* the connection is still alive, set back the association to enable
688 the check below to trigger TRUE */
689 easy->easy_conn->data = easy->easy_handle;
690 }
691 else
692 /* Clear connection pipelines, if Curl_done above was not called */
693 Curl_getoff_all_pipelines(easy->easy_handle, easy->easy_conn);
694 }
695
696 /* figure out if the easy handle is used by one or more connections in the
697 cache */
698 multi_connc_remove_handle(multi, easy->easy_handle);
699
700 if(easy->easy_handle->state.connc->type == CONNCACHE_MULTI) {
701 /* if this was using the shared connection cache we clear the pointer
702 to that since we're not part of that handle anymore */
703 easy->easy_handle->state.connc = NULL;
704
705 /* Since we return the connection back to the communal connection pool
706 we mark the last connection as inaccessible */
707 easy->easy_handle->state.lastconnect = -1;
708
709 /* Modify the connectindex since this handle can't point to the
710 connection cache anymore.
711
712 TODO: consider if this is really what we want. The connection cache
713 is within the multi handle and that owns the connections so we should
714 not need to touch connections like this when we just remove an easy
715 handle...
716 */
717 if(easy->easy_conn && easy_owns_conn &&
718 (easy->easy_conn->send_pipe->size +
719 easy->easy_conn->recv_pipe->size == 0))
720 easy->easy_conn->connectindex = -1;
721 }
722
723 /* change state without using multistate(), only to make singlesocket() do
724 what we want */
725 easy->state = CURLM_STATE_COMPLETED;
726 singlesocket(multi, easy); /* to let the application know what sockets
727 that vanish with this handle */
728
729 Curl_easy_addmulti(easy->easy_handle, NULL); /* clear the association
730 to this multi handle */
731
732 {
733 /* make sure there's no pending message in the queue sent from this easy
734 handle */
735 struct curl_llist_element *e;
736
737 for(e = multi->msglist->head; e; e = e->next) {
738 struct Curl_message *msg = e->ptr;
739
740 if(msg->extmsg.easy_handle == easy->easy_handle) {
741 Curl_llist_remove(multi->msglist, e, NULL);
742 /* there can only be one from this specific handle */
743 break;
744 }
745 }
746 }
747
748 /* make the previous node point to our next */
749 if(easy->prev)
750 easy->prev->next = easy->next;
751 /* make our next point to our previous node */
752 if(easy->next)
753 easy->next->prev = easy->prev;
754
755 easy->easy_handle->set.one_easy = NULL; /* detached */
756
757 /* Null the position in the controlling structure */
758 easy->easy_handle->multi_pos = NULL;
759
760 /* NOTE NOTE NOTE
761 We do not touch the easy handle here! */
762 free(easy);
763
764 multi->num_easy--; /* one less to care about now */
765
766 update_timer(multi);
767 return CURLM_OK;
768 }
769 else
770 return CURLM_BAD_EASY_HANDLE; /* twasn't found */
771 }
772
Curl_multi_canPipeline(const struct Curl_multi * multi)773 bool Curl_multi_canPipeline(const struct Curl_multi* multi)
774 {
775 return multi->pipelining_enabled;
776 }
777
Curl_multi_handlePipeBreak(struct SessionHandle * data)778 void Curl_multi_handlePipeBreak(struct SessionHandle *data)
779 {
780 struct Curl_one_easy *one_easy = data->set.one_easy;
781
782 if(one_easy)
783 one_easy->easy_conn = NULL;
784 }
785
waitconnect_getsock(struct connectdata * conn,curl_socket_t * sock,int numsocks)786 static int waitconnect_getsock(struct connectdata *conn,
787 curl_socket_t *sock,
788 int numsocks)
789 {
790 if(!numsocks)
791 return GETSOCK_BLANK;
792
793 sock[0] = conn->sock[FIRSTSOCKET];
794
795 /* when we've sent a CONNECT to a proxy, we should rather wait for the
796 socket to become readable to be able to get the response headers */
797 if(conn->bits.tunnel_connecting)
798 return GETSOCK_READSOCK(0);
799
800 return GETSOCK_WRITESOCK(0);
801 }
802
domore_getsock(struct connectdata * conn,curl_socket_t * sock,int numsocks)803 static int domore_getsock(struct connectdata *conn,
804 curl_socket_t *sock,
805 int numsocks)
806 {
807 if(!numsocks)
808 return GETSOCK_BLANK;
809
810 /* When in DO_MORE state, we could be either waiting for us
811 to connect to a remote site, or we could wait for that site
812 to connect to us. It makes a difference in the way: if we
813 connect to the site we wait for the socket to become writable, if
814 the site connects to us we wait for it to become readable */
815 sock[0] = conn->sock[SECONDARYSOCKET];
816
817 return GETSOCK_WRITESOCK(0);
818 }
819
820 /* returns bitmapped flags for this handle and its sockets */
multi_getsock(struct Curl_one_easy * easy,curl_socket_t * socks,int numsocks)821 static int multi_getsock(struct Curl_one_easy *easy,
822 curl_socket_t *socks, /* points to numsocks number
823 of sockets */
824 int numsocks)
825 {
826 /* If the pipe broke, or if there's no connection left for this easy handle,
827 then we MUST bail out now with no bitmask set. The no connection case can
828 happen when this is called from curl_multi_remove_handle() =>
829 singlesocket() => multi_getsock().
830 */
831 if(easy->easy_handle->state.pipe_broke || !easy->easy_conn)
832 return 0;
833
834 if(easy->state > CURLM_STATE_CONNECT &&
835 easy->state < CURLM_STATE_COMPLETED) {
836 /* Set up ownership correctly */
837 easy->easy_conn->data = easy->easy_handle;
838 }
839
840 switch(easy->state) {
841 default:
842 #if 0 /* switch back on these cases to get the compiler to check for all enums
843 to be present */
844 case CURLM_STATE_TOOFAST: /* returns 0, so will not select. */
845 case CURLM_STATE_COMPLETED:
846 case CURLM_STATE_MSGSENT:
847 case CURLM_STATE_INIT:
848 case CURLM_STATE_CONNECT:
849 case CURLM_STATE_WAITDO:
850 case CURLM_STATE_DONE:
851 case CURLM_STATE_LAST:
852 /* this will get called with CURLM_STATE_COMPLETED when a handle is
853 removed */
854 #endif
855 return 0;
856
857 case CURLM_STATE_WAITRESOLVE:
858 return Curl_resolv_getsock(easy->easy_conn, socks, numsocks);
859
860 case CURLM_STATE_PROTOCONNECT:
861 return Curl_protocol_getsock(easy->easy_conn, socks, numsocks);
862
863 case CURLM_STATE_DO:
864 case CURLM_STATE_DOING:
865 return Curl_doing_getsock(easy->easy_conn, socks, numsocks);
866
867 case CURLM_STATE_WAITPROXYCONNECT:
868 case CURLM_STATE_WAITCONNECT:
869 return waitconnect_getsock(easy->easy_conn, socks, numsocks);
870
871 case CURLM_STATE_DO_MORE:
872 return domore_getsock(easy->easy_conn, socks, numsocks);
873
874 case CURLM_STATE_DO_DONE: /* since is set after DO is completed, we switch
875 to waiting for the same as the *PERFORM
876 states */
877 case CURLM_STATE_PERFORM:
878 case CURLM_STATE_WAITPERFORM:
879 return Curl_single_getsock(easy->easy_conn, socks, numsocks);
880 }
881
882 }
883
curl_multi_fdset(CURLM * multi_handle,fd_set * read_fd_set,fd_set * write_fd_set,fd_set * exc_fd_set,int * max_fd)884 CURLMcode curl_multi_fdset(CURLM *multi_handle,
885 fd_set *read_fd_set, fd_set *write_fd_set,
886 fd_set *exc_fd_set, int *max_fd)
887 {
888 /* Scan through all the easy handles to get the file descriptors set.
889 Some easy handles may not have connected to the remote host yet,
890 and then we must make sure that is done. */
891 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
892 struct Curl_one_easy *easy;
893 int this_max_fd=-1;
894 curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
895 int bitmap;
896 int i;
897 (void)exc_fd_set; /* not used */
898
899 if(!GOOD_MULTI_HANDLE(multi))
900 return CURLM_BAD_HANDLE;
901
902 easy=multi->easy.next;
903 while(easy != &multi->easy) {
904 bitmap = multi_getsock(easy, sockbunch, MAX_SOCKSPEREASYHANDLE);
905
906 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
907 curl_socket_t s = CURL_SOCKET_BAD;
908
909 if(bitmap & GETSOCK_READSOCK(i)) {
910 FD_SET(sockbunch[i], read_fd_set);
911 s = sockbunch[i];
912 }
913 if(bitmap & GETSOCK_WRITESOCK(i)) {
914 FD_SET(sockbunch[i], write_fd_set);
915 s = sockbunch[i];
916 }
917 if(s == CURL_SOCKET_BAD)
918 /* this socket is unused, break out of loop */
919 break;
920 else {
921 if((int)s > this_max_fd)
922 this_max_fd = (int)s;
923 }
924 }
925
926 easy = easy->next; /* check next handle */
927 }
928
929 *max_fd = this_max_fd;
930
931 return CURLM_OK;
932 }
933
multi_runsingle(struct Curl_multi * multi,struct timeval now,struct Curl_one_easy * easy)934 static CURLMcode multi_runsingle(struct Curl_multi *multi,
935 struct timeval now,
936 struct Curl_one_easy *easy)
937 {
938 struct Curl_message *msg = NULL;
939 bool connected;
940 bool async;
941 bool protocol_connect = FALSE;
942 bool dophase_done;
943 bool done = FALSE;
944 CURLMcode result = CURLM_OK;
945 struct SingleRequest *k;
946 struct SessionHandle *data;
947 long timeout_ms;
948
949 if(!GOOD_EASY_HANDLE(easy->easy_handle))
950 return CURLM_BAD_EASY_HANDLE;
951
952 data = easy->easy_handle;
953
954 do {
955 /* this is a do-while loop just to allow a break to skip to the end
956 of it */
957 bool disconnect_conn = FALSE;
958
959 /* Handle the case when the pipe breaks, i.e., the connection
960 we're using gets cleaned up and we're left with nothing. */
961 if(data->state.pipe_broke) {
962 infof(data, "Pipe broke: handle 0x%p, url = %s\n",
963 easy, data->state.path);
964
965 if(easy->state < CURLM_STATE_COMPLETED) {
966 /* Head back to the CONNECT state */
967 multistate(easy, CURLM_STATE_CONNECT);
968 result = CURLM_CALL_MULTI_PERFORM;
969 easy->result = CURLE_OK;
970 }
971
972 data->state.pipe_broke = FALSE;
973 easy->easy_conn = NULL;
974 break;
975 }
976
977 if(easy->easy_conn && easy->state > CURLM_STATE_CONNECT &&
978 easy->state < CURLM_STATE_COMPLETED)
979 /* Make sure we set the connection's current owner */
980 easy->easy_conn->data = data;
981
982 if(easy->easy_conn &&
983 (easy->state >= CURLM_STATE_CONNECT) &&
984 (easy->state < CURLM_STATE_COMPLETED)) {
985 /* we need to wait for the connect state as only then is the start time
986 stored, but we must not check already completed handles */
987
988 timeout_ms = Curl_timeleft(data, &now,
989 (easy->state <= CURLM_STATE_WAITDO)?
990 TRUE:FALSE);
991
992 if(timeout_ms < 0) {
993 /* Handle timed out */
994 if(easy->state == CURLM_STATE_WAITRESOLVE)
995 failf(data, "Resolving timed out after %ld milliseconds",
996 Curl_tvdiff(now, data->progress.t_startsingle));
997 else if(easy->state == CURLM_STATE_WAITCONNECT)
998 failf(data, "Connection timed out after %ld milliseconds",
999 Curl_tvdiff(now, data->progress.t_startsingle));
1000 else {
1001 k = &data->req;
1002 failf(data, "Operation timed out after %ld milliseconds with %"
1003 FORMAT_OFF_T " out of %" FORMAT_OFF_T " bytes received",
1004 Curl_tvdiff(now, data->progress.t_startsingle), k->bytecount,
1005 k->size);
1006 }
1007
1008 /* Force the connection closed because the server could continue to
1009 send us stuff at any time. (The disconnect_conn logic used below
1010 doesn't work at this point). */
1011 easy->easy_conn->bits.close = TRUE;
1012 easy->result = CURLE_OPERATION_TIMEDOUT;
1013 multistate(easy, CURLM_STATE_COMPLETED);
1014 break;
1015 }
1016 }
1017
1018 switch(easy->state) {
1019 case CURLM_STATE_INIT:
1020 /* init this transfer. */
1021 easy->result=Curl_pretransfer(data);
1022
1023 if(CURLE_OK == easy->result) {
1024 /* after init, go CONNECT */
1025 multistate(easy, CURLM_STATE_CONNECT);
1026 result = CURLM_CALL_MULTI_PERFORM;
1027
1028 data->state.used_interface = Curl_if_multi;
1029 }
1030 break;
1031
1032 case CURLM_STATE_CONNECT:
1033 /* Connect. We get a connection identifier filled in. */
1034 Curl_pgrsTime(data, TIMER_STARTSINGLE);
1035 easy->result = Curl_connect(data, &easy->easy_conn,
1036 &async, &protocol_connect);
1037
1038 if(CURLE_OK == easy->result) {
1039 /* Add this handle to the send or pend pipeline */
1040 easy->result = addHandleToSendOrPendPipeline(data,
1041 easy->easy_conn);
1042 if(CURLE_OK == easy->result) {
1043 if(async)
1044 /* We're now waiting for an asynchronous name lookup */
1045 multistate(easy, CURLM_STATE_WAITRESOLVE);
1046 else {
1047 /* after the connect has been sent off, go WAITCONNECT unless the
1048 protocol connect is already done and we can go directly to
1049 WAITDO or DO! */
1050 result = CURLM_CALL_MULTI_PERFORM;
1051
1052 if(protocol_connect)
1053 multistate(easy, multi->pipelining_enabled?
1054 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1055 else {
1056 #ifndef CURL_DISABLE_HTTP
1057 if(easy->easy_conn->bits.tunnel_connecting)
1058 multistate(easy, CURLM_STATE_WAITPROXYCONNECT);
1059 else
1060 #endif
1061 multistate(easy, CURLM_STATE_WAITCONNECT);
1062 }
1063 }
1064 }
1065 }
1066 break;
1067
1068 case CURLM_STATE_WAITRESOLVE:
1069 /* awaiting an asynch name resolve to complete */
1070 {
1071 struct Curl_dns_entry *dns = NULL;
1072
1073 /* check if we have the name resolved by now */
1074 easy->result = Curl_is_resolved(easy->easy_conn, &dns);
1075
1076 if(dns) {
1077 /* Update sockets here. Mainly because the socket(s) may have been
1078 closed and the application thus needs to be told, even if it is
1079 likely that the same socket(s) will again be used further down. */
1080 singlesocket(multi, easy);
1081
1082 /* Perform the next step in the connection phase, and then move on
1083 to the WAITCONNECT state */
1084 easy->result = Curl_async_resolved(easy->easy_conn,
1085 &protocol_connect);
1086
1087 if(CURLE_OK != easy->result)
1088 /* if Curl_async_resolved() returns failure, the connection struct
1089 is already freed and gone */
1090 easy->easy_conn = NULL; /* no more connection */
1091 else {
1092 /* call again please so that we get the next socket setup */
1093 result = CURLM_CALL_MULTI_PERFORM;
1094 if(protocol_connect)
1095 multistate(easy, multi->pipelining_enabled?
1096 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1097 else {
1098 #ifndef CURL_DISABLE_HTTP
1099 if(easy->easy_conn->bits.tunnel_connecting)
1100 multistate(easy, CURLM_STATE_WAITPROXYCONNECT);
1101 else
1102 #endif
1103 multistate(easy, CURLM_STATE_WAITCONNECT);
1104 }
1105 }
1106 }
1107
1108 if(CURLE_OK != easy->result) {
1109 /* failure detected */
1110 disconnect_conn = TRUE;
1111 break;
1112 }
1113 }
1114 break;
1115
1116 #ifndef CURL_DISABLE_HTTP
1117 case CURLM_STATE_WAITPROXYCONNECT:
1118 /* this is HTTP-specific, but sending CONNECT to a proxy is HTTP... */
1119 easy->result = Curl_http_connect(easy->easy_conn, &protocol_connect);
1120
1121 if(easy->easy_conn->bits.proxy_connect_closed) {
1122 /* reset the error buffer */
1123 if(data->set.errorbuffer)
1124 data->set.errorbuffer[0] = '\0';
1125 data->state.errorbuf = FALSE;
1126
1127 easy->result = CURLE_OK;
1128 result = CURLM_CALL_MULTI_PERFORM;
1129 multistate(easy, CURLM_STATE_CONNECT);
1130 }
1131 else if (CURLE_OK == easy->result) {
1132 if(!easy->easy_conn->bits.tunnel_connecting)
1133 multistate(easy, CURLM_STATE_WAITCONNECT);
1134 }
1135 break;
1136 #endif
1137
1138 case CURLM_STATE_WAITCONNECT:
1139 /* awaiting a completion of an asynch connect */
1140 easy->result = Curl_is_connected(easy->easy_conn,
1141 FIRSTSOCKET,
1142 &connected);
1143 if(connected) {
1144 /* see if we need to do any proxy magic first once we connected */
1145 easy->result = Curl_connected_proxy(easy->easy_conn);
1146
1147 if(!easy->result)
1148 /* if everything is still fine we do the protocol-specific connect
1149 setup */
1150 easy->result = Curl_protocol_connect(easy->easy_conn,
1151 &protocol_connect);
1152 }
1153
1154 if(CURLE_OK != easy->result) {
1155 /* failure detected */
1156 /* Just break, the cleaning up is handled all in one place */
1157 disconnect_conn = TRUE;
1158 break;
1159 }
1160
1161 if(connected) {
1162 if(!protocol_connect) {
1163 /* We have a TCP connection, but 'protocol_connect' may be false
1164 and then we continue to 'STATE_PROTOCONNECT'. If protocol
1165 connect is TRUE, we move on to STATE_DO.
1166 BUT if we are using a proxy we must change to WAITPROXYCONNECT
1167 */
1168 #ifndef CURL_DISABLE_HTTP
1169 if(easy->easy_conn->bits.tunnel_connecting)
1170 multistate(easy, CURLM_STATE_WAITPROXYCONNECT);
1171 else
1172 #endif
1173 multistate(easy, CURLM_STATE_PROTOCONNECT);
1174
1175 }
1176 else
1177 /* after the connect has completed, go WAITDO or DO */
1178 multistate(easy, multi->pipelining_enabled?
1179 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1180
1181 result = CURLM_CALL_MULTI_PERFORM;
1182 }
1183 break;
1184
1185 case CURLM_STATE_PROTOCONNECT:
1186 /* protocol-specific connect phase */
1187 easy->result = Curl_protocol_connecting(easy->easy_conn,
1188 &protocol_connect);
1189 if((easy->result == CURLE_OK) && protocol_connect) {
1190 /* after the connect has completed, go WAITDO or DO */
1191 multistate(easy, multi->pipelining_enabled?
1192 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1193 result = CURLM_CALL_MULTI_PERFORM;
1194 }
1195 else if(easy->result) {
1196 /* failure detected */
1197 Curl_posttransfer(data);
1198 Curl_done(&easy->easy_conn, easy->result, TRUE);
1199 disconnect_conn = TRUE;
1200 }
1201 break;
1202
1203 case CURLM_STATE_WAITDO:
1204 /* Wait for our turn to DO when we're pipelining requests */
1205 #ifdef DEBUGBUILD
1206 infof(data, "Conn %ld send pipe %zu inuse %d athead %d\n",
1207 easy->easy_conn->connectindex,
1208 easy->easy_conn->send_pipe->size,
1209 easy->easy_conn->writechannel_inuse?1:0,
1210 isHandleAtHead(data,
1211 easy->easy_conn->send_pipe)?1:0);
1212 #endif
1213 if(!easy->easy_conn->writechannel_inuse &&
1214 isHandleAtHead(data,
1215 easy->easy_conn->send_pipe)) {
1216 /* Grab the channel */
1217 easy->easy_conn->writechannel_inuse = TRUE;
1218 multistate(easy, CURLM_STATE_DO);
1219 result = CURLM_CALL_MULTI_PERFORM;
1220 }
1221 break;
1222
1223 case CURLM_STATE_DO:
1224 if(data->set.connect_only) {
1225 /* keep connection open for application to use the socket */
1226 easy->easy_conn->bits.close = FALSE;
1227 multistate(easy, CURLM_STATE_DONE);
1228 easy->result = CURLE_OK;
1229 result = CURLM_OK;
1230 }
1231 else {
1232 /* Perform the protocol's DO action */
1233 easy->result = Curl_do(&easy->easy_conn,
1234 &dophase_done);
1235
1236 if(CURLE_OK == easy->result) {
1237 if(!dophase_done) {
1238 /* some steps needed for wildcard matching */
1239 if(data->set.wildcardmatch) {
1240 struct WildcardData *wc = &data->wildcard;
1241 if(wc->state == CURLWC_DONE || wc->state == CURLWC_SKIP) {
1242 /* skip some states if it is important */
1243 Curl_done(&easy->easy_conn, CURLE_OK, FALSE);
1244 multistate(easy, CURLM_STATE_DONE);
1245 result = CURLM_CALL_MULTI_PERFORM;
1246 break;
1247 }
1248 }
1249 /* DO was not completed in one function call, we must continue
1250 DOING... */
1251 multistate(easy, CURLM_STATE_DOING);
1252 result = CURLM_OK;
1253 }
1254
1255 /* after DO, go DO_DONE... or DO_MORE */
1256 else if(easy->easy_conn->bits.do_more) {
1257 /* we're supposed to do more, but we need to sit down, relax
1258 and wait a little while first */
1259 multistate(easy, CURLM_STATE_DO_MORE);
1260 result = CURLM_OK;
1261 }
1262 else {
1263 /* we're done with the DO, now DO_DONE */
1264 multistate(easy, CURLM_STATE_DO_DONE);
1265 result = CURLM_CALL_MULTI_PERFORM;
1266 }
1267 }
1268 else if ((CURLE_SEND_ERROR == easy->result) &&
1269 easy->easy_conn->bits.reuse) {
1270 /*
1271 * In this situation, a connection that we were trying to use
1272 * may have unexpectedly died. If possible, send the connection
1273 * back to the CONNECT phase so we can try again.
1274 */
1275 char *newurl = NULL;
1276 followtype follow=FOLLOW_NONE;
1277 CURLcode drc;
1278 bool retry = FALSE;
1279
1280 drc = Curl_retry_request(easy->easy_conn, &newurl);
1281 if(drc) {
1282 /* a failure here pretty much implies an out of memory */
1283 easy->result = drc;
1284 disconnect_conn = TRUE;
1285 }
1286 else
1287 retry = (bool)(newurl?TRUE:FALSE);
1288
1289 Curl_posttransfer(data);
1290 drc = Curl_done(&easy->easy_conn, easy->result, FALSE);
1291
1292 /* When set to retry the connection, we must to go back to
1293 * the CONNECT state */
1294 if(retry) {
1295 if ((drc == CURLE_OK) || (drc == CURLE_SEND_ERROR)) {
1296 follow = FOLLOW_RETRY;
1297 drc = Curl_follow(data, newurl, follow);
1298 if(drc == CURLE_OK) {
1299 multistate(easy, CURLM_STATE_CONNECT);
1300 result = CURLM_CALL_MULTI_PERFORM;
1301 easy->result = CURLE_OK;
1302 }
1303 else {
1304 /* Follow failed */
1305 easy->result = drc;
1306 free(newurl);
1307 }
1308 }
1309 else {
1310 /* done didn't return OK or SEND_ERROR */
1311 easy->result = drc;
1312 free(newurl);
1313 }
1314 }
1315 else {
1316 /* Have error handler disconnect conn if we can't retry */
1317 disconnect_conn = TRUE;
1318 }
1319 }
1320 else {
1321 /* failure detected */
1322 Curl_posttransfer(data);
1323 Curl_done(&easy->easy_conn, easy->result, FALSE);
1324 disconnect_conn = TRUE;
1325 }
1326 }
1327 break;
1328
1329 case CURLM_STATE_DOING:
1330 /* we continue DOING until the DO phase is complete */
1331 easy->result = Curl_protocol_doing(easy->easy_conn,
1332 &dophase_done);
1333 if(CURLE_OK == easy->result) {
1334 if(dophase_done) {
1335 /* after DO, go PERFORM... or DO_MORE */
1336 if(easy->easy_conn->bits.do_more) {
1337 /* we're supposed to do more, but we need to sit down, relax
1338 and wait a little while first */
1339 multistate(easy, CURLM_STATE_DO_MORE);
1340 result = CURLM_OK;
1341 }
1342 else {
1343 /* we're done with the DO, now DO_DONE */
1344 multistate(easy, CURLM_STATE_DO_DONE);
1345 result = CURLM_CALL_MULTI_PERFORM;
1346 }
1347 } /* dophase_done */
1348 }
1349 else {
1350 /* failure detected */
1351 Curl_posttransfer(data);
1352 Curl_done(&easy->easy_conn, easy->result, FALSE);
1353 disconnect_conn = TRUE;
1354 }
1355 break;
1356
1357 case CURLM_STATE_DO_MORE:
1358 /* Ready to do more? */
1359 easy->result = Curl_is_connected(easy->easy_conn,
1360 SECONDARYSOCKET,
1361 &connected);
1362 if(connected) {
1363 /*
1364 * When we are connected, DO MORE and then go DO_DONE
1365 */
1366 easy->result = Curl_do_more(easy->easy_conn);
1367
1368 /* No need to remove ourselves from the send pipeline here since that
1369 is done for us in Curl_done() */
1370
1371 if(CURLE_OK == easy->result) {
1372 multistate(easy, CURLM_STATE_DO_DONE);
1373 result = CURLM_CALL_MULTI_PERFORM;
1374 }
1375 else {
1376 /* failure detected */
1377 Curl_posttransfer(data);
1378 Curl_done(&easy->easy_conn, easy->result, FALSE);
1379 disconnect_conn = TRUE;
1380 }
1381 }
1382 break;
1383
1384 case CURLM_STATE_DO_DONE:
1385 /* Move ourselves from the send to recv pipeline */
1386 moveHandleFromSendToRecvPipeline(data, easy->easy_conn);
1387 /* Check if we can move pending requests to send pipe */
1388 checkPendPipeline(easy->easy_conn);
1389 multistate(easy, CURLM_STATE_WAITPERFORM);
1390 result = CURLM_CALL_MULTI_PERFORM;
1391 break;
1392
1393 case CURLM_STATE_WAITPERFORM:
1394 /* Wait for our turn to PERFORM */
1395 if(!easy->easy_conn->readchannel_inuse &&
1396 isHandleAtHead(data,
1397 easy->easy_conn->recv_pipe)) {
1398 /* Grab the channel */
1399 easy->easy_conn->readchannel_inuse = TRUE;
1400 multistate(easy, CURLM_STATE_PERFORM);
1401 result = CURLM_CALL_MULTI_PERFORM;
1402 }
1403 #ifdef DEBUGBUILD
1404 else {
1405 infof(data, "Conn %ld recv pipe %zu inuse %d athead %d\n",
1406 easy->easy_conn->connectindex,
1407 easy->easy_conn->recv_pipe->size,
1408 easy->easy_conn->readchannel_inuse?1:0,
1409 isHandleAtHead(data,
1410 easy->easy_conn->recv_pipe)?1:0);
1411 }
1412 #endif
1413 break;
1414
1415 case CURLM_STATE_TOOFAST: /* limit-rate exceeded in either direction */
1416 /* if both rates are within spec, resume transfer */
1417 Curl_pgrsUpdate(easy->easy_conn);
1418 if( ( (data->set.max_send_speed == 0) ||
1419 (data->progress.ulspeed < data->set.max_send_speed )) &&
1420 ( (data->set.max_recv_speed == 0) ||
1421 (data->progress.dlspeed < data->set.max_recv_speed) ) )
1422 multistate(easy, CURLM_STATE_PERFORM);
1423 break;
1424
1425 case CURLM_STATE_PERFORM:
1426 /* check if over send speed */
1427 if( (data->set.max_send_speed > 0) &&
1428 (data->progress.ulspeed > data->set.max_send_speed) ) {
1429 int buffersize;
1430
1431 multistate(easy, CURLM_STATE_TOOFAST);
1432
1433 /* calculate upload rate-limitation timeout. */
1434 buffersize = (int)(data->set.buffer_size ?
1435 data->set.buffer_size : BUFSIZE);
1436 timeout_ms = Curl_sleep_time(data->set.max_send_speed,
1437 data->progress.ulspeed, buffersize);
1438 Curl_expire(data, timeout_ms);
1439 break;
1440 }
1441
1442 /* check if over recv speed */
1443 if( (data->set.max_recv_speed > 0) &&
1444 (data->progress.dlspeed > data->set.max_recv_speed) ) {
1445 int buffersize;
1446
1447 multistate(easy, CURLM_STATE_TOOFAST);
1448
1449 /* Calculate download rate-limitation timeout. */
1450 buffersize = (int)(data->set.buffer_size ?
1451 data->set.buffer_size : BUFSIZE);
1452 timeout_ms = Curl_sleep_time(data->set.max_recv_speed,
1453 data->progress.dlspeed, buffersize);
1454 Curl_expire(data, timeout_ms);
1455 break;
1456 }
1457
1458 /* read/write data if it is ready to do so */
1459 easy->result = Curl_readwrite(easy->easy_conn, &done);
1460
1461 k = &data->req;
1462
1463 if(!(k->keepon & KEEP_RECV)) {
1464 /* We're done receiving */
1465 easy->easy_conn->readchannel_inuse = FALSE;
1466 }
1467
1468 if(!(k->keepon & KEEP_SEND)) {
1469 /* We're done sending */
1470 easy->easy_conn->writechannel_inuse = FALSE;
1471 }
1472
1473 if(easy->result) {
1474 /* The transfer phase returned error, we mark the connection to get
1475 * closed to prevent being re-used. This is because we can't possibly
1476 * know if the connection is in a good shape or not now. Unless it is
1477 * a protocol which uses two "channels" like FTP, as then the error
1478 * happened in the data connection.
1479 */
1480 if(!(easy->easy_conn->handler->flags & PROTOPT_DUAL))
1481 easy->easy_conn->bits.close = TRUE;
1482
1483 Curl_posttransfer(data);
1484 Curl_done(&easy->easy_conn, easy->result, FALSE);
1485 }
1486 else if(TRUE == done) {
1487 char *newurl = NULL;
1488 bool retry = FALSE;
1489 followtype follow=FOLLOW_NONE;
1490
1491 easy->result = Curl_retry_request(easy->easy_conn, &newurl);
1492 if(!easy->result)
1493 retry = (bool)(newurl?TRUE:FALSE);
1494
1495 /* call this even if the readwrite function returned error */
1496 Curl_posttransfer(data);
1497
1498 /* we're no longer receiving */
1499 moveHandleFromRecvToDonePipeline(data,
1500 easy->easy_conn);
1501
1502 /* expire the new receiving pipeline head */
1503 if(easy->easy_conn->recv_pipe->head)
1504 Curl_expire(easy->easy_conn->recv_pipe->head->ptr, 1);
1505
1506 /* Check if we can move pending requests to send pipe */
1507 checkPendPipeline(easy->easy_conn);
1508
1509 /* When we follow redirects or is set to retry the connection, we must
1510 to go back to the CONNECT state */
1511 if(data->req.newurl || retry) {
1512 if(!retry) {
1513 /* if the URL is a follow-location and not just a retried request
1514 then figure out the URL here */
1515 newurl = data->req.newurl;
1516 data->req.newurl = NULL;
1517 follow = FOLLOW_REDIR;
1518 }
1519 else
1520 follow = FOLLOW_RETRY;
1521 easy->result = Curl_done(&easy->easy_conn, CURLE_OK, FALSE);
1522 if(easy->result == CURLE_OK)
1523 easy->result = Curl_follow(data, newurl, follow);
1524 if(CURLE_OK == easy->result) {
1525 multistate(easy, CURLM_STATE_CONNECT);
1526 result = CURLM_CALL_MULTI_PERFORM;
1527 }
1528 else if(newurl)
1529 /* Since we "took it", we are in charge of freeing this on
1530 failure */
1531 free(newurl);
1532 }
1533 else {
1534 /* after the transfer is done, go DONE */
1535
1536 /* but first check to see if we got a location info even though we're
1537 not following redirects */
1538 if (data->req.location) {
1539 newurl = data->req.location;
1540 data->req.location = NULL;
1541 easy->result = Curl_follow(data, newurl, FOLLOW_FAKE);
1542 if (easy->result)
1543 free(newurl);
1544 }
1545
1546 multistate(easy, CURLM_STATE_DONE);
1547 result = CURLM_CALL_MULTI_PERFORM;
1548 }
1549 }
1550
1551 break;
1552
1553 case CURLM_STATE_DONE:
1554
1555 if(easy->easy_conn) {
1556 /* Remove ourselves from the receive and done pipelines. Handle
1557 should be on one of these lists, depending upon how we got here. */
1558 Curl_removeHandleFromPipeline(data,
1559 easy->easy_conn->recv_pipe);
1560 Curl_removeHandleFromPipeline(data,
1561 easy->easy_conn->done_pipe);
1562 /* Check if we can move pending requests to send pipe */
1563 checkPendPipeline(easy->easy_conn);
1564
1565 if(easy->easy_conn->bits.stream_was_rewound) {
1566 /* This request read past its response boundary so we quickly let
1567 the other requests consume those bytes since there is no
1568 guarantee that the socket will become active again */
1569 result = CURLM_CALL_MULTI_PERFORM;
1570 }
1571
1572 /* post-transfer command */
1573 easy->result = Curl_done(&easy->easy_conn, CURLE_OK, FALSE);
1574 /*
1575 * If there are other handles on the pipeline, Curl_done won't set
1576 * easy_conn to NULL. In such a case, curl_multi_remove_handle() can
1577 * access free'd data, if the connection is free'd and the handle
1578 * removed before we perform the processing in CURLM_STATE_COMPLETED
1579 */
1580 if (easy->easy_conn)
1581 easy->easy_conn = NULL;
1582 }
1583
1584 if(data->set.wildcardmatch) {
1585 if(data->wildcard.state != CURLWC_DONE) {
1586 /* if a wildcard is set and we are not ending -> lets start again
1587 with CURLM_STATE_INIT */
1588 result = CURLM_CALL_MULTI_PERFORM;
1589 multistate(easy, CURLM_STATE_INIT);
1590 break;
1591 }
1592 }
1593
1594 /* after we have DONE what we're supposed to do, go COMPLETED, and
1595 it doesn't matter what the Curl_done() returned! */
1596 multistate(easy, CURLM_STATE_COMPLETED);
1597
1598 break;
1599
1600 case CURLM_STATE_COMPLETED:
1601 /* this is a completed transfer, it is likely to still be connected */
1602
1603 /* This node should be delinked from the list now and we should post
1604 an information message that we are complete. */
1605
1606 /* Important: reset the conn pointer so that we don't point to memory
1607 that could be freed anytime */
1608 easy->easy_conn = NULL;
1609
1610 Curl_expire(data, 0); /* stop all timers */
1611 break;
1612
1613 case CURLM_STATE_MSGSENT:
1614 return CURLM_OK; /* do nothing */
1615
1616 default:
1617 return CURLM_INTERNAL_ERROR;
1618 }
1619
1620 if(CURLM_STATE_COMPLETED > easy->state) {
1621 if(CURLE_OK != easy->result) {
1622 /*
1623 * If an error was returned, and we aren't in completed state now,
1624 * then we go to completed and consider this transfer aborted.
1625 */
1626
1627 /* NOTE: no attempt to disconnect connections must be made
1628 in the case blocks above - cleanup happens only here */
1629
1630 data->state.pipe_broke = FALSE;
1631
1632 if(easy->easy_conn) {
1633 /* if this has a connection, unsubscribe from the pipelines */
1634 easy->easy_conn->writechannel_inuse = FALSE;
1635 easy->easy_conn->readchannel_inuse = FALSE;
1636 Curl_removeHandleFromPipeline(data,
1637 easy->easy_conn->send_pipe);
1638 Curl_removeHandleFromPipeline(data,
1639 easy->easy_conn->recv_pipe);
1640 Curl_removeHandleFromPipeline(data,
1641 easy->easy_conn->done_pipe);
1642 /* Check if we can move pending requests to send pipe */
1643 checkPendPipeline(easy->easy_conn);
1644 }
1645
1646 if(disconnect_conn) {
1647 /* disconnect properly */
1648 Curl_disconnect(easy->easy_conn, /* dead_connection */ FALSE);
1649
1650 /* This is where we make sure that the easy_conn pointer is reset.
1651 We don't have to do this in every case block above where a
1652 failure is detected */
1653 easy->easy_conn = NULL;
1654 }
1655
1656 multistate(easy, CURLM_STATE_COMPLETED);
1657 }
1658 /* if there's still a connection to use, call the progress function */
1659 else if(easy->easy_conn && Curl_pgrsUpdate(easy->easy_conn))
1660 easy->result = CURLE_ABORTED_BY_CALLBACK;
1661 }
1662 } while(0);
1663
1664 if(CURLM_STATE_COMPLETED == easy->state) {
1665 if(data->dns.hostcachetype == HCACHE_MULTI) {
1666 /* clear out the usage of the shared DNS cache */
1667 data->dns.hostcache = NULL;
1668 data->dns.hostcachetype = HCACHE_NONE;
1669 }
1670
1671 /* now fill in the Curl_message with this info */
1672 msg = &easy->msg;
1673
1674 msg->extmsg.msg = CURLMSG_DONE;
1675 msg->extmsg.easy_handle = data;
1676 msg->extmsg.data.result = easy->result;
1677
1678 result = multi_addmsg(multi, msg);
1679
1680 multistate(easy, CURLM_STATE_MSGSENT);
1681 }
1682
1683 return result;
1684 }
1685
1686
curl_multi_perform(CURLM * multi_handle,int * running_handles)1687 CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
1688 {
1689 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1690 struct Curl_one_easy *easy;
1691 CURLMcode returncode=CURLM_OK;
1692 struct Curl_tree *t;
1693 struct timeval now = Curl_tvnow();
1694
1695 if(!GOOD_MULTI_HANDLE(multi))
1696 return CURLM_BAD_HANDLE;
1697
1698 easy=multi->easy.next;
1699 while(easy != &multi->easy) {
1700 CURLMcode result;
1701 struct WildcardData *wc = &easy->easy_handle->wildcard;
1702
1703 if(easy->easy_handle->set.wildcardmatch) {
1704 if(!wc->filelist) {
1705 CURLcode ret = Curl_wildcard_init(wc); /* init wildcard structures */
1706 if(ret)
1707 return CURLM_OUT_OF_MEMORY;
1708 }
1709 }
1710
1711 do
1712 result = multi_runsingle(multi, now, easy);
1713 while (CURLM_CALL_MULTI_PERFORM == result);
1714
1715 if(easy->easy_handle->set.wildcardmatch) {
1716 /* destruct wildcard structures if it is needed */
1717 if(wc->state == CURLWC_DONE || result)
1718 Curl_wildcard_dtor(wc);
1719 }
1720
1721 if(result)
1722 returncode = result;
1723
1724 easy = easy->next; /* operate on next handle */
1725 }
1726
1727 /*
1728 * Simply remove all expired timers from the splay since handles are dealt
1729 * with unconditionally by this function and curl_multi_timeout() requires
1730 * that already passed/handled expire times are removed from the splay.
1731 *
1732 * It is important that the 'now' value is set at the entry of this function
1733 * and not for the current time as it may have ticked a little while since
1734 * then and then we risk this loop to remove timers that actually have not
1735 * been handled!
1736 */
1737 do {
1738 multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
1739 if(t)
1740 /* the removed may have another timeout in queue */
1741 (void)add_next_timeout(now, multi, t->payload);
1742
1743 } while(t);
1744
1745 *running_handles = multi->num_alive;
1746
1747 if( CURLM_OK >= returncode )
1748 update_timer(multi);
1749
1750 return returncode;
1751 }
1752
curl_multi_cleanup(CURLM * multi_handle)1753 CURLMcode curl_multi_cleanup(CURLM *multi_handle)
1754 {
1755 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1756 struct Curl_one_easy *easy;
1757 struct Curl_one_easy *nexteasy;
1758 int i;
1759 struct closure *cl;
1760 struct closure *n;
1761
1762 if(GOOD_MULTI_HANDLE(multi)) {
1763 multi->type = 0; /* not good anymore */
1764 Curl_hash_destroy(multi->hostcache);
1765 Curl_hash_destroy(multi->sockhash);
1766 multi->hostcache = NULL;
1767 multi->sockhash = NULL;
1768
1769 /* go over all connections that have close actions */
1770 for(i=0; i< multi->connc->num; i++) {
1771 if(multi->connc->connects[i] &&
1772 multi->connc->connects[i]->handler->flags & PROTOPT_CLOSEACTION) {
1773 Curl_disconnect(multi->connc->connects[i], FALSE);
1774 multi->connc->connects[i] = NULL;
1775 }
1776 }
1777 /* now walk through the list of handles we kept around only to be
1778 able to close connections "properly" */
1779 cl = multi->closure;
1780 while(cl) {
1781 cl->easy_handle->state.shared_conn = NULL; /* no more shared */
1782 if(cl->easy_handle->state.closed)
1783 /* close handle only if curl_easy_cleanup() already has been called
1784 for this easy handle */
1785 Curl_close(cl->easy_handle);
1786 n = cl->next;
1787 free(cl);
1788 cl= n;
1789 }
1790
1791 Curl_rm_connc(multi->connc);
1792
1793 /* remove the pending list of messages */
1794 Curl_llist_destroy(multi->msglist, NULL);
1795
1796 /* remove all easy handles */
1797 easy = multi->easy.next;
1798 while(easy != &multi->easy) {
1799 nexteasy=easy->next;
1800 if(easy->easy_handle->dns.hostcachetype == HCACHE_MULTI) {
1801 /* clear out the usage of the shared DNS cache */
1802 easy->easy_handle->dns.hostcache = NULL;
1803 easy->easy_handle->dns.hostcachetype = HCACHE_NONE;
1804 }
1805
1806 /* Clear the pointer to the connection cache */
1807 easy->easy_handle->state.connc = NULL;
1808
1809 Curl_easy_addmulti(easy->easy_handle, NULL); /* clear the association */
1810
1811 free(easy);
1812 easy = nexteasy;
1813 }
1814
1815 free(multi);
1816
1817 return CURLM_OK;
1818 }
1819 else
1820 return CURLM_BAD_HANDLE;
1821 }
1822
1823 /*
1824 * curl_multi_info_read()
1825 *
1826 * This function is the primary way for a multi/multi_socket application to
1827 * figure out if a transfer has ended. We MUST make this function as fast as
1828 * possible as it will be polled frequently and we MUST NOT scan any lists in
1829 * here to figure out things. We must scale fine to thousands of handles and
1830 * beyond. The current design is fully O(1).
1831 */
1832
curl_multi_info_read(CURLM * multi_handle,int * msgs_in_queue)1833 CURLMsg *curl_multi_info_read(CURLM *multi_handle, int *msgs_in_queue)
1834 {
1835 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1836 struct Curl_message *msg;
1837
1838 *msgs_in_queue = 0; /* default to none */
1839
1840 if(GOOD_MULTI_HANDLE(multi) && Curl_llist_count(multi->msglist)) {
1841 /* there is one or more messages in the list */
1842 struct curl_llist_element *e;
1843
1844 /* extract the head of the list to return */
1845 e = multi->msglist->head;
1846
1847 msg = e->ptr;
1848
1849 /* remove the extracted entry */
1850 Curl_llist_remove(multi->msglist, e, NULL);
1851
1852 *msgs_in_queue = curlx_uztosi(Curl_llist_count(multi->msglist));
1853
1854 return &msg->extmsg;
1855 }
1856 else
1857 return NULL;
1858 }
1859
1860 /*
1861 * singlesocket() checks what sockets we deal with and their "action state"
1862 * and if we have a different state in any of those sockets from last time we
1863 * call the callback accordingly.
1864 */
singlesocket(struct Curl_multi * multi,struct Curl_one_easy * easy)1865 static void singlesocket(struct Curl_multi *multi,
1866 struct Curl_one_easy *easy)
1867 {
1868 curl_socket_t socks[MAX_SOCKSPEREASYHANDLE];
1869 int i;
1870 struct Curl_sh_entry *entry;
1871 curl_socket_t s;
1872 int num;
1873 unsigned int curraction;
1874 struct Curl_one_easy *easy_by_hash;
1875 bool remove_sock_from_hash;
1876
1877 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++)
1878 socks[i] = CURL_SOCKET_BAD;
1879
1880 /* Fill in the 'current' struct with the state as it is now: what sockets to
1881 supervise and for what actions */
1882 curraction = multi_getsock(easy, socks, MAX_SOCKSPEREASYHANDLE);
1883
1884 /* We have 0 .. N sockets already and we get to know about the 0 .. M
1885 sockets we should have from now on. Detect the differences, remove no
1886 longer supervised ones and add new ones */
1887
1888 /* walk over the sockets we got right now */
1889 for(i=0; (i< MAX_SOCKSPEREASYHANDLE) &&
1890 (curraction & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i)));
1891 i++) {
1892 int action = CURL_POLL_NONE;
1893
1894 s = socks[i];
1895
1896 /* get it from the hash */
1897 entry = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
1898
1899 if(curraction & GETSOCK_READSOCK(i))
1900 action |= CURL_POLL_IN;
1901 if(curraction & GETSOCK_WRITESOCK(i))
1902 action |= CURL_POLL_OUT;
1903
1904 if(entry) {
1905 /* yeps, already present so check if it has the same action set */
1906 if(entry->action == action)
1907 /* same, continue */
1908 continue;
1909 }
1910 else {
1911 /* this is a socket we didn't have before, add it! */
1912 entry = sh_addentry(multi->sockhash, s, easy->easy_handle);
1913 if(!entry)
1914 /* fatal */
1915 return;
1916 }
1917
1918 /* we know (entry != NULL) at this point, see the logic above */
1919 multi->socket_cb(easy->easy_handle,
1920 s,
1921 action,
1922 multi->socket_userp,
1923 entry->socketp);
1924
1925 entry->action = action; /* store the current action state */
1926 }
1927
1928 num = i; /* number of sockets */
1929
1930 /* when we've walked over all the sockets we should have right now, we must
1931 make sure to detect sockets that are removed */
1932 for(i=0; i< easy->numsocks; i++) {
1933 int j;
1934 s = easy->sockets[i];
1935 for(j=0; j<num; j++) {
1936 if(s == socks[j]) {
1937 /* this is still supervised */
1938 s = CURL_SOCKET_BAD;
1939 break;
1940 }
1941 }
1942 if(s != CURL_SOCKET_BAD) {
1943
1944 /* this socket has been removed. Tell the app to remove it */
1945 remove_sock_from_hash = TRUE;
1946
1947 entry = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
1948 if(entry) {
1949 /* check if the socket to be removed serves a connection which has
1950 other easy-s in a pipeline. In this case the socket should not be
1951 removed. */
1952 struct connectdata *easy_conn;
1953
1954 easy_by_hash = entry->easy->multi_pos;
1955 easy_conn = easy_by_hash->easy_conn;
1956 if(easy_conn) {
1957 if (easy_conn->recv_pipe && easy_conn->recv_pipe->size > 1) {
1958 /* the handle should not be removed from the pipe yet */
1959 remove_sock_from_hash = FALSE;
1960
1961 /* Update the sockhash entry to instead point to the next in line
1962 for the recv_pipe, or the first (in case this particular easy
1963 isn't already) */
1964 if (entry->easy == easy->easy_handle) {
1965 if (isHandleAtHead(easy->easy_handle, easy_conn->recv_pipe))
1966 entry->easy = easy_conn->recv_pipe->head->next->ptr;
1967 else
1968 entry->easy = easy_conn->recv_pipe->head->ptr;
1969 }
1970 }
1971 if (easy_conn->send_pipe && easy_conn->send_pipe->size > 1) {
1972 /* the handle should not be removed from the pipe yet */
1973 remove_sock_from_hash = FALSE;
1974
1975 /* Update the sockhash entry to instead point to the next in line
1976 for the send_pipe, or the first (in case this particular easy
1977 isn't already) */
1978 if (entry->easy == easy->easy_handle) {
1979 if (isHandleAtHead(easy->easy_handle, easy_conn->send_pipe))
1980 entry->easy = easy_conn->send_pipe->head->next->ptr;
1981 else
1982 entry->easy = easy_conn->send_pipe->head->ptr;
1983 }
1984 }
1985 /* Don't worry about overwriting recv_pipe head with send_pipe_head,
1986 when action will be asked on the socket (see multi_socket()), the
1987 head of the correct pipe will be taken according to the
1988 action. */
1989 }
1990 }
1991 else
1992 /* just a precaution, this socket really SHOULD be in the hash already
1993 but in case it isn't, we don't have to tell the app to remove it
1994 either since it never got to know about it */
1995 remove_sock_from_hash = FALSE;
1996
1997 if (remove_sock_from_hash) {
1998 multi->socket_cb(easy->easy_handle,
1999 s,
2000 CURL_POLL_REMOVE,
2001 multi->socket_userp,
2002 entry ? entry->socketp : NULL);
2003 sh_delentry(multi->sockhash, s);
2004 }
2005
2006 }
2007 }
2008
2009 memcpy(easy->sockets, socks, num*sizeof(curl_socket_t));
2010 easy->numsocks = num;
2011 }
2012
2013 /*
2014 * add_next_timeout()
2015 *
2016 * Each SessionHandle has a list of timeouts. The add_next_timeout() is called
2017 * when it has just been removed from the splay tree because the timeout has
2018 * expired. This function is then to advance in the list to pick the next
2019 * timeout to use (skip the already expired ones) and add this node back to
2020 * the splay tree again.
2021 *
2022 * The splay tree only has each sessionhandle as a single node and the nearest
2023 * timeout is used to sort it on.
2024 */
add_next_timeout(struct timeval now,struct Curl_multi * multi,struct SessionHandle * d)2025 static CURLMcode add_next_timeout(struct timeval now,
2026 struct Curl_multi *multi,
2027 struct SessionHandle *d)
2028 {
2029 struct timeval *tv = &d->state.expiretime;
2030 struct curl_llist *list = d->state.timeoutlist;
2031 struct curl_llist_element *e;
2032
2033 /* move over the timeout list for this specific handle and remove all
2034 timeouts that are now passed tense and store the next pending
2035 timeout in *tv */
2036 for(e = list->head; e; ) {
2037 struct curl_llist_element *n = e->next;
2038 long diff = curlx_tvdiff(*(struct timeval *)e->ptr, now);
2039 if(diff <= 0)
2040 /* remove outdated entry */
2041 Curl_llist_remove(list, e, NULL);
2042 else
2043 /* the list is sorted so get out on the first mismatch */
2044 break;
2045 e = n;
2046 }
2047 if(!list->size) {
2048 /* clear the expire times within the handles that we remove from the
2049 splay tree */
2050 tv->tv_sec = 0;
2051 tv->tv_usec = 0;
2052 }
2053 else {
2054 e = list->head;
2055 /* copy the first entry to 'tv' */
2056 memcpy(tv, e->ptr, sizeof(*tv));
2057
2058 /* remove first entry from list */
2059 Curl_llist_remove(list, e, NULL);
2060
2061 /* insert this node again into the splay */
2062 multi->timetree = Curl_splayinsert(*tv, multi->timetree,
2063 &d->state.timenode);
2064 }
2065 return CURLM_OK;
2066 }
2067
2068
multi_socket(struct Curl_multi * multi,bool checkall,curl_socket_t s,int ev_bitmask,int * running_handles)2069 static CURLMcode multi_socket(struct Curl_multi *multi,
2070 bool checkall,
2071 curl_socket_t s,
2072 int ev_bitmask,
2073 int *running_handles)
2074 {
2075 CURLMcode result = CURLM_OK;
2076 struct SessionHandle *data = NULL;
2077 struct Curl_tree *t;
2078 struct timeval now = Curl_tvnow();
2079
2080 if(checkall) {
2081 struct Curl_one_easy *easyp;
2082 /* *perform() deals with running_handles on its own */
2083 result = curl_multi_perform(multi, running_handles);
2084
2085 /* walk through each easy handle and do the socket state change magic
2086 and callbacks */
2087 easyp=multi->easy.next;
2088 while(easyp != &multi->easy) {
2089 singlesocket(multi, easyp);
2090 easyp = easyp->next;
2091 }
2092
2093 /* or should we fall-through and do the timer-based stuff? */
2094 return result;
2095 }
2096 else if(s != CURL_SOCKET_TIMEOUT) {
2097
2098 struct Curl_sh_entry *entry =
2099 Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
2100
2101 if(!entry)
2102 /* Unmatched socket, we can't act on it but we ignore this fact. In
2103 real-world tests it has been proved that libevent can in fact give
2104 the application actions even though the socket was just previously
2105 asked to get removed, so thus we better survive stray socket actions
2106 and just move on. */
2107 ;
2108 else {
2109 data = entry->easy;
2110
2111 if(data->magic != CURLEASY_MAGIC_NUMBER)
2112 /* bad bad bad bad bad bad bad */
2113 return CURLM_INTERNAL_ERROR;
2114
2115 /* If the pipeline is enabled, take the handle which is in the head of
2116 the pipeline. If we should write into the socket, take the send_pipe
2117 head. If we should read from the socket, take the recv_pipe head. */
2118 if(data->set.one_easy->easy_conn) {
2119 if ((ev_bitmask & CURL_POLL_OUT) &&
2120 data->set.one_easy->easy_conn->send_pipe &&
2121 data->set.one_easy->easy_conn->send_pipe->head)
2122 data = data->set.one_easy->easy_conn->send_pipe->head->ptr;
2123 else if ((ev_bitmask & CURL_POLL_IN) &&
2124 data->set.one_easy->easy_conn->recv_pipe &&
2125 data->set.one_easy->easy_conn->recv_pipe->head)
2126 data = data->set.one_easy->easy_conn->recv_pipe->head->ptr;
2127 }
2128
2129 if(data->set.one_easy->easy_conn &&
2130 !(data->set.one_easy->easy_conn->handler->flags & PROTOPT_DIRLOCK))
2131 /* set socket event bitmask if they're not locked */
2132 data->set.one_easy->easy_conn->cselect_bits = ev_bitmask;
2133
2134 do
2135 result = multi_runsingle(multi, now, data->set.one_easy);
2136 while (CURLM_CALL_MULTI_PERFORM == result);
2137
2138 if(data->set.one_easy->easy_conn &&
2139 !(data->set.one_easy->easy_conn->handler->flags & PROTOPT_DIRLOCK))
2140 /* clear the bitmask only if not locked */
2141 data->set.one_easy->easy_conn->cselect_bits = 0;
2142
2143 if(CURLM_OK >= result)
2144 /* get the socket(s) and check if the state has been changed since
2145 last */
2146 singlesocket(multi, data->set.one_easy);
2147
2148 /* Now we fall-through and do the timer-based stuff, since we don't want
2149 to force the user to have to deal with timeouts as long as at least
2150 one connection in fact has traffic. */
2151
2152 data = NULL; /* set data to NULL again to avoid calling
2153 multi_runsingle() in case there's no need to */
2154 }
2155 }
2156
2157 now.tv_usec += 40000; /* compensate for bad precision timers that might've
2158 triggered too early */
2159 if(now.tv_usec >= 1000000) {
2160 now.tv_sec++;
2161 now.tv_usec -= 1000000;
2162 }
2163
2164 /*
2165 * The loop following here will go on as long as there are expire-times left
2166 * to process in the splay and 'data' will be re-assigned for every expired
2167 * handle we deal with.
2168 */
2169 do {
2170 /* the first loop lap 'data' can be NULL */
2171 if(data) {
2172 do
2173 result = multi_runsingle(multi, now, data->set.one_easy);
2174 while (CURLM_CALL_MULTI_PERFORM == result);
2175
2176 if(CURLM_OK >= result)
2177 /* get the socket(s) and check if the state has been changed since
2178 last */
2179 singlesocket(multi, data->set.one_easy);
2180 }
2181
2182 /* Check if there's one (more) expired timer to deal with! This function
2183 extracts a matching node if there is one */
2184
2185 multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
2186 if(t) {
2187 data = t->payload; /* assign this for next loop */
2188 (void)add_next_timeout(now, multi, t->payload);
2189 }
2190
2191 } while(t);
2192
2193 *running_handles = multi->num_alive;
2194 return result;
2195 }
2196
2197 #undef curl_multi_setopt
curl_multi_setopt(CURLM * multi_handle,CURLMoption option,...)2198 CURLMcode curl_multi_setopt(CURLM *multi_handle,
2199 CURLMoption option, ...)
2200 {
2201 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
2202 CURLMcode res = CURLM_OK;
2203 va_list param;
2204
2205 if(!GOOD_MULTI_HANDLE(multi))
2206 return CURLM_BAD_HANDLE;
2207
2208 va_start(param, option);
2209
2210 switch(option) {
2211 case CURLMOPT_SOCKETFUNCTION:
2212 multi->socket_cb = va_arg(param, curl_socket_callback);
2213 break;
2214 case CURLMOPT_SOCKETDATA:
2215 multi->socket_userp = va_arg(param, void *);
2216 break;
2217 case CURLMOPT_PIPELINING:
2218 multi->pipelining_enabled = (bool)(0 != va_arg(param, long));
2219 break;
2220 case CURLMOPT_TIMERFUNCTION:
2221 multi->timer_cb = va_arg(param, curl_multi_timer_callback);
2222 break;
2223 case CURLMOPT_TIMERDATA:
2224 multi->timer_userp = va_arg(param, void *);
2225 break;
2226 case CURLMOPT_MAXCONNECTS:
2227 multi->maxconnects = va_arg(param, long);
2228 break;
2229 default:
2230 res = CURLM_UNKNOWN_OPTION;
2231 break;
2232 }
2233 va_end(param);
2234 return res;
2235 }
2236
2237 /* we define curl_multi_socket() in the public multi.h header */
2238 #undef curl_multi_socket
2239
curl_multi_socket(CURLM * multi_handle,curl_socket_t s,int * running_handles)2240 CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s,
2241 int *running_handles)
2242 {
2243 CURLMcode result = multi_socket((struct Curl_multi *)multi_handle, FALSE, s,
2244 0, running_handles);
2245 if(CURLM_OK >= result)
2246 update_timer((struct Curl_multi *)multi_handle);
2247 return result;
2248 }
2249
curl_multi_socket_action(CURLM * multi_handle,curl_socket_t s,int ev_bitmask,int * running_handles)2250 CURLMcode curl_multi_socket_action(CURLM *multi_handle, curl_socket_t s,
2251 int ev_bitmask, int *running_handles)
2252 {
2253 CURLMcode result = multi_socket((struct Curl_multi *)multi_handle, FALSE, s,
2254 ev_bitmask, running_handles);
2255 if(CURLM_OK >= result)
2256 update_timer((struct Curl_multi *)multi_handle);
2257 return result;
2258 }
2259
curl_multi_socket_all(CURLM * multi_handle,int * running_handles)2260 CURLMcode curl_multi_socket_all(CURLM *multi_handle, int *running_handles)
2261
2262 {
2263 CURLMcode result = multi_socket((struct Curl_multi *)multi_handle,
2264 TRUE, CURL_SOCKET_BAD, 0, running_handles);
2265 if(CURLM_OK >= result)
2266 update_timer((struct Curl_multi *)multi_handle);
2267 return result;
2268 }
2269
multi_timeout(struct Curl_multi * multi,long * timeout_ms)2270 static CURLMcode multi_timeout(struct Curl_multi *multi,
2271 long *timeout_ms)
2272 {
2273 static struct timeval tv_zero = {0,0};
2274
2275 if(multi->timetree) {
2276 /* we have a tree of expire times */
2277 struct timeval now = Curl_tvnow();
2278
2279 /* splay the lowest to the bottom */
2280 multi->timetree = Curl_splay(tv_zero, multi->timetree);
2281
2282 if(Curl_splaycomparekeys(multi->timetree->key, now) > 0) {
2283 /* some time left before expiration */
2284 *timeout_ms = curlx_tvdiff(multi->timetree->key, now);
2285 if(!*timeout_ms)
2286 /*
2287 * Since we only provide millisecond resolution on the returned value
2288 * and the diff might be less than one millisecond here, we don't
2289 * return zero as that may cause short bursts of busyloops on fast
2290 * processors while the diff is still present but less than one
2291 * millisecond! instead we return 1 until the time is ripe.
2292 */
2293 *timeout_ms=1;
2294 }
2295 else
2296 /* 0 means immediately */
2297 *timeout_ms = 0;
2298 }
2299 else
2300 *timeout_ms = -1;
2301
2302 return CURLM_OK;
2303 }
2304
curl_multi_timeout(CURLM * multi_handle,long * timeout_ms)2305 CURLMcode curl_multi_timeout(CURLM *multi_handle,
2306 long *timeout_ms)
2307 {
2308 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
2309
2310 /* First, make some basic checks that the CURLM handle is a good handle */
2311 if(!GOOD_MULTI_HANDLE(multi))
2312 return CURLM_BAD_HANDLE;
2313
2314 return multi_timeout(multi, timeout_ms);
2315 }
2316
2317 /*
2318 * Tell the application it should update its timers, if it subscribes to the
2319 * update timer callback.
2320 */
update_timer(struct Curl_multi * multi)2321 static int update_timer(struct Curl_multi *multi)
2322 {
2323 long timeout_ms;
2324
2325 if(!multi->timer_cb)
2326 return 0;
2327 if(multi_timeout(multi, &timeout_ms)) {
2328 return -1;
2329 }
2330 if( timeout_ms < 0 ) {
2331 static const struct timeval none={0,0};
2332 if(Curl_splaycomparekeys(none, multi->timer_lastcall)) {
2333 multi->timer_lastcall = none;
2334 /* there's no timeout now but there was one previously, tell the app to
2335 disable it */
2336 return multi->timer_cb((CURLM*)multi, -1, multi->timer_userp);
2337 }
2338 return 0;
2339 }
2340
2341 /* When multi_timeout() is done, multi->timetree points to the node with the
2342 * timeout we got the (relative) time-out time for. We can thus easily check
2343 * if this is the same (fixed) time as we got in a previous call and then
2344 * avoid calling the callback again. */
2345 if(Curl_splaycomparekeys(multi->timetree->key, multi->timer_lastcall) == 0)
2346 return 0;
2347
2348 multi->timer_lastcall = multi->timetree->key;
2349
2350 return multi->timer_cb((CURLM*)multi, timeout_ms, multi->timer_userp);
2351 }
2352
addHandleToSendOrPendPipeline(struct SessionHandle * handle,struct connectdata * conn)2353 static CURLcode addHandleToSendOrPendPipeline(struct SessionHandle *handle,
2354 struct connectdata *conn)
2355 {
2356 size_t pipeLen = conn->send_pipe->size + conn->recv_pipe->size;
2357 struct curl_llist_element *sendhead = conn->send_pipe->head;
2358 struct curl_llist *pipeline;
2359 CURLcode rc;
2360
2361 if(!Curl_isPipeliningEnabled(handle) ||
2362 pipeLen == 0)
2363 pipeline = conn->send_pipe;
2364 else {
2365 if(conn->server_supports_pipelining &&
2366 pipeLen < MAX_PIPELINE_LENGTH)
2367 pipeline = conn->send_pipe;
2368 else
2369 pipeline = conn->pend_pipe;
2370 }
2371
2372 rc = Curl_addHandleToPipeline(handle, pipeline);
2373
2374 if (pipeline == conn->send_pipe && sendhead != conn->send_pipe->head) {
2375 /* this is a new one as head, expire it */
2376 conn->writechannel_inuse = FALSE; /* not in use yet */
2377 #ifdef DEBUGBUILD
2378 infof(conn->data, "%p is at send pipe head!\n",
2379 conn->send_pipe->head->ptr);
2380 #endif
2381 Curl_expire(conn->send_pipe->head->ptr, 1);
2382 }
2383
2384 return rc;
2385 }
2386
checkPendPipeline(struct connectdata * conn)2387 static int checkPendPipeline(struct connectdata *conn)
2388 {
2389 int result = 0;
2390 struct curl_llist_element *sendhead = conn->send_pipe->head;
2391
2392 size_t pipeLen = conn->send_pipe->size + conn->recv_pipe->size;
2393 if (conn->server_supports_pipelining || pipeLen == 0) {
2394 struct curl_llist_element *curr = conn->pend_pipe->head;
2395 const size_t maxPipeLen =
2396 conn->server_supports_pipelining ? MAX_PIPELINE_LENGTH : 1;
2397
2398 while(pipeLen < maxPipeLen && curr) {
2399 Curl_llist_move(conn->pend_pipe, curr,
2400 conn->send_pipe, conn->send_pipe->tail);
2401 Curl_pgrsTime(curr->ptr, TIMER_PRETRANSFER);
2402 ++result; /* count how many handles we moved */
2403 curr = conn->pend_pipe->head;
2404 ++pipeLen;
2405 }
2406 }
2407
2408 if (result) {
2409 conn->now = Curl_tvnow();
2410 /* something moved, check for a new send pipeline leader */
2411 if(sendhead != conn->send_pipe->head) {
2412 /* this is a new one as head, expire it */
2413 conn->writechannel_inuse = FALSE; /* not in use yet */
2414 #ifdef DEBUGBUILD
2415 infof(conn->data, "%p is at send pipe head!\n",
2416 conn->send_pipe->head->ptr);
2417 #endif
2418 Curl_expire(conn->send_pipe->head->ptr, 1);
2419 }
2420 }
2421
2422 return result;
2423 }
2424
2425 /* Move this transfer from the sending list to the receiving list.
2426
2427 Pay special attention to the new sending list "leader" as it needs to get
2428 checked to update what sockets it acts on.
2429
2430 */
moveHandleFromSendToRecvPipeline(struct SessionHandle * handle,struct connectdata * conn)2431 static void moveHandleFromSendToRecvPipeline(struct SessionHandle *handle,
2432 struct connectdata *conn)
2433 {
2434 struct curl_llist_element *curr;
2435
2436 curr = conn->send_pipe->head;
2437 while(curr) {
2438 if(curr->ptr == handle) {
2439 Curl_llist_move(conn->send_pipe, curr,
2440 conn->recv_pipe, conn->recv_pipe->tail);
2441
2442 if(conn->send_pipe->head) {
2443 /* Since there's a new easy handle at the start of the send pipeline,
2444 set its timeout value to 1ms to make it trigger instantly */
2445 conn->writechannel_inuse = FALSE; /* not used now */
2446 #ifdef DEBUGBUILD
2447 infof(conn->data, "%p is at send pipe head B!\n",
2448 conn->send_pipe->head->ptr);
2449 #endif
2450 Curl_expire(conn->send_pipe->head->ptr, 1);
2451 }
2452
2453 /* The receiver's list is not really interesting here since either this
2454 handle is now first in the list and we'll deal with it soon, or
2455 another handle is already first and thus is already taken care of */
2456
2457 break; /* we're done! */
2458 }
2459 curr = curr->next;
2460 }
2461 }
2462
moveHandleFromRecvToDonePipeline(struct SessionHandle * handle,struct connectdata * conn)2463 static void moveHandleFromRecvToDonePipeline(struct SessionHandle *handle,
2464 struct connectdata *conn)
2465 {
2466 struct curl_llist_element *curr;
2467
2468 curr = conn->recv_pipe->head;
2469 while(curr) {
2470 if(curr->ptr == handle) {
2471 Curl_llist_move(conn->recv_pipe, curr,
2472 conn->done_pipe, conn->done_pipe->tail);
2473 break;
2474 }
2475 curr = curr->next;
2476 }
2477 }
isHandleAtHead(struct SessionHandle * handle,struct curl_llist * pipeline)2478 static bool isHandleAtHead(struct SessionHandle *handle,
2479 struct curl_llist *pipeline)
2480 {
2481 struct curl_llist_element *curr = pipeline->head;
2482 if(curr)
2483 return (bool)(curr->ptr == handle);
2484
2485 return FALSE;
2486 }
2487
2488 /*
2489 * multi_freetimeout()
2490 *
2491 * Callback used by the llist system when a single timeout list entry is
2492 * destroyed.
2493 */
multi_freetimeout(void * user,void * entryptr)2494 static void multi_freetimeout(void *user, void *entryptr)
2495 {
2496 (void)user;
2497
2498 /* the entry was plain malloc()'ed */
2499 free(entryptr);
2500 }
2501
2502 /*
2503 * multi_addtimeout()
2504 *
2505 * Add a timestamp to the list of timeouts. Keep the list sorted so that head
2506 * of list is always the timeout nearest in time.
2507 *
2508 */
2509 static CURLMcode
multi_addtimeout(struct curl_llist * timeoutlist,struct timeval * stamp)2510 multi_addtimeout(struct curl_llist *timeoutlist,
2511 struct timeval *stamp)
2512 {
2513 struct curl_llist_element *e;
2514 struct timeval *timedup;
2515 struct curl_llist_element *prev = NULL;
2516
2517 timedup = malloc(sizeof(*timedup));
2518 if(!timedup)
2519 return CURLM_OUT_OF_MEMORY;
2520
2521 /* copy the timestamp */
2522 memcpy(timedup, stamp, sizeof(*timedup));
2523
2524 if(Curl_llist_count(timeoutlist)) {
2525 /* find the correct spot in the list */
2526 for(e = timeoutlist->head; e; e = e->next) {
2527 struct timeval *checktime = e->ptr;
2528 long diff = curlx_tvdiff(*checktime, *timedup);
2529 if(diff > 0)
2530 break;
2531 prev = e;
2532 }
2533
2534 }
2535 /* else
2536 this is the first timeout on the list */
2537
2538 if(!Curl_llist_insert_next(timeoutlist, prev, timedup)) {
2539 free(timedup);
2540 return CURLM_OUT_OF_MEMORY;
2541 }
2542
2543 return CURLM_OK;
2544 }
2545
2546 /*
2547 * Curl_expire()
2548 *
2549 * given a number of milliseconds from now to use to set the 'act before
2550 * this'-time for the transfer, to be extracted by curl_multi_timeout()
2551 *
2552 * Note that the timeout will be added to a queue of timeouts if it defines a
2553 * moment in time that is later than the current head of queue.
2554 *
2555 * Pass zero to clear all timeout values for this handle.
2556 */
Curl_expire(struct SessionHandle * data,long milli)2557 void Curl_expire(struct SessionHandle *data, long milli)
2558 {
2559 struct Curl_multi *multi = data->multi;
2560 struct timeval *nowp = &data->state.expiretime;
2561 int rc;
2562
2563 /* this is only interesting for multi-interface using libcurl, and only
2564 while there is still a multi interface struct remaining! */
2565 if(!multi)
2566 return;
2567
2568 if(!milli) {
2569 /* No timeout, clear the time data. */
2570 if(nowp->tv_sec || nowp->tv_usec) {
2571 /* Since this is an cleared time, we must remove the previous entry from
2572 the splay tree */
2573 struct curl_llist *list = data->state.timeoutlist;
2574
2575 rc = Curl_splayremovebyaddr(multi->timetree,
2576 &data->state.timenode,
2577 &multi->timetree);
2578 if(rc)
2579 infof(data, "Internal error clearing splay node = %d\n", rc);
2580
2581 /* flush the timeout list too */
2582 while(list->size > 0)
2583 Curl_llist_remove(list, list->tail, NULL);
2584
2585 #ifdef DEBUGBUILD
2586 infof(data, "Expire cleared\n");
2587 #endif
2588 nowp->tv_sec = 0;
2589 nowp->tv_usec = 0;
2590 }
2591 }
2592 else {
2593 struct timeval set;
2594
2595 set = Curl_tvnow();
2596 set.tv_sec += milli/1000;
2597 set.tv_usec += (milli%1000)*1000;
2598
2599 if(set.tv_usec >= 1000000) {
2600 set.tv_sec++;
2601 set.tv_usec -= 1000000;
2602 }
2603
2604 if(nowp->tv_sec || nowp->tv_usec) {
2605 /* This means that the struct is added as a node in the splay tree.
2606 Compare if the new time is earlier, and only remove-old/add-new if it
2607 is. */
2608 long diff = curlx_tvdiff(set, *nowp);
2609 if(diff > 0) {
2610 /* the new expire time was later so just add it to the queue
2611 and get out */
2612 multi_addtimeout(data->state.timeoutlist, &set);
2613 return;
2614 }
2615
2616 /* the new time is newer than the presently set one, so add the current
2617 to the queue and update the head */
2618 multi_addtimeout(data->state.timeoutlist, nowp);
2619
2620 /* Since this is an updated time, we must remove the previous entry from
2621 the splay tree first and then re-add the new value */
2622 rc = Curl_splayremovebyaddr(multi->timetree,
2623 &data->state.timenode,
2624 &multi->timetree);
2625 if(rc)
2626 infof(data, "Internal error removing splay node = %d\n", rc);
2627 }
2628
2629 *nowp = set;
2630 data->state.timenode.payload = data;
2631 multi->timetree = Curl_splayinsert(*nowp,
2632 multi->timetree,
2633 &data->state.timenode);
2634 }
2635 #if 0
2636 Curl_splayprint(multi->timetree, 0, TRUE);
2637 #endif
2638 }
2639
curl_multi_assign(CURLM * multi_handle,curl_socket_t s,void * hashp)2640 CURLMcode curl_multi_assign(CURLM *multi_handle,
2641 curl_socket_t s, void *hashp)
2642 {
2643 struct Curl_sh_entry *there = NULL;
2644 struct Curl_multi *multi = (struct Curl_multi *)multi_handle;
2645
2646 if(s != CURL_SOCKET_BAD)
2647 there = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(curl_socket_t));
2648
2649 if(!there)
2650 return CURLM_BAD_SOCKET;
2651
2652 there->socketp = hashp;
2653
2654 return CURLM_OK;
2655 }
2656
multi_connc_remove_handle(struct Curl_multi * multi,struct SessionHandle * data)2657 static void multi_connc_remove_handle(struct Curl_multi *multi,
2658 struct SessionHandle *data)
2659 {
2660 /* a connection in the connection cache pointing to the given 'data' ? */
2661 int i;
2662
2663 for(i=0; i< multi->connc->num; i++) {
2664 struct connectdata * conn = multi->connc->connects[i];
2665
2666 if(conn && conn->data == data) {
2667 /* If this easy_handle was the last one in charge for one or more
2668 connections in the shared connection cache, we might need to keep
2669 this handle around until either A) the connection is closed and
2670 killed properly, or B) another easy_handle uses the connection.
2671
2672 The reason why we need to have a easy_handle associated with a live
2673 connection is simply that some connections will need a handle to get
2674 closed down properly. Currently, the only connections that need to
2675 keep a easy_handle handle around are using FTP(S). Such connections
2676 have the PROT_CLOSEACTION bit set.
2677
2678 Thus, we need to check for all connections in the shared cache that
2679 points to this handle and are using PROT_CLOSEACTION. If there's any,
2680 we need to add this handle to the list of "easy handles kept around
2681 for nice connection closures".
2682 */
2683
2684 if(conn->handler->flags & PROTOPT_CLOSEACTION) {
2685 /* this handle is still being used by a shared connection and
2686 thus we leave it around for now */
2687 if(add_closure(multi, data) == CURLM_OK)
2688 data->state.shared_conn = multi;
2689 else {
2690 /* out of memory - so much for graceful shutdown */
2691 Curl_disconnect(conn, /* dead_connection */ FALSE);
2692 multi->connc->connects[i] = NULL;
2693 }
2694 }
2695 else
2696 /* disconect the easy handle from the connection since the connection
2697 will now remain but this easy handle is going */
2698 conn->data = NULL;
2699 }
2700 }
2701 }
2702
2703 /* Add the given data pointer to the list of 'closure handles' that are kept
2704 around only to be able to close some connections nicely - just make sure
2705 that this handle isn't already added, like for the cases when an easy
2706 handle is removed, added and removed again... */
add_closure(struct Curl_multi * multi,struct SessionHandle * data)2707 static CURLMcode add_closure(struct Curl_multi *multi,
2708 struct SessionHandle *data)
2709 {
2710 struct closure *cl = multi->closure;
2711 struct closure *p = NULL;
2712 bool add = TRUE;
2713
2714 /* Before adding, scan through all the other currently kept handles and see
2715 if there are any connections still referring to them and kill them if
2716 not. */
2717 while(cl) {
2718 struct closure *n;
2719 bool inuse = FALSE;
2720 int i;
2721
2722 for(i=0; i< multi->connc->num; i++) {
2723 if(multi->connc->connects[i] &&
2724 (multi->connc->connects[i]->data == cl->easy_handle)) {
2725 inuse = TRUE;
2726 break;
2727 }
2728 }
2729
2730 n = cl->next;
2731
2732 if(!inuse) {
2733 /* cl->easy_handle is now killable */
2734
2735 /* unmark it as not having a connection around that uses it anymore */
2736 cl->easy_handle->state.shared_conn= NULL;
2737
2738 if(cl->easy_handle->state.closed) {
2739 infof(data, "Delayed kill of easy handle %p\n", cl->easy_handle);
2740 /* close handle only if curl_easy_cleanup() already has been called
2741 for this easy handle */
2742 Curl_close(cl->easy_handle);
2743 }
2744 if(p)
2745 p->next = n;
2746 else
2747 multi->closure = n;
2748 free(cl);
2749 } else {
2750 if(cl->easy_handle == data)
2751 add = FALSE;
2752
2753 p = cl;
2754 }
2755
2756 cl = n;
2757 }
2758
2759 if (add) {
2760 cl = calloc(1, sizeof(struct closure));
2761 if(!cl)
2762 return CURLM_OUT_OF_MEMORY;
2763
2764 cl->easy_handle = data;
2765 cl->next = multi->closure;
2766 multi->closure = cl;
2767 }
2768
2769 return CURLM_OK;
2770 }
2771
2772 #ifdef DEBUGBUILD
Curl_multi_dump(const struct Curl_multi * multi_handle)2773 void Curl_multi_dump(const struct Curl_multi *multi_handle)
2774 {
2775 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
2776 struct Curl_one_easy *easy;
2777 int i;
2778 fprintf(stderr, "* Multi status: %d handles, %d alive\n",
2779 multi->num_easy, multi->num_alive);
2780 for(easy=multi->easy.next; easy != &multi->easy; easy = easy->next) {
2781 if(easy->state < CURLM_STATE_COMPLETED) {
2782 /* only display handles that are not completed */
2783 fprintf(stderr, "handle %p, state %s, %d sockets\n",
2784 (void *)easy->easy_handle,
2785 statename[easy->state], easy->numsocks);
2786 for(i=0; i < easy->numsocks; i++) {
2787 curl_socket_t s = easy->sockets[i];
2788 struct Curl_sh_entry *entry =
2789 Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
2790
2791 fprintf(stderr, "%d ", (int)s);
2792 if(!entry) {
2793 fprintf(stderr, "INTERNAL CONFUSION\n");
2794 continue;
2795 }
2796 fprintf(stderr, "[%s %s] ",
2797 entry->action&CURL_POLL_IN?"RECVING":"",
2798 entry->action&CURL_POLL_OUT?"SENDING":"");
2799 }
2800 if(easy->numsocks)
2801 fprintf(stderr, "\n");
2802 }
2803 }
2804 }
2805 #endif
2806