Coverage Report

Created: 2026-07-30 07:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/curl/lib/transfer.c
Line
Count
Source
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
#include "curl_setup.h"
25
26
#ifdef HAVE_NETINET_IN_H
27
#include <netinet/in.h>
28
#endif
29
#ifdef HAVE_NETDB_H
30
#include <netdb.h>
31
#endif
32
#ifdef HAVE_ARPA_INET_H
33
#include <arpa/inet.h>
34
#endif
35
#ifdef HAVE_NET_IF_H
36
#include <net/if.h>
37
#endif
38
#ifdef HAVE_SYS_IOCTL_H
39
#include <sys/ioctl.h>
40
#endif
41
#include <signal.h>
42
43
#ifdef HAVE_SYS_PARAM_H
44
#include <sys/param.h>
45
#endif
46
47
#ifdef HAVE_SYS_SELECT_H
48
#include <sys/select.h>
49
#elif defined(HAVE_UNISTD_H)
50
#include <unistd.h>
51
#endif
52
53
#ifndef HAVE_SOCKET
54
#error "We cannot compile without socket() support"
55
#endif
56
57
#include "urldata.h"
58
59
#include "hostip.h"
60
#include "cfilters.h"
61
#include "cw-out.h"
62
#include "dnscache.h"
63
#include "transfer.h"
64
#include "sendf.h"
65
#include "curl_trc.h"
66
#include "progress.h"
67
#include "http.h"
68
#include "url.h"
69
#include "getinfo.h"
70
#include "multiif.h"
71
#include "connect.h"
72
#include "hsts.h"
73
#include "setopt.h"
74
#include "headers.h"
75
#include "bufref.h"
76
77
#if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_SMTP) || \
78
  !defined(CURL_DISABLE_IMAP)
79
/*
80
 * checkheaders() checks the linked list of custom headers for a
81
 * particular header (prefix). Provide the prefix without colon!
82
 *
83
 * Returns a pointer to the first matching header or NULL if none matched.
84
 */
85
char *Curl_checkheaders(const struct Curl_easy *data,
86
                        const char *thisheader,
87
                        const size_t thislen)
88
549k
{
89
549k
  struct curl_slist *head;
90
549k
  DEBUGASSERT(thislen);
91
549k
  DEBUGASSERT(thisheader[thislen - 1] != ':');
92
93
1.98M
  for(head = data->set.headers; head; head = head->next) {
94
1.43M
    if(curl_strnequal(head->data, thisheader, thislen) &&
95
6.78k
       Curl_headersep(head->data[thislen]))
96
3.89k
      return head->data;
97
1.43M
  }
98
99
545k
  return NULL;
100
549k
}
101
#endif
102
103
static int data_pending(struct Curl_easy *data, bool rcvd_eagain)
104
142k
{
105
142k
  struct connectdata *conn = data->conn;
106
107
142k
  if(conn->scheme->protocol & PROTO_FAMILY_FTP)
108
5
    return Curl_conn_data_pending(data, SECONDARYSOCKET);
109
110
  /* in the case of libssh2, we can never be really sure that we have emptied
111
     its internal buffers so we MUST always try until we get EAGAIN back */
112
142k
  return (!rcvd_eagain &&
113
0
          conn->scheme->protocol & (CURLPROTO_SCP | CURLPROTO_SFTP)) ||
114
142k
         Curl_conn_data_pending(data, FIRSTSOCKET);
115
142k
}
116
117
/*
118
 * Check to see if CURLOPT_TIMECONDITION was met by comparing the time of the
119
 * remote document with the time provided by CURLOPT_TIMEVAL
120
 */
121
bool Curl_meets_timecondition(struct Curl_easy *data, time_t timeofdoc)
122
303
{
123
303
  if((timeofdoc == 0) || (data->set.timevalue == 0))
124
204
    return TRUE;
125
126
99
  switch(data->set.timecondition) {
127
15
  case CURL_TIMECOND_IFMODSINCE:
128
46
  default:
129
46
    if(timeofdoc <= data->set.timevalue) {
130
15
      infof(data, "The requested document is not new enough");
131
15
      data->info.timecond = TRUE;
132
15
      return FALSE;
133
15
    }
134
31
    break;
135
53
  case CURL_TIMECOND_IFUNMODSINCE:
136
53
    if(timeofdoc >= data->set.timevalue) {
137
32
      infof(data, "The requested document is not old enough");
138
32
      data->info.timecond = TRUE;
139
32
      return FALSE;
140
32
    }
141
21
    break;
142
99
  }
143
144
52
  return TRUE;
145
99
}
146
147
static CURLcode xfer_recv_shutdown(struct Curl_easy *data, bool *done)
148
622
{
149
622
  if(!data || !data->conn)
150
0
    return CURLE_FAILED_INIT;
151
622
  return Curl_conn_shutdown(data, data->conn->recv_idx, done);
152
622
}
153
154
static bool xfer_recv_shutdown_started(struct Curl_easy *data)
155
275k
{
156
275k
  if(!data || !data->conn)
157
0
    return FALSE;
158
275k
  return Curl_shutdown_started(data->conn, data->conn->recv_idx);
159
275k
}
160
161
CURLcode Curl_xfer_send_shutdown(struct Curl_easy *data, bool *done)
162
11
{
163
11
  if(!data || !data->conn)
164
0
    return CURLE_FAILED_INIT;
165
11
  return Curl_conn_shutdown(data, data->conn->send_idx, done);
166
11
}
167
168
/**
169
 * Receive raw response data for the transfer.
170
 * @param data         the transfer
171
 * @param buf          buffer to keep response data received
172
 * @param blen         length of `buf`
173
 * @param eos_reliable if EOS detection in underlying connection is reliable
174
 * @return number of bytes read or -1 for error
175
 */
176
static CURLcode xfer_recv_resp(struct Curl_easy *data,
177
                               char *buf, size_t blen,
178
                               bool eos_reliable,
179
                               size_t *pnread)
180
279k
{
181
279k
  CURLcode result;
182
183
279k
  DEBUGASSERT(blen > 0);
184
279k
  *pnread = 0;
185
  /* If we are reading BODY data and the connection does NOT handle EOF
186
   * and we know the size of the BODY data, limit the read amount */
187
279k
  if(!eos_reliable && !data->req.header && data->req.size != -1) {
188
3.95k
    blen = curlx_sotouz_range(data->req.size - data->req.bytecount, 0, blen);
189
3.95k
  }
190
275k
  else if(xfer_recv_shutdown_started(data)) {
191
    /* we already received everything. Do not try more. */
192
0
    blen = 0;
193
0
  }
194
195
279k
  if(blen) {
196
279k
    result = Curl_xfer_recv(data, buf, blen, pnread);
197
279k
    if(result)
198
161k
      return result;
199
279k
  }
200
201
117k
  if(*pnread == 0) {
202
24.1k
    if(data->req.shutdown) {
203
622
      bool done;
204
622
      result = xfer_recv_shutdown(data, &done);
205
622
      if(result)
206
0
        return result;
207
622
      if(!done) {
208
0
        return CURLE_AGAIN;
209
0
      }
210
622
    }
211
24.1k
    DEBUGF(infof(data, "sendrecv_dl: we are done"));
212
24.1k
  }
213
117k
  return CURLE_OK;
214
117k
}
215
216
/*
217
 * Go ahead and do a read if we have a readable socket or if
218
 * the stream was rewound (in which case we have data in a
219
 * buffer)
220
 */
221
static CURLcode sendrecv_dl(struct Curl_easy *data,
222
                            struct SingleRequest *k)
223
213k
{
224
213k
  struct connectdata *conn = data->conn;
225
213k
  CURLcode result = CURLE_OK;
226
213k
  char *buf, *xfer_buf;
227
213k
  size_t blen, xfer_blen;
228
213k
  int maxloops = 10;
229
213k
  bool is_multiplex = FALSE;
230
213k
  bool rcvd_eagain = FALSE;
231
213k
  bool is_eos = FALSE, rate_limited = FALSE;
232
233
213k
  result = Curl_multi_xfer_buf_borrow(data, &xfer_buf, &xfer_blen);
234
213k
  if(result)
235
0
    goto out;
236
237
  /* This is where we loop until we have read everything there is to
238
     read or we get a CURLE_AGAIN */
239
279k
  do {
240
279k
    size_t bytestoread;
241
242
279k
    if(!is_multiplex) {
243
      /* Multiplexed connection have inherent handling of EOF and we do not
244
       * have to carefully restrict the amount we try to read.
245
       * Multiplexed changes only in one direction. */
246
279k
      is_multiplex = Curl_conn_is_multiplex(conn, FIRSTSOCKET);
247
279k
    }
248
249
279k
    buf = xfer_buf;
250
279k
    bytestoread = xfer_blen;
251
252
279k
    if(bytestoread && Curl_rlimit_active(&data->progress.dl.rlimit)) {
253
212k
      curl_off_t dl_avail = Curl_rlimit_avail(&data->progress.dl.rlimit, NULL);
254
#if 0
255
      DEBUGF(infof(data, "dl_rlimit, available=%" FMT_OFF_T, dl_avail));
256
#endif
257
      /* In case of rate limited downloads: if this loop already got data and
258
       * less than 16k is left in the limit, break out. We want to stutter a
259
       * bit to keep in the limit, but too small receives will cost cpu
260
       * unnecessarily. */
261
212k
      if(dl_avail <= 0) {
262
167
        rate_limited = TRUE;
263
167
        break;
264
167
      }
265
212k
      if(dl_avail < (curl_off_t)bytestoread)
266
67.6k
        bytestoread = (size_t)dl_avail;
267
212k
    }
268
269
279k
    rcvd_eagain = FALSE;
270
279k
    result = xfer_recv_resp(data, buf, bytestoread, is_multiplex, &blen);
271
279k
    if(result) {
272
161k
      if(result != CURLE_AGAIN)
273
19.1k
        goto out; /* real error */
274
142k
      rcvd_eagain = TRUE;
275
142k
      result = CURLE_OK;
276
142k
      if(data->req.download_done && data->req.no_body &&
277
7
         !data->req.resp_trailer) {
278
7
        DEBUGF(infof(data, "EAGAIN, download done, no trailer announced, "
279
7
                     "not waiting for EOS"));
280
7
        blen = 0;
281
        /* continue as if we received the EOS */
282
7
      }
283
142k
      else
284
142k
        break; /* get out of loop */
285
142k
    }
286
287
    /* We only get a 0-length receive at the end of the response */
288
117k
    is_eos = (blen == 0);
289
290
117k
    if(!blen) {
291
24.1k
      result = Curl_req_stop_send_recv(data);
292
24.1k
      if(result)
293
0
        goto out;
294
24.1k
      if(k->eos_written) /* already did write this to client, leave */
295
0
        break;
296
24.1k
    }
297
298
117k
    result = Curl_xfer_write_resp(data, buf, blen, is_eos);
299
117k
    if(result || data->req.done)
300
7.78k
      goto out;
301
302
    /* if we are done, we stop receiving. On multiplexed connections,
303
     * we should read the EOS. Which may arrive as meta data after
304
     * the bytes. Not taking it in might lead to RST of streams. */
305
110k
    if((!is_multiplex && data->req.download_done) || is_eos) {
306
42.8k
      CURL_REQ_CLEAR_RECV(data);
307
42.8k
    }
308
    /* if we stopped receiving, leave the loop */
309
110k
    if(!CURL_REQ_WANT_RECV(data))
310
43.2k
      break;
311
312
110k
  } while(maxloops--);
313
314
186k
  if(!is_eos && !rate_limited && CURL_REQ_WANT_RECV(data) &&
315
143k
     (!rcvd_eagain || data_pending(data, rcvd_eagain))) {
316
    /* Did not read until EAGAIN/EOS or there is still data pending
317
     * in buffers. Mark as read-again via simulated SELECT results. */
318
1.43k
    Curl_multi_mark_dirty(data);
319
1.43k
    CURL_TRC_M(data, "sendrecv_dl() no EAGAIN/pending data, mark as dirty");
320
1.43k
  }
321
322
186k
  if(!CURL_REQ_WANT_RECV(data) && CURL_REQ_WANT_SEND(data) &&
323
172
     (conn->bits.close || is_multiplex)) {
324
    /* When we have read the entire thing and the close bit is set, the server
325
       may now close the connection. If there is now any kind of sending going
326
       on from our side, we need to stop that immediately. */
327
5
    infof(data, "we are done reading and this is set to close, stop send");
328
5
    Curl_req_abort_sending(data);
329
5
  }
330
331
213k
out:
332
213k
  Curl_multi_xfer_buf_release(data, xfer_buf);
333
213k
  if(result)
334
26.6k
    DEBUGF(infof(data, "sendrecv_dl() -> %d", (int)result));
335
213k
  return result;
336
186k
}
337
338
/*
339
 * Send data to upload to the server, when the socket is writable.
340
 */
341
static CURLcode sendrecv_ul(struct Curl_easy *data)
342
14.5k
{
343
  /* We should not get here when the sending is already done. */
344
14.5k
  DEBUGASSERT(!Curl_req_done_sending(data));
345
346
14.5k
  if(!Curl_req_done_sending(data))
347
14.5k
    return Curl_req_send_more(data);
348
0
  return CURLE_OK;
349
14.5k
}
350
351
/*
352
 * Curl_sendrecv() is the low-level function to be called when data is to
353
 * be read and written to/from the connection.
354
 */
355
CURLcode Curl_sendrecv(struct Curl_easy *data)
356
222k
{
357
222k
  struct SingleRequest *k = &data->req;
358
222k
  CURLcode result = CURLE_OK;
359
360
222k
  if(Curl_xfer_is_blocked(data)) {
361
0
    result = CURLE_OK;
362
0
    goto out;
363
0
  }
364
365
  /* We go ahead and do a read if we have a readable socket or if the stream
366
     was rewound (in which case we have data in a buffer) */
367
222k
  if(CURL_REQ_WANT_RECV(data)) {
368
213k
    result = sendrecv_dl(data, k);
369
213k
    if(result || data->req.done)
370
26.9k
      goto out;
371
213k
  }
372
373
  /* If we still have writing to do, we check if we have a writable socket. */
374
195k
  if(Curl_req_want_send(data)) {
375
14.5k
    result = sendrecv_ul(data);
376
14.5k
    if(result)
377
144
      goto out;
378
14.5k
  }
379
380
195k
  result = Curl_pgrsCheck(data);
381
195k
  if(result)
382
0
    goto out;
383
384
195k
  if(CURL_REQ_WANT_IO(data)) {
385
151k
    if(Curl_timeleft_ms(data) < 0) {
386
5
      if(k->size != -1) {
387
0
        failf(data, "Operation timed out after %" FMT_TIMEDIFF_T
388
0
              " milliseconds with %" FMT_OFF_T " out of %"
389
0
              FMT_OFF_T " bytes received",
390
0
              curlx_ptimediff_ms(Curl_pgrs_now(data),
391
0
                                 &data->progress.t_startsingle),
392
0
              k->bytecount, k->size);
393
0
      }
394
5
      else {
395
5
        failf(data, "Operation timed out after %" FMT_TIMEDIFF_T
396
5
              " milliseconds with %" FMT_OFF_T " bytes received",
397
5
              curlx_ptimediff_ms(Curl_pgrs_now(data),
398
5
                                 &data->progress.t_startsingle),
399
5
              k->bytecount);
400
5
      }
401
5
      result = CURLE_OPERATION_TIMEDOUT;
402
5
      goto out;
403
5
    }
404
151k
  }
405
44.0k
  else {
406
    /*
407
     * The transfer has been performed. Make some general checks before
408
     * returning.
409
     */
410
44.0k
    if(!(data->req.no_body) && (k->size != -1) &&
411
7.20k
       (k->bytecount != k->size) && !k->newurl) {
412
859
      failf(data, "transfer closed with %" FMT_OFF_T
413
859
            " bytes remaining to read", k->size - k->bytecount);
414
859
      result = CURLE_PARTIAL_FILE;
415
859
      goto out;
416
859
    }
417
44.0k
  }
418
419
  /* If there is nothing more to send/recv, the request is done */
420
194k
  if(!CURL_REQ_WANT_IO(data))
421
43.2k
    data->req.done = TRUE;
422
423
194k
  result = Curl_pgrsUpdate(data);
424
425
222k
out:
426
222k
  if(result)
427
27.6k
    DEBUGF(infof(data, "Curl_sendrecv() -> %d", (int)result));
428
222k
  return result;
429
194k
}
430
431
/* Curl_init_CONNECT() gets called each time the handle switches to CONNECT
432
   which means this gets called once for each subsequent redirect etc */
433
void Curl_init_CONNECT(struct Curl_easy *data)
434
178k
{
435
178k
  data->state.fread_func = data->set.fread_func_set;
436
178k
  data->state.in = data->set.in_set;
437
178k
  data->state.upload = (data->state.httpreq == HTTPREQ_PUT);
438
178k
}
439
440
/*
441
 * Curl_pretransfer() is called immediately before a transfer starts, and only
442
 * once for one transfer no matter if it has redirects or do multi-pass
443
 * authentication etc.
444
 */
445
CURLcode Curl_pretransfer(struct Curl_easy *data)
446
205k
{
447
205k
  CURLcode result = CURLE_OK;
448
449
  /* Reset the retry count at the start of each request.
450
   * If the retry count is not reset, when the connection drops,
451
   * it will not enter the retry mechanism on CONN_MAX_RETRIES + 1 attempts
452
   * and will immediately throw
453
   * "Connection died, tried CONN_MAX_RETRIES times before giving up".
454
   * By resetting it here, we ensure each new request starts fresh. */
455
205k
  data->state.retrycount = 0;
456
457
205k
  if(!data->set.str[STRING_SET_URL] && !data->set.uh) {
458
    /* we cannot do anything without URL */
459
53.2k
    failf(data, "No URL set");
460
53.2k
    return CURLE_URL_MALFORMAT;
461
53.2k
  }
462
463
  /* CURLOPT_CURLU overrides CURLOPT_URL and the contents of the CURLU handle
464
     is allowed to be changed by the user between transfers */
465
152k
  if(data->set.uh) {
466
0
    CURLUcode uc;
467
0
    curlx_free(data->set.str[STRING_SET_URL]);
468
0
    uc = curl_url_get(data->set.uh,
469
0
                      CURLUPART_URL, &data->set.str[STRING_SET_URL], 0);
470
0
    if(uc) {
471
      /* clear the pointer to not point to freed memory anymore */
472
0
      Curl_bufref_set(&data->state.url, NULL, 0, NULL);
473
0
      failf(data, "No URL set");
474
0
      return CURLE_URL_MALFORMAT;
475
0
    }
476
0
  }
477
478
152k
  Curl_bufref_set(&data->state.url, data->set.str[STRING_SET_URL], 0, NULL);
479
480
152k
  if(data->set.postfields && data->set.set_resume_from) {
481
    /* we cannot */
482
301
    failf(data, "cannot mix POSTFIELDS with RESUME_FROM");
483
301
    return CURLE_BAD_FUNCTION_ARGUMENT;
484
301
  }
485
486
152k
  data->state.prefer_ascii = data->set.prefer_ascii;
487
152k
#ifdef CURL_LIST_ONLY_PROTOCOL
488
152k
  data->state.list_only = data->set.list_only;
489
152k
#endif
490
152k
  data->state.httpreq = data->set.method;
491
492
  /* initial transfer request coming up, forget the initial origin
493
   * from a previous perform() on this handle. */
494
152k
  Curl_peer_unlink(&data->state.initial_origin);
495
152k
  Curl_peer_unlink(&data->state.origin);
496
152k
  data->state.requests = 0;
497
152k
  data->state.followlocation = 0; /* reset the location-follow counter */
498
152k
  data->state.this_is_a_follow = FALSE; /* reset this */
499
152k
  data->state.http_ignorecustom = FALSE; /* use custom HTTP method */
500
152k
  data->state.errorbuf = FALSE; /* no error has occurred */
501
152k
#ifndef CURL_DISABLE_HTTP
502
152k
  Curl_http_neg_init(data, &data->state.http_neg);
503
152k
#endif
504
152k
  data->state.authproblem = FALSE;
505
152k
  data->state.authhost.want = data->set.httpauth;
506
152k
  data->state.authproxy.want = data->set.proxyauth;
507
152k
  curlx_safefree(data->info.wouldredirect);
508
152k
  Curl_data_priority_clear_state(data);
509
152k
  if(data->set.http_auto_referer)
510
563
    Curl_bufref_free(&data->state.referer);
511
152k
  if(data->set.str[STRING_SET_REFERER])
512
717
    Curl_bufref_set(&data->state.referer, data->set.str[STRING_SET_REFERER],
513
717
                    0, NULL);
514
151k
  else
515
151k
    Curl_bufref_free(&data->state.referer);
516
517
152k
  if(data->state.httpreq == HTTPREQ_PUT)
518
1.63k
    data->state.infilesize = data->set.filesize;
519
150k
  else if((data->state.httpreq != HTTPREQ_GET) &&
520
16.0k
          (data->state.httpreq != HTTPREQ_HEAD)) {
521
15.3k
    data->state.infilesize = data->set.postfieldsize;
522
15.3k
    if(data->set.postfields && (data->state.infilesize == -1))
523
844
      data->state.infilesize = (curl_off_t)strlen(data->set.postfields);
524
15.3k
  }
525
135k
  else
526
135k
    data->state.infilesize = 0;
527
528
  /* If there is a list of cookie files to read, do it now! */
529
152k
  result = Curl_cookie_loadfiles(data);
530
152k
  if(!result)
531
152k
    Curl_cookie_run(data); /* activate */
532
533
  /* If there is a list of host pairs to deal with */
534
152k
  if(!result && data->state.resolve)
535
0
    result = Curl_loadhostpairs(data);
536
537
152k
  if(!result)
538
    /* If there is a list of hsts files to read */
539
152k
    result = Curl_hsts_loadfiles(data);
540
541
152k
  if(!result) {
542
    /* Allow data->set.use_port to set which port to use. This needs to be
543
     * disabled for example when we follow Location: headers to URLs using
544
     * different ports! */
545
152k
    data->state.allow_port = TRUE;
546
547
#if defined(HAVE_SIGNAL) && defined(SIGPIPE) && !defined(MSG_NOSIGNAL)
548
    /*************************************************************
549
     * Tell signal handler to ignore SIGPIPE
550
     *************************************************************/
551
    if(!data->set.no_signal)
552
      data->state.prev_signal = signal(SIGPIPE, SIG_IGN);
553
#endif
554
555
152k
    Curl_initinfo(data); /* reset session-specific information "variables" */
556
152k
    Curl_pgrsResetTransferSizes(data);
557
152k
    Curl_pgrsStartNow(data);
558
559
    /* In case the handle is reused and an authentication method was picked
560
       in the session we need to make sure we only use the one(s) we now
561
       consider to be fine */
562
152k
    data->state.authhost.picked &= data->state.authhost.want;
563
152k
    data->state.authproxy.picked &= data->state.authproxy.want;
564
565
152k
#ifndef CURL_DISABLE_FTP
566
152k
    data->state.wildcardmatch = data->set.wildcard_enabled;
567
152k
    if(data->state.wildcardmatch) {
568
1.03k
      struct WildcardData *wc;
569
1.03k
      if(!data->wildcard) {
570
717
        data->wildcard = curlx_calloc(1, sizeof(struct WildcardData));
571
717
        if(!data->wildcard)
572
0
          return CURLE_OUT_OF_MEMORY;
573
717
      }
574
1.03k
      wc = data->wildcard;
575
1.03k
      if(wc->state < CURLWC_INIT) {
576
717
        if(wc->ftpwc)
577
0
          wc->dtor(wc->ftpwc);
578
717
        curlx_safefree(wc->pattern);
579
717
        curlx_safefree(wc->path);
580
717
        Curl_wildcard_init(wc); /* init wildcard structures */
581
717
      }
582
1.03k
    }
583
152k
#endif
584
152k
    result = Curl_hsts_loadcb(data, data->hsts);
585
152k
  }
586
587
  /*
588
   * Set user-agent. Used for HTTP, but since we can attempt to tunnel
589
   * anything through an HTTP proxy we cannot limit this based on protocol.
590
   */
591
152k
  if(!result && data->set.str[STRING_USERAGENT]) {
592
1.46k
    curlx_free(data->state.aptr.uagent);
593
1.46k
    data->state.aptr.uagent =
594
1.46k
      curl_maprintf("User-Agent: %s\r\n", data->set.str[STRING_USERAGENT]);
595
1.46k
    if(!data->state.aptr.uagent)
596
0
      return CURLE_OUT_OF_MEMORY;
597
1.46k
  }
598
599
152k
  data->req.headerbytecount = 0;
600
152k
  Curl_headers_cleanup(data);
601
152k
  return result;
602
152k
}
603
604
/* Returns CURLE_OK *and* sets '*url' if a request retry is wanted.
605
606
   NOTE: that the *url is curlx_malloc()ed. */
607
CURLcode Curl_retry_request(struct Curl_easy *data, char **url)
608
46.2k
{
609
46.2k
  struct connectdata *conn = data->conn;
610
46.2k
  bool retry = FALSE;
611
46.2k
  *url = NULL;
612
613
  /* if we are talking upload, we cannot do the checks below, unless the
614
     protocol is HTTP as when uploading over HTTP we will still get a
615
     response */
616
46.2k
  if(data->state.upload &&
617
1.14k
     !(conn->scheme->protocol & (PROTO_FAMILY_HTTP | CURLPROTO_RTSP)))
618
123
    return CURLE_OK;
619
620
46.1k
  if(conn->bits.reuse &&
621
18.7k
     (data->req.bytecount + data->req.headerbytecount == 0) &&
622
1.53k
     ((!data->req.no_body && !data->req.done) ||
623
1.43k
      (conn->scheme->protocol & PROTO_FAMILY_HTTP))
624
882
#ifndef CURL_DISABLE_RTSP
625
882
     && (data->set.rtspreq != RTSPREQ_RECEIVE)
626
46.1k
#endif
627
46.1k
    )
628
    /* We got no data, we attempted to reuse a connection. For HTTP this
629
       can be a retry so we try again regardless if we expected a body.
630
       For other protocols we only try again only if we expected a body.
631
632
       This might happen if the connection was left alive when we were
633
       done using it before, but that was closed when we wanted to read from
634
       it again. Bad luck. Retry the same request on a fresh connect! */
635
882
    retry = TRUE;
636
45.2k
  else if(data->state.refused_stream &&
637
1.63k
          (data->req.bytecount + data->req.headerbytecount == 0)) {
638
    /* This was sent on a refused stream, safe to rerun. A refused stream
639
       error can typically only happen on HTTP/2 level if the stream is safe
640
       to issue again, but the nghttp2 API can deliver the message to other
641
       streams as well, which is why this adds the check the data counters
642
       too. */
643
1.62k
    infof(data, "REFUSED_STREAM, retrying a fresh connect");
644
1.62k
    data->state.refused_stream = FALSE; /* clear again */
645
1.62k
    retry = TRUE;
646
1.62k
  }
647
46.1k
  if(retry) {
648
2.50k
#define CONN_MAX_RETRIES 5
649
2.50k
    if(data->state.retrycount++ >= CONN_MAX_RETRIES) {
650
0
      failf(data, "Connection died, tried %d times before giving up",
651
0
            CONN_MAX_RETRIES);
652
0
      data->state.retrycount = 0;
653
0
      return CURLE_SEND_ERROR;
654
0
    }
655
2.50k
    infof(data, "Connection died, retrying a fresh connect (retry count: %d)",
656
2.50k
          data->state.retrycount);
657
2.50k
    *url = Curl_bufref_dup(&data->state.url);
658
2.50k
    if(!*url)
659
0
      return CURLE_OUT_OF_MEMORY;
660
661
2.50k
    connclose(conn); /* close this connection */
662
2.50k
    conn->bits.retry = TRUE; /* mark this as a connection we are about to
663
                                retry. Marking it this way should prevent i.e
664
                                HTTP transfers to return error because nothing
665
                                has been transferred! */
666
2.50k
    Curl_creader_set_rewind(data, TRUE);
667
2.50k
  }
668
46.1k
  return CURLE_OK;
669
46.1k
}
670
671
static void xfer_setup(
672
  struct Curl_easy *data,   /* transfer */
673
  int send_idx,             /* sockindex to send on or -1 */
674
  int recv_idx,             /* sockindex to receive on or -1 */
675
  curl_off_t recv_size      /* how much to receive, -1 if unknown */
676
  )
677
74.6k
{
678
74.6k
  struct SingleRequest *k = &data->req;
679
74.6k
  struct connectdata *conn = data->conn;
680
681
74.6k
  DEBUGASSERT(conn);
682
  /* indexes are in range */
683
74.6k
  DEBUGASSERT((send_idx <= 1) && (send_idx >= -1));
684
74.6k
  DEBUGASSERT((recv_idx <= 1) && (recv_idx >= -1));
685
  /* if request wants to send, switching off the send direction is wrong */
686
74.6k
  DEBUGASSERT((send_idx >= 0) || !Curl_req_want_send(data));
687
688
74.6k
  conn->send_idx = send_idx;
689
74.6k
  conn->recv_idx = recv_idx;
690
691
  /* without receiving, there should be not recv_size */
692
74.6k
  DEBUGASSERT((conn->recv_idx >= 0) || (recv_size == -1));
693
74.6k
  k->size = recv_size;
694
74.6k
  k->header = !!conn->scheme->run->write_resp_hd;
695
  /* by default, we do not shutdown at the end of the transfer */
696
74.6k
  k->shutdown = FALSE;
697
74.6k
  k->shutdown_err_ignore = FALSE;
698
699
  /* The code sequence below is placed in this function because all necessary
700
     input is not always known in do_complete() as this function may be called
701
     after that */
702
74.6k
  if(!k->header && (recv_size > 0))
703
722
    Curl_pgrsSetDownloadSize(data, recv_size);
704
705
  /* we want header and/or body, if neither then do not do this! */
706
74.6k
  if(conn->scheme->run->write_resp_hd || !data->req.no_body) {
707
74.4k
    if(conn->recv_idx != -1)
708
72.4k
      CURL_REQ_SET_RECV(data);
709
74.4k
    if(conn->send_idx != -1)
710
69.5k
      CURL_REQ_SET_SEND(data);
711
74.4k
  }
712
74.6k
  CURL_TRC_M(data, "xfer_setup: recv_idx=%d, send_idx=%d",
713
74.6k
             conn->recv_idx, conn->send_idx);
714
74.6k
}
715
716
void Curl_xfer_setup_nop(struct Curl_easy *data)
717
1.48k
{
718
1.48k
  xfer_setup(data, -1, -1, -1);
719
1.48k
}
720
721
void Curl_xfer_setup_sendrecv(struct Curl_easy *data,
722
                              int sockindex,
723
                              curl_off_t recv_size)
724
68.8k
{
725
68.8k
  xfer_setup(data, sockindex, sockindex, recv_size);
726
68.8k
}
727
728
void Curl_xfer_setup_send(struct Curl_easy *data,
729
                          int sockindex)
730
726
{
731
726
  xfer_setup(data, sockindex, -1, -1);
732
726
}
733
734
void Curl_xfer_setup_recv(struct Curl_easy *data,
735
                          int sockindex,
736
                          curl_off_t recv_size)
737
3.57k
{
738
3.57k
  xfer_setup(data, -1, sockindex, recv_size);
739
3.57k
}
740
741
void Curl_xfer_set_shutdown(struct Curl_easy *data,
742
                            bool shutdown,
743
                            bool ignore_errors)
744
638
{
745
  /* Shutdown should only be set when the transfer only sends or receives. */
746
638
  DEBUGASSERT(!shutdown ||
747
638
              (data->conn->send_idx < 0) || (data->conn->recv_idx < 0));
748
638
  data->req.shutdown = shutdown;
749
638
  data->req.shutdown_err_ignore = ignore_errors;
750
638
}
751
752
CURLcode Curl_xfer_write_resp(struct Curl_easy *data,
753
                              const char *buf, size_t blen,
754
                              bool is_eos)
755
118k
{
756
118k
  CURLcode result = CURLE_OK;
757
758
118k
  if(data->conn->scheme->run->write_resp) {
759
    /* protocol handlers offering this function take full responsibility
760
     * for writing all received download data to the client. */
761
115k
    result = data->conn->scheme->run->write_resp(data, buf, blen, is_eos);
762
115k
  }
763
2.88k
  else {
764
    /* No special handling by protocol handler, write all received data
765
     * as BODY to the client. */
766
2.88k
    if(blen || is_eos) {
767
2.88k
      int cwtype = CLIENTWRITE_BODY;
768
2.88k
      if(is_eos)
769
2.14k
        cwtype |= CLIENTWRITE_EOS;
770
2.88k
      result = Curl_client_write(data, cwtype, buf, blen);
771
2.88k
    }
772
2.88k
  }
773
774
118k
  if(!result && is_eos) {
775
    /* If we wrote the EOS, we are definitely done */
776
22.1k
    data->req.eos_written = TRUE;
777
22.1k
    data->req.download_done = TRUE;
778
22.1k
  }
779
118k
  CURL_TRC_WRITE(data, "xfer_write_resp(len=%zu, eos=%d) -> %d",
780
118k
                 blen, is_eos, (int)result);
781
118k
  return result;
782
118k
}
783
784
bool Curl_xfer_write_is_paused(struct Curl_easy *data)
785
807
{
786
807
  return Curl_cwriter_is_paused(data);
787
807
}
788
789
CURLcode Curl_xfer_write_resp_hd(struct Curl_easy *data,
790
                                 const char *hd0, size_t hdlen, bool is_eos)
791
166k
{
792
166k
  if(data->conn->scheme->run->write_resp_hd) {
793
166k
    DEBUGASSERT(!hd0[hdlen]); /* null-terminated */
794
    /* protocol handlers offering this function take full responsibility
795
     * for writing all received download data to the client. */
796
166k
    return data->conn->scheme->run->write_resp_hd(data, hd0, hdlen, is_eos);
797
166k
  }
798
  /* No special handling by protocol handler, write as response bytes */
799
0
  return Curl_xfer_write_resp(data, hd0, hdlen, is_eos);
800
166k
}
801
802
CURLcode Curl_xfer_write_done(struct Curl_easy *data, bool premature)
803
149k
{
804
149k
  (void)premature;
805
149k
  return Curl_cw_out_done(data);
806
149k
}
807
808
bool Curl_xfer_needs_flush(struct Curl_easy *data)
809
355k
{
810
355k
  return Curl_conn_needs_flush(data, data->conn->send_idx);
811
355k
}
812
813
CURLcode Curl_xfer_flush(struct Curl_easy *data)
814
1.57k
{
815
1.57k
  return Curl_conn_flush(data, data->conn->send_idx);
816
1.57k
}
817
818
CURLcode Curl_xfer_send(struct Curl_easy *data,
819
                        const void *buf, size_t blen, bool eos,
820
                        size_t *pnwritten)
821
82.9k
{
822
82.9k
  CURLcode result;
823
824
82.9k
  DEBUGASSERT(data);
825
82.9k
  DEBUGASSERT(data->conn);
826
827
82.9k
  result = Curl_conn_send(data, data->conn->send_idx,
828
82.9k
                          buf, blen, eos, pnwritten);
829
82.9k
  if(result == CURLE_AGAIN) {
830
7.23k
    result = CURLE_OK;
831
7.23k
    *pnwritten = 0;
832
7.23k
  }
833
75.7k
  else if(!result && *pnwritten)
834
75.1k
    data->info.request_size += *pnwritten;
835
836
82.9k
  DEBUGF(infof(data, "Curl_xfer_send(len=%zu, eos=%d) -> %d, %zu",
837
82.9k
               blen, eos, (int)result, *pnwritten));
838
82.9k
  return result;
839
82.9k
}
840
841
CURLcode Curl_xfer_recv(struct Curl_easy *data,
842
                        char *buf, size_t blen,
843
                        size_t *pnrcvd)
844
283k
{
845
283k
  DEBUGASSERT(data);
846
283k
  DEBUGASSERT(data->conn);
847
283k
  DEBUGASSERT(data->set.buffer_size > 0);
848
849
283k
  if(curlx_uitouz(data->set.buffer_size) < blen)
850
1
    blen = curlx_uitouz(data->set.buffer_size);
851
283k
  return Curl_conn_recv(data, data->conn->recv_idx, buf, blen, pnrcvd);
852
283k
}
853
854
CURLcode Curl_xfer_send_close(struct Curl_easy *data)
855
68.4k
{
856
68.4k
  Curl_conn_ev_data_done_send(data);
857
68.4k
  return CURLE_OK;
858
68.4k
}
859
860
bool Curl_xfer_is_blocked(struct Curl_easy *data)
861
222k
{
862
222k
  bool want_send = CURL_REQ_WANT_SEND(data);
863
222k
  bool want_recv = CURL_REQ_WANT_RECV(data);
864
222k
  if(!want_send)
865
207k
    return want_recv && Curl_xfer_recv_is_paused(data);
866
15.0k
  else if(!want_recv)
867
8.72k
    return want_send && Curl_xfer_send_is_paused(data);
868
6.29k
  else
869
6.29k
    return Curl_xfer_recv_is_paused(data) && Curl_xfer_send_is_paused(data);
870
222k
}
871
872
bool Curl_xfer_send_is_paused(struct Curl_easy *data)
873
23.8k
{
874
23.8k
  return Curl_rlimit_is_blocked(&data->progress.ul.rlimit);
875
23.8k
}
876
877
bool Curl_xfer_recv_is_paused(struct Curl_easy *data)
878
416k
{
879
416k
  return Curl_rlimit_is_blocked(&data->progress.dl.rlimit);
880
416k
}
881
882
CURLcode Curl_xfer_pause_send(struct Curl_easy *data, bool enable)
883
0
{
884
0
  CURLcode result = CURLE_OK;
885
0
  Curl_rlimit_block(&data->progress.ul.rlimit, enable, Curl_pgrs_now(data));
886
0
  if(!enable && Curl_creader_is_paused(data))
887
0
    result = Curl_creader_unpause(data);
888
0
  Curl_pgrsSendPause(data, enable);
889
0
  return result;
890
0
}
891
892
CURLcode Curl_xfer_pause_recv(struct Curl_easy *data, bool enable)
893
0
{
894
0
  CURLcode result = CURLE_OK;
895
0
  Curl_rlimit_block(&data->progress.dl.rlimit, enable, Curl_pgrs_now(data));
896
0
  if(!enable && Curl_cwriter_is_paused(data))
897
0
    result = Curl_cwriter_unpause(data);
898
0
  Curl_conn_ev_data_pause(data, enable);
899
0
  Curl_pgrsRecvPause(data, enable);
900
0
  return result;
901
0
}
902
903
bool Curl_xfer_is_secure(struct Curl_easy *data)
904
155k
{
905
155k
#ifndef CURL_DISABLE_PROXY
906
155k
  if(data->conn && data->conn->bits.origin_is_proxy) {
907
    /* talking to a forward proxy, not secure. we do not use
908
     * a forward proxy for https: and other 's' URLs. Let's just check that
909
     * this did not fail somewhere. */
910
4.37k
    DEBUGASSERT(!(data->state.origin->scheme->flags & PROTOPT_SSL));
911
4.37k
    return FALSE;
912
4.37k
  }
913
151k
#endif
914
151k
  return (data->state.origin->scheme->flags & PROTOPT_SSL);
915
155k
}