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