Coverage Report

Created: 2026-09-14 07:05

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