Coverage Report

Created: 2023-06-07 07:02

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