1
/***************************************************************************
3
* Project ___| | | | _ \| |
5
* | (__| |_| | _ <| |___
6
* \___|\___/|_| \_\_____|
8
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
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.
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.
18
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19
* KIND, either express or implied.
21
***************************************************************************/
23
#include "curl_setup.h"
25
#include <curl/curl.h>
39
#include "speedcheck.h"
40
#include "conncache.h"
42
#include "multihandle.h"
44
#define _MPRINTF_REPLACE /* use our functions only */
45
#include <curl/mprintf.h>
47
#include "curl_memory.h"
48
/* The last #include file should be: */
52
CURL_SOCKET_HASH_TABLE_SIZE should be a prime number. Increasing it from 97
53
to 911 takes on a 32-bit machine 4 x 804 = 3211 more bytes. Still, every
54
CURL handle takes 45-50 K memory, therefore this 3K are not significant.
56
#ifndef CURL_SOCKET_HASH_TABLE_SIZE
57
#define CURL_SOCKET_HASH_TABLE_SIZE 911
61
#define CURL_MULTI_HANDLE 0x000bab1e
63
#define GOOD_MULTI_HANDLE(x) \
64
((x) && (((struct Curl_multi *)(x))->type == CURL_MULTI_HANDLE))
65
#define GOOD_EASY_HANDLE(x) \
66
((x) && (((struct SessionHandle *)(x))->magic == CURLEASY_MAGIC_NUMBER))
68
static void singlesocket(struct Curl_multi *multi,
69
struct Curl_one_easy *easy);
70
static int update_timer(struct Curl_multi *multi);
72
static CURLcode addHandleToSendOrPendPipeline(struct SessionHandle *handle,
73
struct connectdata *conn);
74
static int checkPendPipeline(struct connectdata *conn);
75
static void moveHandleFromSendToRecvPipeline(struct SessionHandle *handle,
76
struct connectdata *conn);
77
static void moveHandleFromRecvToDonePipeline(struct SessionHandle *handle,
78
struct connectdata *conn);
79
static bool isHandleAtHead(struct SessionHandle *handle,
80
struct curl_llist *pipeline);
81
static CURLMcode add_next_timeout(struct timeval now,
82
struct Curl_multi *multi,
83
struct SessionHandle *d);
86
static const char * const statename[]={
107
static void multi_freetimeout(void *a, void *b);
109
/* always use this function to change state, to make debugging easier */
110
static void mstate(struct Curl_one_easy *easy, CURLMstate state
117
long connection_id = -5000;
119
CURLMstate oldstate = easy->state;
121
if(oldstate == state)
122
/* don't bother when the new state is the same as the old state */
128
if(easy->easy_conn) {
129
if(easy->state > CURLM_STATE_CONNECT &&
130
easy->state < CURLM_STATE_COMPLETED)
131
connection_id = easy->easy_conn->connection_id;
133
infof(easy->easy_handle,
134
"STATE: %s => %s handle %p; line %d (connection #%ld) \n",
135
statename[oldstate], statename[easy->state],
136
(char *)easy, lineno, connection_id);
139
if(state == CURLM_STATE_COMPLETED)
140
/* changing to COMPLETED means there's one less easy handle 'alive' */
141
easy->easy_handle->multi->num_alive--;
145
#define multistate(x,y) mstate(x,y)
147
#define multistate(x,y) mstate(x,y, __LINE__)
151
* We add one of these structs to the sockhash for a particular socket
154
struct Curl_sh_entry {
155
struct SessionHandle *easy;
157
int action; /* what action READ/WRITE this socket waits for */
158
curl_socket_t socket; /* mainly to ease debugging */
159
void *socketp; /* settable by users with curl_multi_assign() */
161
/* bits for 'action' having no bits means this socket is not expecting any
166
/* make sure this socket is present in the hash for this handle */
167
static struct Curl_sh_entry *sh_addentry(struct curl_hash *sh,
169
struct SessionHandle *data)
171
struct Curl_sh_entry *there =
172
Curl_hash_pick(sh, (char *)&s, sizeof(curl_socket_t));
173
struct Curl_sh_entry *check;
176
/* it is present, return fine */
179
/* not present, add it */
180
check = calloc(1, sizeof(struct Curl_sh_entry));
182
return NULL; /* major failure */
186
/* make/add new hash entry */
187
if(NULL == Curl_hash_add(sh, (char *)&s, sizeof(curl_socket_t), check)) {
189
return NULL; /* major failure */
192
return check; /* things are good in sockhash land */
196
/* delete the given socket + handle from the hash */
197
static void sh_delentry(struct curl_hash *sh, curl_socket_t s)
199
struct Curl_sh_entry *there =
200
Curl_hash_pick(sh, (char *)&s, sizeof(curl_socket_t));
203
/* this socket is in the hash */
204
/* We remove the hash entry. (This'll end up in a call to
206
Curl_hash_delete(sh, (char *)&s, sizeof(curl_socket_t));
211
* free a sockhash entry
213
static void sh_freeentry(void *freethis)
215
struct Curl_sh_entry *p = (struct Curl_sh_entry *) freethis;
221
static size_t fd_key_compare(void*k1, size_t k1_len, void*k2, size_t k2_len)
223
(void) k1_len; (void) k2_len;
225
return (*((int* ) k1)) == (*((int* ) k2));
228
static size_t hash_fd(void* key, size_t key_length, size_t slots_num)
230
int fd = * ((int* ) key);
233
return (fd % (int)slots_num);
237
* sh_init() creates a new socket hash and returns the handle for it.
239
* Quote from README.multi_socket:
241
* "Some tests at 7000 and 9000 connections showed that the socket hash lookup
242
* is somewhat of a bottle neck. Its current implementation may be a bit too
243
* limiting. It simply has a fixed-size array, and on each entry in the array
244
* it has a linked list with entries. So the hash only checks which list to
245
* scan through. The code I had used so for used a list with merely 7 slots
246
* (as that is what the DNS hash uses) but with 7000 connections that would
247
* make an average of 1000 nodes in each list to run through. I upped that to
248
* 97 slots (I believe a prime is suitable) and noticed a significant speed
249
* increase. I need to reconsider the hash implementation or use a rather
250
* large default value like this. At 9000 connections I was still below 10us
254
static struct curl_hash *sh_init(void)
256
return Curl_hash_alloc(CURL_SOCKET_HASH_TABLE_SIZE, hash_fd, fd_key_compare,
263
* Called when a transfer is completed. Adds the given msg pointer to
264
* the list kept in the multi handle.
266
static CURLMcode multi_addmsg(struct Curl_multi *multi,
267
struct Curl_message *msg)
269
if(!Curl_llist_insert_next(multi->msglist, multi->msglist->tail, msg))
270
return CURLM_OUT_OF_MEMORY;
278
* Callback used by the llist system when a single list entry is destroyed.
280
static void multi_freeamsg(void *a, void *b)
286
CURLM *curl_multi_init(void)
288
struct Curl_multi *multi = calloc(1, sizeof(struct Curl_multi));
293
multi->type = CURL_MULTI_HANDLE;
295
multi->hostcache = Curl_mk_dnscache();
296
if(!multi->hostcache)
299
multi->sockhash = sh_init();
303
multi->conn_cache = Curl_conncache_init();
304
if(!multi->conn_cache)
307
multi->msglist = Curl_llist_alloc(multi_freeamsg);
311
/* Let's make the doubly-linked list a circular list. This makes
312
the linked list code simpler and allows inserting at the end
313
with less work (we didn't keep a tail pointer before). */
314
multi->easy.next = &multi->easy;
315
multi->easy.prev = &multi->easy;
317
return (CURLM *) multi;
321
Curl_hash_destroy(multi->sockhash);
322
multi->sockhash = NULL;
323
Curl_hash_destroy(multi->hostcache);
324
multi->hostcache = NULL;
325
Curl_conncache_destroy(multi->conn_cache);
326
multi->conn_cache = NULL;
332
CURLMcode curl_multi_add_handle(CURLM *multi_handle,
335
struct curl_llist *timeoutlist;
336
struct Curl_one_easy *easy;
337
struct Curl_multi *multi = (struct Curl_multi *)multi_handle;
338
struct SessionHandle *data = (struct SessionHandle *)easy_handle;
339
struct SessionHandle *new_closure = NULL;
340
struct curl_hash *hostcache = NULL;
342
/* First, make some basic checks that the CURLM handle is a good handle */
343
if(!GOOD_MULTI_HANDLE(multi))
344
return CURLM_BAD_HANDLE;
346
/* Verify that we got a somewhat good easy handle too */
347
if(!GOOD_EASY_HANDLE(easy_handle))
348
return CURLM_BAD_EASY_HANDLE;
350
/* Prevent users from adding same easy handle more than
351
once and prevent adding to more than one multi stack */
353
/* possibly we should create a new unique error code for this condition */
354
return CURLM_BAD_EASY_HANDLE;
356
/* Allocate and initialize timeout list for easy handle */
357
timeoutlist = Curl_llist_alloc(multi_freetimeout);
359
return CURLM_OUT_OF_MEMORY;
361
/* Allocate new node for the doubly-linked circular list of
362
Curl_one_easy structs that holds pointers to easy handles */
363
easy = calloc(1, sizeof(struct Curl_one_easy));
365
Curl_llist_destroy(timeoutlist, NULL);
366
return CURLM_OUT_OF_MEMORY;
369
/* In case multi handle has no hostcache yet, allocate one */
370
if(!multi->hostcache) {
371
hostcache = Curl_mk_dnscache();
374
Curl_llist_destroy(timeoutlist, NULL);
375
return CURLM_OUT_OF_MEMORY;
379
/* In case multi handle has no closure_handle yet, allocate
380
a new easy handle to use when closing cached connections */
381
if(!multi->closure_handle) {
382
new_closure = (struct SessionHandle *)curl_easy_init();
384
Curl_hash_destroy(hostcache);
386
Curl_llist_destroy(timeoutlist, NULL);
387
return CURLM_OUT_OF_MEMORY;
392
** No failure allowed in this function beyond this point. And
393
** no modification of easy nor multi handle allowed before this
394
** except for potential multi's connection cache growing which
395
** won't be undone in this function no matter what.
398
/* In case a new closure handle has been initialized above, it
399
is associated now with the multi handle which lacked one. */
401
multi->closure_handle = new_closure;
402
Curl_easy_addmulti(multi->closure_handle, multi_handle);
403
multi->closure_handle->state.conn_cache = multi->conn_cache;
406
/* In case hostcache has been allocated above,
407
it is associated now with the multi handle. */
409
multi->hostcache = hostcache;
411
/* Make easy handle use timeout list initialized above */
412
data->state.timeoutlist = timeoutlist;
415
/* set the easy handle */
416
easy->easy_handle = data;
417
multistate(easy, CURLM_STATE_INIT);
419
/* set the back pointer to one_easy to assist in removal */
420
easy->easy_handle->multi_pos = easy;
422
/* for multi interface connections, we share DNS cache automatically if the
423
easy handle's one is currently not set. */
424
if(!easy->easy_handle->dns.hostcache ||
425
(easy->easy_handle->dns.hostcachetype == HCACHE_NONE)) {
426
easy->easy_handle->dns.hostcache = multi->hostcache;
427
easy->easy_handle->dns.hostcachetype = HCACHE_MULTI;
430
/* Point to the multi's connection cache */
431
easy->easy_handle->state.conn_cache = multi->conn_cache;
433
/* This adds the new entry at the 'end' of the doubly-linked circular
434
list of Curl_one_easy structs to try and maintain a FIFO queue so
435
the pipelined requests are in order. */
437
/* We add this new entry last in the list. We make our 'next' point to the
438
'first' struct and our 'prev' point to the previous 'prev' */
439
easy->next = &multi->easy;
440
easy->prev = multi->easy.prev;
442
/* make 'easy' the last node in the chain */
443
multi->easy.prev = easy;
445
/* if there was a prev node, make sure its 'next' pointer links to
447
easy->prev->next = easy;
449
/* make the SessionHandle refer back to this multi handle */
450
Curl_easy_addmulti(easy_handle, multi_handle);
452
/* make the SessionHandle struct refer back to this struct */
453
easy->easy_handle->set.one_easy = easy;
455
/* Set the timeout for this handle to expire really soon so that it will
456
be taken care of even when this handle is added in the midst of operation
457
when only the curl_multi_socket() API is used. During that flow, only
458
sockets that time-out or have actions will be dealt with. Since this
459
handle has no action yet, we make sure it times out to get things to
461
Curl_expire(easy->easy_handle, 1);
463
/* increase the node-counter */
466
/* increase the alive-counter */
469
/* A somewhat crude work-around for a little glitch in update_timer() that
470
happens if the lastcall time is set to the same time when the handle is
471
removed as when the next handle is added, as then the check in
472
update_timer() that prevents calling the application multiple times with
473
the same timer infor will not trigger and then the new handle's timeout
474
will not be notified to the app.
476
The work-around is thus simply to clear the 'lastcall' variable to force
477
update_timer() to always trigger a callback to the app when a new easy
479
memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall));
486
/* Debug-function, used like this:
488
* Curl_hash_print(multi->sockhash, debug_print_sock_hash);
490
* Enable the hash print function first by editing hash.c
492
static void debug_print_sock_hash(void *p)
494
struct Curl_sh_entry *sh = (struct Curl_sh_entry *)p;
496
fprintf(stderr, " [easy %p/magic %x/socket %d]",
497
(void *)sh->easy, sh->easy->magic, (int)sh->socket);
501
CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
504
struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
505
struct Curl_one_easy *easy;
506
struct SessionHandle *data = curl_handle;
508
/* First, make some basic checks that the CURLM handle is a good handle */
509
if(!GOOD_MULTI_HANDLE(multi))
510
return CURLM_BAD_HANDLE;
512
/* Verify that we got a somewhat good easy handle too */
513
if(!GOOD_EASY_HANDLE(curl_handle))
514
return CURLM_BAD_EASY_HANDLE;
516
/* pick-up from the 'curl_handle' the kept position in the list */
517
easy = data->multi_pos;
520
bool premature = (easy->state < CURLM_STATE_COMPLETED) ? TRUE : FALSE;
521
bool easy_owns_conn = (easy->easy_conn &&
522
(easy->easy_conn->data == easy->easy_handle)) ?
525
/* If the 'state' is not INIT or COMPLETED, we might need to do something
526
nice to put the easy_handle in a good known state when this returns. */
528
/* this handle is "alive" so we need to count down the total number of
529
alive connections when this is removed */
532
if(easy->easy_conn &&
533
(easy->easy_conn->send_pipe->size +
534
easy->easy_conn->recv_pipe->size > 1) &&
535
easy->state > CURLM_STATE_WAITDO &&
536
easy->state < CURLM_STATE_COMPLETED) {
537
/* If the handle is in a pipeline and has started sending off its
538
request but not received its response yet, we need to close
540
easy->easy_conn->bits.close = TRUE;
541
/* Set connection owner so that Curl_done() closes it.
542
We can sefely do this here since connection is killed. */
543
easy->easy_conn->data = easy->easy_handle;
546
/* The timer must be shut down before easy->multi is set to NULL,
547
else the timenode will remain in the splay tree after
548
curl_easy_cleanup is called. */
549
Curl_expire(easy->easy_handle, 0);
551
/* destroy the timeout list that is held in the easy handle */
552
if(data->state.timeoutlist) {
553
Curl_llist_destroy(data->state.timeoutlist, NULL);
554
data->state.timeoutlist = NULL;
557
if(easy->easy_handle->dns.hostcachetype == HCACHE_MULTI) {
558
/* stop using the multi handle's DNS cache */
559
easy->easy_handle->dns.hostcache = NULL;
560
easy->easy_handle->dns.hostcachetype = HCACHE_NONE;
563
if(easy->easy_conn) {
565
/* we must call Curl_done() here (if we still "own it") so that we don't
566
leave a half-baked one around */
569
/* Curl_done() clears the conn->data field to lose the association
570
between the easy handle and the connection
572
Note that this ignores the return code simply because there's
573
nothing really useful to do with it anyway! */
574
(void)Curl_done(&easy->easy_conn, easy->result, premature);
577
/* Clear connection pipelines, if Curl_done above was not called */
578
Curl_getoff_all_pipelines(easy->easy_handle, easy->easy_conn);
581
/* as this was using a shared connection cache we clear the pointer
582
to that since we're not part of that multi handle anymore */
583
easy->easy_handle->state.conn_cache = NULL;
585
/* change state without using multistate(), only to make singlesocket() do
587
easy->state = CURLM_STATE_COMPLETED;
588
singlesocket(multi, easy); /* to let the application know what sockets
589
that vanish with this handle */
591
/* Remove the association between the connection and the handle */
592
if(easy->easy_conn) {
593
easy->easy_conn->data = NULL;
594
easy->easy_conn = NULL;
597
Curl_easy_addmulti(easy->easy_handle, NULL); /* clear the association
598
to this multi handle */
601
/* make sure there's no pending message in the queue sent from this easy
603
struct curl_llist_element *e;
605
for(e = multi->msglist->head; e; e = e->next) {
606
struct Curl_message *msg = e->ptr;
608
if(msg->extmsg.easy_handle == easy->easy_handle) {
609
Curl_llist_remove(multi->msglist, e, NULL);
610
/* there can only be one from this specific handle */
616
/* make the previous node point to our next */
618
easy->prev->next = easy->next;
619
/* make our next point to our previous node */
621
easy->next->prev = easy->prev;
623
easy->easy_handle->set.one_easy = NULL; /* detached */
625
/* Null the position in the controlling structure */
626
easy->easy_handle->multi_pos = NULL;
629
We do not touch the easy handle here! */
632
multi->num_easy--; /* one less to care about now */
638
return CURLM_BAD_EASY_HANDLE; /* twasn't found */
641
bool Curl_multi_canPipeline(const struct Curl_multi* multi)
643
return multi->pipelining_enabled;
646
void Curl_multi_handlePipeBreak(struct SessionHandle *data)
648
struct Curl_one_easy *one_easy = data->set.one_easy;
651
one_easy->easy_conn = NULL;
654
static int waitconnect_getsock(struct connectdata *conn,
659
return GETSOCK_BLANK;
661
sock[0] = conn->sock[FIRSTSOCKET];
663
/* when we've sent a CONNECT to a proxy, we should rather wait for the
664
socket to become readable to be able to get the response headers */
665
if(conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
666
return GETSOCK_READSOCK(0);
668
return GETSOCK_WRITESOCK(0);
671
static int domore_getsock(struct connectdata *conn,
672
curl_socket_t *socks,
675
if(conn && conn->handler->domore_getsock)
676
return conn->handler->domore_getsock(conn, socks, numsocks);
677
return GETSOCK_BLANK;
680
/* returns bitmapped flags for this handle and its sockets */
681
static int multi_getsock(struct Curl_one_easy *easy,
682
curl_socket_t *socks, /* points to numsocks number
686
/* If the pipe broke, or if there's no connection left for this easy handle,
687
then we MUST bail out now with no bitmask set. The no connection case can
688
happen when this is called from curl_multi_remove_handle() =>
689
singlesocket() => multi_getsock().
691
if(easy->easy_handle->state.pipe_broke || !easy->easy_conn)
694
if(easy->state > CURLM_STATE_CONNECT &&
695
easy->state < CURLM_STATE_COMPLETED) {
696
/* Set up ownership correctly */
697
easy->easy_conn->data = easy->easy_handle;
700
switch(easy->state) {
702
#if 0 /* switch back on these cases to get the compiler to check for all enums
704
case CURLM_STATE_TOOFAST: /* returns 0, so will not select. */
705
case CURLM_STATE_COMPLETED:
706
case CURLM_STATE_MSGSENT:
707
case CURLM_STATE_INIT:
708
case CURLM_STATE_CONNECT:
709
case CURLM_STATE_WAITDO:
710
case CURLM_STATE_DONE:
711
case CURLM_STATE_LAST:
712
/* this will get called with CURLM_STATE_COMPLETED when a handle is
717
case CURLM_STATE_WAITRESOLVE:
718
return Curl_resolver_getsock(easy->easy_conn, socks, numsocks);
720
case CURLM_STATE_PROTOCONNECT:
721
return Curl_protocol_getsock(easy->easy_conn, socks, numsocks);
724
case CURLM_STATE_DOING:
725
return Curl_doing_getsock(easy->easy_conn, socks, numsocks);
727
case CURLM_STATE_WAITPROXYCONNECT:
728
case CURLM_STATE_WAITCONNECT:
729
return waitconnect_getsock(easy->easy_conn, socks, numsocks);
731
case CURLM_STATE_DO_MORE:
732
return domore_getsock(easy->easy_conn, socks, numsocks);
734
case CURLM_STATE_DO_DONE: /* since is set after DO is completed, we switch
735
to waiting for the same as the *PERFORM
737
case CURLM_STATE_PERFORM:
738
case CURLM_STATE_WAITPERFORM:
739
return Curl_single_getsock(easy->easy_conn, socks, numsocks);
744
CURLMcode curl_multi_fdset(CURLM *multi_handle,
745
fd_set *read_fd_set, fd_set *write_fd_set,
746
fd_set *exc_fd_set, int *max_fd)
748
/* Scan through all the easy handles to get the file descriptors set.
749
Some easy handles may not have connected to the remote host yet,
750
and then we must make sure that is done. */
751
struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
752
struct Curl_one_easy *easy;
754
curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
757
(void)exc_fd_set; /* not used */
759
if(!GOOD_MULTI_HANDLE(multi))
760
return CURLM_BAD_HANDLE;
762
easy=multi->easy.next;
763
while(easy != &multi->easy) {
764
bitmap = multi_getsock(easy, sockbunch, MAX_SOCKSPEREASYHANDLE);
766
for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
767
curl_socket_t s = CURL_SOCKET_BAD;
769
if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK((sockbunch[i]))) {
770
FD_SET(sockbunch[i], read_fd_set);
773
if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK((sockbunch[i]))) {
774
FD_SET(sockbunch[i], write_fd_set);
777
if(s == CURL_SOCKET_BAD)
778
/* this socket is unused, break out of loop */
781
if((int)s > this_max_fd)
782
this_max_fd = (int)s;
786
easy = easy->next; /* check next handle */
789
*max_fd = this_max_fd;
794
CURLMcode curl_multi_wait(CURLM *multi_handle,
795
struct curl_waitfd extra_fds[],
796
unsigned int extra_nfds,
800
struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
801
struct Curl_one_easy *easy;
802
curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
805
unsigned int nfds = extra_nfds;
806
struct pollfd *ufds = NULL;
808
if(!GOOD_MULTI_HANDLE(multi))
809
return CURLM_BAD_HANDLE;
811
/* Count up how many fds we have from the multi handle */
812
easy=multi->easy.next;
813
while(easy != &multi->easy) {
814
bitmap = multi_getsock(easy, sockbunch, MAX_SOCKSPEREASYHANDLE);
816
for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
817
curl_socket_t s = CURL_SOCKET_BAD;
819
if(bitmap & GETSOCK_READSOCK(i)) {
823
if(bitmap & GETSOCK_WRITESOCK(i)) {
827
if(s == CURL_SOCKET_BAD) {
832
easy = easy->next; /* check next handle */
836
ufds = malloc(nfds * sizeof(struct pollfd));
838
return CURLM_OUT_OF_MEMORY;
842
/* Add the curl handles to our pollfds first */
843
easy=multi->easy.next;
844
while(easy != &multi->easy) {
845
bitmap = multi_getsock(easy, sockbunch, MAX_SOCKSPEREASYHANDLE);
847
for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
848
curl_socket_t s = CURL_SOCKET_BAD;
850
if(bitmap & GETSOCK_READSOCK(i)) {
851
ufds[nfds].fd = sockbunch[i];
852
ufds[nfds].events = POLLIN;
856
if(bitmap & GETSOCK_WRITESOCK(i)) {
857
ufds[nfds].fd = sockbunch[i];
858
ufds[nfds].events = POLLOUT;
862
if(s == CURL_SOCKET_BAD) {
867
easy = easy->next; /* check next handle */
870
/* Add external file descriptions from poll-like struct curl_waitfd */
871
for(i = 0; i < extra_nfds; i++) {
872
ufds[nfds].fd = extra_fds[i].fd;
873
ufds[nfds].events = 0;
874
if(extra_fds[i].events & CURL_WAIT_POLLIN)
875
ufds[nfds].events |= POLLIN;
876
if(extra_fds[i].events & CURL_WAIT_POLLPRI)
877
ufds[nfds].events |= POLLPRI;
878
if(extra_fds[i].events & CURL_WAIT_POLLOUT)
879
ufds[nfds].events |= POLLOUT;
885
i = Curl_poll(ufds, nfds, timeout_ms);
895
static CURLMcode multi_runsingle(struct Curl_multi *multi,
897
struct Curl_one_easy *easy)
899
struct Curl_message *msg = NULL;
902
bool protocol_connect = FALSE;
903
bool dophase_done = FALSE;
905
CURLMcode result = CURLM_OK;
906
struct SingleRequest *k;
907
struct SessionHandle *data;
910
if(!GOOD_EASY_HANDLE(easy->easy_handle))
911
return CURLM_BAD_EASY_HANDLE;
913
data = easy->easy_handle;
916
/* this is a single-iteration do-while loop just to allow a
917
break to skip to the end of it */
918
bool disconnect_conn = FALSE;
920
/* Handle the case when the pipe breaks, i.e., the connection
921
we're using gets cleaned up and we're left with nothing. */
922
if(data->state.pipe_broke) {
923
infof(data, "Pipe broke: handle 0x%p, url = %s\n",
924
easy, data->state.path);
926
if(easy->state < CURLM_STATE_COMPLETED) {
927
/* Head back to the CONNECT state */
928
multistate(easy, CURLM_STATE_CONNECT);
929
result = CURLM_CALL_MULTI_PERFORM;
930
easy->result = CURLE_OK;
933
data->state.pipe_broke = FALSE;
934
easy->easy_conn = NULL;
938
if(!easy->easy_conn &&
939
easy->state > CURLM_STATE_CONNECT &&
940
easy->state < CURLM_STATE_DONE) {
941
/* In all these states, the code will blindly access 'easy->easy_conn'
942
so this is precaution that it isn't NULL. And it silences static
944
failf(data, "In state %d with no easy_conn, bail out!\n", easy->state);
945
return CURLM_INTERNAL_ERROR;
948
if(easy->easy_conn && easy->state > CURLM_STATE_CONNECT &&
949
easy->state < CURLM_STATE_COMPLETED)
950
/* Make sure we set the connection's current owner */
951
easy->easy_conn->data = data;
953
if(easy->easy_conn &&
954
(easy->state >= CURLM_STATE_CONNECT) &&
955
(easy->state < CURLM_STATE_COMPLETED)) {
956
/* we need to wait for the connect state as only then is the start time
957
stored, but we must not check already completed handles */
959
timeout_ms = Curl_timeleft(data, &now,
960
(easy->state <= CURLM_STATE_WAITDO)?
964
/* Handle timed out */
965
if(easy->state == CURLM_STATE_WAITRESOLVE)
966
failf(data, "Resolving timed out after %ld milliseconds",
967
Curl_tvdiff(now, data->progress.t_startsingle));
968
else if(easy->state == CURLM_STATE_WAITCONNECT)
969
failf(data, "Connection timed out after %ld milliseconds",
970
Curl_tvdiff(now, data->progress.t_startsingle));
973
failf(data, "Operation timed out after %ld milliseconds with %"
974
FORMAT_OFF_T " out of %" FORMAT_OFF_T " bytes received",
975
Curl_tvdiff(now, data->progress.t_startsingle), k->bytecount,
979
/* Force the connection closed because the server could continue to
980
send us stuff at any time. (The disconnect_conn logic used below
981
doesn't work at this point). */
982
easy->easy_conn->bits.close = TRUE;
983
easy->result = CURLE_OPERATION_TIMEDOUT;
984
multistate(easy, CURLM_STATE_COMPLETED);
989
switch(easy->state) {
990
case CURLM_STATE_INIT:
991
/* init this transfer. */
992
easy->result=Curl_pretransfer(data);
994
if(CURLE_OK == easy->result) {
995
/* after init, go CONNECT */
996
multistate(easy, CURLM_STATE_CONNECT);
997
result = CURLM_CALL_MULTI_PERFORM;
1001
case CURLM_STATE_CONNECT:
1002
/* Connect. We get a connection identifier filled in. */
1003
Curl_pgrsTime(data, TIMER_STARTSINGLE);
1004
easy->result = Curl_connect(data, &easy->easy_conn,
1005
&async, &protocol_connect);
1007
if(CURLE_OK == easy->result) {
1008
/* Add this handle to the send or pend pipeline */
1009
easy->result = addHandleToSendOrPendPipeline(data,
1011
if(CURLE_OK != easy->result)
1012
disconnect_conn = TRUE;
1015
/* We're now waiting for an asynchronous name lookup */
1016
multistate(easy, CURLM_STATE_WAITRESOLVE);
1018
/* after the connect has been sent off, go WAITCONNECT unless the
1019
protocol connect is already done and we can go directly to
1021
result = CURLM_CALL_MULTI_PERFORM;
1023
if(protocol_connect)
1024
multistate(easy, multi->pipelining_enabled?
1025
CURLM_STATE_WAITDO:CURLM_STATE_DO);
1027
#ifndef CURL_DISABLE_HTTP
1028
if(easy->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
1029
multistate(easy, CURLM_STATE_WAITPROXYCONNECT);
1032
multistate(easy, CURLM_STATE_WAITCONNECT);
1039
case CURLM_STATE_WAITRESOLVE:
1040
/* awaiting an asynch name resolve to complete */
1042
struct Curl_dns_entry *dns = NULL;
1044
/* check if we have the name resolved by now */
1045
easy->result = Curl_resolver_is_resolved(easy->easy_conn, &dns);
1047
/* Update sockets here, because the socket(s) may have been
1048
closed and the application thus needs to be told, even if it
1049
is likely that the same socket(s) will again be used further
1050
down. If the name has not yet been resolved, it is likely
1051
that new sockets have been opened in an attempt to contact
1052
another resolver. */
1053
singlesocket(multi, easy);
1056
/* Perform the next step in the connection phase, and then move on
1057
to the WAITCONNECT state */
1058
easy->result = Curl_async_resolved(easy->easy_conn,
1061
if(CURLE_OK != easy->result)
1062
/* if Curl_async_resolved() returns failure, the connection struct
1063
is already freed and gone */
1064
easy->easy_conn = NULL; /* no more connection */
1066
/* call again please so that we get the next socket setup */
1067
result = CURLM_CALL_MULTI_PERFORM;
1068
if(protocol_connect)
1069
multistate(easy, multi->pipelining_enabled?
1070
CURLM_STATE_WAITDO:CURLM_STATE_DO);
1072
#ifndef CURL_DISABLE_HTTP
1073
if(easy->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
1074
multistate(easy, CURLM_STATE_WAITPROXYCONNECT);
1077
multistate(easy, CURLM_STATE_WAITCONNECT);
1082
if(CURLE_OK != easy->result) {
1083
/* failure detected */
1084
disconnect_conn = TRUE;
1090
#ifndef CURL_DISABLE_HTTP
1091
case CURLM_STATE_WAITPROXYCONNECT:
1092
/* this is HTTP-specific, but sending CONNECT to a proxy is HTTP... */
1093
easy->result = Curl_http_connect(easy->easy_conn, &protocol_connect);
1095
if(easy->easy_conn->bits.proxy_connect_closed) {
1096
/* reset the error buffer */
1097
if(data->set.errorbuffer)
1098
data->set.errorbuffer[0] = '\0';
1099
data->state.errorbuf = FALSE;
1101
easy->result = CURLE_OK;
1102
result = CURLM_CALL_MULTI_PERFORM;
1103
multistate(easy, CURLM_STATE_CONNECT);
1105
else if(CURLE_OK == easy->result) {
1106
if(easy->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_COMPLETE)
1107
multistate(easy, CURLM_STATE_WAITCONNECT);
1112
case CURLM_STATE_WAITCONNECT:
1113
/* awaiting a completion of an asynch connect */
1114
easy->result = Curl_is_connected(easy->easy_conn,
1120
/* if everything is still fine we do the protocol-specific connect
1122
easy->result = Curl_protocol_connect(easy->easy_conn,
1126
if(CURLE_OK != easy->result) {
1127
/* failure detected */
1128
/* Just break, the cleaning up is handled all in one place */
1129
disconnect_conn = TRUE;
1134
if(!protocol_connect) {
1135
/* We have a TCP connection, but 'protocol_connect' may be false
1136
and then we continue to 'STATE_PROTOCONNECT'. If protocol
1137
connect is TRUE, we move on to STATE_DO.
1138
BUT if we are using a proxy we must change to WAITPROXYCONNECT
1140
#ifndef CURL_DISABLE_HTTP
1141
if(easy->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
1142
multistate(easy, CURLM_STATE_WAITPROXYCONNECT);
1145
multistate(easy, CURLM_STATE_PROTOCONNECT);
1149
/* after the connect has completed, go WAITDO or DO */
1150
multistate(easy, multi->pipelining_enabled?
1151
CURLM_STATE_WAITDO:CURLM_STATE_DO);
1153
result = CURLM_CALL_MULTI_PERFORM;
1157
case CURLM_STATE_PROTOCONNECT:
1158
/* protocol-specific connect phase */
1159
easy->result = Curl_protocol_connecting(easy->easy_conn,
1161
if((easy->result == CURLE_OK) && protocol_connect) {
1162
/* after the connect has completed, go WAITDO or DO */
1163
multistate(easy, multi->pipelining_enabled?
1164
CURLM_STATE_WAITDO:CURLM_STATE_DO);
1165
result = CURLM_CALL_MULTI_PERFORM;
1167
else if(easy->result) {
1168
/* failure detected */
1169
Curl_posttransfer(data);
1170
Curl_done(&easy->easy_conn, easy->result, TRUE);
1171
disconnect_conn = TRUE;
1175
case CURLM_STATE_WAITDO:
1176
/* Wait for our turn to DO when we're pipelining requests */
1178
infof(data, "WAITDO: Conn %ld send pipe %zu inuse %d athead %d\n",
1179
easy->easy_conn->connection_id,
1180
easy->easy_conn->send_pipe->size,
1181
easy->easy_conn->writechannel_inuse?1:0,
1182
isHandleAtHead(data,
1183
easy->easy_conn->send_pipe)?1:0);
1185
if(!easy->easy_conn->writechannel_inuse &&
1186
isHandleAtHead(data,
1187
easy->easy_conn->send_pipe)) {
1188
/* Grab the channel */
1189
easy->easy_conn->writechannel_inuse = TRUE;
1190
multistate(easy, CURLM_STATE_DO);
1191
result = CURLM_CALL_MULTI_PERFORM;
1195
case CURLM_STATE_DO:
1196
if(data->set.connect_only) {
1197
/* keep connection open for application to use the socket */
1198
easy->easy_conn->bits.close = FALSE;
1199
multistate(easy, CURLM_STATE_DONE);
1200
easy->result = CURLE_OK;
1201
result = CURLM_CALL_MULTI_PERFORM;
1204
/* Perform the protocol's DO action */
1205
easy->result = Curl_do(&easy->easy_conn,
1208
if(CURLE_OK == easy->result) {
1210
/* some steps needed for wildcard matching */
1211
if(data->set.wildcardmatch) {
1212
struct WildcardData *wc = &data->wildcard;
1213
if(wc->state == CURLWC_DONE || wc->state == CURLWC_SKIP) {
1214
/* skip some states if it is important */
1215
Curl_done(&easy->easy_conn, CURLE_OK, FALSE);
1216
multistate(easy, CURLM_STATE_DONE);
1217
result = CURLM_CALL_MULTI_PERFORM;
1221
/* DO was not completed in one function call, we must continue
1223
multistate(easy, CURLM_STATE_DOING);
1227
/* after DO, go DO_DONE... or DO_MORE */
1228
else if(easy->easy_conn->bits.do_more) {
1229
/* we're supposed to do more, but we need to sit down, relax
1230
and wait a little while first */
1231
multistate(easy, CURLM_STATE_DO_MORE);
1235
/* we're done with the DO, now DO_DONE */
1236
multistate(easy, CURLM_STATE_DO_DONE);
1237
result = CURLM_CALL_MULTI_PERFORM;
1240
else if((CURLE_SEND_ERROR == easy->result) &&
1241
easy->easy_conn->bits.reuse) {
1243
* In this situation, a connection that we were trying to use
1244
* may have unexpectedly died. If possible, send the connection
1245
* back to the CONNECT phase so we can try again.
1247
char *newurl = NULL;
1248
followtype follow=FOLLOW_NONE;
1252
drc = Curl_retry_request(easy->easy_conn, &newurl);
1254
/* a failure here pretty much implies an out of memory */
1256
disconnect_conn = TRUE;
1259
retry = (newurl)?TRUE:FALSE;
1261
Curl_posttransfer(data);
1262
drc = Curl_done(&easy->easy_conn, easy->result, FALSE);
1264
/* When set to retry the connection, we must to go back to
1265
* the CONNECT state */
1267
if((drc == CURLE_OK) || (drc == CURLE_SEND_ERROR)) {
1268
follow = FOLLOW_RETRY;
1269
drc = Curl_follow(data, newurl, follow);
1270
if(drc == CURLE_OK) {
1271
multistate(easy, CURLM_STATE_CONNECT);
1272
result = CURLM_CALL_MULTI_PERFORM;
1273
easy->result = CURLE_OK;
1282
/* done didn't return OK or SEND_ERROR */
1288
/* Have error handler disconnect conn if we can't retry */
1289
disconnect_conn = TRUE;
1293
/* failure detected */
1294
Curl_posttransfer(data);
1295
Curl_done(&easy->easy_conn, easy->result, FALSE);
1296
disconnect_conn = TRUE;
1301
case CURLM_STATE_DOING:
1302
/* we continue DOING until the DO phase is complete */
1303
easy->result = Curl_protocol_doing(easy->easy_conn,
1305
if(CURLE_OK == easy->result) {
1307
/* after DO, go DO_DONE or DO_MORE */
1308
multistate(easy, easy->easy_conn->bits.do_more?
1309
CURLM_STATE_DO_MORE:
1310
CURLM_STATE_DO_DONE);
1311
result = CURLM_CALL_MULTI_PERFORM;
1312
} /* dophase_done */
1315
/* failure detected */
1316
Curl_posttransfer(data);
1317
Curl_done(&easy->easy_conn, easy->result, FALSE);
1318
disconnect_conn = TRUE;
1322
case CURLM_STATE_DO_MORE:
1324
* When we are connected, DO MORE and then go DO_DONE
1326
easy->result = Curl_do_more(easy->easy_conn, &dophase_done);
1328
/* No need to remove this handle from the send pipeline here since that
1329
is done in Curl_done() */
1330
if(CURLE_OK == easy->result) {
1332
multistate(easy, CURLM_STATE_DO_DONE);
1333
result = CURLM_CALL_MULTI_PERFORM;
1336
/* stay in DO_MORE */
1340
/* failure detected */
1341
Curl_posttransfer(data);
1342
Curl_done(&easy->easy_conn, easy->result, FALSE);
1343
disconnect_conn = TRUE;
1347
case CURLM_STATE_DO_DONE:
1348
/* Move ourselves from the send to recv pipeline */
1349
moveHandleFromSendToRecvPipeline(data, easy->easy_conn);
1350
/* Check if we can move pending requests to send pipe */
1351
checkPendPipeline(easy->easy_conn);
1352
multistate(easy, CURLM_STATE_WAITPERFORM);
1353
result = CURLM_CALL_MULTI_PERFORM;
1356
case CURLM_STATE_WAITPERFORM:
1357
/* Wait for our turn to PERFORM */
1358
if(!easy->easy_conn->readchannel_inuse &&
1359
isHandleAtHead(data,
1360
easy->easy_conn->recv_pipe)) {
1361
/* Grab the channel */
1362
easy->easy_conn->readchannel_inuse = TRUE;
1363
multistate(easy, CURLM_STATE_PERFORM);
1364
result = CURLM_CALL_MULTI_PERFORM;
1368
infof(data, "WAITPERFORM: Conn %ld recv pipe %zu inuse %d athead %d\n",
1369
easy->easy_conn->connection_id,
1370
easy->easy_conn->recv_pipe->size,
1371
easy->easy_conn->readchannel_inuse?1:0,
1372
isHandleAtHead(data,
1373
easy->easy_conn->recv_pipe)?1:0);
1378
case CURLM_STATE_TOOFAST: /* limit-rate exceeded in either direction */
1379
/* if both rates are within spec, resume transfer */
1380
if(Curl_pgrsUpdate(easy->easy_conn))
1381
easy->result = CURLE_ABORTED_BY_CALLBACK;
1383
easy->result = Curl_speedcheck(data, now);
1385
if(( (data->set.max_send_speed == 0) ||
1386
(data->progress.ulspeed < data->set.max_send_speed )) &&
1387
( (data->set.max_recv_speed == 0) ||
1388
(data->progress.dlspeed < data->set.max_recv_speed)))
1389
multistate(easy, CURLM_STATE_PERFORM);
1392
case CURLM_STATE_PERFORM:
1394
char *newurl = NULL;
1397
/* check if over send speed */
1398
if((data->set.max_send_speed > 0) &&
1399
(data->progress.ulspeed > data->set.max_send_speed)) {
1402
multistate(easy, CURLM_STATE_TOOFAST);
1404
/* calculate upload rate-limitation timeout. */
1405
buffersize = (int)(data->set.buffer_size ?
1406
data->set.buffer_size : BUFSIZE);
1407
timeout_ms = Curl_sleep_time(data->set.max_send_speed,
1408
data->progress.ulspeed, buffersize);
1409
Curl_expire(data, timeout_ms);
1413
/* check if over recv speed */
1414
if((data->set.max_recv_speed > 0) &&
1415
(data->progress.dlspeed > data->set.max_recv_speed)) {
1418
multistate(easy, CURLM_STATE_TOOFAST);
1420
/* Calculate download rate-limitation timeout. */
1421
buffersize = (int)(data->set.buffer_size ?
1422
data->set.buffer_size : BUFSIZE);
1423
timeout_ms = Curl_sleep_time(data->set.max_recv_speed,
1424
data->progress.dlspeed, buffersize);
1425
Curl_expire(data, timeout_ms);
1429
/* read/write data if it is ready to do so */
1430
easy->result = Curl_readwrite(easy->easy_conn, &done);
1434
if(!(k->keepon & KEEP_RECV)) {
1435
/* We're done receiving */
1436
easy->easy_conn->readchannel_inuse = FALSE;
1439
if(!(k->keepon & KEEP_SEND)) {
1440
/* We're done sending */
1441
easy->easy_conn->writechannel_inuse = FALSE;
1444
if(done || (easy->result == CURLE_RECV_ERROR)) {
1445
/* If CURLE_RECV_ERROR happens early enough, we assume it was a race
1446
* condition and the server closed the re-used connection exactly when
1447
* we wanted to use it, so figure out if that is indeed the case.
1449
CURLcode ret = Curl_retry_request(easy->easy_conn, &newurl);
1451
retry = (newurl)?TRUE:FALSE;
1454
/* if we are to retry, set the result to OK and consider the
1456
easy->result = CURLE_OK;
1463
* The transfer phase returned error, we mark the connection to get
1464
* closed to prevent being re-used. This is because we can't possibly
1465
* know if the connection is in a good shape or not now. Unless it is
1466
* a protocol which uses two "channels" like FTP, as then the error
1467
* happened in the data connection.
1470
if(!(easy->easy_conn->handler->flags & PROTOPT_DUAL))
1471
easy->easy_conn->bits.close = TRUE;
1473
Curl_posttransfer(data);
1474
Curl_done(&easy->easy_conn, easy->result, FALSE);
1477
followtype follow=FOLLOW_NONE;
1479
/* call this even if the readwrite function returned error */
1480
Curl_posttransfer(data);
1482
/* we're no longer receiving */
1483
moveHandleFromRecvToDonePipeline(data,
1486
/* expire the new receiving pipeline head */
1487
if(easy->easy_conn->recv_pipe->head)
1488
Curl_expire(easy->easy_conn->recv_pipe->head->ptr, 1);
1490
/* Check if we can move pending requests to send pipe */
1491
checkPendPipeline(easy->easy_conn);
1493
/* When we follow redirects or is set to retry the connection, we must
1494
to go back to the CONNECT state */
1495
if(data->req.newurl || retry) {
1497
/* if the URL is a follow-location and not just a retried request
1498
then figure out the URL here */
1499
newurl = data->req.newurl;
1500
data->req.newurl = NULL;
1501
follow = FOLLOW_REDIR;
1504
follow = FOLLOW_RETRY;
1505
easy->result = Curl_done(&easy->easy_conn, CURLE_OK, FALSE);
1506
if(easy->result == CURLE_OK)
1507
easy->result = Curl_follow(data, newurl, follow);
1508
if(CURLE_OK == easy->result) {
1509
multistate(easy, CURLM_STATE_CONNECT);
1510
result = CURLM_CALL_MULTI_PERFORM;
1511
newurl = NULL; /* handed over the memory ownership to
1512
Curl_follow(), make sure we don't free() it
1517
/* after the transfer is done, go DONE */
1519
/* but first check to see if we got a location info even though we're
1520
not following redirects */
1521
if(data->req.location) {
1524
newurl = data->req.location;
1525
data->req.location = NULL;
1526
easy->result = Curl_follow(data, newurl, FOLLOW_FAKE);
1527
if(CURLE_OK == easy->result)
1528
newurl = NULL; /* allocation was handed over Curl_follow() */
1530
disconnect_conn = TRUE;
1533
multistate(easy, CURLM_STATE_DONE);
1534
result = CURLM_CALL_MULTI_PERFORM;
1543
case CURLM_STATE_DONE:
1545
if(easy->easy_conn) {
1546
/* Remove ourselves from the receive and done pipelines. Handle
1547
should be on one of these lists, depending upon how we got here. */
1548
Curl_removeHandleFromPipeline(data,
1549
easy->easy_conn->recv_pipe);
1550
Curl_removeHandleFromPipeline(data,
1551
easy->easy_conn->done_pipe);
1552
/* Check if we can move pending requests to send pipe */
1553
checkPendPipeline(easy->easy_conn);
1555
if(easy->easy_conn->bits.stream_was_rewound) {
1556
/* This request read past its response boundary so we quickly let
1557
the other requests consume those bytes since there is no
1558
guarantee that the socket will become active again */
1559
result = CURLM_CALL_MULTI_PERFORM;
1562
/* post-transfer command */
1563
easy->result = Curl_done(&easy->easy_conn, CURLE_OK, FALSE);
1565
* If there are other handles on the pipeline, Curl_done won't set
1566
* easy_conn to NULL. In such a case, curl_multi_remove_handle() can
1567
* access free'd data, if the connection is free'd and the handle
1568
* removed before we perform the processing in CURLM_STATE_COMPLETED
1571
easy->easy_conn = NULL;
1574
if(data->set.wildcardmatch) {
1575
if(data->wildcard.state != CURLWC_DONE) {
1576
/* if a wildcard is set and we are not ending -> lets start again
1577
with CURLM_STATE_INIT */
1578
result = CURLM_CALL_MULTI_PERFORM;
1579
multistate(easy, CURLM_STATE_INIT);
1584
/* after we have DONE what we're supposed to do, go COMPLETED, and
1585
it doesn't matter what the Curl_done() returned! */
1586
multistate(easy, CURLM_STATE_COMPLETED);
1590
case CURLM_STATE_COMPLETED:
1591
/* this is a completed transfer, it is likely to still be connected */
1593
/* This node should be delinked from the list now and we should post
1594
an information message that we are complete. */
1596
/* Important: reset the conn pointer so that we don't point to memory
1597
that could be freed anytime */
1598
easy->easy_conn = NULL;
1600
Curl_expire(data, 0); /* stop all timers */
1603
case CURLM_STATE_MSGSENT:
1604
return CURLM_OK; /* do nothing */
1607
return CURLM_INTERNAL_ERROR;
1610
if(easy->state < CURLM_STATE_COMPLETED) {
1611
if(CURLE_OK != easy->result) {
1613
* If an error was returned, and we aren't in completed state now,
1614
* then we go to completed and consider this transfer aborted.
1617
/* NOTE: no attempt to disconnect connections must be made
1618
in the case blocks above - cleanup happens only here */
1620
data->state.pipe_broke = FALSE;
1622
if(easy->easy_conn) {
1623
/* if this has a connection, unsubscribe from the pipelines */
1624
easy->easy_conn->writechannel_inuse = FALSE;
1625
easy->easy_conn->readchannel_inuse = FALSE;
1626
Curl_removeHandleFromPipeline(data,
1627
easy->easy_conn->send_pipe);
1628
Curl_removeHandleFromPipeline(data,
1629
easy->easy_conn->recv_pipe);
1630
Curl_removeHandleFromPipeline(data,
1631
easy->easy_conn->done_pipe);
1632
/* Check if we can move pending requests to send pipe */
1633
checkPendPipeline(easy->easy_conn);
1635
if(disconnect_conn) {
1636
/* disconnect properly */
1637
Curl_disconnect(easy->easy_conn, /* dead_connection */ FALSE);
1639
/* This is where we make sure that the easy_conn pointer is reset.
1640
We don't have to do this in every case block above where a
1641
failure is detected */
1642
easy->easy_conn = NULL;
1645
else if(easy->state == CURLM_STATE_CONNECT) {
1646
/* Curl_connect() failed */
1647
(void)Curl_posttransfer(data);
1650
multistate(easy, CURLM_STATE_COMPLETED);
1652
/* if there's still a connection to use, call the progress function */
1653
else if(easy->easy_conn && Curl_pgrsUpdate(easy->easy_conn)) {
1654
/* aborted due to progress callback return code must close the
1656
easy->easy_conn->bits.close = TRUE;
1658
/* if not yet in DONE state, go there, otherwise COMPLETED */
1659
multistate(easy, (easy->state < CURLM_STATE_DONE)?
1660
CURLM_STATE_DONE: CURLM_STATE_COMPLETED);
1661
result = CURLM_CALL_MULTI_PERFORM;
1664
} WHILE_FALSE; /* just to break out from! */
1666
if(CURLM_STATE_COMPLETED == easy->state) {
1667
/* now fill in the Curl_message with this info */
1670
msg->extmsg.msg = CURLMSG_DONE;
1671
msg->extmsg.easy_handle = data;
1672
msg->extmsg.data.result = easy->result;
1674
result = multi_addmsg(multi, msg);
1676
multistate(easy, CURLM_STATE_MSGSENT);
1683
CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
1685
struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1686
struct Curl_one_easy *easy;
1687
CURLMcode returncode=CURLM_OK;
1688
struct Curl_tree *t;
1689
struct timeval now = Curl_tvnow();
1691
if(!GOOD_MULTI_HANDLE(multi))
1692
return CURLM_BAD_HANDLE;
1694
easy=multi->easy.next;
1695
while(easy != &multi->easy) {
1697
struct WildcardData *wc = &easy->easy_handle->wildcard;
1699
if(easy->easy_handle->set.wildcardmatch) {
1701
CURLcode ret = Curl_wildcard_init(wc); /* init wildcard structures */
1703
return CURLM_OUT_OF_MEMORY;
1708
result = multi_runsingle(multi, now, easy);
1709
while(CURLM_CALL_MULTI_PERFORM == result);
1711
if(easy->easy_handle->set.wildcardmatch) {
1712
/* destruct wildcard structures if it is needed */
1713
if(wc->state == CURLWC_DONE || result)
1714
Curl_wildcard_dtor(wc);
1718
returncode = result;
1720
easy = easy->next; /* operate on next handle */
1724
* Simply remove all expired timers from the splay since handles are dealt
1725
* with unconditionally by this function and curl_multi_timeout() requires
1726
* that already passed/handled expire times are removed from the splay.
1728
* It is important that the 'now' value is set at the entry of this function
1729
* and not for the current time as it may have ticked a little while since
1730
* then and then we risk this loop to remove timers that actually have not
1734
multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
1736
/* the removed may have another timeout in queue */
1737
(void)add_next_timeout(now, multi, t->payload);
1741
*running_handles = multi->num_alive;
1743
if(CURLM_OK >= returncode)
1744
update_timer(multi);
1749
static void close_all_connections(struct Curl_multi *multi)
1751
struct connectdata *conn;
1753
conn = Curl_conncache_find_first_connection(multi->conn_cache);
1755
conn->data = multi->closure_handle;
1757
/* This will remove the connection from the cache */
1758
(void)Curl_disconnect(conn, FALSE);
1760
conn = Curl_conncache_find_first_connection(multi->conn_cache);
1764
CURLMcode curl_multi_cleanup(CURLM *multi_handle)
1766
struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1767
struct Curl_one_easy *easy;
1768
struct Curl_one_easy *nexteasy;
1770
if(GOOD_MULTI_HANDLE(multi)) {
1771
multi->type = 0; /* not good anymore */
1773
/* Close all the connections in the connection cache */
1774
close_all_connections(multi);
1776
multi->closure_handle->dns.hostcache = multi->hostcache;
1777
Curl_hostcache_clean(multi->closure_handle);
1779
Curl_close(multi->closure_handle);
1780
multi->closure_handle = NULL;
1782
Curl_hash_destroy(multi->sockhash);
1783
multi->sockhash = NULL;
1785
Curl_conncache_destroy(multi->conn_cache);
1786
multi->conn_cache = NULL;
1788
/* remove the pending list of messages */
1789
Curl_llist_destroy(multi->msglist, NULL);
1790
multi->msglist = NULL;
1792
/* remove all easy handles */
1793
easy = multi->easy.next;
1794
while(easy != &multi->easy) {
1795
nexteasy=easy->next;
1796
if(easy->easy_handle->dns.hostcachetype == HCACHE_MULTI) {
1797
/* clear out the usage of the shared DNS cache */
1798
Curl_hostcache_clean(easy->easy_handle);
1799
easy->easy_handle->dns.hostcache = NULL;
1800
easy->easy_handle->dns.hostcachetype = HCACHE_NONE;
1803
/* Clear the pointer to the connection cache */
1804
easy->easy_handle->state.conn_cache = NULL;
1806
Curl_easy_addmulti(easy->easy_handle, NULL); /* clear the association */
1812
Curl_hash_destroy(multi->hostcache);
1813
multi->hostcache = NULL;
1820
return CURLM_BAD_HANDLE;
1824
* curl_multi_info_read()
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).
1833
CURLMsg *curl_multi_info_read(CURLM *multi_handle, int *msgs_in_queue)
1835
struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1836
struct Curl_message *msg;
1838
*msgs_in_queue = 0; /* default to none */
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;
1844
/* extract the head of the list to return */
1845
e = multi->msglist->head;
1849
/* remove the extracted entry */
1850
Curl_llist_remove(multi->msglist, e, NULL);
1852
*msgs_in_queue = curlx_uztosi(Curl_llist_count(multi->msglist));
1854
return &msg->extmsg;
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.
1865
static void singlesocket(struct Curl_multi *multi,
1866
struct Curl_one_easy *easy)
1868
curl_socket_t socks[MAX_SOCKSPEREASYHANDLE];
1870
struct Curl_sh_entry *entry;
1873
unsigned int curraction;
1874
struct Curl_one_easy *easy_by_hash;
1875
bool remove_sock_from_hash;
1877
for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++)
1878
socks[i] = CURL_SOCKET_BAD;
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);
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 */
1888
/* walk over the sockets we got right now */
1889
for(i=0; (i< MAX_SOCKSPEREASYHANDLE) &&
1890
(curraction & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i)));
1892
int action = CURL_POLL_NONE;
1896
/* get it from the hash */
1897
entry = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
1899
if(curraction & GETSOCK_READSOCK(i))
1900
action |= CURL_POLL_IN;
1901
if(curraction & GETSOCK_WRITESOCK(i))
1902
action |= CURL_POLL_OUT;
1905
/* yeps, already present so check if it has the same action set */
1906
if(entry->action == action)
1907
/* same, continue */
1911
/* this is a socket we didn't have before, add it! */
1912
entry = sh_addentry(multi->sockhash, s, easy->easy_handle);
1918
/* we know (entry != NULL) at this point, see the logic above */
1919
if(multi->socket_cb)
1920
multi->socket_cb(easy->easy_handle,
1923
multi->socket_userp,
1926
entry->action = action; /* store the current action state */
1929
num = i; /* number of sockets */
1931
/* when we've walked over all the sockets we should have right now, we must
1932
make sure to detect sockets that are removed */
1933
for(i=0; i< easy->numsocks; i++) {
1935
s = easy->sockets[i];
1936
for(j=0; j<num; j++) {
1938
/* this is still supervised */
1939
s = CURL_SOCKET_BAD;
1943
if(s != CURL_SOCKET_BAD) {
1945
/* this socket has been removed. Tell the app to remove it */
1946
remove_sock_from_hash = TRUE;
1948
entry = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
1950
/* check if the socket to be removed serves a connection which has
1951
other easy-s in a pipeline. In this case the socket should not be
1953
struct connectdata *easy_conn;
1955
easy_by_hash = entry->easy->multi_pos;
1956
easy_conn = easy_by_hash->easy_conn;
1958
if(easy_conn->recv_pipe && easy_conn->recv_pipe->size > 1) {
1959
/* the handle should not be removed from the pipe yet */
1960
remove_sock_from_hash = FALSE;
1962
/* Update the sockhash entry to instead point to the next in line
1963
for the recv_pipe, or the first (in case this particular easy
1965
if(entry->easy == easy->easy_handle) {
1966
if(isHandleAtHead(easy->easy_handle, easy_conn->recv_pipe))
1967
entry->easy = easy_conn->recv_pipe->head->next->ptr;
1969
entry->easy = easy_conn->recv_pipe->head->ptr;
1972
if(easy_conn->send_pipe && easy_conn->send_pipe->size > 1) {
1973
/* the handle should not be removed from the pipe yet */
1974
remove_sock_from_hash = FALSE;
1976
/* Update the sockhash entry to instead point to the next in line
1977
for the send_pipe, or the first (in case this particular easy
1979
if(entry->easy == easy->easy_handle) {
1980
if(isHandleAtHead(easy->easy_handle, easy_conn->send_pipe))
1981
entry->easy = easy_conn->send_pipe->head->next->ptr;
1983
entry->easy = easy_conn->send_pipe->head->ptr;
1986
/* Don't worry about overwriting recv_pipe head with send_pipe_head,
1987
when action will be asked on the socket (see multi_socket()), the
1988
head of the correct pipe will be taken according to the
1993
/* just a precaution, this socket really SHOULD be in the hash already
1994
but in case it isn't, we don't have to tell the app to remove it
1995
either since it never got to know about it */
1996
remove_sock_from_hash = FALSE;
1998
if(remove_sock_from_hash) {
1999
/* in this case 'entry' is always non-NULL */
2000
if(multi->socket_cb)
2001
multi->socket_cb(easy->easy_handle,
2004
multi->socket_userp,
2006
sh_delentry(multi->sockhash, s);
2012
memcpy(easy->sockets, socks, num*sizeof(curl_socket_t));
2013
easy->numsocks = num;
2017
* add_next_timeout()
2019
* Each SessionHandle has a list of timeouts. The add_next_timeout() is called
2020
* when it has just been removed from the splay tree because the timeout has
2021
* expired. This function is then to advance in the list to pick the next
2022
* timeout to use (skip the already expired ones) and add this node back to
2023
* the splay tree again.
2025
* The splay tree only has each sessionhandle as a single node and the nearest
2026
* timeout is used to sort it on.
2028
static CURLMcode add_next_timeout(struct timeval now,
2029
struct Curl_multi *multi,
2030
struct SessionHandle *d)
2032
struct timeval *tv = &d->state.expiretime;
2033
struct curl_llist *list = d->state.timeoutlist;
2034
struct curl_llist_element *e;
2036
/* move over the timeout list for this specific handle and remove all
2037
timeouts that are now passed tense and store the next pending
2039
for(e = list->head; e; ) {
2040
struct curl_llist_element *n = e->next;
2041
long diff = curlx_tvdiff(*(struct timeval *)e->ptr, now);
2043
/* remove outdated entry */
2044
Curl_llist_remove(list, e, NULL);
2046
/* the list is sorted so get out on the first mismatch */
2052
/* clear the expire times within the handles that we remove from the
2058
/* copy the first entry to 'tv' */
2059
memcpy(tv, e->ptr, sizeof(*tv));
2061
/* remove first entry from list */
2062
Curl_llist_remove(list, e, NULL);
2064
/* insert this node again into the splay */
2065
multi->timetree = Curl_splayinsert(*tv, multi->timetree,
2066
&d->state.timenode);
2072
static CURLMcode multi_socket(struct Curl_multi *multi,
2076
int *running_handles)
2078
CURLMcode result = CURLM_OK;
2079
struct SessionHandle *data = NULL;
2080
struct Curl_tree *t;
2081
struct timeval now = Curl_tvnow();
2084
struct Curl_one_easy *easyp;
2085
/* *perform() deals with running_handles on its own */
2086
result = curl_multi_perform(multi, running_handles);
2088
/* walk through each easy handle and do the socket state change magic
2090
easyp=multi->easy.next;
2091
while(easyp != &multi->easy) {
2092
singlesocket(multi, easyp);
2093
easyp = easyp->next;
2096
/* or should we fall-through and do the timer-based stuff? */
2099
else if(s != CURL_SOCKET_TIMEOUT) {
2101
struct Curl_sh_entry *entry =
2102
Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
2105
/* Unmatched socket, we can't act on it but we ignore this fact. In
2106
real-world tests it has been proved that libevent can in fact give
2107
the application actions even though the socket was just previously
2108
asked to get removed, so thus we better survive stray socket actions
2109
and just move on. */
2114
if(data->magic != CURLEASY_MAGIC_NUMBER)
2115
/* bad bad bad bad bad bad bad */
2116
return CURLM_INTERNAL_ERROR;
2118
/* If the pipeline is enabled, take the handle which is in the head of
2119
the pipeline. If we should write into the socket, take the send_pipe
2120
head. If we should read from the socket, take the recv_pipe head. */
2121
if(data->set.one_easy->easy_conn) {
2122
if((ev_bitmask & CURL_POLL_OUT) &&
2123
data->set.one_easy->easy_conn->send_pipe &&
2124
data->set.one_easy->easy_conn->send_pipe->head)
2125
data = data->set.one_easy->easy_conn->send_pipe->head->ptr;
2126
else if((ev_bitmask & CURL_POLL_IN) &&
2127
data->set.one_easy->easy_conn->recv_pipe &&
2128
data->set.one_easy->easy_conn->recv_pipe->head)
2129
data = data->set.one_easy->easy_conn->recv_pipe->head->ptr;
2132
if(data->set.one_easy->easy_conn &&
2133
!(data->set.one_easy->easy_conn->handler->flags & PROTOPT_DIRLOCK))
2134
/* set socket event bitmask if they're not locked */
2135
data->set.one_easy->easy_conn->cselect_bits = ev_bitmask;
2138
result = multi_runsingle(multi, now, data->set.one_easy);
2139
while(CURLM_CALL_MULTI_PERFORM == result);
2141
if(data->set.one_easy->easy_conn &&
2142
!(data->set.one_easy->easy_conn->handler->flags & PROTOPT_DIRLOCK))
2143
/* clear the bitmask only if not locked */
2144
data->set.one_easy->easy_conn->cselect_bits = 0;
2146
if(CURLM_OK >= result)
2147
/* get the socket(s) and check if the state has been changed since
2149
singlesocket(multi, data->set.one_easy);
2151
/* Now we fall-through and do the timer-based stuff, since we don't want
2152
to force the user to have to deal with timeouts as long as at least
2153
one connection in fact has traffic. */
2155
data = NULL; /* set data to NULL again to avoid calling
2156
multi_runsingle() in case there's no need to */
2160
now.tv_usec += 40000; /* compensate for bad precision timers that might've
2161
triggered too early */
2162
if(now.tv_usec >= 1000000) {
2164
now.tv_usec -= 1000000;
2168
* The loop following here will go on as long as there are expire-times left
2169
* to process in the splay and 'data' will be re-assigned for every expired
2170
* handle we deal with.
2173
/* the first loop lap 'data' can be NULL */
2176
result = multi_runsingle(multi, now, data->set.one_easy);
2177
while(CURLM_CALL_MULTI_PERFORM == result);
2179
if(CURLM_OK >= result)
2180
/* get the socket(s) and check if the state has been changed since
2182
singlesocket(multi, data->set.one_easy);
2185
/* Check if there's one (more) expired timer to deal with! This function
2186
extracts a matching node if there is one */
2188
multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
2190
data = t->payload; /* assign this for next loop */
2191
(void)add_next_timeout(now, multi, t->payload);
2196
*running_handles = multi->num_alive;
2200
#undef curl_multi_setopt
2201
CURLMcode curl_multi_setopt(CURLM *multi_handle,
2202
CURLMoption option, ...)
2204
struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
2205
CURLMcode res = CURLM_OK;
2208
if(!GOOD_MULTI_HANDLE(multi))
2209
return CURLM_BAD_HANDLE;
2211
va_start(param, option);
2214
case CURLMOPT_SOCKETFUNCTION:
2215
multi->socket_cb = va_arg(param, curl_socket_callback);
2217
case CURLMOPT_SOCKETDATA:
2218
multi->socket_userp = va_arg(param, void *);
2220
case CURLMOPT_PIPELINING:
2221
multi->pipelining_enabled = (0 != va_arg(param, long)) ? TRUE : FALSE;
2223
case CURLMOPT_TIMERFUNCTION:
2224
multi->timer_cb = va_arg(param, curl_multi_timer_callback);
2226
case CURLMOPT_TIMERDATA:
2227
multi->timer_userp = va_arg(param, void *);
2229
case CURLMOPT_MAXCONNECTS:
2230
multi->maxconnects = va_arg(param, long);
2233
res = CURLM_UNKNOWN_OPTION;
2240
/* we define curl_multi_socket() in the public multi.h header */
2241
#undef curl_multi_socket
2243
CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s,
2244
int *running_handles)
2246
CURLMcode result = multi_socket((struct Curl_multi *)multi_handle, FALSE, s,
2247
0, running_handles);
2248
if(CURLM_OK >= result)
2249
update_timer((struct Curl_multi *)multi_handle);
2253
CURLMcode curl_multi_socket_action(CURLM *multi_handle, curl_socket_t s,
2254
int ev_bitmask, int *running_handles)
2256
CURLMcode result = multi_socket((struct Curl_multi *)multi_handle, FALSE, s,
2257
ev_bitmask, running_handles);
2258
if(CURLM_OK >= result)
2259
update_timer((struct Curl_multi *)multi_handle);
2263
CURLMcode curl_multi_socket_all(CURLM *multi_handle, int *running_handles)
2266
CURLMcode result = multi_socket((struct Curl_multi *)multi_handle,
2267
TRUE, CURL_SOCKET_BAD, 0, running_handles);
2268
if(CURLM_OK >= result)
2269
update_timer((struct Curl_multi *)multi_handle);
2273
static CURLMcode multi_timeout(struct Curl_multi *multi,
2276
static struct timeval tv_zero = {0,0};
2278
if(multi->timetree) {
2279
/* we have a tree of expire times */
2280
struct timeval now = Curl_tvnow();
2282
/* splay the lowest to the bottom */
2283
multi->timetree = Curl_splay(tv_zero, multi->timetree);
2285
if(Curl_splaycomparekeys(multi->timetree->key, now) > 0) {
2286
/* some time left before expiration */
2287
*timeout_ms = curlx_tvdiff(multi->timetree->key, now);
2290
* Since we only provide millisecond resolution on the returned value
2291
* and the diff might be less than one millisecond here, we don't
2292
* return zero as that may cause short bursts of busyloops on fast
2293
* processors while the diff is still present but less than one
2294
* millisecond! instead we return 1 until the time is ripe.
2299
/* 0 means immediately */
2308
CURLMcode curl_multi_timeout(CURLM *multi_handle,
2311
struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
2313
/* First, make some basic checks that the CURLM handle is a good handle */
2314
if(!GOOD_MULTI_HANDLE(multi))
2315
return CURLM_BAD_HANDLE;
2317
return multi_timeout(multi, timeout_ms);
2321
* Tell the application it should update its timers, if it subscribes to the
2322
* update timer callback.
2324
static int update_timer(struct Curl_multi *multi)
2328
if(!multi->timer_cb)
2330
if(multi_timeout(multi, &timeout_ms)) {
2333
if(timeout_ms < 0) {
2334
static const struct timeval none={0,0};
2335
if(Curl_splaycomparekeys(none, multi->timer_lastcall)) {
2336
multi->timer_lastcall = none;
2337
/* there's no timeout now but there was one previously, tell the app to
2339
return multi->timer_cb((CURLM*)multi, -1, multi->timer_userp);
2344
/* When multi_timeout() is done, multi->timetree points to the node with the
2345
* timeout we got the (relative) time-out time for. We can thus easily check
2346
* if this is the same (fixed) time as we got in a previous call and then
2347
* avoid calling the callback again. */
2348
if(Curl_splaycomparekeys(multi->timetree->key, multi->timer_lastcall) == 0)
2351
multi->timer_lastcall = multi->timetree->key;
2353
return multi->timer_cb((CURLM*)multi, timeout_ms, multi->timer_userp);
2356
static CURLcode addHandleToSendOrPendPipeline(struct SessionHandle *handle,
2357
struct connectdata *conn)
2359
size_t pipeLen = conn->send_pipe->size + conn->recv_pipe->size;
2360
struct curl_llist_element *sendhead = conn->send_pipe->head;
2361
struct curl_llist *pipeline;
2364
if(!Curl_isPipeliningEnabled(handle) ||
2366
pipeline = conn->send_pipe;
2368
if(conn->server_supports_pipelining &&
2369
pipeLen < MAX_PIPELINE_LENGTH)
2370
pipeline = conn->send_pipe;
2372
pipeline = conn->pend_pipe;
2375
rc = Curl_addHandleToPipeline(handle, pipeline);
2377
if(pipeline == conn->send_pipe && sendhead != conn->send_pipe->head) {
2378
/* this is a new one as head, expire it */
2379
conn->writechannel_inuse = FALSE; /* not in use yet */
2381
infof(conn->data, "%p is at send pipe head!\n",
2382
conn->send_pipe->head->ptr);
2384
Curl_expire(conn->send_pipe->head->ptr, 1);
2390
static int checkPendPipeline(struct connectdata *conn)
2393
struct curl_llist_element *sendhead = conn->send_pipe->head;
2395
size_t pipeLen = conn->send_pipe->size + conn->recv_pipe->size;
2396
if(conn->server_supports_pipelining || pipeLen == 0) {
2397
struct curl_llist_element *curr = conn->pend_pipe->head;
2398
const size_t maxPipeLen =
2399
conn->server_supports_pipelining ? MAX_PIPELINE_LENGTH : 1;
2401
while(pipeLen < maxPipeLen && curr) {
2402
Curl_llist_move(conn->pend_pipe, curr,
2403
conn->send_pipe, conn->send_pipe->tail);
2404
Curl_pgrsTime(curr->ptr, TIMER_PRETRANSFER);
2405
++result; /* count how many handles we moved */
2406
curr = conn->pend_pipe->head;
2412
conn->now = Curl_tvnow();
2413
/* something moved, check for a new send pipeline leader */
2414
if(sendhead != conn->send_pipe->head) {
2415
/* this is a new one as head, expire it */
2416
conn->writechannel_inuse = FALSE; /* not in use yet */
2418
infof(conn->data, "%p is at send pipe head!\n",
2419
conn->send_pipe->head->ptr);
2421
Curl_expire(conn->send_pipe->head->ptr, 1);
2428
/* Move this transfer from the sending list to the receiving list.
2430
Pay special attention to the new sending list "leader" as it needs to get
2431
checked to update what sockets it acts on.
2434
static void moveHandleFromSendToRecvPipeline(struct SessionHandle *handle,
2435
struct connectdata *conn)
2437
struct curl_llist_element *curr;
2439
curr = conn->send_pipe->head;
2441
if(curr->ptr == handle) {
2442
Curl_llist_move(conn->send_pipe, curr,
2443
conn->recv_pipe, conn->recv_pipe->tail);
2445
if(conn->send_pipe->head) {
2446
/* Since there's a new easy handle at the start of the send pipeline,
2447
set its timeout value to 1ms to make it trigger instantly */
2448
conn->writechannel_inuse = FALSE; /* not used now */
2450
infof(conn->data, "%p is at send pipe head B!\n",
2451
conn->send_pipe->head->ptr);
2453
Curl_expire(conn->send_pipe->head->ptr, 1);
2456
/* The receiver's list is not really interesting here since either this
2457
handle is now first in the list and we'll deal with it soon, or
2458
another handle is already first and thus is already taken care of */
2460
break; /* we're done! */
2466
static void moveHandleFromRecvToDonePipeline(struct SessionHandle *handle,
2467
struct connectdata *conn)
2469
struct curl_llist_element *curr;
2471
curr = conn->recv_pipe->head;
2473
if(curr->ptr == handle) {
2474
Curl_llist_move(conn->recv_pipe, curr,
2475
conn->done_pipe, conn->done_pipe->tail);
2481
static bool isHandleAtHead(struct SessionHandle *handle,
2482
struct curl_llist *pipeline)
2484
struct curl_llist_element *curr = pipeline->head;
2486
return (curr->ptr == handle) ? TRUE : FALSE;
2492
* multi_freetimeout()
2494
* Callback used by the llist system when a single timeout list entry is
2497
static void multi_freetimeout(void *user, void *entryptr)
2501
/* the entry was plain malloc()'ed */
2506
* multi_addtimeout()
2508
* Add a timestamp to the list of timeouts. Keep the list sorted so that head
2509
* of list is always the timeout nearest in time.
2513
multi_addtimeout(struct curl_llist *timeoutlist,
2514
struct timeval *stamp)
2516
struct curl_llist_element *e;
2517
struct timeval *timedup;
2518
struct curl_llist_element *prev = NULL;
2520
timedup = malloc(sizeof(*timedup));
2522
return CURLM_OUT_OF_MEMORY;
2524
/* copy the timestamp */
2525
memcpy(timedup, stamp, sizeof(*timedup));
2527
if(Curl_llist_count(timeoutlist)) {
2528
/* find the correct spot in the list */
2529
for(e = timeoutlist->head; e; e = e->next) {
2530
struct timeval *checktime = e->ptr;
2531
long diff = curlx_tvdiff(*checktime, *timedup);
2539
this is the first timeout on the list */
2541
if(!Curl_llist_insert_next(timeoutlist, prev, timedup)) {
2543
return CURLM_OUT_OF_MEMORY;
2552
* given a number of milliseconds from now to use to set the 'act before
2553
* this'-time for the transfer, to be extracted by curl_multi_timeout()
2555
* Note that the timeout will be added to a queue of timeouts if it defines a
2556
* moment in time that is later than the current head of queue.
2558
* Pass zero to clear all timeout values for this handle.
2560
void Curl_expire(struct SessionHandle *data, long milli)
2562
struct Curl_multi *multi = data->multi;
2563
struct timeval *nowp = &data->state.expiretime;
2566
/* this is only interesting for multi-interface using libcurl, and only
2567
while there is still a multi interface struct remaining! */
2572
/* No timeout, clear the time data. */
2573
if(nowp->tv_sec || nowp->tv_usec) {
2574
/* Since this is an cleared time, we must remove the previous entry from
2576
struct curl_llist *list = data->state.timeoutlist;
2578
rc = Curl_splayremovebyaddr(multi->timetree,
2579
&data->state.timenode,
2582
infof(data, "Internal error clearing splay node = %d\n", rc);
2584
/* flush the timeout list too */
2585
while(list->size > 0)
2586
Curl_llist_remove(list, list->tail, NULL);
2589
infof(data, "Expire cleared\n");
2599
set.tv_sec += milli/1000;
2600
set.tv_usec += (milli%1000)*1000;
2602
if(set.tv_usec >= 1000000) {
2604
set.tv_usec -= 1000000;
2607
if(nowp->tv_sec || nowp->tv_usec) {
2608
/* This means that the struct is added as a node in the splay tree.
2609
Compare if the new time is earlier, and only remove-old/add-new if it
2611
long diff = curlx_tvdiff(set, *nowp);
2613
/* the new expire time was later so just add it to the queue
2615
multi_addtimeout(data->state.timeoutlist, &set);
2619
/* the new time is newer than the presently set one, so add the current
2620
to the queue and update the head */
2621
multi_addtimeout(data->state.timeoutlist, nowp);
2623
/* Since this is an updated time, we must remove the previous entry from
2624
the splay tree first and then re-add the new value */
2625
rc = Curl_splayremovebyaddr(multi->timetree,
2626
&data->state.timenode,
2629
infof(data, "Internal error removing splay node = %d\n", rc);
2633
data->state.timenode.payload = data;
2634
multi->timetree = Curl_splayinsert(*nowp,
2636
&data->state.timenode);
2639
Curl_splayprint(multi->timetree, 0, TRUE);
2643
CURLMcode curl_multi_assign(CURLM *multi_handle,
2644
curl_socket_t s, void *hashp)
2646
struct Curl_sh_entry *there = NULL;
2647
struct Curl_multi *multi = (struct Curl_multi *)multi_handle;
2649
if(s != CURL_SOCKET_BAD)
2650
there = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(curl_socket_t));
2653
return CURLM_BAD_SOCKET;
2655
there->socketp = hashp;
2661
void Curl_multi_dump(const struct Curl_multi *multi_handle)
2663
struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
2664
struct Curl_one_easy *easy;
2666
fprintf(stderr, "* Multi status: %d handles, %d alive\n",
2667
multi->num_easy, multi->num_alive);
2668
for(easy=multi->easy.next; easy != &multi->easy; easy = easy->next) {
2669
if(easy->state < CURLM_STATE_COMPLETED) {
2670
/* only display handles that are not completed */
2671
fprintf(stderr, "handle %p, state %s, %d sockets\n",
2672
(void *)easy->easy_handle,
2673
statename[easy->state], easy->numsocks);
2674
for(i=0; i < easy->numsocks; i++) {
2675
curl_socket_t s = easy->sockets[i];
2676
struct Curl_sh_entry *entry =
2677
Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
2679
fprintf(stderr, "%d ", (int)s);
2681
fprintf(stderr, "INTERNAL CONFUSION\n");
2684
fprintf(stderr, "[%s %s] ",
2685
entry->action&CURL_POLL_IN?"RECVING":"",
2686
entry->action&CURL_POLL_OUT?"SENDING":"");
2689
fprintf(stderr, "\n");