blob: ff4bf861b2179b7e2bfac5ba4b1ada4fb3081dd9 [file] [log] [blame]
9487f7f2011-08-03 07:05:30 -07001/***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2010, 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
62struct 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*/
70typedef 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
98struct closure {
99 struct closure *next; /* a simple one-way list of structs */
100 struct SessionHandle *easy_handle;
101};
102
103struct 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 */
132struct 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
180static void multi_connc_remove_handle(struct Curl_multi *multi,
181 struct SessionHandle *data);
182static void singlesocket(struct Curl_multi *multi,
183 struct Curl_one_easy *easy);
184static CURLMcode add_closure(struct Curl_multi *multi,
185 struct SessionHandle *data);
186static int update_timer(struct Curl_multi *multi);
187
188static CURLcode addHandleToSendOrPendPipeline(struct SessionHandle *handle,
189 struct connectdata *conn);
190static int checkPendPipeline(struct connectdata *conn);
191static void moveHandleFromSendToRecvPipeline(struct SessionHandle *handle,
192 struct connectdata *conn);
193static void moveHandleFromRecvToDonePipeline(struct SessionHandle *handle,
194 struct connectdata *conn);
195static bool isHandleAtHead(struct SessionHandle *handle,
196 struct curl_llist *pipeline);
197static CURLMcode add_next_timeout(struct timeval now,
198 struct Curl_multi *multi,
199 struct SessionHandle *d);
200
201#ifdef DEBUGBUILD
202static 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
223static void multi_freetimeout(void *a, void *b);
224
225/* always use this function to change state, to make debugging easier */
226static 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
260struct 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 */
273static 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 */
303static 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 */
319static 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
327static 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
334static 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 */
360static 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 */
372static 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 */
386static void multi_freeamsg(void *a, void *b)
387{
388 (void)a;
389 (void)b;
390}
391
392
393CURLM *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
438CURLMcode 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 */
603static 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
612CURLMcode 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 reponse 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
773bool Curl_multi_canPipeline(const struct Curl_multi* multi)
774{
775 return multi->pipelining_enabled;
776}
777
778void 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
786static 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
803static 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 */
821static 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 states */
876 case CURLM_STATE_PERFORM:
877 case CURLM_STATE_WAITPERFORM:
878 return Curl_single_getsock(easy->easy_conn, socks, numsocks);
879 }
880
881}
882
883CURLMcode curl_multi_fdset(CURLM *multi_handle,
884 fd_set *read_fd_set, fd_set *write_fd_set,
885 fd_set *exc_fd_set, int *max_fd)
886{
887 /* Scan through all the easy handles to get the file descriptors set.
888 Some easy handles may not have connected to the remote host yet,
889 and then we must make sure that is done. */
890 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
891 struct Curl_one_easy *easy;
892 int this_max_fd=-1;
893 curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
894 int bitmap;
895 int i;
896 (void)exc_fd_set; /* not used */
897
898 if(!GOOD_MULTI_HANDLE(multi))
899 return CURLM_BAD_HANDLE;
900
901 easy=multi->easy.next;
902 while(easy != &multi->easy) {
903 bitmap = multi_getsock(easy, sockbunch, MAX_SOCKSPEREASYHANDLE);
904
905 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
906 curl_socket_t s = CURL_SOCKET_BAD;
907
908 if(bitmap & GETSOCK_READSOCK(i)) {
909 FD_SET(sockbunch[i], read_fd_set);
910 s = sockbunch[i];
911 }
912 if(bitmap & GETSOCK_WRITESOCK(i)) {
913 FD_SET(sockbunch[i], write_fd_set);
914 s = sockbunch[i];
915 }
916 if(s == CURL_SOCKET_BAD)
917 /* this socket is unused, break out of loop */
918 break;
919 else {
920 if((int)s > this_max_fd)
921 this_max_fd = (int)s;
922 }
923 }
924
925 easy = easy->next; /* check next handle */
926 }
927
928 *max_fd = this_max_fd;
929
930 return CURLM_OK;
931}
932
933static CURLMcode multi_runsingle(struct Curl_multi *multi,
934 struct timeval now,
935 struct Curl_one_easy *easy)
936{
937 struct Curl_message *msg = NULL;
938 bool connected;
939 bool async;
940 bool protocol_connect = FALSE;
941 bool dophase_done;
942 bool done = FALSE;
943 CURLMcode result = CURLM_OK;
944 struct SingleRequest *k;
945 struct SessionHandle *data;
946 long timeout_ms;
947
948 if(!GOOD_EASY_HANDLE(easy->easy_handle))
949 return CURLM_BAD_EASY_HANDLE;
950
951 data = easy->easy_handle;
952
953 do {
954 /* this is a do-while loop just to allow a break to skip to the end
955 of it */
956 bool disconnect_conn = FALSE;
957
958 /* Handle the case when the pipe breaks, i.e., the connection
959 we're using gets cleaned up and we're left with nothing. */
960 if(data->state.pipe_broke) {
961 infof(data, "Pipe broke: handle 0x%p, url = %s\n",
962 easy, data->state.path);
963
964 if(easy->state < CURLM_STATE_COMPLETED) {
965 /* Head back to the CONNECT state */
966 multistate(easy, CURLM_STATE_CONNECT);
967 result = CURLM_CALL_MULTI_PERFORM;
968 easy->result = CURLE_OK;
969 }
970
971 data->state.pipe_broke = FALSE;
972 easy->easy_conn = NULL;
973 break;
974 }
975
976 if(easy->easy_conn && easy->state > CURLM_STATE_CONNECT &&
977 easy->state < CURLM_STATE_COMPLETED)
978 /* Make sure we set the connection's current owner */
979 easy->easy_conn->data = data;
980
981 if(easy->easy_conn &&
982 (easy->state >= CURLM_STATE_CONNECT) &&
983 (easy->state < CURLM_STATE_COMPLETED)) {
984 /* we need to wait for the connect state as only then is the start time
985 stored, but we must not check already completed handles */
986
987 timeout_ms = Curl_timeleft(easy->easy_conn, &now,
988 (easy->state <= CURLM_STATE_WAITDO)?
989 TRUE:FALSE);
990
991 if(timeout_ms < 0) {
992 /* Handle timed out */
993 if(easy->state == CURLM_STATE_WAITRESOLVE)
994 failf(data, "Resolving timed out after %ld milliseconds",
995 Curl_tvdiff(now, data->progress.t_startsingle));
996 else if(easy->state == CURLM_STATE_WAITCONNECT)
997 failf(data, "Connection timed out after %ld milliseconds",
998 Curl_tvdiff(now, data->progress.t_startsingle));
999 else {
1000 k = &data->req;
1001 failf(data, "Operation timed out after %ld milliseconds with %"
1002 FORMAT_OFF_T " out of %" FORMAT_OFF_T " bytes received",
1003 Curl_tvdiff(now, data->progress.t_startsingle), k->bytecount,
1004 k->size);
1005 }
1006 easy->result = CURLE_OPERATION_TIMEDOUT;
1007 multistate(easy, CURLM_STATE_COMPLETED);
1008 break;
1009 }
1010 }
1011
1012 switch(easy->state) {
1013 case CURLM_STATE_INIT:
1014 /* init this transfer. */
1015 easy->result=Curl_pretransfer(data);
1016
1017 if(CURLE_OK == easy->result) {
1018 /* after init, go CONNECT */
1019 multistate(easy, CURLM_STATE_CONNECT);
1020 result = CURLM_CALL_MULTI_PERFORM;
1021
1022 data->state.used_interface = Curl_if_multi;
1023 }
1024 break;
1025
1026 case CURLM_STATE_CONNECT:
1027 /* Connect. We get a connection identifier filled in. */
1028 Curl_pgrsTime(data, TIMER_STARTSINGLE);
1029 easy->result = Curl_connect(data, &easy->easy_conn,
1030 &async, &protocol_connect);
1031
1032 if(CURLE_OK == easy->result) {
1033 /* Add this handle to the send or pend pipeline */
1034 easy->result = addHandleToSendOrPendPipeline(data,
1035 easy->easy_conn);
1036 if(CURLE_OK == easy->result) {
1037 if(async)
1038 /* We're now waiting for an asynchronous name lookup */
1039 multistate(easy, CURLM_STATE_WAITRESOLVE);
1040 else {
1041 /* after the connect has been sent off, go WAITCONNECT unless the
1042 protocol connect is already done and we can go directly to
1043 WAITDO or DO! */
1044 result = CURLM_CALL_MULTI_PERFORM;
1045
1046 if(protocol_connect)
1047 multistate(easy, multi->pipelining_enabled?
1048 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1049 else {
1050#ifndef CURL_DISABLE_HTTP
1051 if(easy->easy_conn->bits.tunnel_connecting)
1052 multistate(easy, CURLM_STATE_WAITPROXYCONNECT);
1053 else
1054#endif
1055 multistate(easy, CURLM_STATE_WAITCONNECT);
1056 }
1057 }
1058 }
1059 }
1060 break;
1061
1062 case CURLM_STATE_WAITRESOLVE:
1063 /* awaiting an asynch name resolve to complete */
1064 {
1065 struct Curl_dns_entry *dns = NULL;
1066
1067 /* check if we have the name resolved by now */
1068 easy->result = Curl_is_resolved(easy->easy_conn, &dns);
1069
1070 if(dns) {
1071 /* Update sockets here. Mainly because the socket(s) may have been
1072 closed and the application thus needs to be told, even if it is
1073 likely that the same socket(s) will again be used further down. */
1074 singlesocket(multi, easy);
1075
1076 /* Perform the next step in the connection phase, and then move on
1077 to the WAITCONNECT state */
1078 easy->result = Curl_async_resolved(easy->easy_conn,
1079 &protocol_connect);
1080
1081 if(CURLE_OK != easy->result)
1082 /* if Curl_async_resolved() returns failure, the connection struct
1083 is already freed and gone */
1084 easy->easy_conn = NULL; /* no more connection */
1085 else {
1086 /* call again please so that we get the next socket setup */
1087 result = CURLM_CALL_MULTI_PERFORM;
1088 if(protocol_connect)
1089 multistate(easy, multi->pipelining_enabled?
1090 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1091 else {
1092#ifndef CURL_DISABLE_HTTP
1093 if(easy->easy_conn->bits.tunnel_connecting)
1094 multistate(easy, CURLM_STATE_WAITPROXYCONNECT);
1095 else
1096#endif
1097 multistate(easy, CURLM_STATE_WAITCONNECT);
1098 }
1099 }
1100 }
1101
1102 if(CURLE_OK != easy->result) {
1103 /* failure detected */
1104 disconnect_conn = TRUE;
1105 break;
1106 }
1107 }
1108 break;
1109
1110#ifndef CURL_DISABLE_HTTP
1111 case CURLM_STATE_WAITPROXYCONNECT:
1112 /* this is HTTP-specific, but sending CONNECT to a proxy is HTTP... */
1113 easy->result = Curl_http_connect(easy->easy_conn, &protocol_connect);
1114
1115 if(easy->easy_conn->bits.proxy_connect_closed) {
1116 /* reset the error buffer */
1117 if(data->set.errorbuffer)
1118 data->set.errorbuffer[0] = '\0';
1119 data->state.errorbuf = FALSE;
1120
1121 easy->result = CURLE_OK;
1122 result = CURLM_CALL_MULTI_PERFORM;
1123 multistate(easy, CURLM_STATE_CONNECT);
1124 }
1125 else if (CURLE_OK == easy->result) {
1126 if(!easy->easy_conn->bits.tunnel_connecting)
1127 multistate(easy, CURLM_STATE_WAITCONNECT);
1128 }
1129 break;
1130#endif
1131
1132 case CURLM_STATE_WAITCONNECT:
1133 /* awaiting a completion of an asynch connect */
1134 easy->result = Curl_is_connected(easy->easy_conn,
1135 FIRSTSOCKET,
1136 &connected);
1137 if(connected) {
1138 /* see if we need to do any proxy magic first once we connected */
1139 easy->result = Curl_connected_proxy(easy->easy_conn);
1140
1141 if(!easy->result)
1142 /* if everything is still fine we do the protocol-specific connect
1143 setup */
1144 easy->result = Curl_protocol_connect(easy->easy_conn,
1145 &protocol_connect);
1146 }
1147
1148 if(CURLE_OK != easy->result) {
1149 /* failure detected */
1150 /* Just break, the cleaning up is handled all in one place */
1151 disconnect_conn = TRUE;
1152 break;
1153 }
1154
1155 if(connected) {
1156 if(!protocol_connect) {
1157 /* We have a TCP connection, but 'protocol_connect' may be false
1158 and then we continue to 'STATE_PROTOCONNECT'. If protocol
1159 connect is TRUE, we move on to STATE_DO.
1160 BUT if we are using a proxy we must change to WAITPROXYCONNECT
1161 */
1162#ifndef CURL_DISABLE_HTTP
1163 if(easy->easy_conn->bits.tunnel_connecting)
1164 multistate(easy, CURLM_STATE_WAITPROXYCONNECT);
1165 else
1166#endif
1167 multistate(easy, CURLM_STATE_PROTOCONNECT);
1168
1169 }
1170 else
1171 /* after the connect has completed, go WAITDO or DO */
1172 multistate(easy, multi->pipelining_enabled?
1173 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1174
1175 result = CURLM_CALL_MULTI_PERFORM;
1176 }
1177 break;
1178
1179 case CURLM_STATE_PROTOCONNECT:
1180 /* protocol-specific connect phase */
1181 easy->result = Curl_protocol_connecting(easy->easy_conn,
1182 &protocol_connect);
1183 if((easy->result == CURLE_OK) && protocol_connect) {
1184 /* after the connect has completed, go WAITDO or DO */
1185 multistate(easy, multi->pipelining_enabled?
1186 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1187 result = CURLM_CALL_MULTI_PERFORM;
1188 }
1189 else if(easy->result) {
1190 /* failure detected */
1191 Curl_posttransfer(data);
1192 Curl_done(&easy->easy_conn, easy->result, FALSE);
1193 disconnect_conn = TRUE;
1194 }
1195 break;
1196
1197 case CURLM_STATE_WAITDO:
1198 /* Wait for our turn to DO when we're pipelining requests */
1199#ifdef DEBUGBUILD
1200 infof(data, "Conn %ld send pipe %zu inuse %d athead %d\n",
1201 easy->easy_conn->connectindex,
1202 easy->easy_conn->send_pipe->size,
1203 easy->easy_conn->writechannel_inuse?1:0,
1204 isHandleAtHead(data,
1205 easy->easy_conn->send_pipe)?1:0);
1206#endif
1207 if(!easy->easy_conn->writechannel_inuse &&
1208 isHandleAtHead(data,
1209 easy->easy_conn->send_pipe)) {
1210 /* Grab the channel */
1211 easy->easy_conn->writechannel_inuse = TRUE;
1212 multistate(easy, CURLM_STATE_DO);
1213 result = CURLM_CALL_MULTI_PERFORM;
1214 }
1215 break;
1216
1217 case CURLM_STATE_DO:
1218 if(data->set.connect_only) {
1219 /* keep connection open for application to use the socket */
1220 easy->easy_conn->bits.close = FALSE;
1221 multistate(easy, CURLM_STATE_DONE);
1222 easy->result = CURLE_OK;
1223 result = CURLM_OK;
1224 }
1225 else {
1226 /* Perform the protocol's DO action */
1227 easy->result = Curl_do(&easy->easy_conn,
1228 &dophase_done);
1229
1230 if(CURLE_OK == easy->result) {
1231 if(!dophase_done) {
1232 /* some steps needed for wildcard matching */
1233 if(data->set.wildcardmatch) {
1234 struct WildcardData *wc = &data->wildcard;
1235 if(wc->state == CURLWC_DONE || wc->state == CURLWC_SKIP) {
1236 /* skip some states if it is important */
1237 Curl_done(&easy->easy_conn, CURLE_OK, FALSE);
1238 multistate(easy, CURLM_STATE_DONE);
1239 result = CURLM_CALL_MULTI_PERFORM;
1240 break;
1241 }
1242 }
1243 /* DO was not completed in one function call, we must continue
1244 DOING... */
1245 multistate(easy, CURLM_STATE_DOING);
1246 result = CURLM_OK;
1247 }
1248
1249 /* after DO, go DO_DONE... or DO_MORE */
1250 else if(easy->easy_conn->bits.do_more) {
1251 /* we're supposed to do more, but we need to sit down, relax
1252 and wait a little while first */
1253 multistate(easy, CURLM_STATE_DO_MORE);
1254 result = CURLM_OK;
1255 }
1256 else {
1257 /* we're done with the DO, now DO_DONE */
1258 multistate(easy, CURLM_STATE_DO_DONE);
1259 result = CURLM_CALL_MULTI_PERFORM;
1260 }
1261 }
1262 else if ((CURLE_SEND_ERROR == easy->result) &&
1263 easy->easy_conn->bits.reuse) {
1264 /*
1265 * In this situation, a connection that we were trying to use
1266 * may have unexpectedly died. If possible, send the connection
1267 * back to the CONNECT phase so we can try again.
1268 */
1269 char *newurl = NULL;
1270 followtype follow=FOLLOW_NONE;
1271 CURLcode drc;
1272 bool retry = FALSE;
1273
1274 drc = Curl_retry_request(easy->easy_conn, &newurl);
1275 if(drc) {
1276 /* a failure here pretty much implies an out of memory */
1277 easy->result = drc;
1278 disconnect_conn = TRUE;
1279 }
1280 else
1281 retry = (bool)(newurl?TRUE:FALSE);
1282
1283 Curl_posttransfer(data);
1284 drc = Curl_done(&easy->easy_conn, easy->result, FALSE);
1285
1286 /* When set to retry the connection, we must to go back to
1287 * the CONNECT state */
1288 if(retry) {
1289 if ((drc == CURLE_OK) || (drc == CURLE_SEND_ERROR)) {
1290 follow = FOLLOW_RETRY;
1291 drc = Curl_follow(data, newurl, follow);
1292 if(drc == CURLE_OK) {
1293 multistate(easy, CURLM_STATE_CONNECT);
1294 result = CURLM_CALL_MULTI_PERFORM;
1295 easy->result = CURLE_OK;
1296 }
1297 else {
1298 /* Follow failed */
1299 easy->result = drc;
1300 free(newurl);
1301 }
1302 }
1303 else {
1304 /* done didn't return OK or SEND_ERROR */
1305 easy->result = drc;
1306 free(newurl);
1307 }
1308 }
1309 else {
1310 /* Have error handler disconnect conn if we can't retry */
1311 disconnect_conn = TRUE;
1312 }
1313 }
1314 else {
1315 /* failure detected */
1316 Curl_posttransfer(data);
1317 Curl_done(&easy->easy_conn, easy->result, FALSE);
1318 disconnect_conn = TRUE;
1319 }
1320 }
1321 break;
1322
1323 case CURLM_STATE_DOING:
1324 /* we continue DOING until the DO phase is complete */
1325 easy->result = Curl_protocol_doing(easy->easy_conn,
1326 &dophase_done);
1327 if(CURLE_OK == easy->result) {
1328 if(dophase_done) {
1329 /* after DO, go PERFORM... or DO_MORE */
1330 if(easy->easy_conn->bits.do_more) {
1331 /* we're supposed to do more, but we need to sit down, relax
1332 and wait a little while first */
1333 multistate(easy, CURLM_STATE_DO_MORE);
1334 result = CURLM_OK;
1335 }
1336 else {
1337 /* we're done with the DO, now DO_DONE */
1338 multistate(easy, CURLM_STATE_DO_DONE);
1339 result = CURLM_CALL_MULTI_PERFORM;
1340 }
1341 } /* dophase_done */
1342 }
1343 else {
1344 /* failure detected */
1345 Curl_posttransfer(data);
1346 Curl_done(&easy->easy_conn, easy->result, FALSE);
1347 disconnect_conn = TRUE;
1348 }
1349 break;
1350
1351 case CURLM_STATE_DO_MORE:
1352 /* Ready to do more? */
1353 easy->result = Curl_is_connected(easy->easy_conn,
1354 SECONDARYSOCKET,
1355 &connected);
1356 if(connected) {
1357 /*
1358 * When we are connected, DO MORE and then go DO_DONE
1359 */
1360 easy->result = Curl_do_more(easy->easy_conn);
1361
1362 /* No need to remove ourselves from the send pipeline here since that
1363 is done for us in Curl_done() */
1364
1365 if(CURLE_OK == easy->result) {
1366 multistate(easy, CURLM_STATE_DO_DONE);
1367 result = CURLM_CALL_MULTI_PERFORM;
1368 }
1369 else {
1370 /* failure detected */
1371 Curl_posttransfer(data);
1372 Curl_done(&easy->easy_conn, easy->result, FALSE);
1373 disconnect_conn = TRUE;
1374 }
1375 }
1376 break;
1377
1378 case CURLM_STATE_DO_DONE:
1379 /* Move ourselves from the send to recv pipeline */
1380 moveHandleFromSendToRecvPipeline(data, easy->easy_conn);
1381 /* Check if we can move pending requests to send pipe */
1382 checkPendPipeline(easy->easy_conn);
1383 multistate(easy, CURLM_STATE_WAITPERFORM);
1384 result = CURLM_CALL_MULTI_PERFORM;
1385 break;
1386
1387 case CURLM_STATE_WAITPERFORM:
1388 /* Wait for our turn to PERFORM */
1389 if(!easy->easy_conn->readchannel_inuse &&
1390 isHandleAtHead(data,
1391 easy->easy_conn->recv_pipe)) {
1392 /* Grab the channel */
1393 easy->easy_conn->readchannel_inuse = TRUE;
1394 multistate(easy, CURLM_STATE_PERFORM);
1395 result = CURLM_CALL_MULTI_PERFORM;
1396 }
1397#ifdef DEBUGBUILD
1398 else {
1399 infof(data, "Conn %ld recv pipe %zu inuse %d athead %d\n",
1400 easy->easy_conn->connectindex,
1401 easy->easy_conn->recv_pipe->size,
1402 easy->easy_conn->readchannel_inuse?1:0,
1403 isHandleAtHead(data,
1404 easy->easy_conn->recv_pipe)?1:0);
1405 }
1406#endif
1407 break;
1408
1409 case CURLM_STATE_TOOFAST: /* limit-rate exceeded in either direction */
1410 /* if both rates are within spec, resume transfer */
1411 if( ( (data->set.max_send_speed == 0) ||
1412 (data->progress.ulspeed < data->set.max_send_speed )) &&
1413 ( (data->set.max_recv_speed == 0) ||
1414 (data->progress.dlspeed < data->set.max_recv_speed) ) )
1415 multistate(easy, CURLM_STATE_PERFORM);
1416 break;
1417
1418 case CURLM_STATE_PERFORM:
1419 /* check if over send speed */
1420 if( (data->set.max_send_speed > 0) &&
1421 (data->progress.ulspeed > data->set.max_send_speed) ) {
1422 int buffersize;
1423
1424 multistate(easy, CURLM_STATE_TOOFAST);
1425
1426 /* calculate upload rate-limitation timeout. */
1427 buffersize = (int)(data->set.buffer_size ?
1428 data->set.buffer_size : BUFSIZE);
1429 timeout_ms = Curl_sleep_time(data->set.max_send_speed,
1430 data->progress.ulspeed, buffersize);
1431 Curl_expire(data, timeout_ms);
1432 break;
1433 }
1434
1435 /* check if over recv speed */
1436 if( (data->set.max_recv_speed > 0) &&
1437 (data->progress.dlspeed > data->set.max_recv_speed) ) {
1438 int buffersize;
1439
1440 multistate(easy, CURLM_STATE_TOOFAST);
1441
1442 /* Calculate download rate-limitation timeout. */
1443 buffersize = (int)(data->set.buffer_size ?
1444 data->set.buffer_size : BUFSIZE);
1445 timeout_ms = Curl_sleep_time(data->set.max_recv_speed,
1446 data->progress.dlspeed, buffersize);
1447 Curl_expire(data, timeout_ms);
1448 break;
1449 }
1450
1451 /* read/write data if it is ready to do so */
1452 easy->result = Curl_readwrite(easy->easy_conn, &done);
1453
1454 k = &data->req;
1455
1456 if(!(k->keepon & KEEP_RECV)) {
1457 /* We're done receiving */
1458 easy->easy_conn->readchannel_inuse = FALSE;
1459 }
1460
1461 if(!(k->keepon & KEEP_SEND)) {
1462 /* We're done sending */
1463 easy->easy_conn->writechannel_inuse = FALSE;
1464 }
1465
1466 if(easy->result) {
1467 /* The transfer phase returned error, we mark the connection to get
1468 * closed to prevent being re-used. This is because we can't possibly
1469 * know if the connection is in a good shape or not now. Unless it is
1470 * a protocol which uses two "channels" like FTP, as then the error
1471 * happened in the data connection.
1472 */
1473 if(!(easy->easy_conn->protocol & PROT_DUALCHANNEL))
1474 easy->easy_conn->bits.close = TRUE;
1475
1476 Curl_posttransfer(data);
1477 Curl_done(&easy->easy_conn, easy->result, FALSE);
1478 }
1479 else if(TRUE == done) {
1480 char *newurl = NULL;
1481 bool retry = FALSE;
1482 followtype follow=FOLLOW_NONE;
1483
1484 easy->result = Curl_retry_request(easy->easy_conn, &newurl);
1485 if(!easy->result)
1486 retry = (bool)(newurl?TRUE:FALSE);
1487
1488 /* call this even if the readwrite function returned error */
1489 Curl_posttransfer(data);
1490
1491 /* we're no longer receving */
1492 moveHandleFromRecvToDonePipeline(data,
1493 easy->easy_conn);
1494
1495 /* expire the new receiving pipeline head */
1496 if(easy->easy_conn->recv_pipe->head)
1497 Curl_expire(easy->easy_conn->recv_pipe->head->ptr, 1);
1498
1499 /* Check if we can move pending requests to send pipe */
1500 checkPendPipeline(easy->easy_conn);
1501
1502 /* When we follow redirects or is set to retry the connection, we must
1503 to go back to the CONNECT state */
1504 if(data->req.newurl || retry) {
1505 if(!retry) {
1506 /* if the URL is a follow-location and not just a retried request
1507 then figure out the URL here */
1508 newurl = data->req.newurl;
1509 data->req.newurl = NULL;
1510 follow = FOLLOW_REDIR;
1511 }
1512 else
1513 follow = FOLLOW_RETRY;
1514 easy->result = Curl_done(&easy->easy_conn, CURLE_OK, FALSE);
1515 if(easy->result == CURLE_OK)
1516 easy->result = Curl_follow(data, newurl, follow);
1517 if(CURLE_OK == easy->result) {
1518 multistate(easy, CURLM_STATE_CONNECT);
1519 result = CURLM_CALL_MULTI_PERFORM;
1520 }
1521 else if(newurl)
1522 /* Since we "took it", we are in charge of freeing this on
1523 failure */
1524 free(newurl);
1525 }
1526 else {
1527 /* after the transfer is done, go DONE */
1528
1529 /* but first check to see if we got a location info even though we're
1530 not following redirects */
1531 if (data->req.location) {
1532 newurl = data->req.location;
1533 data->req.location = NULL;
1534 easy->result = Curl_follow(data, newurl, FOLLOW_FAKE);
1535 if (easy->result)
1536 free(newurl);
1537 }
1538
1539 multistate(easy, CURLM_STATE_DONE);
1540 result = CURLM_CALL_MULTI_PERFORM;
1541 }
1542 }
1543
1544 break;
1545
1546 case CURLM_STATE_DONE:
1547
1548 if(easy->easy_conn) {
1549 /* Remove ourselves from the receive and done pipelines. Handle
1550 should be on one of these lists, depending upon how we got here. */
1551 Curl_removeHandleFromPipeline(data,
1552 easy->easy_conn->recv_pipe);
1553 Curl_removeHandleFromPipeline(data,
1554 easy->easy_conn->done_pipe);
1555 /* Check if we can move pending requests to send pipe */
1556 checkPendPipeline(easy->easy_conn);
1557
1558 if(easy->easy_conn->bits.stream_was_rewound) {
1559 /* This request read past its response boundary so we quickly let
1560 the other requests consume those bytes since there is no
1561 guarantee that the socket will become active again */
1562 result = CURLM_CALL_MULTI_PERFORM;
1563 }
1564
1565 /* post-transfer command */
1566 easy->result = Curl_done(&easy->easy_conn, CURLE_OK, FALSE);
1567 /*
1568 * If there are other handles on the pipeline, Curl_done won't set
1569 * easy_conn to NULL. In such a case, curl_multi_remove_handle() can
1570 * access free'd data, if the connection is free'd and the handle
1571 * removed before we perform the processing in CURLM_STATE_COMPLETED
1572 */
1573 if (easy->easy_conn)
1574 easy->easy_conn = NULL;
1575 }
1576
1577 if(data->set.wildcardmatch) {
1578 if(data->wildcard.state != CURLWC_DONE) {
1579 /* if a wildcard is set and we are not ending -> lets start again
1580 with CURLM_STATE_INIT */
1581 result = CURLM_CALL_MULTI_PERFORM;
1582 multistate(easy, CURLM_STATE_INIT);
1583 break;
1584 }
1585 }
1586
1587 /* after we have DONE what we're supposed to do, go COMPLETED, and
1588 it doesn't matter what the Curl_done() returned! */
1589 multistate(easy, CURLM_STATE_COMPLETED);
1590
1591 break;
1592
1593 case CURLM_STATE_COMPLETED:
1594 /* this is a completed transfer, it is likely to still be connected */
1595
1596 /* This node should be delinked from the list now and we should post
1597 an information message that we are complete. */
1598
1599 /* Important: reset the conn pointer so that we don't point to memory
1600 that could be freed anytime */
1601 easy->easy_conn = NULL;
1602
1603 Curl_expire(data, 0); /* stop all timers */
1604 break;
1605
1606 case CURLM_STATE_MSGSENT:
1607 return CURLM_OK; /* do nothing */
1608
1609 default:
1610 return CURLM_INTERNAL_ERROR;
1611 }
1612
1613 if(CURLM_STATE_COMPLETED > easy->state) {
1614 if(CURLE_OK != easy->result) {
1615 /*
1616 * If an error was returned, and we aren't in completed state now,
1617 * then we go to completed and consider this transfer aborted.
1618 */
1619
1620 /* NOTE: no attempt to disconnect connections must be made
1621 in the case blocks above - cleanup happens only here */
1622
1623 data->state.pipe_broke = FALSE;
1624
1625 if(easy->easy_conn) {
1626 /* if this has a connection, unsubscribe from the pipelines */
1627 easy->easy_conn->writechannel_inuse = FALSE;
1628 easy->easy_conn->readchannel_inuse = FALSE;
1629 Curl_removeHandleFromPipeline(data,
1630 easy->easy_conn->send_pipe);
1631 Curl_removeHandleFromPipeline(data,
1632 easy->easy_conn->recv_pipe);
1633 Curl_removeHandleFromPipeline(data,
1634 easy->easy_conn->done_pipe);
1635 /* Check if we can move pending requests to send pipe */
1636 checkPendPipeline(easy->easy_conn);
1637 }
1638
1639 if(disconnect_conn) {
1640 /* disconnect properly */
1641 Curl_disconnect(easy->easy_conn, /* dead_connection */ FALSE);
1642
1643 /* This is where we make sure that the easy_conn pointer is reset.
1644 We don't have to do this in every case block above where a
1645 failure is detected */
1646 easy->easy_conn = NULL;
1647 }
1648
1649 multistate(easy, CURLM_STATE_COMPLETED);
1650 }
1651 /* if there's still a connection to use, call the progress function */
1652 else if(easy->easy_conn && Curl_pgrsUpdate(easy->easy_conn))
1653 easy->result = CURLE_ABORTED_BY_CALLBACK;
1654 }
1655 } while(0);
1656
1657 if(CURLM_STATE_COMPLETED == easy->state) {
1658 if(data->dns.hostcachetype == HCACHE_MULTI) {
1659 /* clear out the usage of the shared DNS cache */
1660 data->dns.hostcache = NULL;
1661 data->dns.hostcachetype = HCACHE_NONE;
1662 }
1663
1664 /* now fill in the Curl_message with this info */
1665 msg = &easy->msg;
1666
1667 msg->extmsg.msg = CURLMSG_DONE;
1668 msg->extmsg.easy_handle = data;
1669 msg->extmsg.data.result = easy->result;
1670
1671 result = multi_addmsg(multi, msg);
1672
1673 multistate(easy, CURLM_STATE_MSGSENT);
1674 }
1675
1676 return result;
1677}
1678
1679
1680CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
1681{
1682 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1683 struct Curl_one_easy *easy;
1684 CURLMcode returncode=CURLM_OK;
1685 struct Curl_tree *t;
1686 struct timeval now = Curl_tvnow();
1687
1688 if(!GOOD_MULTI_HANDLE(multi))
1689 return CURLM_BAD_HANDLE;
1690
1691 easy=multi->easy.next;
1692 while(easy != &multi->easy) {
1693 CURLMcode result;
1694 struct WildcardData *wc = &easy->easy_handle->wildcard;
1695
1696 if(easy->easy_handle->set.wildcardmatch) {
1697 if(!wc->filelist) {
1698 CURLcode ret = Curl_wildcard_init(wc); /* init wildcard structures */
1699 if(ret)
1700 return CURLM_OUT_OF_MEMORY;
1701 }
1702 }
1703
1704 do
1705 result = multi_runsingle(multi, now, easy);
1706 while (CURLM_CALL_MULTI_PERFORM == result);
1707
1708 if(easy->easy_handle->set.wildcardmatch) {
1709 /* destruct wildcard structures if it is needed */
1710 if(wc->state == CURLWC_DONE || result)
1711 Curl_wildcard_dtor(wc);
1712 }
1713
1714 if(result)
1715 returncode = result;
1716
1717 easy = easy->next; /* operate on next handle */
1718 }
1719
1720 /*
1721 * Simply remove all expired timers from the splay since handles are dealt
1722 * with unconditionally by this function and curl_multi_timeout() requires
1723 * that already passed/handled expire times are removed from the splay.
1724 *
1725 * It is important that the 'now' value is set at the entry of this function
1726 * and not for the current time as it may have ticked a little while since
1727 * then and then we risk this loop to remove timers that actually have not
1728 * been handled!
1729 */
1730 do {
1731 multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
1732 if(t)
1733 /* the removed may have another timeout in queue */
1734 (void)add_next_timeout(now, multi, t->payload);
1735
1736 } while(t);
1737
1738 *running_handles = multi->num_alive;
1739
1740 if( CURLM_OK >= returncode )
1741 update_timer(multi);
1742
1743 return returncode;
1744}
1745
1746CURLMcode curl_multi_cleanup(CURLM *multi_handle)
1747{
1748 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1749 struct Curl_one_easy *easy;
1750 struct Curl_one_easy *nexteasy;
1751 int i;
1752 struct closure *cl;
1753 struct closure *n;
1754
1755 if(GOOD_MULTI_HANDLE(multi)) {
1756 multi->type = 0; /* not good anymore */
1757 Curl_hash_destroy(multi->hostcache);
1758 Curl_hash_destroy(multi->sockhash);
1759 multi->hostcache = NULL;
1760 multi->sockhash = NULL;
1761
1762 /* go over all connections that have close actions */
1763 for(i=0; i< multi->connc->num; i++) {
1764 if(multi->connc->connects[i] &&
1765 multi->connc->connects[i]->protocol & PROT_CLOSEACTION) {
1766 Curl_disconnect(multi->connc->connects[i], /* dead_connection */ FALSE);
1767 multi->connc->connects[i] = NULL;
1768 }
1769 }
1770 /* now walk through the list of handles we kept around only to be
1771 able to close connections "properly" */
1772 cl = multi->closure;
1773 while(cl) {
1774 cl->easy_handle->state.shared_conn = NULL; /* no more shared */
1775 if(cl->easy_handle->state.closed)
1776 /* close handle only if curl_easy_cleanup() already has been called
1777 for this easy handle */
1778 Curl_close(cl->easy_handle);
1779 n = cl->next;
1780 free(cl);
1781 cl= n;
1782 }
1783
1784 Curl_rm_connc(multi->connc);
1785
1786 /* remove the pending list of messages */
1787 Curl_llist_destroy(multi->msglist, NULL);
1788
1789 /* remove all easy handles */
1790 easy = multi->easy.next;
1791 while(easy != &multi->easy) {
1792 nexteasy=easy->next;
1793 if(easy->easy_handle->dns.hostcachetype == HCACHE_MULTI) {
1794 /* clear out the usage of the shared DNS cache */
1795 easy->easy_handle->dns.hostcache = NULL;
1796 easy->easy_handle->dns.hostcachetype = HCACHE_NONE;
1797 }
1798
1799 /* Clear the pointer to the connection cache */
1800 easy->easy_handle->state.connc = NULL;
1801
1802 Curl_easy_addmulti(easy->easy_handle, NULL); /* clear the association */
1803
1804 free(easy);
1805 easy = nexteasy;
1806 }
1807
1808 free(multi);
1809
1810 return CURLM_OK;
1811 }
1812 else
1813 return CURLM_BAD_HANDLE;
1814}
1815
1816/*
1817 * curl_multi_info_read()
1818 *
1819 * This function is the primary way for a multi/multi_socket application to
1820 * figure out if a transfer has ended. We MUST make this function as fast as
1821 * possible as it will be polled frequently and we MUST NOT scan any lists in
1822 * here to figure out things. We must scale fine to thousands of handles and
1823 * beyond. The current design is fully O(1).
1824 */
1825
1826CURLMsg *curl_multi_info_read(CURLM *multi_handle, int *msgs_in_queue)
1827{
1828 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1829 struct Curl_message *msg;
1830
1831 *msgs_in_queue = 0; /* default to none */
1832
1833 if(GOOD_MULTI_HANDLE(multi) && Curl_llist_count(multi->msglist)) {
1834 /* there is one or more messages in the list */
1835 struct curl_llist_element *e;
1836
1837 /* extract the head of the list to return */
1838 e = multi->msglist->head;
1839
1840 msg = e->ptr;
1841
1842 /* remove the extracted entry */
1843 Curl_llist_remove(multi->msglist, e, NULL);
1844
1845 *msgs_in_queue = curlx_uztosi(Curl_llist_count(multi->msglist));
1846
1847 return &msg->extmsg;
1848 }
1849 else
1850 return NULL;
1851}
1852
1853/*
1854 * singlesocket() checks what sockets we deal with and their "action state"
1855 * and if we have a different state in any of those sockets from last time we
1856 * call the callback accordingly.
1857 */
1858static void singlesocket(struct Curl_multi *multi,
1859 struct Curl_one_easy *easy)
1860{
1861 curl_socket_t socks[MAX_SOCKSPEREASYHANDLE];
1862 int i;
1863 struct Curl_sh_entry *entry;
1864 curl_socket_t s;
1865 int num;
1866 unsigned int curraction;
1867 struct Curl_one_easy *easy_by_hash;
1868 bool remove_sock_from_hash;
1869
1870 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++)
1871 socks[i] = CURL_SOCKET_BAD;
1872
1873 /* Fill in the 'current' struct with the state as it is now: what sockets to
1874 supervise and for what actions */
1875 curraction = multi_getsock(easy, socks, MAX_SOCKSPEREASYHANDLE);
1876
1877 /* We have 0 .. N sockets already and we get to know about the 0 .. M
1878 sockets we should have from now on. Detect the differences, remove no
1879 longer supervised ones and add new ones */
1880
1881 /* walk over the sockets we got right now */
1882 for(i=0; (i< MAX_SOCKSPEREASYHANDLE) &&
1883 (curraction & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i)));
1884 i++) {
1885 int action = CURL_POLL_NONE;
1886
1887 s = socks[i];
1888
1889 /* get it from the hash */
1890 entry = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
1891
1892 if(curraction & GETSOCK_READSOCK(i))
1893 action |= CURL_POLL_IN;
1894 if(curraction & GETSOCK_WRITESOCK(i))
1895 action |= CURL_POLL_OUT;
1896
1897 if(entry) {
1898 /* yeps, already present so check if it has the same action set */
1899 if(entry->action == action)
1900 /* same, continue */
1901 continue;
1902 }
1903 else {
1904 /* this is a socket we didn't have before, add it! */
1905 entry = sh_addentry(multi->sockhash, s, easy->easy_handle);
1906 if(!entry)
1907 /* fatal */
1908 return;
1909 }
1910
1911 /* we know (entry != NULL) at this point, see the logic above */
1912 multi->socket_cb(easy->easy_handle,
1913 s,
1914 action,
1915 multi->socket_userp,
1916 entry->socketp);
1917
1918 entry->action = action; /* store the current action state */
1919 }
1920
1921 num = i; /* number of sockets */
1922
1923 /* when we've walked over all the sockets we should have right now, we must
1924 make sure to detect sockets that are removed */
1925 for(i=0; i< easy->numsocks; i++) {
1926 int j;
1927 s = easy->sockets[i];
1928 for(j=0; j<num; j++) {
1929 if(s == socks[j]) {
1930 /* this is still supervised */
1931 s = CURL_SOCKET_BAD;
1932 break;
1933 }
1934 }
1935 if(s != CURL_SOCKET_BAD) {
1936
1937 /* this socket has been removed. Tell the app to remove it */
1938 remove_sock_from_hash = TRUE;
1939
1940 entry = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
1941 if(entry) {
1942 /* check if the socket to be removed serves a connection which has
1943 other easy-s in a pipeline. In this case the socket should not be
1944 removed. */
1945 struct connectdata *easy_conn;
1946
1947 easy_by_hash = entry->easy->multi_pos;
1948 easy_conn = easy_by_hash->easy_conn;
1949 if(easy_conn) {
1950 if (easy_conn->recv_pipe && easy_conn->recv_pipe->size > 1) {
1951 /* the handle should not be removed from the pipe yet */
1952 remove_sock_from_hash = FALSE;
1953
1954 /* Update the sockhash entry to instead point to the next in line
1955 for the recv_pipe, or the first (in case this particular easy
1956 isn't already) */
1957 if (entry->easy == easy->easy_handle) {
1958 if (isHandleAtHead(easy->easy_handle, easy_conn->recv_pipe))
1959 entry->easy = easy_conn->recv_pipe->head->next->ptr;
1960 else
1961 entry->easy = easy_conn->recv_pipe->head->ptr;
1962 }
1963 }
1964 if (easy_conn->send_pipe && easy_conn->send_pipe->size > 1) {
1965 /* the handle should not be removed from the pipe yet */
1966 remove_sock_from_hash = FALSE;
1967
1968 /* Update the sockhash entry to instead point to the next in line
1969 for the send_pipe, or the first (in case this particular easy
1970 isn't already) */
1971 if (entry->easy == easy->easy_handle) {
1972 if (isHandleAtHead(easy->easy_handle, easy_conn->send_pipe))
1973 entry->easy = easy_conn->send_pipe->head->next->ptr;
1974 else
1975 entry->easy = easy_conn->send_pipe->head->ptr;
1976 }
1977 }
1978 /* Don't worry about overwriting recv_pipe head with send_pipe_head,
1979 when action will be asked on the socket (see multi_socket()), the
1980 head of the correct pipe will be taken according to the
1981 action. */
1982 }
1983 }
1984 else
1985 /* just a precaution, this socket really SHOULD be in the hash already
1986 but in case it isn't, we don't have to tell the app to remove it
1987 either since it never got to know about it */
1988 remove_sock_from_hash = FALSE;
1989
1990 if (remove_sock_from_hash) {
1991 multi->socket_cb(easy->easy_handle,
1992 s,
1993 CURL_POLL_REMOVE,
1994 multi->socket_userp,
1995 entry ? entry->socketp : NULL);
1996 sh_delentry(multi->sockhash, s);
1997 }
1998
1999 }
2000 }
2001
2002 memcpy(easy->sockets, socks, num*sizeof(curl_socket_t));
2003 easy->numsocks = num;
2004}
2005
2006/*
2007 * add_next_timeout()
2008 *
2009 * Each SessionHandle has a list of timeouts. The add_next_timeout() is called
2010 * when it has just been removed from the splay tree because the timeout has
2011 * expired. This function is then to advance in the list to pick the next
2012 * timeout to use (skip the already expired ones) and add this node back to
2013 * the splay tree again.
2014 *
2015 * The splay tree only has each sessionhandle as a single node and the nearest
2016 * timeout is used to sort it on.
2017 */
2018static CURLMcode add_next_timeout(struct timeval now,
2019 struct Curl_multi *multi,
2020 struct SessionHandle *d)
2021{
2022 struct timeval *tv = &d->state.expiretime;
2023 struct curl_llist *list = d->state.timeoutlist;
2024 struct curl_llist_element *e;
2025
2026 /* move over the timeout list for this specific handle and remove all
2027 timeouts that are now passed tense and store the next pending
2028 timeout in *tv */
2029 for(e = list->head; e; ) {
2030 struct curl_llist_element *n = e->next;
2031 long diff = curlx_tvdiff(*(struct timeval *)e->ptr, now);
2032 if(diff <= 0)
2033 /* remove outdated entry */
2034 Curl_llist_remove(list, e, NULL);
2035 else
2036 /* the list is sorted so get out on the first mismatch */
2037 break;
2038 e = n;
2039 }
2040 if(!list->size) {
2041 /* clear the expire times within the handles that we remove from the
2042 splay tree */
2043 tv->tv_sec = 0;
2044 tv->tv_usec = 0;
2045 }
2046 else {
2047 e = list->head;
2048 /* copy the first entry to 'tv' */
2049 memcpy(tv, e->ptr, sizeof(*tv));
2050
2051 /* remove first entry from list */
2052 Curl_llist_remove(list, e, NULL);
2053
2054 /* insert this node again into the splay */
2055 multi->timetree = Curl_splayinsert(*tv, multi->timetree,
2056 &d->state.timenode);
2057 }
2058 return CURLM_OK;
2059}
2060
2061
2062static CURLMcode multi_socket(struct Curl_multi *multi,
2063 bool checkall,
2064 curl_socket_t s,
2065 int ev_bitmask,
2066 int *running_handles)
2067{
2068 CURLMcode result = CURLM_OK;
2069 struct SessionHandle *data = NULL;
2070 struct Curl_tree *t;
2071 struct timeval now = Curl_tvnow();
2072
2073 if(checkall) {
2074 struct Curl_one_easy *easyp;
2075 /* *perform() deals with running_handles on its own */
2076 result = curl_multi_perform(multi, running_handles);
2077
2078 /* walk through each easy handle and do the socket state change magic
2079 and callbacks */
2080 easyp=multi->easy.next;
2081 while(easyp != &multi->easy) {
2082 singlesocket(multi, easyp);
2083 easyp = easyp->next;
2084 }
2085
2086 /* or should we fall-through and do the timer-based stuff? */
2087 return result;
2088 }
2089 else if(s != CURL_SOCKET_TIMEOUT) {
2090
2091 struct Curl_sh_entry *entry =
2092 Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
2093
2094 if(!entry)
2095 /* Unmatched socket, we can't act on it but we ignore this fact. In
2096 real-world tests it has been proved that libevent can in fact give
2097 the application actions even though the socket was just previously
2098 asked to get removed, so thus we better survive stray socket actions
2099 and just move on. */
2100 ;
2101 else {
2102 data = entry->easy;
2103
2104 if(data->magic != CURLEASY_MAGIC_NUMBER)
2105 /* bad bad bad bad bad bad bad */
2106 return CURLM_INTERNAL_ERROR;
2107
2108 /* If the pipeline is enabled, take the handle which is in the head of
2109 the pipeline. If we should write into the socket, take the send_pipe
2110 head. If we should read from the socket, take the recv_pipe head. */
2111 if(data->set.one_easy->easy_conn) {
2112 if ((ev_bitmask & CURL_POLL_OUT) &&
2113 data->set.one_easy->easy_conn->send_pipe &&
2114 data->set.one_easy->easy_conn->send_pipe->head)
2115 data = data->set.one_easy->easy_conn->send_pipe->head->ptr;
2116 else if ((ev_bitmask & CURL_POLL_IN) &&
2117 data->set.one_easy->easy_conn->recv_pipe &&
2118 data->set.one_easy->easy_conn->recv_pipe->head)
2119 data = data->set.one_easy->easy_conn->recv_pipe->head->ptr;
2120 }
2121
2122 if(data->set.one_easy->easy_conn) /* set socket event bitmask */
2123 data->set.one_easy->easy_conn->cselect_bits = ev_bitmask;
2124
2125 do
2126 result = multi_runsingle(multi, now, data->set.one_easy);
2127 while (CURLM_CALL_MULTI_PERFORM == result);
2128
2129 if(data->set.one_easy->easy_conn)
2130 data->set.one_easy->easy_conn->cselect_bits = 0;
2131
2132 if(CURLM_OK >= result)
2133 /* get the socket(s) and check if the state has been changed since
2134 last */
2135 singlesocket(multi, data->set.one_easy);
2136
2137 /* Now we fall-through and do the timer-based stuff, since we don't want
2138 to force the user to have to deal with timeouts as long as at least
2139 one connection in fact has traffic. */
2140
2141 data = NULL; /* set data to NULL again to avoid calling
2142 multi_runsingle() in case there's no need to */
2143 }
2144 }
2145
2146 now.tv_usec += 40000; /* compensate for bad precision timers that might've
2147 triggered too early */
2148 if(now.tv_usec >= 1000000) {
2149 now.tv_sec++;
2150 now.tv_usec -= 1000000;
2151 }
2152
2153 /*
2154 * The loop following here will go on as long as there are expire-times left
2155 * to process in the splay and 'data' will be re-assigned for every expired
2156 * handle we deal with.
2157 */
2158 do {
2159 /* the first loop lap 'data' can be NULL */
2160 if(data) {
2161 do
2162 result = multi_runsingle(multi, now, data->set.one_easy);
2163 while (CURLM_CALL_MULTI_PERFORM == result);
2164
2165 if(CURLM_OK >= result)
2166 /* get the socket(s) and check if the state has been changed since
2167 last */
2168 singlesocket(multi, data->set.one_easy);
2169 }
2170
2171 /* Check if there's one (more) expired timer to deal with! This function
2172 extracts a matching node if there is one */
2173
2174 multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
2175 if(t) {
2176 data = t->payload; /* assign this for next loop */
2177 (void)add_next_timeout(now, multi, t->payload);
2178 }
2179
2180 } while(t);
2181
2182 *running_handles = multi->num_alive;
2183 return result;
2184}
2185
2186#undef curl_multi_setopt
2187CURLMcode curl_multi_setopt(CURLM *multi_handle,
2188 CURLMoption option, ...)
2189{
2190 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
2191 CURLMcode res = CURLM_OK;
2192 va_list param;
2193
2194 if(!GOOD_MULTI_HANDLE(multi))
2195 return CURLM_BAD_HANDLE;
2196
2197 va_start(param, option);
2198
2199 switch(option) {
2200 case CURLMOPT_SOCKETFUNCTION:
2201 multi->socket_cb = va_arg(param, curl_socket_callback);
2202 break;
2203 case CURLMOPT_SOCKETDATA:
2204 multi->socket_userp = va_arg(param, void *);
2205 break;
2206 case CURLMOPT_PIPELINING:
2207 multi->pipelining_enabled = (bool)(0 != va_arg(param, long));
2208 break;
2209 case CURLMOPT_TIMERFUNCTION:
2210 multi->timer_cb = va_arg(param, curl_multi_timer_callback);
2211 break;
2212 case CURLMOPT_TIMERDATA:
2213 multi->timer_userp = va_arg(param, void *);
2214 break;
2215 case CURLMOPT_MAXCONNECTS:
2216 multi->maxconnects = va_arg(param, long);
2217 break;
2218 default:
2219 res = CURLM_UNKNOWN_OPTION;
2220 break;
2221 }
2222 va_end(param);
2223 return res;
2224}
2225
2226/* we define curl_multi_socket() in the public multi.h header */
2227#undef curl_multi_socket
2228
2229CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s,
2230 int *running_handles)
2231{
2232 CURLMcode result = multi_socket((struct Curl_multi *)multi_handle, FALSE, s,
2233 0, running_handles);
2234 if(CURLM_OK >= result)
2235 update_timer((struct Curl_multi *)multi_handle);
2236 return result;
2237}
2238
2239CURLMcode curl_multi_socket_action(CURLM *multi_handle, curl_socket_t s,
2240 int ev_bitmask, int *running_handles)
2241{
2242 CURLMcode result = multi_socket((struct Curl_multi *)multi_handle, FALSE, s,
2243 ev_bitmask, running_handles);
2244 if(CURLM_OK >= result)
2245 update_timer((struct Curl_multi *)multi_handle);
2246 return result;
2247}
2248
2249CURLMcode curl_multi_socket_all(CURLM *multi_handle, int *running_handles)
2250
2251{
2252 CURLMcode result = multi_socket((struct Curl_multi *)multi_handle,
2253 TRUE, CURL_SOCKET_BAD, 0, running_handles);
2254 if(CURLM_OK >= result)
2255 update_timer((struct Curl_multi *)multi_handle);
2256 return result;
2257}
2258
2259static CURLMcode multi_timeout(struct Curl_multi *multi,
2260 long *timeout_ms)
2261{
2262 static struct timeval tv_zero = {0,0};
2263
2264 if(multi->timetree) {
2265 /* we have a tree of expire times */
2266 struct timeval now = Curl_tvnow();
2267
2268 /* splay the lowest to the bottom */
2269 multi->timetree = Curl_splay(tv_zero, multi->timetree);
2270
2271 if(Curl_splaycomparekeys(multi->timetree->key, now) > 0) {
2272 /* some time left before expiration */
2273 *timeout_ms = curlx_tvdiff(multi->timetree->key, now);
2274 if(!*timeout_ms)
2275 /*
2276 * Since we only provide millisecond resolution on the returned value
2277 * and the diff might be less than one millisecond here, we don't
2278 * return zero as that may cause short bursts of busyloops on fast
2279 * processors while the diff is still present but less than one
2280 * millisecond! instead we return 1 until the time is ripe.
2281 */
2282 *timeout_ms=1;
2283 }
2284 else
2285 /* 0 means immediately */
2286 *timeout_ms = 0;
2287 }
2288 else
2289 *timeout_ms = -1;
2290
2291 return CURLM_OK;
2292}
2293
2294CURLMcode curl_multi_timeout(CURLM *multi_handle,
2295 long *timeout_ms)
2296{
2297 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
2298
2299 /* First, make some basic checks that the CURLM handle is a good handle */
2300 if(!GOOD_MULTI_HANDLE(multi))
2301 return CURLM_BAD_HANDLE;
2302
2303 return multi_timeout(multi, timeout_ms);
2304}
2305
2306/*
2307 * Tell the application it should update its timers, if it subscribes to the
2308 * update timer callback.
2309 */
2310static int update_timer(struct Curl_multi *multi)
2311{
2312 long timeout_ms;
2313
2314 if(!multi->timer_cb)
2315 return 0;
2316 if(multi_timeout(multi, &timeout_ms)) {
2317 return -1;
2318 }
2319 if( timeout_ms < 0 ) {
2320 static const struct timeval none={0,0};
2321 if(Curl_splaycomparekeys(none, multi->timer_lastcall)) {
2322 multi->timer_lastcall = none;
2323 /* there's no timeout now but there was one previously, tell the app to
2324 disable it */
2325 return multi->timer_cb((CURLM*)multi, -1, multi->timer_userp);
2326 }
2327 return 0;
2328 }
2329
2330 /* When multi_timeout() is done, multi->timetree points to the node with the
2331 * timeout we got the (relative) time-out time for. We can thus easily check
2332 * if this is the same (fixed) time as we got in a previous call and then
2333 * avoid calling the callback again. */
2334 if(Curl_splaycomparekeys(multi->timetree->key, multi->timer_lastcall) == 0)
2335 return 0;
2336
2337 multi->timer_lastcall = multi->timetree->key;
2338
2339 return multi->timer_cb((CURLM*)multi, timeout_ms, multi->timer_userp);
2340}
2341
2342static CURLcode addHandleToSendOrPendPipeline(struct SessionHandle *handle,
2343 struct connectdata *conn)
2344{
2345 size_t pipeLen = conn->send_pipe->size + conn->recv_pipe->size;
2346 struct curl_llist_element *sendhead = conn->send_pipe->head;
2347 struct curl_llist *pipeline;
2348 CURLcode rc;
2349
2350 if(!Curl_isPipeliningEnabled(handle) ||
2351 pipeLen == 0)
2352 pipeline = conn->send_pipe;
2353 else {
2354 if(conn->server_supports_pipelining &&
2355 pipeLen < MAX_PIPELINE_LENGTH)
2356 pipeline = conn->send_pipe;
2357 else
2358 pipeline = conn->pend_pipe;
2359 }
2360
2361 rc = Curl_addHandleToPipeline(handle, pipeline);
2362
2363 if (pipeline == conn->send_pipe && sendhead != conn->send_pipe->head) {
2364 /* this is a new one as head, expire it */
2365 conn->writechannel_inuse = FALSE; /* not in use yet */
2366 infof(conn->data, "%p is at send pipe head!\n",
2367 conn->send_pipe->head->ptr);
2368 Curl_expire(conn->send_pipe->head->ptr, 1);
2369 }
2370
2371 return rc;
2372}
2373
2374static int checkPendPipeline(struct connectdata *conn)
2375{
2376 int result = 0;
2377 struct curl_llist_element *sendhead = conn->send_pipe->head;
2378
2379 size_t pipeLen = conn->send_pipe->size + conn->recv_pipe->size;
2380 if (conn->server_supports_pipelining || pipeLen == 0) {
2381 struct curl_llist_element *curr = conn->pend_pipe->head;
2382 const size_t maxPipeLen =
2383 conn->server_supports_pipelining ? MAX_PIPELINE_LENGTH : 1;
2384
2385 while(pipeLen < maxPipeLen && curr) {
2386 Curl_llist_move(conn->pend_pipe, curr,
2387 conn->send_pipe, conn->send_pipe->tail);
2388 Curl_pgrsTime(curr->ptr, TIMER_PRETRANSFER);
2389 ++result; /* count how many handles we moved */
2390 curr = conn->pend_pipe->head;
2391 ++pipeLen;
2392 }
2393 }
2394
2395 if (result) {
2396 conn->now = Curl_tvnow();
2397 /* something moved, check for a new send pipeline leader */
2398 if(sendhead != conn->send_pipe->head) {
2399 /* this is a new one as head, expire it */
2400 conn->writechannel_inuse = FALSE; /* not in use yet */
2401 infof(conn->data, "%p is at send pipe head!\n",
2402 conn->send_pipe->head->ptr);
2403 Curl_expire(conn->send_pipe->head->ptr, 1);
2404 }
2405 }
2406
2407 return result;
2408}
2409
2410/* Move this transfer from the sending list to the receiving list.
2411
2412 Pay special attention to the new sending list "leader" as it needs to get
2413 checked to update what sockets it acts on.
2414
2415*/
2416static void moveHandleFromSendToRecvPipeline(struct SessionHandle *handle,
2417 struct connectdata *conn)
2418{
2419 struct curl_llist_element *curr;
2420
2421 curr = conn->send_pipe->head;
2422 while(curr) {
2423 if(curr->ptr == handle) {
2424 Curl_llist_move(conn->send_pipe, curr,
2425 conn->recv_pipe, conn->recv_pipe->tail);
2426
2427 if(conn->send_pipe->head) {
2428 /* Since there's a new easy handle at the start of the send pipeline,
2429 set its timeout value to 1ms to make it trigger instantly */
2430 conn->writechannel_inuse = FALSE; /* not used now */
2431 infof(conn->data, "%p is at send pipe head B!\n",
2432 conn->send_pipe->head->ptr);
2433 Curl_expire(conn->send_pipe->head->ptr, 1);
2434 }
2435
2436 /* The receiver's list is not really interesting here since either this
2437 handle is now first in the list and we'll deal with it soon, or
2438 another handle is already first and thus is already taken care of */
2439
2440 break; /* we're done! */
2441 }
2442 curr = curr->next;
2443 }
2444}
2445
2446static void moveHandleFromRecvToDonePipeline(struct SessionHandle *handle,
2447 struct connectdata *conn)
2448{
2449 struct curl_llist_element *curr;
2450
2451 curr = conn->recv_pipe->head;
2452 while(curr) {
2453 if(curr->ptr == handle) {
2454 Curl_llist_move(conn->recv_pipe, curr,
2455 conn->done_pipe, conn->done_pipe->tail);
2456 break;
2457 }
2458 curr = curr->next;
2459 }
2460}
2461static bool isHandleAtHead(struct SessionHandle *handle,
2462 struct curl_llist *pipeline)
2463{
2464 struct curl_llist_element *curr = pipeline->head;
2465 if(curr)
2466 return (bool)(curr->ptr == handle);
2467
2468 return FALSE;
2469}
2470
2471/*
2472 * multi_freetimeout()
2473 *
2474 * Callback used by the llist system when a single timeout list entry is
2475 * destroyed.
2476 */
2477static void multi_freetimeout(void *user, void *entryptr)
2478{
2479 (void)user;
2480
2481 /* the entry was plain malloc()'ed */
2482 free(entryptr);
2483}
2484
2485/*
2486 * multi_addtimeout()
2487 *
2488 * Add a timestamp to the list of timeouts. Keep the list sorted so that head
2489 * of list is always the timeout nearest in time.
2490 *
2491 */
2492static CURLMcode
2493multi_addtimeout(struct curl_llist *timeoutlist,
2494 struct timeval *stamp)
2495{
2496 struct curl_llist_element *e;
2497 struct timeval *timedup;
2498 struct curl_llist_element *prev = NULL;
2499
2500 timedup = malloc(sizeof(*timedup));
2501 if(!timedup)
2502 return CURLM_OUT_OF_MEMORY;
2503
2504 /* copy the timestamp */
2505 memcpy(timedup, stamp, sizeof(*timedup));
2506
2507 if(Curl_llist_count(timeoutlist)) {
2508 /* find the correct spot in the list */
2509 for(e = timeoutlist->head; e; e = e->next) {
2510 struct timeval *checktime = e->ptr;
2511 long diff = curlx_tvdiff(*checktime, *timedup);
2512 if(diff > 0)
2513 break;
2514 prev = e;
2515 }
2516
2517 }
2518 /* else
2519 this is the first timeout on the list */
2520
2521 if(!Curl_llist_insert_next(timeoutlist, prev, timedup)) {
2522 free(timedup);
2523 return CURLM_OUT_OF_MEMORY;
2524 }
2525
2526 return CURLM_OK;
2527}
2528
2529/*
2530 * Curl_expire()
2531 *
2532 * given a number of milliseconds from now to use to set the 'act before
2533 * this'-time for the transfer, to be extracted by curl_multi_timeout()
2534 *
2535 * Note that the timeout will be added to a queue of timeouts if it defines a
2536 * moment in time that is later than the current head of queue.
2537 *
2538 * Pass zero to clear all timeout values for this handle.
2539*/
2540void Curl_expire(struct SessionHandle *data, long milli)
2541{
2542 struct Curl_multi *multi = data->multi;
2543 struct timeval *nowp = &data->state.expiretime;
2544 int rc;
2545
2546 /* this is only interesting for multi-interface using libcurl, and only
2547 while there is still a multi interface struct remaining! */
2548 if(!multi)
2549 return;
2550
2551 if(!milli) {
2552 /* No timeout, clear the time data. */
2553 if(nowp->tv_sec || nowp->tv_usec) {
2554 /* Since this is an cleared time, we must remove the previous entry from
2555 the splay tree */
2556 struct curl_llist *list = data->state.timeoutlist;
2557
2558 rc = Curl_splayremovebyaddr(multi->timetree,
2559 &data->state.timenode,
2560 &multi->timetree);
2561 if(rc)
2562 infof(data, "Internal error clearing splay node = %d\n", rc);
2563
2564 /* flush the timeout list too */
2565 while(list->size > 0)
2566 Curl_llist_remove(list, list->tail, NULL);
2567
2568 infof(data, "Expire cleared\n");
2569 nowp->tv_sec = 0;
2570 nowp->tv_usec = 0;
2571 }
2572 }
2573 else {
2574 struct timeval set;
2575
2576 set = Curl_tvnow();
2577 set.tv_sec += milli/1000;
2578 set.tv_usec += (milli%1000)*1000;
2579
2580 if(set.tv_usec >= 1000000) {
2581 set.tv_sec++;
2582 set.tv_usec -= 1000000;
2583 }
2584
2585 if(nowp->tv_sec || nowp->tv_usec) {
2586 /* This means that the struct is added as a node in the splay tree.
2587 Compare if the new time is earlier, and only remove-old/add-new if it
2588 is. */
2589 long diff = curlx_tvdiff(set, *nowp);
2590 if(diff > 0) {
2591 /* the new expire time was later so just add it to the queue
2592 and get out */
2593 multi_addtimeout(data->state.timeoutlist, &set);
2594 return;
2595 }
2596
2597 /* the new time is newer than the presently set one, so add the current
2598 to the queue and update the head */
2599 multi_addtimeout(data->state.timeoutlist, nowp);
2600
2601 /* Since this is an updated time, we must remove the previous entry from
2602 the splay tree first and then re-add the new value */
2603 rc = Curl_splayremovebyaddr(multi->timetree,
2604 &data->state.timenode,
2605 &multi->timetree);
2606 if(rc)
2607 infof(data, "Internal error removing splay node = %d\n", rc);
2608 }
2609
2610 *nowp = set;
2611 data->state.timenode.payload = data;
2612 multi->timetree = Curl_splayinsert(*nowp,
2613 multi->timetree,
2614 &data->state.timenode);
2615 }
2616#if 0
2617 Curl_splayprint(multi->timetree, 0, TRUE);
2618#endif
2619}
2620
2621CURLMcode curl_multi_assign(CURLM *multi_handle,
2622 curl_socket_t s, void *hashp)
2623{
2624 struct Curl_sh_entry *there = NULL;
2625 struct Curl_multi *multi = (struct Curl_multi *)multi_handle;
2626
2627 if(s != CURL_SOCKET_BAD)
2628 there = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(curl_socket_t));
2629
2630 if(!there)
2631 return CURLM_BAD_SOCKET;
2632
2633 there->socketp = hashp;
2634
2635 return CURLM_OK;
2636}
2637
2638static void multi_connc_remove_handle(struct Curl_multi *multi,
2639 struct SessionHandle *data)
2640{
2641 /* a connection in the connection cache pointing to the given 'data' ? */
2642 int i;
2643
2644 for(i=0; i< multi->connc->num; i++) {
2645 struct connectdata * conn = multi->connc->connects[i];
2646
2647 if(conn && conn->data == data) {
2648 /* If this easy_handle was the last one in charge for one or more
2649 connections in the shared connection cache, we might need to keep
2650 this handle around until either A) the connection is closed and
2651 killed properly, or B) another easy_handle uses the connection.
2652
2653 The reason why we need to have a easy_handle associated with a live
2654 connection is simply that some connections will need a handle to get
2655 closed down properly. Currently, the only connections that need to
2656 keep a easy_handle handle around are using FTP(S). Such connections
2657 have the PROT_CLOSEACTION bit set.
2658
2659 Thus, we need to check for all connections in the shared cache that
2660 points to this handle and are using PROT_CLOSEACTION. If there's any,
2661 we need to add this handle to the list of "easy handles kept around
2662 for nice connection closures".
2663 */
2664
2665 if(conn->protocol & PROT_CLOSEACTION) {
2666 /* this handle is still being used by a shared connection and
2667 thus we leave it around for now */
2668 if(add_closure(multi, data) == CURLM_OK)
2669 data->state.shared_conn = multi;
2670 else {
2671 /* out of memory - so much for graceful shutdown */
2672 Curl_disconnect(conn, /* dead_connection */ FALSE);
2673 multi->connc->connects[i] = NULL;
2674 }
2675 }
2676 else
2677 /* disconect the easy handle from the connection since the connection
2678 will now remain but this easy handle is going */
2679 conn->data = NULL;
2680 }
2681 }
2682}
2683
2684/* Add the given data pointer to the list of 'closure handles' that are kept
2685 around only to be able to close some connections nicely - just make sure
2686 that this handle isn't already added, like for the cases when an easy
2687 handle is removed, added and removed again... */
2688static CURLMcode add_closure(struct Curl_multi *multi,
2689 struct SessionHandle *data)
2690{
2691 struct closure *cl = multi->closure;
2692 struct closure *p = NULL;
2693 bool add = TRUE;
2694
2695 /* Before adding, scan through all the other currently kept handles and see
2696 if there are any connections still referring to them and kill them if
2697 not. */
2698 while(cl) {
2699 struct closure *n;
2700 bool inuse = FALSE;
2701 int i;
2702
2703 for(i=0; i< multi->connc->num; i++) {
2704 if(multi->connc->connects[i] &&
2705 (multi->connc->connects[i]->data == cl->easy_handle)) {
2706 inuse = TRUE;
2707 break;
2708 }
2709 }
2710
2711 n = cl->next;
2712
2713 if(!inuse) {
2714 /* cl->easy_handle is now killable */
2715
2716 /* unmark it as not having a connection around that uses it anymore */
2717 cl->easy_handle->state.shared_conn= NULL;
2718
2719 if(cl->easy_handle->state.closed) {
2720 infof(data, "Delayed kill of easy handle %p\n", cl->easy_handle);
2721 /* close handle only if curl_easy_cleanup() already has been called
2722 for this easy handle */
2723 Curl_close(cl->easy_handle);
2724 }
2725 if(p)
2726 p->next = n;
2727 else
2728 multi->closure = n;
2729 free(cl);
2730 } else {
2731 if(cl->easy_handle == data)
2732 add = FALSE;
2733
2734 p = cl;
2735 }
2736
2737 cl = n;
2738 }
2739
2740 if (add) {
2741 cl = calloc(1, sizeof(struct closure));
2742 if(!cl)
2743 return CURLM_OUT_OF_MEMORY;
2744
2745 cl->easy_handle = data;
2746 cl->next = multi->closure;
2747 multi->closure = cl;
2748 }
2749
2750 return CURLM_OK;
2751}
2752
2753#ifdef DEBUGBUILD
2754void Curl_multi_dump(const struct Curl_multi *multi_handle)
2755{
2756 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
2757 struct Curl_one_easy *easy;
2758 int i;
2759 fprintf(stderr, "* Multi status: %d handles, %d alive\n",
2760 multi->num_easy, multi->num_alive);
2761 for(easy=multi->easy.next; easy != &multi->easy; easy = easy->next) {
2762 if(easy->state < CURLM_STATE_COMPLETED) {
2763 /* only display handles that are not completed */
2764 fprintf(stderr, "handle %p, state %s, %d sockets\n",
2765 (void *)easy->easy_handle,
2766 statename[easy->state], easy->numsocks);
2767 for(i=0; i < easy->numsocks; i++) {
2768 curl_socket_t s = easy->sockets[i];
2769 struct Curl_sh_entry *entry =
2770 Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
2771
2772 fprintf(stderr, "%d ", (int)s);
2773 if(!entry) {
2774 fprintf(stderr, "INTERNAL CONFUSION\n");
2775 continue;
2776 }
2777 fprintf(stderr, "[%s %s] ",
2778 entry->action&CURL_POLL_IN?"RECVING":"",
2779 entry->action&CURL_POLL_OUT?"SENDING":"");
2780 }
2781 if(easy->numsocks)
2782 fprintf(stderr, "\n");
2783 }
2784 }
2785}
2786#endif