Coverage Report

Created: 2024-02-25 06:14

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