~ubuntu-branches/ubuntu/saucy/curl/saucy-updates

« back to all changes in this revision

Viewing changes to .pc/08_lp1124508.patch/lib/multi.c

  • Committer: Package Import Robot
  • Author(s): Barry Warsaw
  • Date: 2013-04-03 17:26:06 UTC
  • Revision ID: package-import@ubuntu.com-20130403172606-r1c1trgqtiupxjt8
Tags: 7.29.0-1ubuntu2
debian/patches/08_lp1124508.patch: Backport fix for upstream bug 1194,
segfault in curl_multi_cleanup() when multi->closure_handle is NULL.
(LP: #1124508)

Show diffs side-by-side

added added

removed removed

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