~ubuntu-branches/ubuntu/vivid/curl/vivid

« back to all changes in this revision

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

  • Committer: Package Import Robot
  • Author(s): Sebastien Bacher
  • Date: 2013-05-07 12:16:37 UTC
  • mfrom: (3.4.37 sid)
  • Revision ID: package-import@ubuntu.com-20130507121637-9t3i98qgsyr9dw5d
Tags: 7.30.0-1ubuntu1
* Resynchronize on Debian. Remaining changes:
  - Drop dependencies not in main:
    + Build-Depends: Drop stunnel4 and libssh2-1-dev.
    + Drop libssh2-1-dev from binary package Depends.
  - Add new libcurl3-udeb package.
  - Add new curl-udeb package.
* Add warning to debian/patches/series.

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