Coverage Report

Created: 2024-05-04 12:45

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