Coverage Report

Created: 2023-12-08 06:48

/src/curl/lib/multi.c
Line
Count
Source (jump to first uncovered line)
1
/***************************************************************************
2
 *                                  _   _ ____  _
3
 *  Project                     ___| | | |  _ \| |
4
 *                             / __| | | | |_) | |
5
 *                            | (__| |_| |  _ <| |___
6
 *                             \___|\___/|_| \_\_____|
7
 *
8
 * Copyright (C) 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 https://curl.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
 * SPDX-License-Identifier: curl
22
 *
23
 ***************************************************************************/
24
25
#include "curl_setup.h"
26
27
#include <curl/curl.h>
28
29
#include "urldata.h"
30
#include "transfer.h"
31
#include "url.h"
32
#include "cfilters.h"
33
#include "connect.h"
34
#include "progress.h"
35
#include "easyif.h"
36
#include "share.h"
37
#include "psl.h"
38
#include "multiif.h"
39
#include "sendf.h"
40
#include "timeval.h"
41
#include "http.h"
42
#include "select.h"
43
#include "warnless.h"
44
#include "speedcheck.h"
45
#include "conncache.h"
46
#include "multihandle.h"
47
#include "sigpipe.h"
48
#include "vtls/vtls.h"
49
#include "http_proxy.h"
50
#include "http2.h"
51
#include "socketpair.h"
52
#include "socks.h"
53
/* The last 3 #include files should be in this order */
54
#include "curl_printf.h"
55
#include "curl_memory.h"
56
#include "memdebug.h"
57
58
/*
59
  CURL_SOCKET_HASH_TABLE_SIZE should be a prime number. Increasing it from 97
60
  to 911 takes on a 32-bit machine 4 x 804 = 3211 more bytes.  Still, every
61
  CURL handle takes 45-50 K memory, therefore this 3K are not significant.
62
*/
63
#ifndef CURL_SOCKET_HASH_TABLE_SIZE
64
0
#define CURL_SOCKET_HASH_TABLE_SIZE 911
65
#endif
66
67
#ifndef CURL_CONNECTION_HASH_SIZE
68
0
#define CURL_CONNECTION_HASH_SIZE 97
69
#endif
70
71
#ifndef CURL_DNS_HASH_SIZE
72
0
#define CURL_DNS_HASH_SIZE 71
73
#endif
74
75
0
#define CURL_MULTI_HANDLE 0x000bab1e
76
77
#ifdef DEBUGBUILD
78
/* On a debug build, we want to fail hard on multi handles that
79
 * are not NULL, but no longer have the MAGIC touch. This gives
80
 * us early warning on things only discovered by valgrind otherwise. */
81
#define GOOD_MULTI_HANDLE(x) \
82
0
  (((x) && (x)->magic == CURL_MULTI_HANDLE)? TRUE: \
83
0
  (DEBUGASSERT(!(x)), FALSE))
84
#else
85
#define GOOD_MULTI_HANDLE(x) \
86
  ((x) && (x)->magic == CURL_MULTI_HANDLE)
87
#endif
88
89
static CURLMcode singlesocket(struct Curl_multi *multi,
90
                              struct Curl_easy *data);
91
static CURLMcode add_next_timeout(struct curltime now,
92
                                  struct Curl_multi *multi,
93
                                  struct Curl_easy *d);
94
static CURLMcode multi_timeout(struct Curl_multi *multi,
95
                               long *timeout_ms);
96
static void process_pending_handles(struct Curl_multi *multi);
97
98
#ifdef DEBUGBUILD
99
static const char * const multi_statename[]={
100
  "INIT",
101
  "PENDING",
102
  "CONNECT",
103
  "RESOLVING",
104
  "CONNECTING",
105
  "TUNNELING",
106
  "PROTOCONNECT",
107
  "PROTOCONNECTING",
108
  "DO",
109
  "DOING",
110
  "DOING_MORE",
111
  "DID",
112
  "PERFORMING",
113
  "RATELIMITING",
114
  "DONE",
115
  "COMPLETED",
116
  "MSGSENT",
117
};
118
#endif
119
120
/* function pointer called once when switching TO a state */
121
typedef void (*init_multistate_func)(struct Curl_easy *data);
122
123
/* called in DID state, before PERFORMING state */
124
static void before_perform(struct Curl_easy *data)
125
0
{
126
0
  data->req.chunk = FALSE;
127
0
  Curl_pgrsTime(data, TIMER_PRETRANSFER);
128
0
}
129
130
static void init_completed(struct Curl_easy *data)
131
0
{
132
  /* this is a completed transfer */
133
134
  /* Important: reset the conn pointer so that we don't point to memory
135
     that could be freed anytime */
136
0
  Curl_detach_connection(data);
137
0
  Curl_expire_clear(data); /* stop all timers */
138
0
}
139
140
/* always use this function to change state, to make debugging easier */
141
static void mstate(struct Curl_easy *data, CURLMstate state
142
#ifdef DEBUGBUILD
143
                   , int lineno
144
#endif
145
)
146
0
{
147
0
  CURLMstate oldstate = data->mstate;
148
0
  static const init_multistate_func finit[MSTATE_LAST] = {
149
0
    NULL,              /* INIT */
150
0
    NULL,              /* PENDING */
151
0
    Curl_init_CONNECT, /* CONNECT */
152
0
    NULL,              /* RESOLVING */
153
0
    NULL,              /* CONNECTING */
154
0
    NULL,              /* TUNNELING */
155
0
    NULL,              /* PROTOCONNECT */
156
0
    NULL,              /* PROTOCONNECTING */
157
0
    NULL,              /* DO */
158
0
    NULL,              /* DOING */
159
0
    NULL,              /* DOING_MORE */
160
0
    before_perform,    /* DID */
161
0
    NULL,              /* PERFORMING */
162
0
    NULL,              /* RATELIMITING */
163
0
    NULL,              /* DONE */
164
0
    init_completed,    /* COMPLETED */
165
    NULL               /* MSGSENT */
166
0
  };
167
168
#if defined(DEBUGBUILD) && defined(CURL_DISABLE_VERBOSE_STRINGS)
169
  (void) lineno;
170
#endif
171
172
0
  if(oldstate == state)
173
    /* don't bother when the new state is the same as the old state */
174
0
    return;
175
176
0
  data->mstate = state;
177
178
0
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
179
0
  if(data->mstate >= MSTATE_PENDING &&
180
0
     data->mstate < MSTATE_COMPLETED) {
181
0
    infof(data,
182
0
          "STATE: %s => %s handle %p; line %d",
183
0
          multi_statename[oldstate], multi_statename[data->mstate],
184
0
          (void *)data, lineno);
185
0
  }
186
0
#endif
187
188
0
  if(state == MSTATE_COMPLETED) {
189
    /* changing to COMPLETED means there's one less easy handle 'alive' */
190
0
    DEBUGASSERT(data->multi->num_alive > 0);
191
0
    data->multi->num_alive--;
192
0
  }
193
194
  /* if this state has an init-function, run it */
195
0
  if(finit[state])
196
0
    finit[state](data);
197
0
}
198
199
#ifndef DEBUGBUILD
200
#define multistate(x,y) mstate(x,y)
201
#else
202
0
#define multistate(x,y) mstate(x,y, __LINE__)
203
#endif
204
205
/*
206
 * We add one of these structs to the sockhash for each socket
207
 */
208
209
struct Curl_sh_entry {
210
  struct Curl_hash transfers; /* hash of transfers using this socket */
211
  unsigned int action;  /* what combined action READ/WRITE this socket waits
212
                           for */
213
  unsigned int users; /* number of transfers using this */
214
  void *socketp; /* settable by users with curl_multi_assign() */
215
  unsigned int readers; /* this many transfers want to read */
216
  unsigned int writers; /* this many transfers want to write */
217
};
218
219
/* look up a given socket in the socket hash, skip invalid sockets */
220
static struct Curl_sh_entry *sh_getentry(struct Curl_hash *sh,
221
                                         curl_socket_t s)
222
0
{
223
0
  if(s != CURL_SOCKET_BAD) {
224
    /* only look for proper sockets */
225
0
    return Curl_hash_pick(sh, (char *)&s, sizeof(curl_socket_t));
226
0
  }
227
0
  return NULL;
228
0
}
229
230
0
#define TRHASH_SIZE 13
231
static size_t trhash(void *key, size_t key_length, size_t slots_num)
232
0
{
233
0
  size_t keyval = (size_t)*(struct Curl_easy **)key;
234
0
  (void) key_length;
235
236
0
  return (keyval % slots_num);
237
0
}
238
239
static size_t trhash_compare(void *k1, size_t k1_len, void *k2, size_t k2_len)
240
0
{
241
0
  (void)k1_len;
242
0
  (void)k2_len;
243
244
0
  return *(struct Curl_easy **)k1 == *(struct Curl_easy **)k2;
245
0
}
246
247
static void trhash_dtor(void *nada)
248
0
{
249
0
  (void)nada;
250
0
}
251
252
/*
253
 * The sockhash has its own separate subhash in each entry that need to be
254
 * safely destroyed first.
255
 */
256
static void sockhash_destroy(struct Curl_hash *h)
257
0
{
258
0
  struct Curl_hash_iterator iter;
259
0
  struct Curl_hash_element *he;
260
261
0
  DEBUGASSERT(h);
262
0
  Curl_hash_start_iterate(h, &iter);
263
0
  he = Curl_hash_next_element(&iter);
264
0
  while(he) {
265
0
    struct Curl_sh_entry *sh = (struct Curl_sh_entry *)he->ptr;
266
0
    Curl_hash_destroy(&sh->transfers);
267
0
    he = Curl_hash_next_element(&iter);
268
0
  }
269
0
  Curl_hash_destroy(h);
270
0
}
271
272
273
/* make sure this socket is present in the hash for this handle */
274
static struct Curl_sh_entry *sh_addentry(struct Curl_hash *sh,
275
                                         curl_socket_t s)
276
0
{
277
0
  struct Curl_sh_entry *there = sh_getentry(sh, s);
278
0
  struct Curl_sh_entry *check;
279
280
0
  if(there) {
281
    /* it is present, return fine */
282
0
    return there;
283
0
  }
284
285
  /* not present, add it */
286
0
  check = calloc(1, sizeof(struct Curl_sh_entry));
287
0
  if(!check)
288
0
    return NULL; /* major failure */
289
290
0
  Curl_hash_init(&check->transfers, TRHASH_SIZE, trhash, trhash_compare,
291
0
                 trhash_dtor);
292
293
  /* make/add new hash entry */
294
0
  if(!Curl_hash_add(sh, (char *)&s, sizeof(curl_socket_t), check)) {
295
0
    Curl_hash_destroy(&check->transfers);
296
0
    free(check);
297
0
    return NULL; /* major failure */
298
0
  }
299
300
0
  return check; /* things are good in sockhash land */
301
0
}
302
303
304
/* delete the given socket + handle from the hash */
305
static void sh_delentry(struct Curl_sh_entry *entry,
306
                        struct Curl_hash *sh, curl_socket_t s)
307
0
{
308
0
  Curl_hash_destroy(&entry->transfers);
309
310
  /* We remove the hash entry. This will end up in a call to
311
     sh_freeentry(). */
312
0
  Curl_hash_delete(sh, (char *)&s, sizeof(curl_socket_t));
313
0
}
314
315
/*
316
 * free a sockhash entry
317
 */
318
static void sh_freeentry(void *freethis)
319
0
{
320
0
  struct Curl_sh_entry *p = (struct Curl_sh_entry *) freethis;
321
322
0
  free(p);
323
0
}
324
325
static size_t fd_key_compare(void *k1, size_t k1_len, void *k2, size_t k2_len)
326
0
{
327
0
  (void) k1_len; (void) k2_len;
328
329
0
  return (*((curl_socket_t *) k1)) == (*((curl_socket_t *) k2));
330
0
}
331
332
static size_t hash_fd(void *key, size_t key_length, size_t slots_num)
333
0
{
334
0
  curl_socket_t fd = *((curl_socket_t *) key);
335
0
  (void) key_length;
336
337
0
  return (fd % slots_num);
338
0
}
339
340
/*
341
 * sh_init() creates a new socket hash and returns the handle for it.
342
 *
343
 * Quote from README.multi_socket:
344
 *
345
 * "Some tests at 7000 and 9000 connections showed that the socket hash lookup
346
 * is somewhat of a bottle neck. Its current implementation may be a bit too
347
 * limiting. It simply has a fixed-size array, and on each entry in the array
348
 * it has a linked list with entries. So the hash only checks which list to
349
 * scan through. The code I had used so for used a list with merely 7 slots
350
 * (as that is what the DNS hash uses) but with 7000 connections that would
351
 * make an average of 1000 nodes in each list to run through. I upped that to
352
 * 97 slots (I believe a prime is suitable) and noticed a significant speed
353
 * increase.  I need to reconsider the hash implementation or use a rather
354
 * large default value like this. At 9000 connections I was still below 10us
355
 * per call."
356
 *
357
 */
358
static void sh_init(struct Curl_hash *hash, int hashsize)
359
0
{
360
0
  Curl_hash_init(hash, hashsize, hash_fd, fd_key_compare,
361
0
                 sh_freeentry);
362
0
}
363
364
/*
365
 * multi_addmsg()
366
 *
367
 * Called when a transfer is completed. Adds the given msg pointer to
368
 * the list kept in the multi handle.
369
 */
370
static void multi_addmsg(struct Curl_multi *multi, struct Curl_message *msg)
371
0
{
372
0
  Curl_llist_insert_next(&multi->msglist, multi->msglist.tail, msg,
373
0
                         &msg->list);
374
0
}
375
376
struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
377
                                     int chashsize, /* connection hash */
378
                                     int dnssize) /* dns hash */
379
0
{
380
0
  struct Curl_multi *multi = calloc(1, sizeof(struct Curl_multi));
381
382
0
  if(!multi)
383
0
    return NULL;
384
385
0
  multi->magic = CURL_MULTI_HANDLE;
386
387
0
  Curl_init_dnscache(&multi->hostcache, dnssize);
388
389
0
  sh_init(&multi->sockhash, hashsize);
390
391
0
  if(Curl_conncache_init(&multi->conn_cache, chashsize))
392
0
    goto error;
393
394
0
  Curl_llist_init(&multi->msglist, NULL);
395
0
  Curl_llist_init(&multi->pending, NULL);
396
0
  Curl_llist_init(&multi->msgsent, NULL);
397
398
0
  multi->multiplexing = TRUE;
399
0
  multi->max_concurrent_streams = 100;
400
401
#ifdef USE_WINSOCK
402
  multi->wsa_event = WSACreateEvent();
403
  if(multi->wsa_event == WSA_INVALID_EVENT)
404
    goto error;
405
#else
406
0
#ifdef ENABLE_WAKEUP
407
0
  if(wakeup_create(multi->wakeup_pair) < 0) {
408
0
    multi->wakeup_pair[0] = CURL_SOCKET_BAD;
409
0
    multi->wakeup_pair[1] = CURL_SOCKET_BAD;
410
0
  }
411
0
  else if(curlx_nonblock(multi->wakeup_pair[0], TRUE) < 0 ||
412
0
          curlx_nonblock(multi->wakeup_pair[1], TRUE) < 0) {
413
0
    wakeup_close(multi->wakeup_pair[0]);
414
0
    wakeup_close(multi->wakeup_pair[1]);
415
0
    multi->wakeup_pair[0] = CURL_SOCKET_BAD;
416
0
    multi->wakeup_pair[1] = CURL_SOCKET_BAD;
417
0
  }
418
0
#endif
419
0
#endif
420
421
0
  return multi;
422
423
0
error:
424
425
0
  sockhash_destroy(&multi->sockhash);
426
0
  Curl_hash_destroy(&multi->hostcache);
427
0
  Curl_conncache_destroy(&multi->conn_cache);
428
0
  free(multi);
429
0
  return NULL;
430
0
}
431
432
struct Curl_multi *curl_multi_init(void)
433
0
{
434
0
  return Curl_multi_handle(CURL_SOCKET_HASH_TABLE_SIZE,
435
0
                           CURL_CONNECTION_HASH_SIZE,
436
0
                           CURL_DNS_HASH_SIZE);
437
0
}
438
439
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
440
static void multi_warn_debug(struct Curl_multi *multi, struct Curl_easy *data)
441
0
{
442
0
  if(!multi->warned) {
443
0
    infof(data, "!!! WARNING !!!");
444
0
    infof(data, "This is a debug build of libcurl, "
445
0
          "do not use in production.");
446
0
    multi->warned = true;
447
0
  }
448
0
}
449
#else
450
#define multi_warn_debug(x,y) Curl_nop_stmt
451
#endif
452
453
/* returns TRUE if the easy handle is supposed to be present in the main link
454
   list */
455
static bool in_main_list(struct Curl_easy *data)
456
0
{
457
0
  return ((data->mstate != MSTATE_PENDING) &&
458
0
          (data->mstate != MSTATE_MSGSENT));
459
0
}
460
461
static void link_easy(struct Curl_multi *multi,
462
                      struct Curl_easy *data)
463
0
{
464
  /* We add the new easy entry last in the list. */
465
0
  data->next = NULL; /* end of the line */
466
0
  if(multi->easyp) {
467
0
    struct Curl_easy *last = multi->easylp;
468
0
    last->next = data;
469
0
    data->prev = last;
470
0
    multi->easylp = data; /* the new last node */
471
0
  }
472
0
  else {
473
    /* first node, make prev NULL! */
474
0
    data->prev = NULL;
475
0
    multi->easylp = multi->easyp = data; /* both first and last */
476
0
  }
477
0
}
478
479
/* unlink the given easy handle from the linked list of easy handles */
480
static void unlink_easy(struct Curl_multi *multi,
481
                        struct Curl_easy *data)
482
0
{
483
  /* make the previous node point to our next */
484
0
  if(data->prev)
485
0
    data->prev->next = data->next;
486
0
  else
487
0
    multi->easyp = data->next; /* point to first node */
488
489
  /* make our next point to our previous node */
490
0
  if(data->next)
491
0
    data->next->prev = data->prev;
492
0
  else
493
0
    multi->easylp = data->prev; /* point to last node */
494
495
0
  data->prev = data->next = NULL;
496
0
}
497
498
499
CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
500
                                struct Curl_easy *data)
501
0
{
502
0
  CURLMcode rc;
503
  /* First, make some basic checks that the CURLM handle is a good handle */
504
0
  if(!GOOD_MULTI_HANDLE(multi))
505
0
    return CURLM_BAD_HANDLE;
506
507
  /* Verify that we got a somewhat good easy handle too */
508
0
  if(!GOOD_EASY_HANDLE(data))
509
0
    return CURLM_BAD_EASY_HANDLE;
510
511
  /* Prevent users from adding same easy handle more than once and prevent
512
     adding to more than one multi stack */
513
0
  if(data->multi)
514
0
    return CURLM_ADDED_ALREADY;
515
516
0
  if(multi->in_callback)
517
0
    return CURLM_RECURSIVE_API_CALL;
518
519
0
  if(multi->dead) {
520
    /* a "dead" handle cannot get added transfers while any existing easy
521
       handles are still alive - but if there are none alive anymore, it is
522
       fine to start over and unmark the "deadness" of this handle */
523
0
    if(multi->num_alive)
524
0
      return CURLM_ABORTED_BY_CALLBACK;
525
0
    multi->dead = FALSE;
526
0
  }
527
528
  /* Initialize timeout list for this handle */
529
0
  Curl_llist_init(&data->state.timeoutlist, NULL);
530
531
  /*
532
   * No failure allowed in this function beyond this point. And no
533
   * modification of easy nor multi handle allowed before this except for
534
   * potential multi's connection cache growing which won't be undone in this
535
   * function no matter what.
536
   */
537
0
  if(data->set.errorbuffer)
538
0
    data->set.errorbuffer[0] = 0;
539
540
  /* make the Curl_easy refer back to this multi handle - before Curl_expire()
541
     is called. */
542
0
  data->multi = multi;
543
544
  /* Set the timeout for this handle to expire really soon so that it will
545
     be taken care of even when this handle is added in the midst of operation
546
     when only the curl_multi_socket() API is used. During that flow, only
547
     sockets that time-out or have actions will be dealt with. Since this
548
     handle has no action yet, we make sure it times out to get things to
549
     happen. */
550
0
  Curl_expire(data, 0, EXPIRE_RUN_NOW);
551
552
  /* A somewhat crude work-around for a little glitch in Curl_update_timer()
553
     that happens if the lastcall time is set to the same time when the handle
554
     is removed as when the next handle is added, as then the check in
555
     Curl_update_timer() that prevents calling the application multiple times
556
     with the same timer info will not trigger and then the new handle's
557
     timeout will not be notified to the app.
558
559
     The work-around is thus simply to clear the 'lastcall' variable to force
560
     Curl_update_timer() to always trigger a callback to the app when a new
561
     easy handle is added */
562
0
  memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall));
563
564
0
  rc = Curl_update_timer(multi);
565
0
  if(rc)
566
0
    return rc;
567
568
  /* set the easy handle */
569
0
  multistate(data, MSTATE_INIT);
570
571
  /* for multi interface connections, we share DNS cache automatically if the
572
     easy handle's one is currently not set. */
573
0
  if(!data->dns.hostcache ||
574
0
     (data->dns.hostcachetype == HCACHE_NONE)) {
575
0
    data->dns.hostcache = &multi->hostcache;
576
0
    data->dns.hostcachetype = HCACHE_MULTI;
577
0
  }
578
579
  /* Point to the shared or multi handle connection cache */
580
0
  if(data->share && (data->share->specifier & (1<< CURL_LOCK_DATA_CONNECT)))
581
0
    data->state.conn_cache = &data->share->conn_cache;
582
0
  else
583
0
    data->state.conn_cache = &multi->conn_cache;
584
0
  data->state.lastconnect_id = -1;
585
586
#ifdef USE_LIBPSL
587
  /* Do the same for PSL. */
588
  if(data->share && (data->share->specifier & (1 << CURL_LOCK_DATA_PSL)))
589
    data->psl = &data->share->psl;
590
  else
591
    data->psl = &multi->psl;
592
#endif
593
594
0
  link_easy(multi, data);
595
596
  /* increase the node-counter */
597
0
  multi->num_easy++;
598
599
  /* increase the alive-counter */
600
0
  multi->num_alive++;
601
602
0
  CONNCACHE_LOCK(data);
603
  /* The closure handle only ever has default timeouts set. To improve the
604
     state somewhat we clone the timeouts from each added handle so that the
605
     closure handle always has the same timeouts as the most recently added
606
     easy handle. */
607
0
  data->state.conn_cache->closure_handle->set.timeout = data->set.timeout;
608
0
  data->state.conn_cache->closure_handle->set.server_response_timeout =
609
0
    data->set.server_response_timeout;
610
0
  data->state.conn_cache->closure_handle->set.no_signal =
611
0
    data->set.no_signal;
612
0
  data->id = data->state.conn_cache->next_easy_id++;
613
0
  if(data->state.conn_cache->next_easy_id <= 0)
614
0
    data->state.conn_cache->next_easy_id = 0;
615
0
  CONNCACHE_UNLOCK(data);
616
617
0
  multi_warn_debug(multi, data);
618
619
0
  return CURLM_OK;
620
0
}
621
622
#if 0
623
/* Debug-function, used like this:
624
 *
625
 * Curl_hash_print(&multi->sockhash, debug_print_sock_hash);
626
 *
627
 * Enable the hash print function first by editing hash.c
628
 */
629
static void debug_print_sock_hash(void *p)
630
{
631
  struct Curl_sh_entry *sh = (struct Curl_sh_entry *)p;
632
633
  fprintf(stderr, " [readers %u][writers %u]",
634
          sh->readers, sh->writers);
635
}
636
#endif
637
638
static CURLcode multi_done(struct Curl_easy *data,
639
                           CURLcode status,  /* an error if this is called
640
                                                after an error was detected */
641
                           bool premature)
642
0
{
643
0
  CURLcode result;
644
0
  struct connectdata *conn = data->conn;
645
646
0
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
647
0
  DEBUGF(infof(data, "multi_done[%s]: status: %d prem: %d done: %d",
648
0
               multi_statename[data->mstate],
649
0
               (int)status, (int)premature, data->state.done));
650
#else
651
  DEBUGF(infof(data, "multi_done: status: %d prem: %d done: %d",
652
               (int)status, (int)premature, data->state.done));
653
#endif
654
655
0
  if(data->state.done)
656
    /* Stop if multi_done() has already been called */
657
0
    return CURLE_OK;
658
659
  /* Stop the resolver and free its own resources (but not dns_entry yet). */
660
0
  Curl_resolver_kill(data);
661
662
  /* Cleanup possible redirect junk */
663
0
  Curl_safefree(data->req.newurl);
664
0
  Curl_safefree(data->req.location);
665
666
0
  switch(status) {
667
0
  case CURLE_ABORTED_BY_CALLBACK:
668
0
  case CURLE_READ_ERROR:
669
0
  case CURLE_WRITE_ERROR:
670
    /* When we're aborted due to a callback return code it basically have to
671
       be counted as premature as there is trouble ahead if we don't. We have
672
       many callbacks and protocols work differently, we could potentially do
673
       this more fine-grained in the future. */
674
0
    premature = TRUE;
675
0
  default:
676
0
    break;
677
0
  }
678
679
  /* this calls the protocol-specific function pointer previously set */
680
0
  if(conn->handler->done)
681
0
    result = conn->handler->done(data, status, premature);
682
0
  else
683
0
    result = status;
684
685
0
  if(CURLE_ABORTED_BY_CALLBACK != result) {
686
    /* avoid this if we already aborted by callback to avoid this calling
687
       another callback */
688
0
    int rc = Curl_pgrsDone(data);
689
0
    if(!result && rc)
690
0
      result = CURLE_ABORTED_BY_CALLBACK;
691
0
  }
692
693
  /* Inform connection filters that this transfer is done */
694
0
  Curl_conn_ev_data_done(data, premature);
695
696
0
  process_pending_handles(data->multi); /* connection / multiplex */
697
698
0
  Curl_safefree(data->state.ulbuf);
699
700
0
  Curl_client_cleanup(data);
701
702
0
  CONNCACHE_LOCK(data);
703
0
  Curl_detach_connection(data);
704
0
  if(CONN_INUSE(conn)) {
705
    /* Stop if still used. */
706
0
    CONNCACHE_UNLOCK(data);
707
0
    DEBUGF(infof(data, "Connection still in use %zu, "
708
0
                 "no more multi_done now!",
709
0
                 conn->easyq.size));
710
0
    return CURLE_OK;
711
0
  }
712
713
0
  data->state.done = TRUE; /* called just now! */
714
715
0
  if(conn->dns_entry) {
716
0
    Curl_resolv_unlock(data, conn->dns_entry); /* done with this */
717
0
    conn->dns_entry = NULL;
718
0
  }
719
0
  Curl_hostcache_prune(data);
720
721
  /* if data->set.reuse_forbid is TRUE, it means the libcurl client has
722
     forced us to close this connection. This is ignored for requests taking
723
     place in a NTLM/NEGOTIATE authentication handshake
724
725
     if conn->bits.close is TRUE, it means that the connection should be
726
     closed in spite of all our efforts to be nice, due to protocol
727
     restrictions in our or the server's end
728
729
     if premature is TRUE, it means this connection was said to be DONE before
730
     the entire request operation is complete and thus we can't know in what
731
     state it is for reusing, so we're forced to close it. In a perfect world
732
     we can add code that keep track of if we really must close it here or not,
733
     but currently we have no such detail knowledge.
734
  */
735
736
0
  data->state.recent_conn_id = conn->connection_id;
737
0
  if((data->set.reuse_forbid
738
#if defined(USE_NTLM)
739
      && !(conn->http_ntlm_state == NTLMSTATE_TYPE2 ||
740
           conn->proxy_ntlm_state == NTLMSTATE_TYPE2)
741
#endif
742
#if defined(USE_SPNEGO)
743
      && !(conn->http_negotiate_state == GSS_AUTHRECV ||
744
           conn->proxy_negotiate_state == GSS_AUTHRECV)
745
#endif
746
0
     ) || conn->bits.close
747
0
       || (premature && !Curl_conn_is_multiplex(conn, FIRSTSOCKET))) {
748
0
    DEBUGF(infof(data, "multi_done, not reusing connection=%"
749
0
                       CURL_FORMAT_CURL_OFF_T ", forbid=%d"
750
0
                       ", close=%d, premature=%d, conn_multiplex=%d",
751
0
                 conn->connection_id,
752
0
                 data->set.reuse_forbid, conn->bits.close, premature,
753
0
                 Curl_conn_is_multiplex(conn, FIRSTSOCKET)));
754
0
    connclose(conn, "disconnecting");
755
0
    Curl_conncache_remove_conn(data, conn, FALSE);
756
0
    CONNCACHE_UNLOCK(data);
757
0
    Curl_disconnect(data, conn, premature);
758
0
  }
759
0
  else {
760
0
    char buffer[256];
761
0
    const char *host =
762
0
#ifndef CURL_DISABLE_PROXY
763
0
      conn->bits.socksproxy ?
764
0
      conn->socks_proxy.host.dispname :
765
0
      conn->bits.httpproxy ? conn->http_proxy.host.dispname :
766
0
#endif
767
0
      conn->bits.conn_to_host ? conn->conn_to_host.dispname :
768
0
      conn->host.dispname;
769
    /* create string before returning the connection */
770
0
    curl_off_t connection_id = conn->connection_id;
771
0
    msnprintf(buffer, sizeof(buffer),
772
0
              "Connection #%" CURL_FORMAT_CURL_OFF_T " to host %s left intact",
773
0
              connection_id, host);
774
    /* the connection is no longer in use by this transfer */
775
0
    CONNCACHE_UNLOCK(data);
776
0
    if(Curl_conncache_return_conn(data, conn)) {
777
      /* remember the most recently used connection */
778
0
      data->state.lastconnect_id = connection_id;
779
0
      data->state.recent_conn_id = connection_id;
780
0
      infof(data, "%s", buffer);
781
0
    }
782
0
    else
783
0
      data->state.lastconnect_id = -1;
784
0
  }
785
786
0
  Curl_safefree(data->state.buffer);
787
0
  return result;
788
0
}
789
790
static int close_connect_only(struct Curl_easy *data,
791
                              struct connectdata *conn, void *param)
792
0
{
793
0
  (void)param;
794
0
  if(data->state.lastconnect_id != conn->connection_id)
795
0
    return 0;
796
797
0
  if(!conn->connect_only)
798
0
    return 1;
799
800
0
  connclose(conn, "Removing connect-only easy handle");
801
802
0
  return 1;
803
0
}
804
805
CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
806
                                   struct Curl_easy *data)
807
0
{
808
0
  struct Curl_easy *easy = data;
809
0
  bool premature;
810
0
  struct Curl_llist_element *e;
811
0
  CURLMcode rc;
812
813
  /* First, make some basic checks that the CURLM handle is a good handle */
814
0
  if(!GOOD_MULTI_HANDLE(multi))
815
0
    return CURLM_BAD_HANDLE;
816
817
  /* Verify that we got a somewhat good easy handle too */
818
0
  if(!GOOD_EASY_HANDLE(data))
819
0
    return CURLM_BAD_EASY_HANDLE;
820
821
  /* Prevent users from trying to remove same easy handle more than once */
822
0
  if(!data->multi)
823
0
    return CURLM_OK; /* it is already removed so let's say it is fine! */
824
825
  /* Prevent users from trying to remove an easy handle from the wrong multi */
826
0
  if(data->multi != multi)
827
0
    return CURLM_BAD_EASY_HANDLE;
828
829
0
  if(multi->in_callback)
830
0
    return CURLM_RECURSIVE_API_CALL;
831
832
0
  premature = (data->mstate < MSTATE_COMPLETED) ? TRUE : FALSE;
833
834
  /* If the 'state' is not INIT or COMPLETED, we might need to do something
835
     nice to put the easy_handle in a good known state when this returns. */
836
0
  if(premature) {
837
    /* this handle is "alive" so we need to count down the total number of
838
       alive connections when this is removed */
839
0
    multi->num_alive--;
840
0
  }
841
842
0
  if(data->conn &&
843
0
     data->mstate > MSTATE_DO &&
844
0
     data->mstate < MSTATE_COMPLETED) {
845
    /* Set connection owner so that the DONE function closes it.  We can
846
       safely do this here since connection is killed. */
847
0
    streamclose(data->conn, "Removed with partial response");
848
0
  }
849
850
0
  if(data->conn) {
851
    /* multi_done() clears the association between the easy handle and the
852
       connection.
853
854
       Note that this ignores the return code simply because there's
855
       nothing really useful to do with it anyway! */
856
0
    (void)multi_done(data, data->result, premature);
857
0
  }
858
859
  /* The timer must be shut down before data->multi is set to NULL, else the
860
     timenode will remain in the splay tree after curl_easy_cleanup is
861
     called. Do it after multi_done() in case that sets another time! */
862
0
  Curl_expire_clear(data);
863
864
0
  if(data->connect_queue.ptr) {
865
    /* the handle is in the pending or msgsent lists, so go ahead and remove
866
       it */
867
0
    if(data->mstate == MSTATE_PENDING)
868
0
      Curl_llist_remove(&multi->pending, &data->connect_queue, NULL);
869
0
    else
870
0
      Curl_llist_remove(&multi->msgsent, &data->connect_queue, NULL);
871
0
  }
872
0
  if(in_main_list(data))
873
0
    unlink_easy(multi, data);
874
875
0
  if(data->dns.hostcachetype == HCACHE_MULTI) {
876
    /* stop using the multi handle's DNS cache, *after* the possible
877
       multi_done() call above */
878
0
    data->dns.hostcache = NULL;
879
0
    data->dns.hostcachetype = HCACHE_NONE;
880
0
  }
881
882
0
  Curl_wildcard_dtor(&data->wildcard);
883
884
  /* change state without using multistate(), only to make singlesocket() do
885
     what we want */
886
0
  data->mstate = MSTATE_COMPLETED;
887
888
  /* This ignores the return code even in case of problems because there's
889
     nothing more to do about that, here */
890
0
  (void)singlesocket(multi, easy); /* to let the application know what sockets
891
                                      that vanish with this handle */
892
893
  /* Remove the association between the connection and the handle */
894
0
  Curl_detach_connection(data);
895
896
0
  if(data->set.connect_only && !data->multi_easy) {
897
    /* This removes a handle that was part the multi interface that used
898
       CONNECT_ONLY, that connection is now left alive but since this handle
899
       has bits.close set nothing can use that transfer anymore and it is
900
       forbidden from reuse. And this easy handle cannot find the connection
901
       anymore once removed from the multi handle
902
903
       Better close the connection here, at once.
904
    */
905
0
    struct connectdata *c;
906
0
    curl_socket_t s;
907
0
    s = Curl_getconnectinfo(data, &c);
908
0
    if((s != CURL_SOCKET_BAD) && c) {
909
0
      Curl_conncache_remove_conn(data, c, TRUE);
910
0
      Curl_disconnect(data, c, TRUE);
911
0
    }
912
0
  }
913
914
0
  if(data->state.lastconnect_id != -1) {
915
    /* Mark any connect-only connection for closure */
916
0
    Curl_conncache_foreach(data, data->state.conn_cache,
917
0
                           NULL, close_connect_only);
918
0
  }
919
920
#ifdef USE_LIBPSL
921
  /* Remove the PSL association. */
922
  if(data->psl == &multi->psl)
923
    data->psl = NULL;
924
#endif
925
926
  /* as this was using a shared connection cache we clear the pointer to that
927
     since we're not part of that multi handle anymore */
928
0
  data->state.conn_cache = NULL;
929
930
0
  data->multi = NULL; /* clear the association to this multi handle */
931
932
  /* make sure there's no pending message in the queue sent from this easy
933
     handle */
934
0
  for(e = multi->msglist.head; e; e = e->next) {
935
0
    struct Curl_message *msg = e->ptr;
936
937
0
    if(msg->extmsg.easy_handle == easy) {
938
0
      Curl_llist_remove(&multi->msglist, e, NULL);
939
      /* there can only be one from this specific handle */
940
0
      break;
941
0
    }
942
0
  }
943
944
  /* NOTE NOTE NOTE
945
     We do not touch the easy handle here! */
946
0
  multi->num_easy--; /* one less to care about now */
947
948
0
  process_pending_handles(multi);
949
950
0
  rc = Curl_update_timer(multi);
951
0
  if(rc)
952
0
    return rc;
953
0
  return CURLM_OK;
954
0
}
955
956
/* Return TRUE if the application asked for multiplexing */
957
bool Curl_multiplex_wanted(const struct Curl_multi *multi)
958
0
{
959
0
  return (multi && (multi->multiplexing));
960
0
}
961
962
/*
963
 * Curl_detach_connection() removes the given transfer from the connection.
964
 *
965
 * This is the only function that should clear data->conn. This will
966
 * occasionally be called with the data->conn pointer already cleared.
967
 */
968
void Curl_detach_connection(struct Curl_easy *data)
969
1.16k
{
970
1.16k
  struct connectdata *conn = data->conn;
971
1.16k
  if(conn) {
972
0
    Curl_conn_ev_data_detach(conn, data);
973
0
    Curl_llist_remove(&conn->easyq, &data->conn_queue, NULL);
974
0
  }
975
1.16k
  data->conn = NULL;
976
1.16k
}
977
978
/*
979
 * Curl_attach_connection() attaches this transfer to this connection.
980
 *
981
 * This is the only function that should assign data->conn
982
 */
983
void Curl_attach_connection(struct Curl_easy *data,
984
                             struct connectdata *conn)
985
0
{
986
0
  DEBUGASSERT(!data->conn);
987
0
  DEBUGASSERT(conn);
988
0
  data->conn = conn;
989
0
  Curl_llist_insert_next(&conn->easyq, conn->easyq.tail, data,
990
0
                         &data->conn_queue);
991
0
  if(conn->handler && conn->handler->attach)
992
0
    conn->handler->attach(data, conn);
993
0
  Curl_conn_ev_data_attach(conn, data);
994
0
}
995
996
static int domore_getsock(struct Curl_easy *data,
997
                          struct connectdata *conn,
998
                          curl_socket_t *socks)
999
0
{
1000
0
  if(conn && conn->handler->domore_getsock)
1001
0
    return conn->handler->domore_getsock(data, conn, socks);
1002
0
  return GETSOCK_BLANK;
1003
0
}
1004
1005
static int doing_getsock(struct Curl_easy *data,
1006
                         struct connectdata *conn,
1007
                         curl_socket_t *socks)
1008
0
{
1009
0
  if(conn && conn->handler->doing_getsock)
1010
0
    return conn->handler->doing_getsock(data, conn, socks);
1011
0
  return GETSOCK_BLANK;
1012
0
}
1013
1014
static int protocol_getsock(struct Curl_easy *data,
1015
                            struct connectdata *conn,
1016
                            curl_socket_t *socks)
1017
0
{
1018
0
  if(conn->handler->proto_getsock)
1019
0
    return conn->handler->proto_getsock(data, conn, socks);
1020
0
  return GETSOCK_BLANK;
1021
0
}
1022
1023
/* Initializes `poll_set` with the current socket poll actions needed
1024
 * for transfer `data`. */
1025
static void multi_getsock(struct Curl_easy *data,
1026
                          struct easy_pollset *ps)
1027
0
{
1028
  /* The no connection case can happen when this is called from
1029
     curl_multi_remove_handle() => singlesocket() => multi_getsock().
1030
  */
1031
0
  Curl_pollset_reset(data, ps);
1032
0
  if(!data->conn)
1033
0
    return;
1034
1035
0
  switch(data->mstate) {
1036
0
  default:
1037
0
    break;
1038
1039
0
  case MSTATE_RESOLVING:
1040
0
    Curl_pollset_add_socks2(data, ps, Curl_resolv_getsock);
1041
    /* connection filters are not involved in this phase */
1042
0
    return;
1043
1044
0
  case MSTATE_PROTOCONNECTING:
1045
0
  case MSTATE_PROTOCONNECT:
1046
0
    Curl_pollset_add_socks(data, ps, protocol_getsock);
1047
0
    break;
1048
1049
0
  case MSTATE_DO:
1050
0
  case MSTATE_DOING:
1051
0
    Curl_pollset_add_socks(data, ps, doing_getsock);
1052
0
    break;
1053
1054
0
  case MSTATE_TUNNELING:
1055
0
  case MSTATE_CONNECTING:
1056
0
    break;
1057
1058
0
  case MSTATE_DOING_MORE:
1059
0
    Curl_pollset_add_socks(data, ps, domore_getsock);
1060
0
    break;
1061
1062
0
  case MSTATE_DID: /* since is set after DO is completed, we switch to
1063
                        waiting for the same as the PERFORMING state */
1064
0
  case MSTATE_PERFORMING:
1065
0
    Curl_pollset_add_socks(data, ps, Curl_single_getsock);
1066
0
    break;
1067
1068
0
  case MSTATE_RATELIMITING:
1069
    /* nothing to wait for */
1070
0
    return;
1071
0
  }
1072
1073
  /* Let connection filters add/remove as needed */
1074
0
  Curl_conn_adjust_pollset(data, ps);
1075
0
}
1076
1077
CURLMcode curl_multi_fdset(struct Curl_multi *multi,
1078
                           fd_set *read_fd_set, fd_set *write_fd_set,
1079
                           fd_set *exc_fd_set, int *max_fd)
1080
0
{
1081
  /* Scan through all the easy handles to get the file descriptors set.
1082
     Some easy handles may not have connected to the remote host yet,
1083
     and then we must make sure that is done. */
1084
0
  struct Curl_easy *data;
1085
0
  int this_max_fd = -1;
1086
0
  struct easy_pollset ps;
1087
0
  unsigned int i;
1088
0
  (void)exc_fd_set; /* not used */
1089
1090
0
  if(!GOOD_MULTI_HANDLE(multi))
1091
0
    return CURLM_BAD_HANDLE;
1092
1093
0
  if(multi->in_callback)
1094
0
    return CURLM_RECURSIVE_API_CALL;
1095
1096
0
  memset(&ps, 0, sizeof(ps));
1097
0
  for(data = multi->easyp; data; data = data->next) {
1098
0
    multi_getsock(data, &ps);
1099
1100
0
    for(i = 0; i < ps.num; i++) {
1101
0
      if(!FDSET_SOCK(ps.sockets[i]))
1102
        /* pretend it doesn't exist */
1103
0
        continue;
1104
0
      if(ps.actions[i] & CURL_POLL_IN)
1105
0
        FD_SET(ps.sockets[i], read_fd_set);
1106
0
      if(ps.actions[i] & CURL_POLL_OUT)
1107
0
        FD_SET(ps.sockets[i], write_fd_set);
1108
0
      if((int)ps.sockets[i] > this_max_fd)
1109
0
        this_max_fd = (int)ps.sockets[i];
1110
0
    }
1111
0
  }
1112
1113
0
  *max_fd = this_max_fd;
1114
1115
0
  return CURLM_OK;
1116
0
}
1117
1118
#ifdef USE_WINSOCK
1119
/* Reset FD_WRITE for TCP sockets. Nothing is actually sent. UDP sockets can't
1120
 * be reset this way because an empty datagram would be sent. #9203
1121
 *
1122
 * "On Windows the internal state of FD_WRITE as returned from
1123
 * WSAEnumNetworkEvents is only reset after successful send()."
1124
 */
1125
static void reset_socket_fdwrite(curl_socket_t s)
1126
{
1127
  int t;
1128
  int l = (int)sizeof(t);
1129
  if(!getsockopt(s, SOL_SOCKET, SO_TYPE, (char *)&t, &l) && t == SOCK_STREAM)
1130
    send(s, NULL, 0, 0);
1131
}
1132
#endif
1133
1134
0
#define NUM_POLLS_ON_STACK 10
1135
1136
static CURLMcode multi_wait(struct Curl_multi *multi,
1137
                            struct curl_waitfd extra_fds[],
1138
                            unsigned int extra_nfds,
1139
                            int timeout_ms,
1140
                            int *ret,
1141
                            bool extrawait, /* when no socket, wait */
1142
                            bool use_wakeup)
1143
0
{
1144
0
  struct Curl_easy *data;
1145
0
  struct easy_pollset ps;
1146
0
  size_t i;
1147
0
  unsigned int nfds = 0;
1148
0
  unsigned int curlfds;
1149
0
  long timeout_internal;
1150
0
  int retcode = 0;
1151
0
  struct pollfd a_few_on_stack[NUM_POLLS_ON_STACK];
1152
0
  struct pollfd *ufds = &a_few_on_stack[0];
1153
0
  bool ufds_malloc = FALSE;
1154
#ifdef USE_WINSOCK
1155
  WSANETWORKEVENTS wsa_events;
1156
  DEBUGASSERT(multi->wsa_event != WSA_INVALID_EVENT);
1157
#endif
1158
#ifndef ENABLE_WAKEUP
1159
  (void)use_wakeup;
1160
#endif
1161
1162
0
  if(!GOOD_MULTI_HANDLE(multi))
1163
0
    return CURLM_BAD_HANDLE;
1164
1165
0
  if(multi->in_callback)
1166
0
    return CURLM_RECURSIVE_API_CALL;
1167
1168
0
  if(timeout_ms < 0)
1169
0
    return CURLM_BAD_FUNCTION_ARGUMENT;
1170
1171
  /* Count up how many fds we have from the multi handle */
1172
0
  memset(&ps, 0, sizeof(ps));
1173
0
  for(data = multi->easyp; data; data = data->next) {
1174
0
    multi_getsock(data, &ps);
1175
0
    nfds += ps.num;
1176
0
  }
1177
1178
  /* If the internally desired timeout is actually shorter than requested from
1179
     the outside, then use the shorter time! But only if the internal timer
1180
     is actually larger than -1! */
1181
0
  (void)multi_timeout(multi, &timeout_internal);
1182
0
  if((timeout_internal >= 0) && (timeout_internal < (long)timeout_ms))
1183
0
    timeout_ms = (int)timeout_internal;
1184
1185
0
  curlfds = nfds; /* number of internal file descriptors */
1186
0
  nfds += extra_nfds; /* add the externally provided ones */
1187
1188
0
#ifdef ENABLE_WAKEUP
1189
#ifdef USE_WINSOCK
1190
  if(use_wakeup) {
1191
#else
1192
0
  if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) {
1193
0
#endif
1194
0
    ++nfds;
1195
0
  }
1196
0
#endif
1197
1198
0
  if(nfds > NUM_POLLS_ON_STACK) {
1199
    /* 'nfds' is a 32 bit value and 'struct pollfd' is typically 8 bytes
1200
       big, so at 2^29 sockets this value might wrap. When a process gets
1201
       the capability to actually handle over 500 million sockets this
1202
       calculation needs a integer overflow check. */
1203
0
    ufds = malloc(nfds * sizeof(struct pollfd));
1204
0
    if(!ufds)
1205
0
      return CURLM_OUT_OF_MEMORY;
1206
0
    ufds_malloc = TRUE;
1207
0
  }
1208
0
  nfds = 0;
1209
1210
  /* only do the second loop if we found descriptors in the first stage run
1211
     above */
1212
1213
0
  if(curlfds) {
1214
    /* Add the curl handles to our pollfds first */
1215
0
    for(data = multi->easyp; data; data = data->next) {
1216
0
      multi_getsock(data, &ps);
1217
1218
0
      for(i = 0; i < ps.num; i++) {
1219
0
        struct pollfd *ufd = &ufds[nfds++];
1220
#ifdef USE_WINSOCK
1221
        long mask = 0;
1222
#endif
1223
0
        ufd->fd = ps.sockets[i];
1224
0
        ufd->events = 0;
1225
0
        if(ps.actions[i] & CURL_POLL_IN) {
1226
#ifdef USE_WINSOCK
1227
          mask |= FD_READ|FD_ACCEPT|FD_CLOSE;
1228
#endif
1229
0
          ufd->events |= POLLIN;
1230
0
        }
1231
0
        if(ps.actions[i] & CURL_POLL_OUT) {
1232
#ifdef USE_WINSOCK
1233
          mask |= FD_WRITE|FD_CONNECT|FD_CLOSE;
1234
          reset_socket_fdwrite(ps.sockets[i]);
1235
#endif
1236
0
          ufd->events |= POLLOUT;
1237
0
        }
1238
#ifdef USE_WINSOCK
1239
        if(WSAEventSelect(ps.sockets[i], multi->wsa_event, mask) != 0) {
1240
          if(ufds_malloc)
1241
            free(ufds);
1242
          return CURLM_INTERNAL_ERROR;
1243
        }
1244
#endif
1245
0
      }
1246
0
    }
1247
0
  }
1248
1249
  /* Add external file descriptions from poll-like struct curl_waitfd */
1250
0
  for(i = 0; i < extra_nfds; i++) {
1251
#ifdef USE_WINSOCK
1252
    long mask = 0;
1253
    if(extra_fds[i].events & CURL_WAIT_POLLIN)
1254
      mask |= FD_READ|FD_ACCEPT|FD_CLOSE;
1255
    if(extra_fds[i].events & CURL_WAIT_POLLPRI)
1256
      mask |= FD_OOB;
1257
    if(extra_fds[i].events & CURL_WAIT_POLLOUT) {
1258
      mask |= FD_WRITE|FD_CONNECT|FD_CLOSE;
1259
      reset_socket_fdwrite(extra_fds[i].fd);
1260
    }
1261
    if(WSAEventSelect(extra_fds[i].fd, multi->wsa_event, mask) != 0) {
1262
      if(ufds_malloc)
1263
        free(ufds);
1264
      return CURLM_INTERNAL_ERROR;
1265
    }
1266
#endif
1267
0
    ufds[nfds].fd = extra_fds[i].fd;
1268
0
    ufds[nfds].events = 0;
1269
0
    if(extra_fds[i].events & CURL_WAIT_POLLIN)
1270
0
      ufds[nfds].events |= POLLIN;
1271
0
    if(extra_fds[i].events & CURL_WAIT_POLLPRI)
1272
0
      ufds[nfds].events |= POLLPRI;
1273
0
    if(extra_fds[i].events & CURL_WAIT_POLLOUT)
1274
0
      ufds[nfds].events |= POLLOUT;
1275
0
    ++nfds;
1276
0
  }
1277
1278
0
#ifdef ENABLE_WAKEUP
1279
0
#ifndef USE_WINSOCK
1280
0
  if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) {
1281
0
    ufds[nfds].fd = multi->wakeup_pair[0];
1282
0
    ufds[nfds].events = POLLIN;
1283
0
    ++nfds;
1284
0
  }
1285
0
#endif
1286
0
#endif
1287
1288
#if defined(ENABLE_WAKEUP) && defined(USE_WINSOCK)
1289
  if(nfds || use_wakeup) {
1290
#else
1291
0
  if(nfds) {
1292
0
#endif
1293
0
    int pollrc;
1294
#ifdef USE_WINSOCK
1295
    if(nfds)
1296
      pollrc = Curl_poll(ufds, nfds, 0); /* just pre-check with WinSock */
1297
    else
1298
      pollrc = 0;
1299
#else
1300
0
    pollrc = Curl_poll(ufds, nfds, timeout_ms); /* wait... */
1301
0
#endif
1302
0
    if(pollrc < 0)
1303
0
      return CURLM_UNRECOVERABLE_POLL;
1304
1305
0
    if(pollrc > 0) {
1306
0
      retcode = pollrc;
1307
#ifdef USE_WINSOCK
1308
    }
1309
    else { /* now wait... if not ready during the pre-check (pollrc == 0) */
1310
      WSAWaitForMultipleEvents(1, &multi->wsa_event, FALSE, timeout_ms, FALSE);
1311
    }
1312
    /* With WinSock, we have to run the following section unconditionally
1313
       to call WSAEventSelect(fd, event, 0) on all the sockets */
1314
    {
1315
#endif
1316
      /* copy revents results from the poll to the curl_multi_wait poll
1317
         struct, the bit values of the actual underlying poll() implementation
1318
         may not be the same as the ones in the public libcurl API! */
1319
0
      for(i = 0; i < extra_nfds; i++) {
1320
0
        unsigned r = ufds[curlfds + i].revents;
1321
0
        unsigned short mask = 0;
1322
#ifdef USE_WINSOCK
1323
        curl_socket_t s = extra_fds[i].fd;
1324
        wsa_events.lNetworkEvents = 0;
1325
        if(WSAEnumNetworkEvents(s, NULL, &wsa_events) == 0) {
1326
          if(wsa_events.lNetworkEvents & (FD_READ|FD_ACCEPT|FD_CLOSE))
1327
            mask |= CURL_WAIT_POLLIN;
1328
          if(wsa_events.lNetworkEvents & (FD_WRITE|FD_CONNECT|FD_CLOSE))
1329
            mask |= CURL_WAIT_POLLOUT;
1330
          if(wsa_events.lNetworkEvents & FD_OOB)
1331
            mask |= CURL_WAIT_POLLPRI;
1332
          if(ret && !pollrc && wsa_events.lNetworkEvents)
1333
            retcode++;
1334
        }
1335
        WSAEventSelect(s, multi->wsa_event, 0);
1336
        if(!pollrc) {
1337
          extra_fds[i].revents = mask;
1338
          continue;
1339
        }
1340
#endif
1341
0
        if(r & POLLIN)
1342
0
          mask |= CURL_WAIT_POLLIN;
1343
0
        if(r & POLLOUT)
1344
0
          mask |= CURL_WAIT_POLLOUT;
1345
0
        if(r & POLLPRI)
1346
0
          mask |= CURL_WAIT_POLLPRI;
1347
0
        extra_fds[i].revents = mask;
1348
0
      }
1349
1350
#ifdef USE_WINSOCK
1351
      /* Count up all our own sockets that had activity,
1352
         and remove them from the event. */
1353
      if(curlfds) {
1354
1355
        for(data = multi->easyp; data; data = data->next) {
1356
          multi_getsock(data, &ps);
1357
1358
          for(i = 0; i < ps.num; i++) {
1359
            wsa_events.lNetworkEvents = 0;
1360
            if(WSAEnumNetworkEvents(ps.sockets[i], NULL,
1361
                                    &wsa_events) == 0) {
1362
              if(ret && !pollrc && wsa_events.lNetworkEvents)
1363
                retcode++;
1364
            }
1365
            WSAEventSelect(ps.sockets[i], multi->wsa_event, 0);
1366
          }
1367
        }
1368
      }
1369
1370
      WSAResetEvent(multi->wsa_event);
1371
#else
1372
0
#ifdef ENABLE_WAKEUP
1373
0
      if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) {
1374
0
        if(ufds[curlfds + extra_nfds].revents & POLLIN) {
1375
0
          char buf[64];
1376
0
          ssize_t nread;
1377
0
          while(1) {
1378
            /* the reading socket is non-blocking, try to read
1379
               data from it until it receives an error (except EINTR).
1380
               In normal cases it will get EAGAIN or EWOULDBLOCK
1381
               when there is no more data, breaking the loop. */
1382
0
            nread = wakeup_read(multi->wakeup_pair[0], buf, sizeof(buf));
1383
0
            if(nread <= 0) {
1384
0
              if(nread < 0 && EINTR == SOCKERRNO)
1385
0
                continue;
1386
0
              break;
1387
0
            }
1388
0
          }
1389
          /* do not count the wakeup socket into the returned value */
1390
0
          retcode--;
1391
0
        }
1392
0
      }
1393
0
#endif
1394
0
#endif
1395
0
    }
1396
0
  }
1397
1398
0
  if(ufds_malloc)
1399
0
    free(ufds);
1400
0
  if(ret)
1401
0
    *ret = retcode;
1402
#if defined(ENABLE_WAKEUP) && defined(USE_WINSOCK)
1403
  if(extrawait && !nfds && !use_wakeup) {
1404
#else
1405
0
  if(extrawait && !nfds) {
1406
0
#endif
1407
0
    long sleep_ms = 0;
1408
1409
    /* Avoid busy-looping when there's nothing particular to wait for */
1410
0
    if(!curl_multi_timeout(multi, &sleep_ms) && sleep_ms) {
1411
0
      if(sleep_ms > timeout_ms)
1412
0
        sleep_ms = timeout_ms;
1413
      /* when there are no easy handles in the multi, this holds a -1
1414
         timeout */
1415
0
      else if(sleep_ms < 0)
1416
0
        sleep_ms = timeout_ms;
1417
0
      Curl_wait_ms(sleep_ms);
1418
0
    }
1419
0
  }
1420
1421
0
  return CURLM_OK;
1422
0
}
1423
1424
CURLMcode curl_multi_wait(struct Curl_multi *multi,
1425
                          struct curl_waitfd extra_fds[],
1426
                          unsigned int extra_nfds,
1427
                          int timeout_ms,
1428
                          int *ret)
1429
0
{
1430
0
  return multi_wait(multi, extra_fds, extra_nfds, timeout_ms, ret, FALSE,
1431
0
                    FALSE);
1432
0
}
1433
1434
CURLMcode curl_multi_poll(struct Curl_multi *multi,
1435
                          struct curl_waitfd extra_fds[],
1436
                          unsigned int extra_nfds,
1437
                          int timeout_ms,
1438
                          int *ret)
1439
0
{
1440
0
  return multi_wait(multi, extra_fds, extra_nfds, timeout_ms, ret, TRUE,
1441
0
                    TRUE);
1442
0
}
1443
1444
CURLMcode curl_multi_wakeup(struct Curl_multi *multi)
1445
0
{
1446
  /* this function is usually called from another thread,
1447
     it has to be careful only to access parts of the
1448
     Curl_multi struct that are constant */
1449
1450
  /* GOOD_MULTI_HANDLE can be safely called */
1451
0
  if(!GOOD_MULTI_HANDLE(multi))
1452
0
    return CURLM_BAD_HANDLE;
1453
1454
0
#ifdef ENABLE_WAKEUP
1455
#ifdef USE_WINSOCK
1456
  if(WSASetEvent(multi->wsa_event))
1457
    return CURLM_OK;
1458
#else
1459
  /* the wakeup_pair variable is only written during init and cleanup,
1460
     making it safe to access from another thread after the init part
1461
     and before cleanup */
1462
0
  if(multi->wakeup_pair[1] != CURL_SOCKET_BAD) {
1463
0
    char buf[1];
1464
0
    buf[0] = 1;
1465
0
    while(1) {
1466
      /* swrite() is not thread-safe in general, because concurrent calls
1467
         can have their messages interleaved, but in this case the content
1468
         of the messages does not matter, which makes it ok to call.
1469
1470
         The write socket is set to non-blocking, this way this function
1471
         cannot block, making it safe to call even from the same thread
1472
         that will call curl_multi_wait(). If swrite() returns that it
1473
         would block, it's considered successful because it means that
1474
         previous calls to this function will wake up the poll(). */
1475
0
      if(wakeup_write(multi->wakeup_pair[1], buf, sizeof(buf)) < 0) {
1476
0
        int err = SOCKERRNO;
1477
0
        int return_success;
1478
#ifdef USE_WINSOCK
1479
        return_success = WSAEWOULDBLOCK == err;
1480
#else
1481
0
        if(EINTR == err)
1482
0
          continue;
1483
0
        return_success = EWOULDBLOCK == err || EAGAIN == err;
1484
0
#endif
1485
0
        if(!return_success)
1486
0
          return CURLM_WAKEUP_FAILURE;
1487
0
      }
1488
0
      return CURLM_OK;
1489
0
    }
1490
0
  }
1491
0
#endif
1492
0
#endif
1493
0
  return CURLM_WAKEUP_FAILURE;
1494
0
}
1495
1496
/*
1497
 * multi_ischanged() is called
1498
 *
1499
 * Returns TRUE/FALSE whether the state is changed to trigger a CONNECT_PEND
1500
 * => CONNECT action.
1501
 *
1502
 * Set 'clear' to TRUE to have it also clear the state variable.
1503
 */
1504
static bool multi_ischanged(struct Curl_multi *multi, bool clear)
1505
0
{
1506
0
  bool retval = multi->recheckstate;
1507
0
  if(clear)
1508
0
    multi->recheckstate = FALSE;
1509
0
  return retval;
1510
0
}
1511
1512
/*
1513
 * Curl_multi_connchanged() is called to tell that there is a connection in
1514
 * this multi handle that has changed state (multiplexing become possible, the
1515
 * number of allowed streams changed or similar), and a subsequent use of this
1516
 * multi handle should move CONNECT_PEND handles back to CONNECT to have them
1517
 * retry.
1518
 */
1519
void Curl_multi_connchanged(struct Curl_multi *multi)
1520
0
{
1521
0
  multi->recheckstate = TRUE;
1522
0
}
1523
1524
CURLMcode Curl_multi_add_perform(struct Curl_multi *multi,
1525
                                 struct Curl_easy *data,
1526
                                 struct connectdata *conn)
1527
0
{
1528
0
  CURLMcode rc;
1529
1530
0
  if(multi->in_callback)
1531
0
    return CURLM_RECURSIVE_API_CALL;
1532
1533
0
  rc = curl_multi_add_handle(multi, data);
1534
0
  if(!rc) {
1535
0
    struct SingleRequest *k = &data->req;
1536
1537
    /* pass in NULL for 'conn' here since we don't want to init the
1538
       connection, only this transfer */
1539
0
    Curl_init_do(data, NULL);
1540
1541
    /* take this handle to the perform state right away */
1542
0
    multistate(data, MSTATE_PERFORMING);
1543
0
    Curl_attach_connection(data, conn);
1544
0
    k->keepon |= KEEP_RECV; /* setup to receive! */
1545
0
  }
1546
0
  return rc;
1547
0
}
1548
1549
static CURLcode multi_do(struct Curl_easy *data, bool *done)
1550
0
{
1551
0
  CURLcode result = CURLE_OK;
1552
0
  struct connectdata *conn = data->conn;
1553
1554
0
  DEBUGASSERT(conn);
1555
0
  DEBUGASSERT(conn->handler);
1556
1557
0
  if(conn->handler->do_it)
1558
0
    result = conn->handler->do_it(data, done);
1559
1560
0
  return result;
1561
0
}
1562
1563
/*
1564
 * multi_do_more() is called during the DO_MORE multi state. It is basically a
1565
 * second stage DO state which (wrongly) was introduced to support FTP's
1566
 * second connection.
1567
 *
1568
 * 'complete' can return 0 for incomplete, 1 for done and -1 for go back to
1569
 * DOING state there's more work to do!
1570
 */
1571
1572
static CURLcode multi_do_more(struct Curl_easy *data, int *complete)
1573
0
{
1574
0
  CURLcode result = CURLE_OK;
1575
0
  struct connectdata *conn = data->conn;
1576
1577
0
  *complete = 0;
1578
1579
0
  if(conn->handler->do_more)
1580
0
    result = conn->handler->do_more(data, complete);
1581
1582
0
  return result;
1583
0
}
1584
1585
/*
1586
 * Check whether a timeout occurred, and handle it if it did
1587
 */
1588
static bool multi_handle_timeout(struct Curl_easy *data,
1589
                                 struct curltime *now,
1590
                                 bool *stream_error,
1591
                                 CURLcode *result,
1592
                                 bool connect_timeout)
1593
0
{
1594
0
  timediff_t timeout_ms;
1595
0
  timeout_ms = Curl_timeleft(data, now, connect_timeout);
1596
1597
0
  if(timeout_ms < 0) {
1598
    /* Handle timed out */
1599
0
    if(data->mstate == MSTATE_RESOLVING)
1600
0
      failf(data, "Resolving timed out after %" CURL_FORMAT_TIMEDIFF_T
1601
0
            " milliseconds",
1602
0
            Curl_timediff(*now, data->progress.t_startsingle));
1603
0
    else if(data->mstate == MSTATE_CONNECTING)
1604
0
      failf(data, "Connection timed out after %" CURL_FORMAT_TIMEDIFF_T
1605
0
            " milliseconds",
1606
0
            Curl_timediff(*now, data->progress.t_startsingle));
1607
0
    else {
1608
0
      struct SingleRequest *k = &data->req;
1609
0
      if(k->size != -1) {
1610
0
        failf(data, "Operation timed out after %" CURL_FORMAT_TIMEDIFF_T
1611
0
              " milliseconds with %" CURL_FORMAT_CURL_OFF_T " out of %"
1612
0
              CURL_FORMAT_CURL_OFF_T " bytes received",
1613
0
              Curl_timediff(*now, data->progress.t_startsingle),
1614
0
              k->bytecount, k->size);
1615
0
      }
1616
0
      else {
1617
0
        failf(data, "Operation timed out after %" CURL_FORMAT_TIMEDIFF_T
1618
0
              " milliseconds with %" CURL_FORMAT_CURL_OFF_T
1619
0
              " bytes received",
1620
0
              Curl_timediff(*now, data->progress.t_startsingle),
1621
0
              k->bytecount);
1622
0
      }
1623
0
    }
1624
1625
    /* Force connection closed if the connection has indeed been used */
1626
0
    if(data->mstate > MSTATE_DO) {
1627
0
      streamclose(data->conn, "Disconnected with pending data");
1628
0
      *stream_error = TRUE;
1629
0
    }
1630
0
    *result = CURLE_OPERATION_TIMEDOUT;
1631
0
    (void)multi_done(data, *result, TRUE);
1632
0
  }
1633
1634
0
  return (timeout_ms < 0);
1635
0
}
1636
1637
/*
1638
 * We are doing protocol-specific connecting and this is being called over and
1639
 * over from the multi interface until the connection phase is done on
1640
 * protocol layer.
1641
 */
1642
1643
static CURLcode protocol_connecting(struct Curl_easy *data, bool *done)
1644
0
{
1645
0
  CURLcode result = CURLE_OK;
1646
0
  struct connectdata *conn = data->conn;
1647
1648
0
  if(conn && conn->handler->connecting) {
1649
0
    *done = FALSE;
1650
0
    result = conn->handler->connecting(data, done);
1651
0
  }
1652
0
  else
1653
0
    *done = TRUE;
1654
1655
0
  return result;
1656
0
}
1657
1658
/*
1659
 * We are DOING this is being called over and over from the multi interface
1660
 * until the DOING phase is done on protocol layer.
1661
 */
1662
1663
static CURLcode protocol_doing(struct Curl_easy *data, bool *done)
1664
0
{
1665
0
  CURLcode result = CURLE_OK;
1666
0
  struct connectdata *conn = data->conn;
1667
1668
0
  if(conn && conn->handler->doing) {
1669
0
    *done = FALSE;
1670
0
    result = conn->handler->doing(data, done);
1671
0
  }
1672
0
  else
1673
0
    *done = TRUE;
1674
1675
0
  return result;
1676
0
}
1677
1678
/*
1679
 * We have discovered that the TCP connection has been successful, we can now
1680
 * proceed with some action.
1681
 *
1682
 */
1683
static CURLcode protocol_connect(struct Curl_easy *data,
1684
                                 bool *protocol_done)
1685
0
{
1686
0
  CURLcode result = CURLE_OK;
1687
0
  struct connectdata *conn = data->conn;
1688
0
  DEBUGASSERT(conn);
1689
0
  DEBUGASSERT(protocol_done);
1690
1691
0
  *protocol_done = FALSE;
1692
1693
0
  if(Curl_conn_is_connected(conn, FIRSTSOCKET)
1694
0
     && conn->bits.protoconnstart) {
1695
    /* We already are connected, get back. This may happen when the connect
1696
       worked fine in the first call, like when we connect to a local server
1697
       or proxy. Note that we don't know if the protocol is actually done.
1698
1699
       Unless this protocol doesn't have any protocol-connect callback, as
1700
       then we know we're done. */
1701
0
    if(!conn->handler->connecting)
1702
0
      *protocol_done = TRUE;
1703
1704
0
    return CURLE_OK;
1705
0
  }
1706
1707
0
  if(!conn->bits.protoconnstart) {
1708
0
    if(conn->handler->connect_it) {
1709
      /* is there a protocol-specific connect() procedure? */
1710
1711
      /* Call the protocol-specific connect function */
1712
0
      result = conn->handler->connect_it(data, protocol_done);
1713
0
    }
1714
0
    else
1715
0
      *protocol_done = TRUE;
1716
1717
    /* it has started, possibly even completed but that knowledge isn't stored
1718
       in this bit! */
1719
0
    if(!result)
1720
0
      conn->bits.protoconnstart = TRUE;
1721
0
  }
1722
1723
0
  return result; /* pass back status */
1724
0
}
1725
1726
/*
1727
 * readrewind() rewinds the read stream. This is typically used for HTTP
1728
 * POST/PUT with multi-pass authentication when a sending was denied and a
1729
 * resend is necessary.
1730
 */
1731
static CURLcode readrewind(struct Curl_easy *data)
1732
0
{
1733
0
  curl_mimepart *mimepart = &data->set.mimepost;
1734
0
  DEBUGASSERT(data->conn);
1735
1736
0
  data->state.rewindbeforesend = FALSE; /* we rewind now */
1737
1738
  /* explicitly switch off sending data on this connection now since we are
1739
     about to restart a new transfer and thus we want to avoid inadvertently
1740
     sending more data on the existing connection until the next transfer
1741
     starts */
1742
0
  data->req.keepon &= ~KEEP_SEND;
1743
1744
  /* We have sent away data. If not using CURLOPT_POSTFIELDS or
1745
     CURLOPT_HTTPPOST, call app to rewind
1746
  */
1747
0
#ifndef CURL_DISABLE_HTTP
1748
0
  if(data->conn->handler->protocol & PROTO_FAMILY_HTTP) {
1749
0
    if(data->state.mimepost)
1750
0
      mimepart = data->state.mimepost;
1751
0
  }
1752
0
#endif
1753
0
  if(data->set.postfields ||
1754
0
     (data->state.httpreq == HTTPREQ_GET) ||
1755
0
     (data->state.httpreq == HTTPREQ_HEAD))
1756
0
    ; /* no need to rewind */
1757
0
  else if(data->state.httpreq == HTTPREQ_POST_MIME ||
1758
0
          data->state.httpreq == HTTPREQ_POST_FORM) {
1759
0
    CURLcode result = Curl_mime_rewind(mimepart);
1760
0
    if(result) {
1761
0
      failf(data, "Cannot rewind mime/post data");
1762
0
      return result;
1763
0
    }
1764
0
  }
1765
0
  else {
1766
0
    if(data->set.seek_func) {
1767
0
      int err;
1768
1769
0
      Curl_set_in_callback(data, true);
1770
0
      err = (data->set.seek_func)(data->set.seek_client, 0, SEEK_SET);
1771
0
      Curl_set_in_callback(data, false);
1772
0
      if(err) {
1773
0
        failf(data, "seek callback returned error %d", (int)err);
1774
0
        return CURLE_SEND_FAIL_REWIND;
1775
0
      }
1776
0
    }
1777
0
    else if(data->set.ioctl_func) {
1778
0
      curlioerr err;
1779
1780
0
      Curl_set_in_callback(data, true);
1781
0
      err = (data->set.ioctl_func)(data, CURLIOCMD_RESTARTREAD,
1782
0
                                   data->set.ioctl_client);
1783
0
      Curl_set_in_callback(data, false);
1784
0
      infof(data, "the ioctl callback returned %d", (int)err);
1785
1786
0
      if(err) {
1787
0
        failf(data, "ioctl callback returned error %d", (int)err);
1788
0
        return CURLE_SEND_FAIL_REWIND;
1789
0
      }
1790
0
    }
1791
0
    else {
1792
      /* If no CURLOPT_READFUNCTION is used, we know that we operate on a
1793
         given FILE * stream and we can actually attempt to rewind that
1794
         ourselves with fseek() */
1795
0
      if(data->state.fread_func == (curl_read_callback)fread) {
1796
0
        if(-1 != fseek(data->state.in, 0, SEEK_SET))
1797
          /* successful rewind */
1798
0
          return CURLE_OK;
1799
0
      }
1800
1801
      /* no callback set or failure above, makes us fail at once */
1802
0
      failf(data, "necessary data rewind wasn't possible");
1803
0
      return CURLE_SEND_FAIL_REWIND;
1804
0
    }
1805
0
  }
1806
0
  return CURLE_OK;
1807
0
}
1808
1809
/*
1810
 * Curl_preconnect() is called immediately before a connect starts. When a
1811
 * redirect is followed, this is then called multiple times during a single
1812
 * transfer.
1813
 */
1814
CURLcode Curl_preconnect(struct Curl_easy *data)
1815
0
{
1816
0
  if(!data->state.buffer) {
1817
0
    data->state.buffer = malloc(data->set.buffer_size + 1);
1818
0
    if(!data->state.buffer)
1819
0
      return CURLE_OUT_OF_MEMORY;
1820
0
  }
1821
1822
0
  return CURLE_OK;
1823
0
}
1824
1825
static void set_in_callback(struct Curl_multi *multi, bool value)
1826
0
{
1827
0
  multi->in_callback = value;
1828
0
}
1829
1830
static CURLMcode multi_runsingle(struct Curl_multi *multi,
1831
                                 struct curltime *nowp,
1832
                                 struct Curl_easy *data)
1833
0
{
1834
0
  struct Curl_message *msg = NULL;
1835
0
  bool connected;
1836
0
  bool async;
1837
0
  bool protocol_connected = FALSE;
1838
0
  bool dophase_done = FALSE;
1839
0
  bool done = FALSE;
1840
0
  CURLMcode rc;
1841
0
  CURLcode result = CURLE_OK;
1842
0
  timediff_t recv_timeout_ms;
1843
0
  timediff_t send_timeout_ms;
1844
0
  int control;
1845
1846
0
  if(!GOOD_EASY_HANDLE(data))
1847
0
    return CURLM_BAD_EASY_HANDLE;
1848
1849
0
  if(multi->dead) {
1850
    /* a multi-level callback returned error before, meaning every individual
1851
     transfer now has failed */
1852
0
    result = CURLE_ABORTED_BY_CALLBACK;
1853
0
    Curl_posttransfer(data);
1854
0
    multi_done(data, result, FALSE);
1855
0
    multistate(data, MSTATE_COMPLETED);
1856
0
  }
1857
1858
0
  multi_warn_debug(multi, data);
1859
1860
0
  do {
1861
    /* A "stream" here is a logical stream if the protocol can handle that
1862
       (HTTP/2), or the full connection for older protocols */
1863
0
    bool stream_error = FALSE;
1864
0
    rc = CURLM_OK;
1865
1866
0
    if(multi_ischanged(multi, TRUE)) {
1867
0
      DEBUGF(infof(data, "multi changed, check CONNECT_PEND queue"));
1868
0
      process_pending_handles(multi); /* multiplexed */
1869
0
    }
1870
1871
0
    if(data->mstate > MSTATE_CONNECT &&
1872
0
       data->mstate < MSTATE_COMPLETED) {
1873
      /* Make sure we set the connection's current owner */
1874
0
      DEBUGASSERT(data->conn);
1875
0
      if(!data->conn)
1876
0
        return CURLM_INTERNAL_ERROR;
1877
0
    }
1878
1879
0
    if(data->conn &&
1880
0
       (data->mstate >= MSTATE_CONNECT) &&
1881
0
       (data->mstate < MSTATE_COMPLETED)) {
1882
      /* Check for overall operation timeout here but defer handling the
1883
       * connection timeout to later, to allow for a connection to be set up
1884
       * in the window since we last checked timeout. This prevents us
1885
       * tearing down a completed connection in the case where we were slow
1886
       * to check the timeout (e.g. process descheduled during this loop).
1887
       * We set connect_timeout=FALSE to do this. */
1888
1889
      /* we need to wait for the connect state as only then is the start time
1890
         stored, but we must not check already completed handles */
1891
0
      if(multi_handle_timeout(data, nowp, &stream_error, &result, FALSE)) {
1892
        /* Skip the statemachine and go directly to error handling section. */
1893
0
        goto statemachine_end;
1894
0
      }
1895
0
    }
1896
1897
0
    switch(data->mstate) {
1898
0
    case MSTATE_INIT:
1899
      /* init this transfer. */
1900
0
      result = Curl_pretransfer(data);
1901
1902
0
      if(!result) {
1903
        /* after init, go CONNECT */
1904
0
        multistate(data, MSTATE_CONNECT);
1905
0
        *nowp = Curl_pgrsTime(data, TIMER_STARTOP);
1906
0
        rc = CURLM_CALL_MULTI_PERFORM;
1907
0
      }
1908
0
      break;
1909
1910
0
    case MSTATE_CONNECT:
1911
      /* Connect. We want to get a connection identifier filled in. */
1912
      /* init this transfer. */
1913
0
      result = Curl_preconnect(data);
1914
0
      if(result)
1915
0
        break;
1916
1917
0
      *nowp = Curl_pgrsTime(data, TIMER_STARTSINGLE);
1918
0
      if(data->set.timeout)
1919
0
        Curl_expire(data, data->set.timeout, EXPIRE_TIMEOUT);
1920
1921
0
      if(data->set.connecttimeout)
1922
0
        Curl_expire(data, data->set.connecttimeout, EXPIRE_CONNECTTIMEOUT);
1923
1924
0
      result = Curl_connect(data, &async, &connected);
1925
0
      if(CURLE_NO_CONNECTION_AVAILABLE == result) {
1926
        /* There was no connection available. We will go to the pending
1927
           state and wait for an available connection. */
1928
0
        multistate(data, MSTATE_PENDING);
1929
1930
        /* add this handle to the list of connect-pending handles */
1931
0
        Curl_llist_insert_next(&multi->pending, multi->pending.tail, data,
1932
0
                               &data->connect_queue);
1933
        /* unlink from the main list */
1934
0
        unlink_easy(multi, data);
1935
0
        result = CURLE_OK;
1936
0
        break;
1937
0
      }
1938
0
      else if(data->state.previouslypending) {
1939
        /* this transfer comes from the pending queue so try move another */
1940
0
        infof(data, "Transfer was pending, now try another");
1941
0
        process_pending_handles(data->multi);
1942
0
      }
1943
1944
0
      if(!result) {
1945
0
        if(async)
1946
          /* We're now waiting for an asynchronous name lookup */
1947
0
          multistate(data, MSTATE_RESOLVING);
1948
0
        else {
1949
          /* after the connect has been sent off, go WAITCONNECT unless the
1950
             protocol connect is already done and we can go directly to
1951
             WAITDO or DO! */
1952
0
          rc = CURLM_CALL_MULTI_PERFORM;
1953
1954
0
          if(connected)
1955
0
            multistate(data, MSTATE_PROTOCONNECT);
1956
0
          else {
1957
0
            multistate(data, MSTATE_CONNECTING);
1958
0
          }
1959
0
        }
1960
0
      }
1961
0
      break;
1962
1963
0
    case MSTATE_RESOLVING:
1964
      /* awaiting an asynch name resolve to complete */
1965
0
    {
1966
0
      struct Curl_dns_entry *dns = NULL;
1967
0
      struct connectdata *conn = data->conn;
1968
0
      const char *hostname;
1969
1970
0
      DEBUGASSERT(conn);
1971
0
#ifndef CURL_DISABLE_PROXY
1972
0
      if(conn->bits.httpproxy)
1973
0
        hostname = conn->http_proxy.host.name;
1974
0
      else
1975
0
#endif
1976
0
        if(conn->bits.conn_to_host)
1977
0
          hostname = conn->conn_to_host.name;
1978
0
      else
1979
0
        hostname = conn->host.name;
1980
1981
      /* check if we have the name resolved by now */
1982
0
      dns = Curl_fetch_addr(data, hostname, (int)conn->port);
1983
1984
0
      if(dns) {
1985
0
#ifdef CURLRES_ASYNCH
1986
0
        conn->resolve_async.dns = dns;
1987
0
        conn->resolve_async.done = TRUE;
1988
0
#endif
1989
0
        result = CURLE_OK;
1990
0
        infof(data, "Hostname '%s' was found in DNS cache", hostname);
1991
0
      }
1992
1993
0
      if(!dns)
1994
0
        result = Curl_resolv_check(data, &dns);
1995
1996
      /* Update sockets here, because the socket(s) may have been
1997
         closed and the application thus needs to be told, even if it
1998
         is likely that the same socket(s) will again be used further
1999
         down.  If the name has not yet been resolved, it is likely
2000
         that new sockets have been opened in an attempt to contact
2001
         another resolver. */
2002
0
      rc = singlesocket(multi, data);
2003
0
      if(rc)
2004
0
        return rc;
2005
2006
0
      if(dns) {
2007
        /* Perform the next step in the connection phase, and then move on
2008
           to the WAITCONNECT state */
2009
0
        result = Curl_once_resolved(data, &connected);
2010
2011
0
        if(result)
2012
          /* if Curl_once_resolved() returns failure, the connection struct
2013
             is already freed and gone */
2014
0
          data->conn = NULL; /* no more connection */
2015
0
        else {
2016
          /* call again please so that we get the next socket setup */
2017
0
          rc = CURLM_CALL_MULTI_PERFORM;
2018
0
          if(connected)
2019
0
            multistate(data, MSTATE_PROTOCONNECT);
2020
0
          else {
2021
0
            multistate(data, MSTATE_CONNECTING);
2022
0
          }
2023
0
        }
2024
0
      }
2025
2026
0
      if(result) {
2027
        /* failure detected */
2028
0
        stream_error = TRUE;
2029
0
        break;
2030
0
      }
2031
0
    }
2032
0
    break;
2033
2034
0
#ifndef CURL_DISABLE_HTTP
2035
0
    case MSTATE_TUNNELING:
2036
      /* this is HTTP-specific, but sending CONNECT to a proxy is HTTP... */
2037
0
      DEBUGASSERT(data->conn);
2038
0
      result = Curl_http_connect(data, &protocol_connected);
2039
0
#ifndef CURL_DISABLE_PROXY
2040
0
      if(data->conn->bits.proxy_connect_closed) {
2041
0
        rc = CURLM_CALL_MULTI_PERFORM;
2042
        /* connect back to proxy again */
2043
0
        result = CURLE_OK;
2044
0
        multi_done(data, CURLE_OK, FALSE);
2045
0
        multistate(data, MSTATE_CONNECT);
2046
0
      }
2047
0
      else
2048
0
#endif
2049
0
        if(!result) {
2050
0
          rc = CURLM_CALL_MULTI_PERFORM;
2051
          /* initiate protocol connect phase */
2052
0
          multistate(data, MSTATE_PROTOCONNECT);
2053
0
        }
2054
0
      else
2055
0
        stream_error = TRUE;
2056
0
      break;
2057
0
#endif
2058
2059
0
    case MSTATE_CONNECTING:
2060
      /* awaiting a completion of an asynch TCP connect */
2061
0
      DEBUGASSERT(data->conn);
2062
0
      result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &connected);
2063
0
      if(connected && !result) {
2064
0
        rc = CURLM_CALL_MULTI_PERFORM;
2065
0
        multistate(data, MSTATE_PROTOCONNECT);
2066
0
      }
2067
0
      else if(result) {
2068
        /* failure detected */
2069
0
        Curl_posttransfer(data);
2070
0
        multi_done(data, result, TRUE);
2071
0
        stream_error = TRUE;
2072
0
        break;
2073
0
      }
2074
0
      break;
2075
2076
0
    case MSTATE_PROTOCONNECT:
2077
0
      if(data->state.rewindbeforesend)
2078
0
        result = readrewind(data);
2079
2080
0
      if(!result && data->conn->bits.reuse) {
2081
        /* ftp seems to hang when protoconnect on reused connection
2082
         * since we handle PROTOCONNECT in general inside the filers, it
2083
         * seems wrong to restart this on a reused connection. */
2084
0
        multistate(data, MSTATE_DO);
2085
0
        rc = CURLM_CALL_MULTI_PERFORM;
2086
0
        break;
2087
0
      }
2088
0
      if(!result)
2089
0
        result = protocol_connect(data, &protocol_connected);
2090
0
      if(!result && !protocol_connected) {
2091
        /* switch to waiting state */
2092
0
        multistate(data, MSTATE_PROTOCONNECTING);
2093
0
        rc = CURLM_CALL_MULTI_PERFORM;
2094
0
      }
2095
0
      else if(!result) {
2096
        /* protocol connect has completed, go WAITDO or DO */
2097
0
        multistate(data, MSTATE_DO);
2098
0
        rc = CURLM_CALL_MULTI_PERFORM;
2099
0
      }
2100
0
      else {
2101
        /* failure detected */
2102
0
        Curl_posttransfer(data);
2103
0
        multi_done(data, result, TRUE);
2104
0
        stream_error = TRUE;
2105
0
      }
2106
0
      break;
2107
2108
0
    case MSTATE_PROTOCONNECTING:
2109
      /* protocol-specific connect phase */
2110
0
      result = protocol_connecting(data, &protocol_connected);
2111
0
      if(!result && protocol_connected) {
2112
        /* after the connect has completed, go WAITDO or DO */
2113
0
        multistate(data, MSTATE_DO);
2114
0
        rc = CURLM_CALL_MULTI_PERFORM;
2115
0
      }
2116
0
      else if(result) {
2117
        /* failure detected */
2118
0
        Curl_posttransfer(data);
2119
0
        multi_done(data, result, TRUE);
2120
0
        stream_error = TRUE;
2121
0
      }
2122
0
      break;
2123
2124
0
    case MSTATE_DO:
2125
0
      if(data->set.fprereq) {
2126
0
        int prereq_rc;
2127
2128
        /* call the prerequest callback function */
2129
0
        Curl_set_in_callback(data, true);
2130
0
        prereq_rc = data->set.fprereq(data->set.prereq_userp,
2131
0
                                      data->info.conn_primary_ip,
2132
0
                                      data->info.conn_local_ip,
2133
0
                                      data->info.conn_primary_port,
2134
0
                                      data->info.conn_local_port);
2135
0
        Curl_set_in_callback(data, false);
2136
0
        if(prereq_rc != CURL_PREREQFUNC_OK) {
2137
0
          failf(data, "operation aborted by pre-request callback");
2138
          /* failure in pre-request callback - don't do any other processing */
2139
0
          result = CURLE_ABORTED_BY_CALLBACK;
2140
0
          Curl_posttransfer(data);
2141
0
          multi_done(data, result, FALSE);
2142
0
          stream_error = TRUE;
2143
0
          break;
2144
0
        }
2145
0
      }
2146
2147
0
      if(data->set.connect_only == 1) {
2148
        /* keep connection open for application to use the socket */
2149
0
        connkeep(data->conn, "CONNECT_ONLY");
2150
0
        multistate(data, MSTATE_DONE);
2151
0
        result = CURLE_OK;
2152
0
        rc = CURLM_CALL_MULTI_PERFORM;
2153
0
      }
2154
0
      else {
2155
        /* Perform the protocol's DO action */
2156
0
        result = multi_do(data, &dophase_done);
2157
2158
        /* When multi_do() returns failure, data->conn might be NULL! */
2159
2160
0
        if(!result) {
2161
0
          if(!dophase_done) {
2162
0
#ifndef CURL_DISABLE_FTP
2163
            /* some steps needed for wildcard matching */
2164
0
            if(data->state.wildcardmatch) {
2165
0
              struct WildcardData *wc = data->wildcard;
2166
0
              if(wc->state == CURLWC_DONE || wc->state == CURLWC_SKIP) {
2167
                /* skip some states if it is important */
2168
0
                multi_done(data, CURLE_OK, FALSE);
2169
2170
                /* if there's no connection left, skip the DONE state */
2171
0
                multistate(data, data->conn ?
2172
0
                           MSTATE_DONE : MSTATE_COMPLETED);
2173
0
                rc = CURLM_CALL_MULTI_PERFORM;
2174
0
                break;
2175
0
              }
2176
0
            }
2177
0
#endif
2178
            /* DO was not completed in one function call, we must continue
2179
               DOING... */
2180
0
            multistate(data, MSTATE_DOING);
2181
0
            rc = CURLM_CALL_MULTI_PERFORM;
2182
0
          }
2183
2184
          /* after DO, go DO_DONE... or DO_MORE */
2185
0
          else if(data->conn->bits.do_more) {
2186
            /* we're supposed to do more, but we need to sit down, relax
2187
               and wait a little while first */
2188
0
            multistate(data, MSTATE_DOING_MORE);
2189
0
            rc = CURLM_CALL_MULTI_PERFORM;
2190
0
          }
2191
0
          else {
2192
            /* we're done with the DO, now DID */
2193
0
            multistate(data, MSTATE_DID);
2194
0
            rc = CURLM_CALL_MULTI_PERFORM;
2195
0
          }
2196
0
        }
2197
0
        else if((CURLE_SEND_ERROR == result) &&
2198
0
                data->conn->bits.reuse) {
2199
          /*
2200
           * In this situation, a connection that we were trying to use
2201
           * may have unexpectedly died.  If possible, send the connection
2202
           * back to the CONNECT phase so we can try again.
2203
           */
2204
0
          char *newurl = NULL;
2205
0
          followtype follow = FOLLOW_NONE;
2206
0
          CURLcode drc;
2207
2208
0
          drc = Curl_retry_request(data, &newurl);
2209
0
          if(drc) {
2210
            /* a failure here pretty much implies an out of memory */
2211
0
            result = drc;
2212
0
            stream_error = TRUE;
2213
0
          }
2214
2215
0
          Curl_posttransfer(data);
2216
0
          drc = multi_done(data, result, FALSE);
2217
2218
          /* When set to retry the connection, we must go back to the CONNECT
2219
           * state */
2220
0
          if(newurl) {
2221
0
            if(!drc || (drc == CURLE_SEND_ERROR)) {
2222
0
              follow = FOLLOW_RETRY;
2223
0
              drc = Curl_follow(data, newurl, follow);
2224
0
              if(!drc) {
2225
0
                multistate(data, MSTATE_CONNECT);
2226
0
                rc = CURLM_CALL_MULTI_PERFORM;
2227
0
                result = CURLE_OK;
2228
0
              }
2229
0
              else {
2230
                /* Follow failed */
2231
0
                result = drc;
2232
0
              }
2233
0
            }
2234
0
            else {
2235
              /* done didn't return OK or SEND_ERROR */
2236
0
              result = drc;
2237
0
            }
2238
0
          }
2239
0
          else {
2240
            /* Have error handler disconnect conn if we can't retry */
2241
0
            stream_error = TRUE;
2242
0
          }
2243
0
          free(newurl);
2244
0
        }
2245
0
        else {
2246
          /* failure detected */
2247
0
          Curl_posttransfer(data);
2248
0
          if(data->conn)
2249
0
            multi_done(data, result, FALSE);
2250
0
          stream_error = TRUE;
2251
0
        }
2252
0
      }
2253
0
      break;
2254
2255
0
    case MSTATE_DOING:
2256
      /* we continue DOING until the DO phase is complete */
2257
0
      DEBUGASSERT(data->conn);
2258
0
      result = protocol_doing(data, &dophase_done);
2259
0
      if(!result) {
2260
0
        if(dophase_done) {
2261
          /* after DO, go DO_DONE or DO_MORE */
2262
0
          multistate(data, data->conn->bits.do_more?
2263
0
                     MSTATE_DOING_MORE : MSTATE_DID);
2264
0
          rc = CURLM_CALL_MULTI_PERFORM;
2265
0
        } /* dophase_done */
2266
0
      }
2267
0
      else {
2268
        /* failure detected */
2269
0
        Curl_posttransfer(data);
2270
0
        multi_done(data, result, FALSE);
2271
0
        stream_error = TRUE;
2272
0
      }
2273
0
      break;
2274
2275
0
    case MSTATE_DOING_MORE:
2276
      /*
2277
       * When we are connected, DOING MORE and then go DID
2278
       */
2279
0
      DEBUGASSERT(data->conn);
2280
0
      result = multi_do_more(data, &control);
2281
2282
0
      if(!result) {
2283
0
        if(control) {
2284
          /* if positive, advance to DO_DONE
2285
             if negative, go back to DOING */
2286
0
          multistate(data, control == 1?
2287
0
                     MSTATE_DID : MSTATE_DOING);
2288
0
          rc = CURLM_CALL_MULTI_PERFORM;
2289
0
        }
2290
        /* else
2291
           stay in DO_MORE */
2292
0
      }
2293
0
      else {
2294
        /* failure detected */
2295
0
        Curl_posttransfer(data);
2296
0
        multi_done(data, result, FALSE);
2297
0
        stream_error = TRUE;
2298
0
      }
2299
0
      break;
2300
2301
0
    case MSTATE_DID:
2302
0
      DEBUGASSERT(data->conn);
2303
0
      if(data->conn->bits.multiplex)
2304
        /* Check if we can move pending requests to send pipe */
2305
0
        process_pending_handles(multi); /*  multiplexed */
2306
2307
      /* Only perform the transfer if there's a good socket to work with.
2308
         Having both BAD is a signal to skip immediately to DONE */
2309
0
      if((data->conn->sockfd != CURL_SOCKET_BAD) ||
2310
0
         (data->conn->writesockfd != CURL_SOCKET_BAD))
2311
0
        multistate(data, MSTATE_PERFORMING);
2312
0
      else {
2313
0
#ifndef CURL_DISABLE_FTP
2314
0
        if(data->state.wildcardmatch &&
2315
0
           ((data->conn->handler->flags & PROTOPT_WILDCARD) == 0)) {
2316
0
          data->wildcard->state = CURLWC_DONE;
2317
0
        }
2318
0
#endif
2319
0
        multistate(data, MSTATE_DONE);
2320
0
      }
2321
0
      rc = CURLM_CALL_MULTI_PERFORM;
2322
0
      break;
2323
2324
0
    case MSTATE_RATELIMITING: /* limit-rate exceeded in either direction */
2325
0
      DEBUGASSERT(data->conn);
2326
      /* if both rates are within spec, resume transfer */
2327
0
      if(Curl_pgrsUpdate(data))
2328
0
        result = CURLE_ABORTED_BY_CALLBACK;
2329
0
      else
2330
0
        result = Curl_speedcheck(data, *nowp);
2331
2332
0
      if(result) {
2333
0
        if(!(data->conn->handler->flags & PROTOPT_DUAL) &&
2334
0
           result != CURLE_HTTP2_STREAM)
2335
0
          streamclose(data->conn, "Transfer returned error");
2336
2337
0
        Curl_posttransfer(data);
2338
0
        multi_done(data, result, TRUE);
2339
0
      }
2340
0
      else {
2341
0
        send_timeout_ms = 0;
2342
0
        if(data->set.max_send_speed)
2343
0
          send_timeout_ms =
2344
0
            Curl_pgrsLimitWaitTime(data->progress.uploaded,
2345
0
                                   data->progress.ul_limit_size,
2346
0
                                   data->set.max_send_speed,
2347
0
                                   data->progress.ul_limit_start,
2348
0
                                   *nowp);
2349
2350
0
        recv_timeout_ms = 0;
2351
0
        if(data->set.max_recv_speed)
2352
0
          recv_timeout_ms =
2353
0
            Curl_pgrsLimitWaitTime(data->progress.downloaded,
2354
0
                                   data->progress.dl_limit_size,
2355
0
                                   data->set.max_recv_speed,
2356
0
                                   data->progress.dl_limit_start,
2357
0
                                   *nowp);
2358
2359
0
        if(!send_timeout_ms && !recv_timeout_ms) {
2360
0
          multistate(data, MSTATE_PERFORMING);
2361
0
          Curl_ratelimit(data, *nowp);
2362
0
        }
2363
0
        else if(send_timeout_ms >= recv_timeout_ms)
2364
0
          Curl_expire(data, send_timeout_ms, EXPIRE_TOOFAST);
2365
0
        else
2366
0
          Curl_expire(data, recv_timeout_ms, EXPIRE_TOOFAST);
2367
0
      }
2368
0
      break;
2369
2370
0
    case MSTATE_PERFORMING:
2371
0
    {
2372
0
      char *newurl = NULL;
2373
0
      bool retry = FALSE;
2374
0
      bool comeback = FALSE;
2375
0
      DEBUGASSERT(data->state.buffer);
2376
      /* check if over send speed */
2377
0
      send_timeout_ms = 0;
2378
0
      if(data->set.max_send_speed)
2379
0
        send_timeout_ms = Curl_pgrsLimitWaitTime(data->progress.uploaded,
2380
0
                                                 data->progress.ul_limit_size,
2381
0
                                                 data->set.max_send_speed,
2382
0
                                                 data->progress.ul_limit_start,
2383
0
                                                 *nowp);
2384
2385
      /* check if over recv speed */
2386
0
      recv_timeout_ms = 0;
2387
0
      if(data->set.max_recv_speed)
2388
0
        recv_timeout_ms = Curl_pgrsLimitWaitTime(data->progress.downloaded,
2389
0
                                                 data->progress.dl_limit_size,
2390
0
                                                 data->set.max_recv_speed,
2391
0
                                                 data->progress.dl_limit_start,
2392
0
                                                 *nowp);
2393
2394
0
      if(send_timeout_ms || recv_timeout_ms) {
2395
0
        Curl_ratelimit(data, *nowp);
2396
0
        multistate(data, MSTATE_RATELIMITING);
2397
0
        if(send_timeout_ms >= recv_timeout_ms)
2398
0
          Curl_expire(data, send_timeout_ms, EXPIRE_TOOFAST);
2399
0
        else
2400
0
          Curl_expire(data, recv_timeout_ms, EXPIRE_TOOFAST);
2401
0
        break;
2402
0
      }
2403
2404
      /* read/write data if it is ready to do so */
2405
0
      result = Curl_readwrite(data->conn, data, &done, &comeback);
2406
2407
0
      if(done || (result == CURLE_RECV_ERROR)) {
2408
        /* If CURLE_RECV_ERROR happens early enough, we assume it was a race
2409
         * condition and the server closed the reused connection exactly when
2410
         * we wanted to use it, so figure out if that is indeed the case.
2411
         */
2412
0
        CURLcode ret = Curl_retry_request(data, &newurl);
2413
0
        if(!ret)
2414
0
          retry = (newurl)?TRUE:FALSE;
2415
0
        else if(!result)
2416
0
          result = ret;
2417
2418
0
        if(retry) {
2419
          /* if we are to retry, set the result to OK and consider the
2420
             request as done */
2421
0
          result = CURLE_OK;
2422
0
          done = TRUE;
2423
0
        }
2424
0
      }
2425
0
      else if((CURLE_HTTP2_STREAM == result) &&
2426
0
              Curl_h2_http_1_1_error(data)) {
2427
0
        CURLcode ret = Curl_retry_request(data, &newurl);
2428
2429
0
        if(!ret) {
2430
0
          infof(data, "Downgrades to HTTP/1.1");
2431
0
          streamclose(data->conn, "Disconnect HTTP/2 for HTTP/1");
2432
0
          data->state.httpwant = CURL_HTTP_VERSION_1_1;
2433
          /* clear the error message bit too as we ignore the one we got */
2434
0
          data->state.errorbuf = FALSE;
2435
0
          if(!newurl)
2436
            /* typically for HTTP_1_1_REQUIRED error on first flight */
2437
0
            newurl = strdup(data->state.url);
2438
          /* if we are to retry, set the result to OK and consider the request
2439
             as done */
2440
0
          retry = TRUE;
2441
0
          result = CURLE_OK;
2442
0
          done = TRUE;
2443
0
        }
2444
0
        else
2445
0
          result = ret;
2446
0
      }
2447
2448
0
      if(result) {
2449
        /*
2450
         * The transfer phase returned error, we mark the connection to get
2451
         * closed to prevent being reused. This is because we can't possibly
2452
         * know if the connection is in a good shape or not now.  Unless it is
2453
         * a protocol which uses two "channels" like FTP, as then the error
2454
         * happened in the data connection.
2455
         */
2456
2457
0
        if(!(data->conn->handler->flags & PROTOPT_DUAL) &&
2458
0
           result != CURLE_HTTP2_STREAM)
2459
0
          streamclose(data->conn, "Transfer returned error");
2460
2461
0
        Curl_posttransfer(data);
2462
0
        multi_done(data, result, TRUE);
2463
0
      }
2464
0
      else if(done) {
2465
2466
        /* call this even if the readwrite function returned error */
2467
0
        Curl_posttransfer(data);
2468
2469
        /* When we follow redirects or is set to retry the connection, we must
2470
           to go back to the CONNECT state */
2471
0
        if(data->req.newurl || retry) {
2472
0
          followtype follow = FOLLOW_NONE;
2473
0
          if(!retry) {
2474
            /* if the URL is a follow-location and not just a retried request
2475
               then figure out the URL here */
2476
0
            free(newurl);
2477
0
            newurl = data->req.newurl;
2478
0
            data->req.newurl = NULL;
2479
0
            follow = FOLLOW_REDIR;
2480
0
          }
2481
0
          else
2482
0
            follow = FOLLOW_RETRY;
2483
0
          (void)multi_done(data, CURLE_OK, FALSE);
2484
          /* multi_done() might return CURLE_GOT_NOTHING */
2485
0
          result = Curl_follow(data, newurl, follow);
2486
0
          if(!result) {
2487
0
            multistate(data, MSTATE_CONNECT);
2488
0
            rc = CURLM_CALL_MULTI_PERFORM;
2489
0
          }
2490
0
          free(newurl);
2491
0
        }
2492
0
        else {
2493
          /* after the transfer is done, go DONE */
2494
2495
          /* but first check to see if we got a location info even though we're
2496
             not following redirects */
2497
0
          if(data->req.location) {
2498
0
            free(newurl);
2499
0
            newurl = data->req.location;
2500
0
            data->req.location = NULL;
2501
0
            result = Curl_follow(data, newurl, FOLLOW_FAKE);
2502
0
            free(newurl);
2503
0
            if(result) {
2504
0
              stream_error = TRUE;
2505
0
              result = multi_done(data, result, TRUE);
2506
0
            }
2507
0
          }
2508
2509
0
          if(!result) {
2510
0
            multistate(data, MSTATE_DONE);
2511
0
            rc = CURLM_CALL_MULTI_PERFORM;
2512
0
          }
2513
0
        }
2514
0
      }
2515
0
      else if(comeback) {
2516
        /* This avoids CURLM_CALL_MULTI_PERFORM so that a very fast transfer
2517
           won't get stuck on this transfer at the expense of other concurrent
2518
           transfers */
2519
0
        Curl_expire(data, 0, EXPIRE_RUN_NOW);
2520
0
      }
2521
0
      break;
2522
0
    }
2523
2524
0
    case MSTATE_DONE:
2525
      /* this state is highly transient, so run another loop after this */
2526
0
      rc = CURLM_CALL_MULTI_PERFORM;
2527
2528
0
      if(data->conn) {
2529
0
        CURLcode res;
2530
2531
0
        if(data->conn->bits.multiplex)
2532
          /* Check if we can move pending requests to connection */
2533
0
          process_pending_handles(multi); /* multiplexing */
2534
2535
        /* post-transfer command */
2536
0
        res = multi_done(data, result, FALSE);
2537
2538
        /* allow a previously set error code take precedence */
2539
0
        if(!result)
2540
0
          result = res;
2541
0
      }
2542
2543
0
#ifndef CURL_DISABLE_FTP
2544
0
      if(data->state.wildcardmatch) {
2545
0
        if(data->wildcard->state != CURLWC_DONE) {
2546
          /* if a wildcard is set and we are not ending -> lets start again
2547
             with MSTATE_INIT */
2548
0
          multistate(data, MSTATE_INIT);
2549
0
          break;
2550
0
        }
2551
0
      }
2552
0
#endif
2553
      /* after we have DONE what we're supposed to do, go COMPLETED, and
2554
         it doesn't matter what the multi_done() returned! */
2555
0
      multistate(data, MSTATE_COMPLETED);
2556
0
      break;
2557
2558
0
    case MSTATE_COMPLETED:
2559
0
      break;
2560
2561
0
    case MSTATE_PENDING:
2562
0
    case MSTATE_MSGSENT:
2563
      /* handles in these states should NOT be in this list */
2564
0
      DEBUGASSERT(0);
2565
0
      break;
2566
2567
0
    default:
2568
0
      return CURLM_INTERNAL_ERROR;
2569
0
    }
2570
2571
0
    if(data->conn &&
2572
0
       data->mstate >= MSTATE_CONNECT &&
2573
0
       data->mstate < MSTATE_DO &&
2574
0
       rc != CURLM_CALL_MULTI_PERFORM &&
2575
0
       !multi_ischanged(multi, false)) {
2576
      /* We now handle stream timeouts if and only if this will be the last
2577
       * loop iteration. We only check this on the last iteration to ensure
2578
       * that if we know we have additional work to do immediately
2579
       * (i.e. CURLM_CALL_MULTI_PERFORM == TRUE) then we should do that before
2580
       * declaring the connection timed out as we may almost have a completed
2581
       * connection. */
2582
0
      multi_handle_timeout(data, nowp, &stream_error, &result, TRUE);
2583
0
    }
2584
2585
0
statemachine_end:
2586
2587
0
    if(data->mstate < MSTATE_COMPLETED) {
2588
0
      if(result) {
2589
        /*
2590
         * If an error was returned, and we aren't in completed state now,
2591
         * then we go to completed and consider this transfer aborted.
2592
         */
2593
2594
        /* NOTE: no attempt to disconnect connections must be made
2595
           in the case blocks above - cleanup happens only here */
2596
2597
        /* Check if we can move pending requests to send pipe */
2598
0
        process_pending_handles(multi); /* connection */
2599
2600
0
        if(data->conn) {
2601
0
          if(stream_error) {
2602
            /* Don't attempt to send data over a connection that timed out */
2603
0
            bool dead_connection = result == CURLE_OPERATION_TIMEDOUT;
2604
0
            struct connectdata *conn = data->conn;
2605
2606
            /* This is where we make sure that the conn pointer is reset.
2607
               We don't have to do this in every case block above where a
2608
               failure is detected */
2609
0
            Curl_detach_connection(data);
2610
2611
            /* remove connection from cache */
2612
0
            Curl_conncache_remove_conn(data, conn, TRUE);
2613
2614
            /* disconnect properly */
2615
0
            Curl_disconnect(data, conn, dead_connection);
2616
0
          }
2617
0
        }
2618
0
        else if(data->mstate == MSTATE_CONNECT) {
2619
          /* Curl_connect() failed */
2620
0
          (void)Curl_posttransfer(data);
2621
0
        }
2622
2623
0
        multistate(data, MSTATE_COMPLETED);
2624
0
        rc = CURLM_CALL_MULTI_PERFORM;
2625
0
      }
2626
      /* if there's still a connection to use, call the progress function */
2627
0
      else if(data->conn && Curl_pgrsUpdate(data)) {
2628
        /* aborted due to progress callback return code must close the
2629
           connection */
2630
0
        result = CURLE_ABORTED_BY_CALLBACK;
2631
0
        streamclose(data->conn, "Aborted by callback");
2632
2633
        /* if not yet in DONE state, go there, otherwise COMPLETED */
2634
0
        multistate(data, (data->mstate < MSTATE_DONE)?
2635
0
                   MSTATE_DONE: MSTATE_COMPLETED);
2636
0
        rc = CURLM_CALL_MULTI_PERFORM;
2637
0
      }
2638
0
    }
2639
2640
0
    if(MSTATE_COMPLETED == data->mstate) {
2641
0
      if(data->set.fmultidone) {
2642
        /* signal via callback instead */
2643
0
        data->set.fmultidone(data, result);
2644
0
      }
2645
0
      else {
2646
        /* now fill in the Curl_message with this info */
2647
0
        msg = &data->msg;
2648
2649
0
        msg->extmsg.msg = CURLMSG_DONE;
2650
0
        msg->extmsg.easy_handle = data;
2651
0
        msg->extmsg.data.result = result;
2652
2653
0
        multi_addmsg(multi, msg);
2654
0
        DEBUGASSERT(!data->conn);
2655
0
      }
2656
0
      multistate(data, MSTATE_MSGSENT);
2657
2658
      /* add this handle to the list of msgsent handles */
2659
0
      Curl_llist_insert_next(&multi->msgsent, multi->msgsent.tail, data,
2660
0
                             &data->connect_queue);
2661
      /* unlink from the main list */
2662
0
      unlink_easy(multi, data);
2663
0
      return CURLM_OK;
2664
0
    }
2665
0
  } while((rc == CURLM_CALL_MULTI_PERFORM) || multi_ischanged(multi, FALSE));
2666
2667
0
  data->result = result;
2668
0
  return rc;
2669
0
}
2670
2671
2672
CURLMcode curl_multi_perform(struct Curl_multi *multi, int *running_handles)
2673
0
{
2674
0
  struct Curl_easy *data;
2675
0
  CURLMcode returncode = CURLM_OK;
2676
0
  struct Curl_tree *t;
2677
0
  struct curltime now = Curl_now();
2678
2679
0
  if(!GOOD_MULTI_HANDLE(multi))
2680
0
    return CURLM_BAD_HANDLE;
2681
2682
0
  if(multi->in_callback)
2683
0
    return CURLM_RECURSIVE_API_CALL;
2684
2685
0
  data = multi->easyp;
2686
0
  if(data) {
2687
0
    CURLMcode result;
2688
0
    bool nosig = data->set.no_signal;
2689
0
    SIGPIPE_VARIABLE(pipe_st);
2690
0
    sigpipe_ignore(data, &pipe_st);
2691
    /* Do the loop and only alter the signal ignore state if the next handle
2692
       has a different NO_SIGNAL state than the previous */
2693
0
    do {
2694
      /* the current node might be unlinked in multi_runsingle(), get the next
2695
         pointer now */
2696
0
      struct Curl_easy *datanext = data->next;
2697
0
      if(data->set.no_signal != nosig) {
2698
0
        sigpipe_restore(&pipe_st);
2699
0
        sigpipe_ignore(data, &pipe_st);
2700
0
        nosig = data->set.no_signal;
2701
0
      }
2702
0
      result = multi_runsingle(multi, &now, data);
2703
0
      if(result)
2704
0
        returncode = result;
2705
0
      data = datanext; /* operate on next handle */
2706
0
    } while(data);
2707
0
    sigpipe_restore(&pipe_st);
2708
0
  }
2709
2710
  /*
2711
   * Simply remove all expired timers from the splay since handles are dealt
2712
   * with unconditionally by this function and curl_multi_timeout() requires
2713
   * that already passed/handled expire times are removed from the splay.
2714
   *
2715
   * It is important that the 'now' value is set at the entry of this function
2716
   * and not for the current time as it may have ticked a little while since
2717
   * then and then we risk this loop to remove timers that actually have not
2718
   * been handled!
2719
   */
2720
0
  do {
2721
0
    multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
2722
0
    if(t)
2723
      /* the removed may have another timeout in queue */
2724
0
      (void)add_next_timeout(now, multi, t->payload);
2725
2726
0
  } while(t);
2727
2728
0
  *running_handles = multi->num_alive;
2729
2730
0
  if(CURLM_OK >= returncode)
2731
0
    returncode = Curl_update_timer(multi);
2732
2733
0
  return returncode;
2734
0
}
2735
2736
/* unlink_all_msgsent_handles() detaches all those easy handles from this
2737
   multi handle */
2738
static void unlink_all_msgsent_handles(struct Curl_multi *multi)
2739
0
{
2740
0
  struct Curl_llist_element *e = multi->msgsent.head;
2741
0
  if(e) {
2742
0
    struct Curl_easy *data = e->ptr;
2743
0
    DEBUGASSERT(data->mstate == MSTATE_MSGSENT);
2744
0
    data->multi = NULL;
2745
0
  }
2746
0
}
2747
2748
CURLMcode curl_multi_cleanup(struct Curl_multi *multi)
2749
0
{
2750
0
  struct Curl_easy *data;
2751
0
  struct Curl_easy *nextdata;
2752
2753
0
  if(GOOD_MULTI_HANDLE(multi)) {
2754
0
    if(multi->in_callback)
2755
0
      return CURLM_RECURSIVE_API_CALL;
2756
2757
0
    multi->magic = 0; /* not good anymore */
2758
2759
0
    unlink_all_msgsent_handles(multi);
2760
0
    process_pending_handles(multi);
2761
    /* First remove all remaining easy handles */
2762
0
    data = multi->easyp;
2763
0
    while(data) {
2764
0
      nextdata = data->next;
2765
0
      if(!data->state.done && data->conn)
2766
        /* if DONE was never called for this handle */
2767
0
        (void)multi_done(data, CURLE_OK, TRUE);
2768
0
      if(data->dns.hostcachetype == HCACHE_MULTI) {
2769
        /* clear out the usage of the shared DNS cache */
2770
0
        Curl_hostcache_clean(data, data->dns.hostcache);
2771
0
        data->dns.hostcache = NULL;
2772
0
        data->dns.hostcachetype = HCACHE_NONE;
2773
0
      }
2774
2775
      /* Clear the pointer to the connection cache */
2776
0
      data->state.conn_cache = NULL;
2777
0
      data->multi = NULL; /* clear the association */
2778
2779
#ifdef USE_LIBPSL
2780
      if(data->psl == &multi->psl)
2781
        data->psl = NULL;
2782
#endif
2783
2784
0
      data = nextdata;
2785
0
    }
2786
2787
    /* Close all the connections in the connection cache */
2788
0
    Curl_conncache_close_all_connections(&multi->conn_cache);
2789
2790
0
    sockhash_destroy(&multi->sockhash);
2791
0
    Curl_conncache_destroy(&multi->conn_cache);
2792
0
    Curl_hash_destroy(&multi->hostcache);
2793
0
    Curl_psl_destroy(&multi->psl);
2794
2795
#ifdef USE_WINSOCK
2796
    WSACloseEvent(multi->wsa_event);
2797
#else
2798
0
#ifdef ENABLE_WAKEUP
2799
0
    wakeup_close(multi->wakeup_pair[0]);
2800
0
    wakeup_close(multi->wakeup_pair[1]);
2801
0
#endif
2802
0
#endif
2803
2804
#ifdef USE_SSL
2805
    Curl_free_multi_ssl_backend_data(multi->ssl_backend_data);
2806
#endif
2807
2808
0
    free(multi);
2809
2810
0
    return CURLM_OK;
2811
0
  }
2812
0
  return CURLM_BAD_HANDLE;
2813
0
}
2814
2815
/*
2816
 * curl_multi_info_read()
2817
 *
2818
 * This function is the primary way for a multi/multi_socket application to
2819
 * figure out if a transfer has ended. We MUST make this function as fast as
2820
 * possible as it will be polled frequently and we MUST NOT scan any lists in
2821
 * here to figure out things. We must scale fine to thousands of handles and
2822
 * beyond. The current design is fully O(1).
2823
 */
2824
2825
CURLMsg *curl_multi_info_read(struct Curl_multi *multi, int *msgs_in_queue)
2826
0
{
2827
0
  struct Curl_message *msg;
2828
2829
0
  *msgs_in_queue = 0; /* default to none */
2830
2831
0
  if(GOOD_MULTI_HANDLE(multi) &&
2832
0
     !multi->in_callback &&
2833
0
     Curl_llist_count(&multi->msglist)) {
2834
    /* there is one or more messages in the list */
2835
0
    struct Curl_llist_element *e;
2836
2837
    /* extract the head of the list to return */
2838
0
    e = multi->msglist.head;
2839
2840
0
    msg = e->ptr;
2841
2842
    /* remove the extracted entry */
2843
0
    Curl_llist_remove(&multi->msglist, e, NULL);
2844
2845
0
    *msgs_in_queue = curlx_uztosi(Curl_llist_count(&multi->msglist));
2846
2847
0
    return &msg->extmsg;
2848
0
  }
2849
0
  return NULL;
2850
0
}
2851
2852
/*
2853
 * singlesocket() checks what sockets we deal with and their "action state"
2854
 * and if we have a different state in any of those sockets from last time we
2855
 * call the callback accordingly.
2856
 */
2857
static CURLMcode singlesocket(struct Curl_multi *multi,
2858
                              struct Curl_easy *data)
2859
0
{
2860
0
  struct easy_pollset cur_poll;
2861
0
  unsigned int i;
2862
0
  struct Curl_sh_entry *entry;
2863
0
  curl_socket_t s;
2864
0
  int rc;
2865
2866
  /* Fill in the 'current' struct with the state as it is now: what sockets to
2867
     supervise and for what actions */
2868
0
  multi_getsock(data, &cur_poll);
2869
2870
  /* We have 0 .. N sockets already and we get to know about the 0 .. M
2871
     sockets we should have from now on. Detect the differences, remove no
2872
     longer supervised ones and add new ones */
2873
2874
  /* walk over the sockets we got right now */
2875
0
  for(i = 0; i < cur_poll.num; i++) {
2876
0
    unsigned char cur_action = cur_poll.actions[i];
2877
0
    unsigned char last_action = 0;
2878
0
    int comboaction;
2879
2880
0
    s = cur_poll.sockets[i];
2881
2882
    /* get it from the hash */
2883
0
    entry = sh_getentry(&multi->sockhash, s);
2884
0
    if(entry) {
2885
      /* check if new for this transfer */
2886
0
      unsigned int j;
2887
0
      for(j = 0; j< data->last_poll.num; j++) {
2888
0
        if(s == data->last_poll.sockets[j]) {
2889
0
          last_action = data->last_poll.actions[j];
2890
0
          break;
2891
0
        }
2892
0
      }
2893
0
    }
2894
0
    else {
2895
      /* this is a socket we didn't have before, add it to the hash! */
2896
0
      entry = sh_addentry(&multi->sockhash, s);
2897
0
      if(!entry)
2898
        /* fatal */
2899
0
        return CURLM_OUT_OF_MEMORY;
2900
0
    }
2901
0
    if(last_action && (last_action != cur_action)) {
2902
      /* Socket was used already, but different action now */
2903
0
      if(last_action & CURL_POLL_IN)
2904
0
        entry->readers--;
2905
0
      if(last_action & CURL_POLL_OUT)
2906
0
        entry->writers--;
2907
0
      if(cur_action & CURL_POLL_IN)
2908
0
        entry->readers++;
2909
0
      if(cur_action & CURL_POLL_OUT)
2910
0
        entry->writers++;
2911
0
    }
2912
0
    else if(!last_action) {
2913
      /* a new transfer using this socket */
2914
0
      entry->users++;
2915
0
      if(cur_action & CURL_POLL_IN)
2916
0
        entry->readers++;
2917
0
      if(cur_action & CURL_POLL_OUT)
2918
0
        entry->writers++;
2919
2920
      /* add 'data' to the transfer hash on this socket! */
2921
0
      if(!Curl_hash_add(&entry->transfers, (char *)&data, /* hash key */
2922
0
                        sizeof(struct Curl_easy *), data)) {
2923
0
        Curl_hash_destroy(&entry->transfers);
2924
0
        return CURLM_OUT_OF_MEMORY;
2925
0
      }
2926
0
    }
2927
2928
0
    comboaction = (entry->writers ? CURL_POLL_OUT : 0) |
2929
0
                   (entry->readers ? CURL_POLL_IN : 0);
2930
2931
    /* socket existed before and has the same action set as before */
2932
0
    if(last_action && ((int)entry->action == comboaction))
2933
      /* same, continue */
2934
0
      continue;
2935
2936
0
    if(multi->socket_cb) {
2937
0
      set_in_callback(multi, TRUE);
2938
0
      rc = multi->socket_cb(data, s, comboaction, multi->socket_userp,
2939
0
                            entry->socketp);
2940
2941
0
      set_in_callback(multi, FALSE);
2942
0
      if(rc == -1) {
2943
0
        multi->dead = TRUE;
2944
0
        return CURLM_ABORTED_BY_CALLBACK;
2945
0
      }
2946
0
    }
2947
2948
0
    entry->action = comboaction; /* store the current action state */
2949
0
  }
2950
2951
  /* Check for last_poll.sockets that no longer appear in cur_poll.sockets.
2952
   * Need to remove the easy handle from the multi->sockhash->transfers and
2953
   * remove multi->sockhash entry when this was the last transfer */
2954
0
  for(i = 0; i< data->last_poll.num; i++) {
2955
0
    unsigned int j;
2956
0
    bool stillused = FALSE;
2957
0
    s = data->last_poll.sockets[i];
2958
0
    for(j = 0; j < cur_poll.num; j++) {
2959
0
      if(s == cur_poll.sockets[j]) {
2960
        /* this is still supervised */
2961
0
        stillused = TRUE;
2962
0
        break;
2963
0
      }
2964
0
    }
2965
0
    if(stillused)
2966
0
      continue;
2967
2968
0
    entry = sh_getentry(&multi->sockhash, s);
2969
    /* if this is NULL here, the socket has been closed and notified so
2970
       already by Curl_multi_closed() */
2971
0
    if(entry) {
2972
0
      unsigned char oldactions = data->last_poll.actions[i];
2973
      /* this socket has been removed. Decrease user count */
2974
0
      entry->users--;
2975
0
      if(oldactions & CURL_POLL_OUT)
2976
0
        entry->writers--;
2977
0
      if(oldactions & CURL_POLL_IN)
2978
0
        entry->readers--;
2979
0
      if(!entry->users) {
2980
0
        if(multi->socket_cb) {
2981
0
          set_in_callback(multi, TRUE);
2982
0
          rc = multi->socket_cb(data, s, CURL_POLL_REMOVE,
2983
0
                                multi->socket_userp, entry->socketp);
2984
0
          set_in_callback(multi, FALSE);
2985
0
          if(rc == -1) {
2986
0
            multi->dead = TRUE;
2987
0
            return CURLM_ABORTED_BY_CALLBACK;
2988
0
          }
2989
0
        }
2990
0
        sh_delentry(entry, &multi->sockhash, s);
2991
0
      }
2992
0
      else {
2993
        /* still users, but remove this handle as a user of this socket */
2994
0
        if(Curl_hash_delete(&entry->transfers, (char *)&data,
2995
0
                            sizeof(struct Curl_easy *))) {
2996
0
          DEBUGASSERT(NULL);
2997
0
        }
2998
0
      }
2999
0
    }
3000
0
  } /* for loop over num */
3001
3002
  /* Remember for next time */
3003
0
  memcpy(&data->last_poll, &cur_poll, sizeof(data->last_poll));
3004
0
  return CURLM_OK;
3005
0
}
3006
3007
CURLcode Curl_updatesocket(struct Curl_easy *data)
3008
0
{
3009
0
  if(singlesocket(data->multi, data))
3010
0
    return CURLE_ABORTED_BY_CALLBACK;
3011
0
  return CURLE_OK;
3012
0
}
3013
3014
3015
/*
3016
 * Curl_multi_closed()
3017
 *
3018
 * Used by the connect code to tell the multi_socket code that one of the
3019
 * sockets we were using is about to be closed.  This function will then
3020
 * remove it from the sockethash for this handle to make the multi_socket API
3021
 * behave properly, especially for the case when libcurl will create another
3022
 * socket again and it gets the same file descriptor number.
3023
 */
3024
3025
void Curl_multi_closed(struct Curl_easy *data, curl_socket_t s)
3026
0
{
3027
0
  if(data) {
3028
    /* if there's still an easy handle associated with this connection */
3029
0
    struct Curl_multi *multi = data->multi;
3030
0
    if(multi) {
3031
      /* this is set if this connection is part of a handle that is added to
3032
         a multi handle, and only then this is necessary */
3033
0
      struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s);
3034
3035
0
      if(entry) {
3036
0
        int rc = 0;
3037
0
        if(multi->socket_cb) {
3038
0
          set_in_callback(multi, TRUE);
3039
0
          rc = multi->socket_cb(data, s, CURL_POLL_REMOVE,
3040
0
                                multi->socket_userp, entry->socketp);
3041
0
          set_in_callback(multi, FALSE);
3042
0
        }
3043
3044
        /* now remove it from the socket hash */
3045
0
        sh_delentry(entry, &multi->sockhash, s);
3046
0
        if(rc == -1)
3047
          /* This just marks the multi handle as "dead" without returning an
3048
             error code primarily because this function is used from many
3049
             places where propagating an error back is tricky. */
3050
0
          multi->dead = TRUE;
3051
0
      }
3052
0
    }
3053
0
  }
3054
0
}
3055
3056
/*
3057
 * add_next_timeout()
3058
 *
3059
 * Each Curl_easy has a list of timeouts. The add_next_timeout() is called
3060
 * when it has just been removed from the splay tree because the timeout has
3061
 * expired. This function is then to advance in the list to pick the next
3062
 * timeout to use (skip the already expired ones) and add this node back to
3063
 * the splay tree again.
3064
 *
3065
 * The splay tree only has each sessionhandle as a single node and the nearest
3066
 * timeout is used to sort it on.
3067
 */
3068
static CURLMcode add_next_timeout(struct curltime now,
3069
                                  struct Curl_multi *multi,
3070
                                  struct Curl_easy *d)
3071
0
{
3072
0
  struct curltime *tv = &d->state.expiretime;
3073
0
  struct Curl_llist *list = &d->state.timeoutlist;
3074
0
  struct Curl_llist_element *e;
3075
0
  struct time_node *node = NULL;
3076
3077
  /* move over the timeout list for this specific handle and remove all
3078
     timeouts that are now passed tense and store the next pending
3079
     timeout in *tv */
3080
0
  for(e = list->head; e;) {
3081
0
    struct Curl_llist_element *n = e->next;
3082
0
    timediff_t diff;
3083
0
    node = (struct time_node *)e->ptr;
3084
0
    diff = Curl_timediff_us(node->time, now);
3085
0
    if(diff <= 0)
3086
      /* remove outdated entry */
3087
0
      Curl_llist_remove(list, e, NULL);
3088
0
    else
3089
      /* the list is sorted so get out on the first mismatch */
3090
0
      break;
3091
0
    e = n;
3092
0
  }
3093
0
  e = list->head;
3094
0
  if(!e) {
3095
    /* clear the expire times within the handles that we remove from the
3096
       splay tree */
3097
0
    tv->tv_sec = 0;
3098
0
    tv->tv_usec = 0;
3099
0
  }
3100
0
  else {
3101
    /* copy the first entry to 'tv' */
3102
0
    memcpy(tv, &node->time, sizeof(*tv));
3103
3104
    /* Insert this node again into the splay.  Keep the timer in the list in
3105
       case we need to recompute future timers. */
3106
0
    multi->timetree = Curl_splayinsert(*tv, multi->timetree,
3107
0
                                       &d->state.timenode);
3108
0
  }
3109
0
  return CURLM_OK;
3110
0
}
3111
3112
static CURLMcode multi_socket(struct Curl_multi *multi,
3113
                              bool checkall,
3114
                              curl_socket_t s,
3115
                              int ev_bitmask,
3116
                              int *running_handles)
3117
0
{
3118
0
  CURLMcode result = CURLM_OK;
3119
0
  struct Curl_easy *data = NULL;
3120
0
  struct Curl_tree *t;
3121
0
  struct curltime now = Curl_now();
3122
0
  bool first = FALSE;
3123
0
  bool nosig = FALSE;
3124
0
  SIGPIPE_VARIABLE(pipe_st);
3125
3126
0
  if(checkall) {
3127
    /* *perform() deals with running_handles on its own */
3128
0
    result = curl_multi_perform(multi, running_handles);
3129
3130
    /* walk through each easy handle and do the socket state change magic
3131
       and callbacks */
3132
0
    if(result != CURLM_BAD_HANDLE) {
3133
0
      data = multi->easyp;
3134
0
      while(data && !result) {
3135
0
        result = singlesocket(multi, data);
3136
0
        data = data->next;
3137
0
      }
3138
0
    }
3139
3140
    /* or should we fall-through and do the timer-based stuff? */
3141
0
    return result;
3142
0
  }
3143
0
  if(s != CURL_SOCKET_TIMEOUT) {
3144
0
    struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s);
3145
3146
0
    if(!entry)
3147
      /* Unmatched socket, we can't act on it but we ignore this fact.  In
3148
         real-world tests it has been proved that libevent can in fact give
3149
         the application actions even though the socket was just previously
3150
         asked to get removed, so thus we better survive stray socket actions
3151
         and just move on. */
3152
0
      ;
3153
0
    else {
3154
0
      struct Curl_hash_iterator iter;
3155
0
      struct Curl_hash_element *he;
3156
3157
      /* the socket can be shared by many transfers, iterate */
3158
0
      Curl_hash_start_iterate(&entry->transfers, &iter);
3159
0
      for(he = Curl_hash_next_element(&iter); he;
3160
0
          he = Curl_hash_next_element(&iter)) {
3161
0
        data = (struct Curl_easy *)he->ptr;
3162
0
        DEBUGASSERT(data);
3163
0
        DEBUGASSERT(data->magic == CURLEASY_MAGIC_NUMBER);
3164
3165
0
        if(data->conn && !(data->conn->handler->flags & PROTOPT_DIRLOCK))
3166
          /* set socket event bitmask if they're not locked */
3167
0
          data->conn->cselect_bits = (unsigned char)ev_bitmask;
3168
3169
0
        Curl_expire(data, 0, EXPIRE_RUN_NOW);
3170
0
      }
3171
3172
      /* Now we fall-through and do the timer-based stuff, since we don't want
3173
         to force the user to have to deal with timeouts as long as at least
3174
         one connection in fact has traffic. */
3175
3176
0
      data = NULL; /* set data to NULL again to avoid calling
3177
                      multi_runsingle() in case there's no need to */
3178
0
      now = Curl_now(); /* get a newer time since the multi_runsingle() loop
3179
                           may have taken some time */
3180
0
    }
3181
0
  }
3182
0
  else {
3183
    /* Asked to run due to time-out. Clear the 'lastcall' variable to force
3184
       Curl_update_timer() to trigger a callback to the app again even if the
3185
       same timeout is still the one to run after this call. That handles the
3186
       case when the application asks libcurl to run the timeout
3187
       prematurely. */
3188
0
    memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall));
3189
0
  }
3190
3191
  /*
3192
   * The loop following here will go on as long as there are expire-times left
3193
   * to process in the splay and 'data' will be re-assigned for every expired
3194
   * handle we deal with.
3195
   */
3196
0
  do {
3197
    /* the first loop lap 'data' can be NULL */
3198
0
    if(data) {
3199
0
      if(!first) {
3200
0
        first = TRUE;
3201
0
        nosig = data->set.no_signal; /* initial state */
3202
0
        sigpipe_ignore(data, &pipe_st);
3203
0
      }
3204
0
      else if(data->set.no_signal != nosig) {
3205
0
        sigpipe_restore(&pipe_st);
3206
0
        sigpipe_ignore(data, &pipe_st);
3207
0
        nosig = data->set.no_signal; /* remember new state */
3208
0
      }
3209
0
      result = multi_runsingle(multi, &now, data);
3210
3211
0
      if(CURLM_OK >= result) {
3212
        /* get the socket(s) and check if the state has been changed since
3213
           last */
3214
0
        result = singlesocket(multi, data);
3215
0
        if(result)
3216
0
          break;
3217
0
      }
3218
0
    }
3219
3220
    /* Check if there's one (more) expired timer to deal with! This function
3221
       extracts a matching node if there is one */
3222
3223
0
    multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
3224
0
    if(t) {
3225
0
      data = t->payload; /* assign this for next loop */
3226
0
      (void)add_next_timeout(now, multi, t->payload);
3227
0
    }
3228
3229
0
  } while(t);
3230
0
  if(first)
3231
0
    sigpipe_restore(&pipe_st);
3232
3233
0
  *running_handles = multi->num_alive;
3234
0
  return result;
3235
0
}
3236
3237
#undef curl_multi_setopt
3238
CURLMcode curl_multi_setopt(struct Curl_multi *multi,
3239
                            CURLMoption option, ...)
3240
0
{
3241
0
  CURLMcode res = CURLM_OK;
3242
0
  va_list param;
3243
0
  unsigned long uarg;
3244
3245
0
  if(!GOOD_MULTI_HANDLE(multi))
3246
0
    return CURLM_BAD_HANDLE;
3247
3248
0
  if(multi->in_callback)
3249
0
    return CURLM_RECURSIVE_API_CALL;
3250
3251
0
  va_start(param, option);
3252
3253
0
  switch(option) {
3254
0
  case CURLMOPT_SOCKETFUNCTION:
3255
0
    multi->socket_cb = va_arg(param, curl_socket_callback);
3256
0
    break;
3257
0
  case CURLMOPT_SOCKETDATA:
3258
0
    multi->socket_userp = va_arg(param, void *);
3259
0
    break;
3260
0
  case CURLMOPT_PUSHFUNCTION:
3261
0
    multi->push_cb = va_arg(param, curl_push_callback);
3262
0
    break;
3263
0
  case CURLMOPT_PUSHDATA:
3264
0
    multi->push_userp = va_arg(param, void *);
3265
0
    break;
3266
0
  case CURLMOPT_PIPELINING:
3267
0
    multi->multiplexing = va_arg(param, long) & CURLPIPE_MULTIPLEX ? 1 : 0;
3268
0
    break;
3269
0
  case CURLMOPT_TIMERFUNCTION:
3270
0
    multi->timer_cb = va_arg(param, curl_multi_timer_callback);
3271
0
    break;
3272
0
  case CURLMOPT_TIMERDATA:
3273
0
    multi->timer_userp = va_arg(param, void *);
3274
0
    break;
3275
0
  case CURLMOPT_MAXCONNECTS:
3276
0
    uarg = va_arg(param, unsigned long);
3277
0
    if(uarg <= UINT_MAX)
3278
0
      multi->maxconnects = (unsigned int)uarg;
3279
0
    break;
3280
0
  case CURLMOPT_MAX_HOST_CONNECTIONS:
3281
0
    multi->max_host_connections = va_arg(param, long);
3282
0
    break;
3283
0
  case CURLMOPT_MAX_TOTAL_CONNECTIONS:
3284
0
    multi->max_total_connections = va_arg(param, long);
3285
0
    break;
3286
    /* options formerly used for pipelining */
3287
0
  case CURLMOPT_MAX_PIPELINE_LENGTH:
3288
0
    break;
3289
0
  case CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE:
3290
0
    break;
3291
0
  case CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE:
3292
0
    break;
3293
0
  case CURLMOPT_PIPELINING_SITE_BL:
3294
0
    break;
3295
0
  case CURLMOPT_PIPELINING_SERVER_BL:
3296
0
    break;
3297
0
  case CURLMOPT_MAX_CONCURRENT_STREAMS:
3298
0
    {
3299
0
      long streams = va_arg(param, long);
3300
0
      if((streams < 1) || (streams > INT_MAX))
3301
0
        streams = 100;
3302
0
      multi->max_concurrent_streams = (unsigned int)streams;
3303
0
    }
3304
0
    break;
3305
0
  default:
3306
0
    res = CURLM_UNKNOWN_OPTION;
3307
0
    break;
3308
0
  }
3309
0
  va_end(param);
3310
0
  return res;
3311
0
}
3312
3313
/* we define curl_multi_socket() in the public multi.h header */
3314
#undef curl_multi_socket
3315
3316
CURLMcode curl_multi_socket(struct Curl_multi *multi, curl_socket_t s,
3317
                            int *running_handles)
3318
0
{
3319
0
  CURLMcode result;
3320
0
  if(multi->in_callback)
3321
0
    return CURLM_RECURSIVE_API_CALL;
3322
0
  result = multi_socket(multi, FALSE, s, 0, running_handles);
3323
0
  if(CURLM_OK >= result)
3324
0
    result = Curl_update_timer(multi);
3325
0
  return result;
3326
0
}
3327
3328
CURLMcode curl_multi_socket_action(struct Curl_multi *multi, curl_socket_t s,
3329
                                   int ev_bitmask, int *running_handles)
3330
0
{
3331
0
  CURLMcode result;
3332
0
  if(multi->in_callback)
3333
0
    return CURLM_RECURSIVE_API_CALL;
3334
0
  result = multi_socket(multi, FALSE, s, ev_bitmask, running_handles);
3335
0
  if(CURLM_OK >= result)
3336
0
    result = Curl_update_timer(multi);
3337
0
  return result;
3338
0
}
3339
3340
CURLMcode curl_multi_socket_all(struct Curl_multi *multi, int *running_handles)
3341
0
{
3342
0
  CURLMcode result;
3343
0
  if(multi->in_callback)
3344
0
    return CURLM_RECURSIVE_API_CALL;
3345
0
  result = multi_socket(multi, TRUE, CURL_SOCKET_BAD, 0, running_handles);
3346
0
  if(CURLM_OK >= result)
3347
0
    result = Curl_update_timer(multi);
3348
0
  return result;
3349
0
}
3350
3351
static CURLMcode multi_timeout(struct Curl_multi *multi,
3352
                               long *timeout_ms)
3353
0
{
3354
0
  static const struct curltime tv_zero = {0, 0};
3355
3356
0
  if(multi->dead) {
3357
0
    *timeout_ms = 0;
3358
0
    return CURLM_OK;
3359
0
  }
3360
3361
0
  if(multi->timetree) {
3362
    /* we have a tree of expire times */
3363
0
    struct curltime now = Curl_now();
3364
3365
    /* splay the lowest to the bottom */
3366
0
    multi->timetree = Curl_splay(tv_zero, multi->timetree);
3367
3368
0
    if(Curl_splaycomparekeys(multi->timetree->key, now) > 0) {
3369
      /* some time left before expiration */
3370
0
      timediff_t diff = Curl_timediff_ceil(multi->timetree->key, now);
3371
      /* this should be safe even on 32 bit archs, as we don't use that
3372
         overly long timeouts */
3373
0
      *timeout_ms = (long)diff;
3374
0
    }
3375
0
    else
3376
      /* 0 means immediately */
3377
0
      *timeout_ms = 0;
3378
0
  }
3379
0
  else
3380
0
    *timeout_ms = -1;
3381
3382
0
  return CURLM_OK;
3383
0
}
3384
3385
CURLMcode curl_multi_timeout(struct Curl_multi *multi,
3386
                             long *timeout_ms)
3387
0
{
3388
  /* First, make some basic checks that the CURLM handle is a good handle */
3389
0
  if(!GOOD_MULTI_HANDLE(multi))
3390
0
    return CURLM_BAD_HANDLE;
3391
3392
0
  if(multi->in_callback)
3393
0
    return CURLM_RECURSIVE_API_CALL;
3394
3395
0
  return multi_timeout(multi, timeout_ms);
3396
0
}
3397
3398
/*
3399
 * Tell the application it should update its timers, if it subscribes to the
3400
 * update timer callback.
3401
 */
3402
CURLMcode Curl_update_timer(struct Curl_multi *multi)
3403
0
{
3404
0
  long timeout_ms;
3405
0
  int rc;
3406
3407
0
  if(!multi->timer_cb || multi->dead)
3408
0
    return CURLM_OK;
3409
0
  if(multi_timeout(multi, &timeout_ms)) {
3410
0
    return CURLM_OK;
3411
0
  }
3412
0
  if(timeout_ms < 0) {
3413
0
    static const struct curltime none = {0, 0};
3414
0
    if(Curl_splaycomparekeys(none, multi->timer_lastcall)) {
3415
0
      multi->timer_lastcall = none;
3416
      /* there's no timeout now but there was one previously, tell the app to
3417
         disable it */
3418
0
      set_in_callback(multi, TRUE);
3419
0
      rc = multi->timer_cb(multi, -1, multi->timer_userp);
3420
0
      set_in_callback(multi, FALSE);
3421
0
      if(rc == -1) {
3422
0
        multi->dead = TRUE;
3423
0
        return CURLM_ABORTED_BY_CALLBACK;
3424
0
      }
3425
0
      return CURLM_OK;
3426
0
    }
3427
0
    return CURLM_OK;
3428
0
  }
3429
3430
  /* When multi_timeout() is done, multi->timetree points to the node with the
3431
   * timeout we got the (relative) time-out time for. We can thus easily check
3432
   * if this is the same (fixed) time as we got in a previous call and then
3433
   * avoid calling the callback again. */
3434
0
  if(Curl_splaycomparekeys(multi->timetree->key, multi->timer_lastcall) == 0)
3435
0
    return CURLM_OK;
3436
3437
0
  multi->timer_lastcall = multi->timetree->key;
3438
3439
0
  set_in_callback(multi, TRUE);
3440
0
  rc = multi->timer_cb(multi, timeout_ms, multi->timer_userp);
3441
0
  set_in_callback(multi, FALSE);
3442
0
  if(rc == -1) {
3443
0
    multi->dead = TRUE;
3444
0
    return CURLM_ABORTED_BY_CALLBACK;
3445
0
  }
3446
0
  return CURLM_OK;
3447
0
}
3448
3449
/*
3450
 * multi_deltimeout()
3451
 *
3452
 * Remove a given timestamp from the list of timeouts.
3453
 */
3454
static void
3455
multi_deltimeout(struct Curl_easy *data, expire_id eid)
3456
0
{
3457
0
  struct Curl_llist_element *e;
3458
0
  struct Curl_llist *timeoutlist = &data->state.timeoutlist;
3459
  /* find and remove the specific node from the list */
3460
0
  for(e = timeoutlist->head; e; e = e->next) {
3461
0
    struct time_node *n = (struct time_node *)e->ptr;
3462
0
    if(n->eid == eid) {
3463
0
      Curl_llist_remove(timeoutlist, e, NULL);
3464
0
      return;
3465
0
    }
3466
0
  }
3467
0
}
3468
3469
/*
3470
 * multi_addtimeout()
3471
 *
3472
 * Add a timestamp to the list of timeouts. Keep the list sorted so that head
3473
 * of list is always the timeout nearest in time.
3474
 *
3475
 */
3476
static CURLMcode
3477
multi_addtimeout(struct Curl_easy *data,
3478
                 struct curltime *stamp,
3479
                 expire_id eid)
3480
0
{
3481
0
  struct Curl_llist_element *e;
3482
0
  struct time_node *node;
3483
0
  struct Curl_llist_element *prev = NULL;
3484
0
  size_t n;
3485
0
  struct Curl_llist *timeoutlist = &data->state.timeoutlist;
3486
3487
0
  node = &data->state.expires[eid];
3488
3489
  /* copy the timestamp and id */
3490
0
  memcpy(&node->time, stamp, sizeof(*stamp));
3491
0
  node->eid = eid; /* also marks it as in use */
3492
3493
0
  n = Curl_llist_count(timeoutlist);
3494
0
  if(n) {
3495
    /* find the correct spot in the list */
3496
0
    for(e = timeoutlist->head; e; e = e->next) {
3497
0
      struct time_node *check = (struct time_node *)e->ptr;
3498
0
      timediff_t diff = Curl_timediff(check->time, node->time);
3499
0
      if(diff > 0)
3500
0
        break;
3501
0
      prev = e;
3502
0
    }
3503
3504
0
  }
3505
  /* else
3506
     this is the first timeout on the list */
3507
3508
0
  Curl_llist_insert_next(timeoutlist, prev, node, &node->list);
3509
0
  return CURLM_OK;
3510
0
}
3511
3512
/*
3513
 * Curl_expire()
3514
 *
3515
 * given a number of milliseconds from now to use to set the 'act before
3516
 * this'-time for the transfer, to be extracted by curl_multi_timeout()
3517
 *
3518
 * The timeout will be added to a queue of timeouts if it defines a moment in
3519
 * time that is later than the current head of queue.
3520
 *
3521
 * Expire replaces a former timeout using the same id if already set.
3522
 */
3523
void Curl_expire(struct Curl_easy *data, timediff_t milli, expire_id id)
3524
0
{
3525
0
  struct Curl_multi *multi = data->multi;
3526
0
  struct curltime *nowp = &data->state.expiretime;
3527
0
  struct curltime set;
3528
3529
  /* this is only interesting while there is still an associated multi struct
3530
     remaining! */
3531
0
  if(!multi)
3532
0
    return;
3533
3534
0
  DEBUGASSERT(id < EXPIRE_LAST);
3535
3536
0
  set = Curl_now();
3537
0
  set.tv_sec += (time_t)(milli/1000); /* might be a 64 to 32 bit conversion */
3538
0
  set.tv_usec += (unsigned int)(milli%1000)*1000;
3539
3540
0
  if(set.tv_usec >= 1000000) {
3541
0
    set.tv_sec++;
3542
0
    set.tv_usec -= 1000000;
3543
0
  }
3544
3545
  /* Remove any timer with the same id just in case. */
3546
0
  multi_deltimeout(data, id);
3547
3548
  /* Add it to the timer list.  It must stay in the list until it has expired
3549
     in case we need to recompute the minimum timer later. */
3550
0
  multi_addtimeout(data, &set, id);
3551
3552
0
  if(nowp->tv_sec || nowp->tv_usec) {
3553
    /* This means that the struct is added as a node in the splay tree.
3554
       Compare if the new time is earlier, and only remove-old/add-new if it
3555
       is. */
3556
0
    timediff_t diff = Curl_timediff(set, *nowp);
3557
0
    int rc;
3558
3559
0
    if(diff > 0) {
3560
      /* The current splay tree entry is sooner than this new expiry time.
3561
         We don't need to update our splay tree entry. */
3562
0
      return;
3563
0
    }
3564
3565
    /* Since this is an updated time, we must remove the previous entry from
3566
       the splay tree first and then re-add the new value */
3567
0
    rc = Curl_splayremove(multi->timetree, &data->state.timenode,
3568
0
                          &multi->timetree);
3569
0
    if(rc)
3570
0
      infof(data, "Internal error removing splay node = %d", rc);
3571
0
  }
3572
3573
  /* Indicate that we are in the splay tree and insert the new timer expiry
3574
     value since it is our local minimum. */
3575
0
  *nowp = set;
3576
0
  data->state.timenode.payload = data;
3577
0
  multi->timetree = Curl_splayinsert(*nowp, multi->timetree,
3578
0
                                     &data->state.timenode);
3579
0
}
3580
3581
/*
3582
 * Curl_expire_done()
3583
 *
3584
 * Removes the expire timer. Marks it as done.
3585
 *
3586
 */
3587
void Curl_expire_done(struct Curl_easy *data, expire_id id)
3588
0
{
3589
  /* remove the timer, if there */
3590
0
  multi_deltimeout(data, id);
3591
0
}
3592
3593
/*
3594
 * Curl_expire_clear()
3595
 *
3596
 * Clear ALL timeout values for this handle.
3597
 */
3598
void Curl_expire_clear(struct Curl_easy *data)
3599
1.16k
{
3600
1.16k
  struct Curl_multi *multi = data->multi;
3601
1.16k
  struct curltime *nowp = &data->state.expiretime;
3602
3603
  /* this is only interesting while there is still an associated multi struct
3604
     remaining! */
3605
1.16k
  if(!multi)
3606
1.16k
    return;
3607
3608
0
  if(nowp->tv_sec || nowp->tv_usec) {
3609
    /* Since this is an cleared time, we must remove the previous entry from
3610
       the splay tree */
3611
0
    struct Curl_llist *list = &data->state.timeoutlist;
3612
0
    int rc;
3613
3614
0
    rc = Curl_splayremove(multi->timetree, &data->state.timenode,
3615
0
                          &multi->timetree);
3616
0
    if(rc)
3617
0
      infof(data, "Internal error clearing splay node = %d", rc);
3618
3619
    /* flush the timeout list too */
3620
0
    while(list->size > 0) {
3621
0
      Curl_llist_remove(list, list->tail, NULL);
3622
0
    }
3623
3624
0
#ifdef DEBUGBUILD
3625
0
    infof(data, "Expire cleared");
3626
0
#endif
3627
0
    nowp->tv_sec = 0;
3628
0
    nowp->tv_usec = 0;
3629
0
  }
3630
0
}
3631
3632
3633
3634
3635
CURLMcode curl_multi_assign(struct Curl_multi *multi, curl_socket_t s,
3636
                            void *hashp)
3637
0
{
3638
0
  struct Curl_sh_entry *there = NULL;
3639
3640
0
  there = sh_getentry(&multi->sockhash, s);
3641
3642
0
  if(!there)
3643
0
    return CURLM_BAD_SOCKET;
3644
3645
0
  there->socketp = hashp;
3646
3647
0
  return CURLM_OK;
3648
0
}
3649
3650
size_t Curl_multi_max_host_connections(struct Curl_multi *multi)
3651
0
{
3652
0
  return multi ? multi->max_host_connections : 0;
3653
0
}
3654
3655
size_t Curl_multi_max_total_connections(struct Curl_multi *multi)
3656
0
{
3657
0
  return multi ? multi->max_total_connections : 0;
3658
0
}
3659
3660
/*
3661
 * When information about a connection has appeared, call this!
3662
 */
3663
3664
void Curl_multiuse_state(struct Curl_easy *data,
3665
                         int bundlestate) /* use BUNDLE_* defines */
3666
0
{
3667
0
  struct connectdata *conn;
3668
0
  DEBUGASSERT(data);
3669
0
  DEBUGASSERT(data->multi);
3670
0
  conn = data->conn;
3671
0
  DEBUGASSERT(conn);
3672
0
  DEBUGASSERT(conn->bundle);
3673
3674
0
  conn->bundle->multiuse = bundlestate;
3675
0
  process_pending_handles(data->multi);
3676
0
}
3677
3678
/* process_pending_handles() moves all handles from PENDING
3679
   back into the main list and change state to CONNECT */
3680
static void process_pending_handles(struct Curl_multi *multi)
3681
0
{
3682
0
  struct Curl_llist_element *e = multi->pending.head;
3683
0
  if(e) {
3684
0
    struct Curl_easy *data = e->ptr;
3685
3686
0
    DEBUGASSERT(data->mstate == MSTATE_PENDING);
3687
3688
    /* put it back into the main list */
3689
0
    link_easy(multi, data);
3690
3691
0
    multistate(data, MSTATE_CONNECT);
3692
3693
    /* Remove this node from the list */
3694
0
    Curl_llist_remove(&multi->pending, e, NULL);
3695
3696
    /* Make sure that the handle will be processed soonish. */
3697
0
    Curl_expire(data, 0, EXPIRE_RUN_NOW);
3698
3699
    /* mark this as having been in the pending queue */
3700
0
    data->state.previouslypending = TRUE;
3701
0
  }
3702
0
}
3703
3704
void Curl_set_in_callback(struct Curl_easy *data, bool value)
3705
0
{
3706
  /* might get called when there is no data pointer! */
3707
0
  if(data) {
3708
0
    if(data->multi_easy)
3709
0
      data->multi_easy->in_callback = value;
3710
0
    else if(data->multi)
3711
0
      data->multi->in_callback = value;
3712
0
  }
3713
0
}
3714
3715
bool Curl_is_in_callback(struct Curl_easy *easy)
3716
0
{
3717
0
  return ((easy->multi && easy->multi->in_callback) ||
3718
0
          (easy->multi_easy && easy->multi_easy->in_callback));
3719
0
}
3720
3721
unsigned int Curl_multi_max_concurrent_streams(struct Curl_multi *multi)
3722
0
{
3723
0
  DEBUGASSERT(multi);
3724
0
  return multi->max_concurrent_streams;
3725
0
}
3726
3727
struct Curl_easy **curl_multi_get_handles(struct Curl_multi *multi)
3728
0
{
3729
0
  struct Curl_easy **a = malloc(sizeof(struct Curl_easy *) *
3730
0
                                (multi->num_easy + 1));
3731
0
  if(a) {
3732
0
    unsigned int i = 0;
3733
0
    struct Curl_easy *e = multi->easyp;
3734
0
    while(e) {
3735
0
      DEBUGASSERT(i < multi->num_easy);
3736
0
      if(!e->state.internal)
3737
0
        a[i++] = e;
3738
0
      e = e->next;
3739
0
    }
3740
0
    a[i] = NULL; /* last entry is a NULL */
3741
0
  }
3742
0
  return a;
3743
0
}