Coverage Report

Created: 2026-10-22 06:50

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
174k
{
88
174k
  struct curl_slist *head;
89
174k
  DEBUGASSERT(thislen);
90
174k
  DEBUGASSERT(thisheader[thislen - 1] != ':');
91
92
283k
  for(head = data->set.headers; head; head = head->next) {
93
110k
    if(curl_strnequal(head->data, thisheader, thislen) &&
94
1.67k
       Curl_headersep(head->data[thislen]))
95
1.12k
      return head->data;
96
110k
  }
97
98
173k
  return NULL;
99
174k
}
100
#endif
101
102
static int data_pending(struct Curl_easy *data, bool rcvd_eagain)
103
82.1k
{
104
82.1k
  struct connectdata *conn = data->conn;
105
106
82.1k
  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
82.1k
  return (!rcvd_eagain &&
112
0
          conn->scheme->protocol & (CURLPROTO_SCP | CURLPROTO_SFTP)) ||
113
82.1k
         Curl_conn_data_pending(data, FIRSTSOCKET);
114
82.1k
}
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
36
{
122
36
  if((timeofdoc == 0) || (data->set.timevalue == 0))
123
36
    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
120k
{
155
120k
  if(!data || !data->conn)
156
0
    return FALSE;
157
120k
  return CURL_CONN_IN_SHUTDOWN(data->conn, data->conn->recv_idx);
158
120k
}
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
122k
{
180
122k
  CURLcode result;
181
182
122k
  DEBUGASSERT(blen > 0);
183
122k
  *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
122k
  if(!eos_reliable && !data->req.header && data->req.size != -1) {
187
1.72k
    blen = curlx_sotouz_range(data->req.size - data->req.bytecount, 0, blen);
188
1.72k
  }
189
120k
  else if(xfer_recv_shutdown_started(data)) {
190
    /* we already received everything. Do not try more. */
191
0
    blen = 0;
192
0
  }
193
194
122k
  if(blen) {
195
122k
    result = Curl_xfer_recv(data, buf, blen, pnread);
196
122k
    if(result)
197
98.6k
      return result;
198
122k
  }
199
200
23.6k
  if(*pnread == 0) {
201
11.4k
    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
11.4k
    DEBUGF(infof(data, "sendrecv_dl: we are done"));
211
11.4k
  }
212
23.6k
  return CURLE_OK;
213
23.6k
}
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
112k
{
223
112k
  struct connectdata *conn = data->conn;
224
112k
  CURLcode result = CURLE_OK;
225
112k
  char *buf, *xfer_buf;
226
112k
  size_t blen, xfer_blen;
227
112k
  int maxloops = 10;
228
112k
  bool is_multiplex = FALSE;
229
112k
  bool rcvd_eagain = FALSE;
230
112k
  bool is_eos = FALSE, rate_limited = FALSE;
231
232
112k
  result = Curl_multi_xfer_buf_borrow(data, &xfer_buf, &xfer_blen);
233
112k
  if(result)
234
7
    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
122k
  do {
239
122k
    size_t bytestoread;
240
241
122k
    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
122k
      is_multiplex = Curl_conn_is_multiplex(conn, FIRSTSOCKET);
246
122k
    }
247
248
122k
    buf = xfer_buf;
249
122k
    bytestoread = xfer_blen;
250
251
122k
    if(bytestoread && Curl_rlimit_active(&data->progress.dl.rlimit)) {
252
132
      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
132
      if(dl_avail <= 0) {
261
132
        rate_limited = TRUE;
262
132
        break;
263
132
      }
264
0
      if(dl_avail < (curl_off_t)bytestoread)
265
0
        bytestoread = (size_t)dl_avail;
266
0
    }
267
268
122k
    rcvd_eagain = FALSE;
269
122k
    result = xfer_recv_resp(data, buf, bytestoread, is_multiplex, &blen);
270
122k
    if(result) {
271
98.6k
      if(result != CURLE_AGAIN)
272
16.3k
        goto out; /* real error */
273
82.3k
      rcvd_eagain = TRUE;
274
82.3k
      result = CURLE_OK;
275
82.3k
      if(data->req.download_done && data->req.no_body &&
276
43
         !data->req.resp_trailer) {
277
43
        DEBUGF(infof(data, "EAGAIN, download done, no trailer announced, "
278
43
                     "not waiting for EOS"));
279
43
        blen = 0;
280
        /* continue as if we received the EOS */
281
43
      }
282
82.2k
      else
283
82.2k
        break; /* get out of loop */
284
82.3k
    }
285
286
    /* We only get a 0-length receive at the end of the response */
287
23.7k
    is_eos = (blen == 0);
288
289
23.7k
    if(!blen) {
290
11.5k
      result = Curl_req_stop_send_recv(data);
291
11.5k
      if(result)
292
0
        goto out;
293
11.5k
      if(k->eos_written) /* already did write this to client, leave */
294
0
        break;
295
11.5k
    }
296
297
23.7k
    result = Curl_xfer_write_resp(data, buf, blen, is_eos);
298
23.7k
    if(result || data->req.done)
299
1.75k
      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
21.9k
    if((!is_multiplex && data->req.download_done) || is_eos) {
305
12.0k
      CURL_REQ_CLEAR_RECV(data);
306
12.0k
    }
307
    /* if we stopped receiving, leave the loop */
308
21.9k
    if(!CURL_REQ_WANT_RECV(data))
309
12.0k
      break;
310
311
21.9k
  } while(maxloops--);
312
313
94.5k
  if(!is_eos && !rate_limited && CURL_REQ_WANT_RECV(data) &&
314
82.2k
     (!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
61
    Curl_multi_mark_dirty(data);
318
61
    CURL_TRC_M(data, "sendrecv_dl() no EAGAIN/pending data, mark as dirty");
319
61
  }
320
321
94.5k
  if(!CURL_REQ_WANT_RECV(data) && CURL_REQ_WANT_SEND(data) &&
322
257
     (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
97
    infof(data, "we are done reading and this is set to close, stop send");
327
97
    Curl_req_abort_sending(data);
328
97
  }
329
330
112k
out:
331
112k
  Curl_multi_xfer_buf_release(data, xfer_buf);
332
112k
  if(result)
333
17.7k
    DEBUGF(infof(data, "sendrecv_dl() -> %d", (int)result));
334
112k
  return result;
335
94.5k
}
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
28.0k
{
342
  /* We should not get here when the sending is already done. */
343
28.0k
  DEBUGASSERT(!Curl_req_done_sending(data));
344
345
28.0k
  if(!Curl_req_done_sending(data))
346
28.0k
    return Curl_req_send_more(data);
347
0
  return CURLE_OK;
348
28.0k
}
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
114k
{
356
114k
  struct SingleRequest *k = &data->req;
357
114k
  const struct curltime *pnow = NULL;
358
114k
  CURLcode result = CURLE_OK;
359
360
114k
  if(Curl_xfer_is_blocked(data)) {
361
9
    result = CURLE_OK;
362
9
    goto out;
363
9
  }
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
114k
  if(CURL_REQ_WANT_RECV(data)) {
368
112k
    result = sendrecv_dl(data, k);
369
112k
    if(result || data->req.done)
370
18.1k
      goto out;
371
112k
  }
372
373
  /* If we still have writing to do, we check if we have a writable socket. */
374
96.2k
  if(Curl_req_want_send(data)) {
375
28.0k
    result = sendrecv_ul(data);
376
28.0k
    if(result)
377
98
      goto out;
378
28.0k
  }
379
380
96.1k
  pnow = Curl_pgrs_now(data);
381
96.1k
  if(CURL_REQ_WANT_IO(data)) {
382
84.1k
    if(Curl_timeleft_now_ms(data, pnow) < 0) {
383
1
      if(k->size != -1) {
384
1
        failf(data, "Operation timed out after %" FMT_TIMEDIFF_T
385
1
              " milliseconds with %" FMT_OFF_T " out of %"
386
1
              FMT_OFF_T " bytes received",
387
1
              Curl_pgrs_since_ms(data, NULL, TIMER_STARTSINGLE),
388
1
              k->bytecount, k->size);
389
1
      }
390
0
      else {
391
0
        failf(data, "Operation timed out after %" FMT_TIMEDIFF_T
392
0
              " milliseconds with %" FMT_OFF_T " bytes received",
393
0
              Curl_pgrs_since_ms(data, NULL, TIMER_STARTSINGLE),
394
0
              k->bytecount);
395
0
      }
396
1
      result = CURLE_OPERATION_TIMEDOUT;
397
1
      goto out;
398
1
    }
399
84.1k
  }
400
12.0k
  else {
401
    /*
402
     * The transfer has been performed. Make some general checks before
403
     * returning.
404
     */
405
12.0k
    if(!data->req.no_body && (k->size != -1) &&
406
3.20k
       (k->bytecount != k->size) && !k->newurl) {
407
31
      failf(data, "transfer closed with %" FMT_OFF_T
408
31
            " bytes remaining to read", k->size - k->bytecount);
409
31
      result = CURLE_PARTIAL_FILE;
410
31
      goto out;
411
31
    }
412
12.0k
  }
413
414
  /* If there is nothing more to send/recv, the request is done */
415
96.1k
  if(!CURL_REQ_WANT_IO(data))
416
12.0k
    data->req.done = TRUE;
417
418
96.1k
  result = Curl_pgrsCheckX(data, pnow);
419
420
114k
out:
421
114k
  if(result)
422
17.8k
    DEBUGF(infof(data, "Curl_sendrecv() -> %d", (int)result));
423
114k
  return result;
424
96.1k
}
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
35.1k
{
430
35.1k
  data->state.fread_func = data->set.fread_func_set;
431
35.1k
  data->state.in = data->set.in_set;
432
35.1k
  data->state.upload = (data->state.httpreq == HTTPREQ_PUT);
433
35.1k
}
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
24.1k
{
442
24.1k
  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
24.1k
  data->state.retrycount = 0;
451
452
24.1k
  if(!CURL_EASY_STR(data, STRING_SET_URL) && !data->set.uh) {
453
    /* we cannot do anything without URL */
454
14
    failf(data, "No URL set");
455
14
    return CURLE_URL_MALFORMAT;
456
14
  }
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
24.0k
  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
24.0k
  Curl_bufref_set(&data->state.url, CURL_EASY_STR(data, STRING_SET_URL),
476
24.0k
                  0, NULL);
477
478
24.0k
  if(data->set.postfields && data->set.set_resume_from) {
479
    /* we cannot */
480
67
    failf(data, "cannot mix POSTFIELDS with RESUME_FROM");
481
67
    return CURLE_BAD_FUNCTION_ARGUMENT;
482
67
  }
483
484
24.0k
  data->state.prefer_ascii = data->set.prefer_ascii;
485
24.0k
#ifdef CURL_LIST_ONLY_PROTOCOL
486
24.0k
  data->state.list_only = data->set.list_only;
487
24.0k
#endif
488
24.0k
  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
24.0k
  Curl_peer_unlink(&data->state.initial_origin);
493
24.0k
  Curl_peer_unlink(&data->state.origin);
494
24.0k
  data->state.requests = 0;
495
24.0k
  data->state.followlocation = 0; /* reset the location-follow counter */
496
24.0k
  data->state.this_is_a_follow = FALSE; /* reset this */
497
24.0k
  data->state.http_ignorecustom = FALSE; /* use custom HTTP method */
498
24.0k
  data->state.errorbuf = FALSE; /* no error has occurred */
499
24.0k
#ifndef CURL_DISABLE_HTTP
500
24.0k
  Curl_http_neg_init(data, &data->state.http_neg);
501
24.0k
#endif
502
24.0k
  data->state.authproblem = FALSE;
503
24.0k
  data->state.authhost.want = data->set.httpauth;
504
24.0k
  data->state.authproxy.want = data->set.proxyauth;
505
24.0k
  curlx_safefree(data->info.wouldredirect);
506
24.0k
  curlx_safefree(data->info.effective_url);
507
24.0k
  Curl_data_priority_clear_state(data);
508
24.0k
  if(data->set.http_auto_referer)
509
56
    Curl_bufref_free(&data->state.referer);
510
24.0k
  if(CURL_EASY_STR(data, STRING_SET_REFERER))
511
57
    Curl_bufref_set(&data->state.referer,
512
57
                    CURL_EASY_STR(data, STRING_SET_REFERER), 0, NULL);
513
23.9k
  else
514
23.9k
    Curl_bufref_free(&data->state.referer);
515
516
24.0k
  if(data->state.httpreq == HTTPREQ_PUT)
517
650
    data->state.infilesize = data->set.filesize;
518
23.3k
  else if((data->state.httpreq != HTTPREQ_GET) &&
519
4.58k
          (data->state.httpreq != HTTPREQ_HEAD)) {
520
4.46k
    data->state.infilesize = data->set.postfieldsize;
521
4.46k
    if(data->set.postfields && (data->state.infilesize == -1))
522
0
      data->state.infilesize = (curl_off_t)strlen(data->set.postfields);
523
4.46k
  }
524
18.9k
  else
525
18.9k
    data->state.infilesize = 0;
526
527
  /* If there is a list of cookie files to read, do it now! */
528
24.0k
  result = Curl_cookie_loadfiles(data,
529
24.0k
                                 data->set.cookiesession ?
530
24.0k
                                 COOKIE_NOSESSION : 0);
531
24.0k
  if(!result)
532
23.9k
    Curl_cookie_run(data); /* activate */
533
534
  /* If there is a list of host pairs to deal with */
535
24.0k
  if(!result && data->state.resolve)
536
0
    result = Curl_loadhostpairs(data);
537
538
24.0k
  if(!result)
539
    /* If there is a list of hsts files to read */
540
23.9k
    result = Curl_hsts_loadfiles(data);
541
542
24.0k
  if(!result) {
543
    /* Allow data->set.use_port to set which port to use. This needs to be
544
     * disabled for example when we follow Location: headers to URLs using
545
     * different ports! */
546
23.9k
    data->state.allow_port = TRUE;
547
548
#if defined(HAVE_SIGNAL) && defined(SIGPIPE) && !defined(MSG_NOSIGNAL)
549
    /*************************************************************
550
     * Tell signal handler to ignore SIGPIPE
551
     *************************************************************/
552
    if(!data->set.no_signal)
553
      data->state.prev_signal = signal(SIGPIPE, SIG_IGN);
554
#endif
555
556
23.9k
    Curl_initinfo(data); /* reset session-specific information "variables" */
557
23.9k
    Curl_pgrsResetTransferSizes(data);
558
23.9k
    Curl_pgrsStart(data, NULL);
559
560
    /* In case the handle is reused and an authentication method was picked
561
       in the session we need to make sure we only use the one(s) we now
562
       consider to be fine */
563
23.9k
    data->state.authhost.picked &= data->state.authhost.want;
564
23.9k
    data->state.authproxy.picked &= data->state.authproxy.want;
565
566
23.9k
#ifndef CURL_DISABLE_FTP
567
23.9k
    data->state.wildcardmatch = data->set.wildcard_enabled;
568
23.9k
#ifdef DEBUGBUILD
569
23.9k
  if(getenv("CURL_DBG_FTP_WILDCARD"))
570
0
    data->state.wildcardmatch = TRUE;
571
23.9k
#endif
572
23.9k
    if(data->state.wildcardmatch) {
573
0
      struct WildcardData *wc;
574
0
      if(!data->wildcard) {
575
0
        data->wildcard = curlx_calloc(1, sizeof(struct WildcardData));
576
0
        if(!data->wildcard)
577
0
          return CURLE_OUT_OF_MEMORY;
578
0
      }
579
0
      wc = data->wildcard;
580
0
      if(wc->state < CURLWC_INIT) {
581
0
        if(wc->ftpwc)
582
0
          wc->dtor(wc->ftpwc);
583
0
        curlx_safefree(wc->pattern);
584
0
        curlx_safefree(wc->path);
585
0
        Curl_wildcard_init(wc); /* init wildcard structures */
586
0
      }
587
0
    }
588
23.9k
#endif
589
23.9k
    result = Curl_hsts_loadcb(data, data->hsts);
590
23.9k
  }
591
592
24.0k
  data->req.headerbytecount = 0;
593
  /* a previous transfer on this handle may have ended with a rewind request
594
   * still pending (a follow or auth retry that failed). This is a new
595
   * transfer, so drop those readers now instead of letting a later upload
596
   * read from them. */
597
24.0k
  data->req.rewind_read = FALSE;
598
24.0k
  Curl_client_reset(data);
599
24.0k
  Curl_headers_cleanup(data);
600
24.0k
  return result;
601
24.0k
}
602
603
/* Returns CURLE_OK *and* sets '*url' if a request retry is wanted.
604
605
   NOTE: that the *url is curlx_malloc()ed. */
606
CURLcode Curl_retry_request(struct Curl_easy *data, char **url)
607
20.4k
{
608
20.4k
  struct connectdata *conn = data->conn;
609
20.4k
  bool retry = FALSE;
610
20.4k
  *url = NULL;
611
612
  /* if we are talking upload, we cannot do the checks below, unless the
613
     protocol is HTTP as when uploading over HTTP we will still get a
614
     response */
615
20.4k
  if(data->state.upload &&
616
593
     !(conn->scheme->protocol & (PROTO_FAMILY_HTTP | CURLPROTO_RTSP)))
617
0
    return CURLE_OK;
618
619
20.4k
  if(conn->bits.reuse &&
620
1.42k
     (data->req.bytecount + data->req.headerbytecount == 0) &&
621
1.40k
     ((!data->req.no_body && !data->req.done) ||
622
138
      (conn->scheme->protocol & PROTO_FAMILY_HTTP))
623
1.40k
#ifndef CURL_DISABLE_RTSP
624
1.40k
     && (data->set.rtspreq != RTSPREQ_RECEIVE)
625
20.4k
#endif
626
20.4k
    )
627
    /* We got no data, we attempted to reuse a connection. For HTTP this
628
       can be a retry so we try again regardless if we expected a body.
629
       For other protocols we only try again only if we expected a body.
630
631
       This might happen if the connection was left alive when we were
632
       done using it before, but that was closed when we wanted to read from
633
       it again. Bad luck. Retry the same request on a fresh connect! */
634
1.40k
    retry = TRUE;
635
19.0k
  else if(data->state.refused_stream &&
636
7.62k
          (data->req.bytecount + data->req.headerbytecount == 0)) {
637
    /* This was sent on a refused stream, safe to rerun. A refused stream
638
       error can typically only happen on HTTP/2 level if the stream is safe
639
       to issue again, but the nghttp2 API can deliver the message to other
640
       streams as well, which is why this adds the check the data counters
641
       too. */
642
6.63k
    infof(data, "REFUSED_STREAM, retrying a fresh connect");
643
6.63k
    data->state.refused_stream = FALSE; /* clear again */
644
6.63k
    retry = TRUE;
645
6.63k
  }
646
20.4k
  if(retry) {
647
8.03k
#define CONN_MAX_RETRIES 5
648
8.03k
    if(data->state.retrycount++ >= CONN_MAX_RETRIES) {
649
0
      failf(data, "Connection died, tried %d times before giving up",
650
0
            CONN_MAX_RETRIES);
651
0
      data->state.retrycount = 0;
652
0
      return CURLE_SEND_ERROR;
653
0
    }
654
8.03k
    infof(data, "Connection died, retrying a fresh connect (retry count: %d)",
655
8.03k
          data->state.retrycount);
656
8.03k
    *url = Curl_bufref_dup(&data->state.url);
657
8.03k
    if(!*url)
658
5
      return CURLE_OUT_OF_MEMORY;
659
660
8.02k
    connclose(conn); /* close this connection */
661
8.02k
    conn->bits.retry = TRUE; /* mark this as a connection we are about to
662
                                retry. Marking it this way should prevent i.e
663
                                HTTP transfers to return error because nothing
664
                                has been transferred! */
665
8.02k
    Curl_creader_set_rewind(data, TRUE);
666
8.02k
  }
667
20.4k
  return CURLE_OK;
668
20.4k
}
669
670
static void xfer_setup(
671
  struct Curl_easy *data,   /* transfer */
672
  int8_t send_idx,             /* sockindex to send on or -1 */
673
  int8_t recv_idx,             /* sockindex to receive on or -1 */
674
  curl_off_t recv_size      /* how much to receive, -1 if unknown */
675
  )
676
30.6k
{
677
30.6k
  struct SingleRequest *k = &data->req;
678
30.6k
  struct connectdata *conn = data->conn;
679
680
30.6k
  DEBUGASSERT(conn);
681
  /* indexes are in range */
682
30.6k
  DEBUGASSERT((send_idx <= 1) && (send_idx >= -1));
683
30.6k
  DEBUGASSERT((recv_idx <= 1) && (recv_idx >= -1));
684
  /* if request wants to send, switching off the send direction is wrong */
685
30.6k
  DEBUGASSERT((send_idx >= 0) || !Curl_req_want_send(data));
686
687
30.6k
  conn->send_idx = send_idx;
688
30.6k
  conn->recv_idx = recv_idx;
689
690
  /* without receiving, there should be not recv_size */
691
30.6k
  DEBUGASSERT((conn->recv_idx >= 0) || (recv_size == -1));
692
30.6k
  k->size = recv_size;
693
30.6k
  k->header = !!conn->scheme->run->write_resp_hd;
694
  /* by default, we do not shutdown at the end of the transfer */
695
30.6k
  k->shutdown = FALSE;
696
30.6k
  k->shutdown_err_ignore = FALSE;
697
698
  /* The code sequence below is placed in this function because all necessary
699
     input is not always known in do_complete() as this function may be called
700
     after that */
701
30.6k
  if(!k->header && (recv_size > 0))
702
0
    Curl_pgrsSetDownloadSize(data, recv_size);
703
704
  /* we want header and/or body, if neither then do not do this! */
705
30.6k
  if(conn->scheme->run->write_resp_hd || !data->req.no_body) {
706
30.6k
    if(conn->recv_idx != -1)
707
30.6k
      CURL_REQ_SET_RECV(data);
708
30.6k
    if(conn->send_idx != -1)
709
30.6k
      CURL_REQ_SET_SEND(data);
710
30.6k
  }
711
30.6k
  CURL_TRC_M(data, "xfer_setup: recv_idx=%d, send_idx=%d",
712
30.6k
             conn->recv_idx, conn->send_idx);
713
30.6k
}
714
715
void Curl_xfer_setup_nop(struct Curl_easy *data)
716
0
{
717
0
  xfer_setup(data, -1, -1, -1);
718
0
}
719
720
void Curl_xfer_setup_sendrecv(struct Curl_easy *data,
721
                              int8_t sockindex,
722
                              curl_off_t recv_size)
723
30.6k
{
724
30.6k
  xfer_setup(data, sockindex, sockindex, recv_size);
725
30.6k
}
726
727
void Curl_xfer_setup_send(struct Curl_easy *data,
728
                          int8_t sockindex)
729
0
{
730
0
  xfer_setup(data, sockindex, -1, -1);
731
0
}
732
733
void Curl_xfer_setup_recv(struct Curl_easy *data,
734
                          int8_t sockindex,
735
                          curl_off_t recv_size)
736
0
{
737
0
  xfer_setup(data, -1, sockindex, recv_size);
738
0
}
739
740
void Curl_xfer_set_shutdown(struct Curl_easy *data,
741
                            bool shutdown,
742
                            bool ignore_errors)
743
0
{
744
  /* Shutdown should only be set when the transfer only sends or receives. */
745
0
  DEBUGASSERT(!shutdown ||
746
0
              (data->conn->send_idx < 0) || (data->conn->recv_idx < 0));
747
0
  data->req.shutdown = shutdown;
748
0
  data->req.shutdown_err_ignore = ignore_errors;
749
0
}
750
751
CURLcode Curl_xfer_write_resp(struct Curl_easy *data,
752
                              const char *buf, size_t blen,
753
                              bool is_eos)
754
23.9k
{
755
23.9k
  CURLcode result = CURLE_OK;
756
757
23.9k
  if(data->conn->scheme->run->write_resp) {
758
    /* protocol handlers offering this function take full responsibility
759
     * for writing all received download data to the client. */
760
23.9k
    result = data->conn->scheme->run->write_resp(data, buf, blen, is_eos);
761
23.9k
  }
762
0
  else {
763
    /* No special handling by protocol handler, write all received data
764
     * as BODY to the client. */
765
0
    if(blen || is_eos) {
766
0
      int cwtype = CLIENTWRITE_BODY;
767
0
      if(is_eos)
768
0
        cwtype |= CLIENTWRITE_EOS;
769
0
      result = Curl_client_write(data, cwtype, buf, blen);
770
0
    }
771
0
  }
772
773
23.9k
  if(!result && is_eos) {
774
    /* If we wrote the EOS, we are definitely done */
775
11.3k
    data->req.eos_written = TRUE;
776
11.3k
    data->req.download_done = TRUE;
777
11.3k
  }
778
23.9k
  CURL_TRC_WRITE(data, "xfer_write_resp(len=%zu, eos=%d) -> %d",
779
23.9k
                 blen, is_eos, (int)result);
780
23.9k
  return result;
781
23.9k
}
782
783
bool Curl_xfer_write_is_paused(struct Curl_easy *data)
784
196
{
785
196
  return Curl_cwriter_is_paused(data);
786
196
}
787
788
CURLcode Curl_xfer_write_resp_hd(struct Curl_easy *data,
789
                                 const char *hd0, size_t hdlen, bool is_eos)
790
322k
{
791
322k
  if(data->conn->scheme->run->write_resp_hd) {
792
322k
    DEBUGASSERT(!hd0[hdlen]); /* null-terminated */
793
    /* protocol handlers offering this function take full responsibility
794
     * for writing all received download data to the client. */
795
322k
    return data->conn->scheme->run->write_resp_hd(data, hd0, hdlen, is_eos);
796
322k
  }
797
  /* No special handling by protocol handler, write as response bytes */
798
0
  return Curl_xfer_write_resp(data, hd0, hdlen, is_eos);
799
322k
}
800
801
CURLcode Curl_xfer_write_done(struct Curl_easy *data, bool premature)
802
32.5k
{
803
32.5k
  (void)premature;
804
32.5k
  return Curl_cw_out_done(data);
805
32.5k
}
806
807
bool Curl_xfer_needs_flush(struct Curl_easy *data)
808
151k
{
809
151k
  return Curl_conn_needs_flush(data, data->conn->send_idx);
810
151k
}
811
812
CURLcode Curl_xfer_flush(struct Curl_easy *data)
813
16.8k
{
814
16.8k
  return Curl_conn_flush(data, data->conn->send_idx);
815
16.8k
}
816
817
CURLcode Curl_xfer_send(struct Curl_easy *data,
818
                        const void *buf, size_t blen, bool eos,
819
                        size_t *pnwritten)
820
41.9k
{
821
41.9k
  CURLcode result;
822
823
41.9k
  DEBUGASSERT(data);
824
41.9k
  DEBUGASSERT(data->conn);
825
826
41.9k
  result = Curl_conn_send(data, data->conn->send_idx,
827
41.9k
                          buf, blen, eos, pnwritten);
828
41.9k
  if(result == CURLE_AGAIN) {
829
3.84k
    result = CURLE_OK;
830
3.84k
    *pnwritten = 0;
831
3.84k
  }
832
38.0k
  else if(!result && *pnwritten)
833
36.9k
    data->info.request_size += *pnwritten;
834
835
41.9k
  DEBUGF(infof(data, "Curl_xfer_send(len=%zu, eos=%d) -> %d, %zu",
836
41.9k
               blen, eos, (int)result, *pnwritten));
837
41.9k
  return result;
838
41.9k
}
839
840
CURLcode Curl_xfer_recv(struct Curl_easy *data,
841
                        char *buf, size_t blen,
842
                        size_t *pnrcvd)
843
122k
{
844
122k
  DEBUGASSERT(data);
845
122k
  DEBUGASSERT(data->conn);
846
122k
  DEBUGASSERT(data->set.buffer_size > 0);
847
848
122k
  if(curlx_uitouz(data->set.buffer_size) < blen)
849
0
    blen = curlx_uitouz(data->set.buffer_size);
850
122k
  return Curl_conn_recv(data, data->conn->recv_idx, buf, blen, pnrcvd);
851
122k
}
852
853
CURLcode Curl_xfer_send_close(struct Curl_easy *data)
854
28.8k
{
855
28.8k
  Curl_conn_ev_data_done_send(data);
856
28.8k
  return CURLE_OK;
857
28.8k
}
858
859
bool Curl_xfer_is_blocked(struct Curl_easy *data)
860
117k
{
861
117k
  bool want_send = CURL_REQ_WANT_SEND(data);
862
117k
  bool want_recv = CURL_REQ_WANT_RECV(data);
863
117k
  if(!want_send)
864
99.6k
    return want_recv && Curl_xfer_recv_is_paused(data);
865
18.2k
  else if(!want_recv)
866
1.96k
    return want_send && Curl_xfer_send_is_paused(data);
867
16.2k
  else
868
16.2k
    return Curl_xfer_recv_is_paused(data) && Curl_xfer_send_is_paused(data);
869
117k
}
870
871
bool Curl_xfer_send_is_paused(struct Curl_easy *data)
872
23.1k
{
873
23.1k
  return Curl_rlimit_is_blocked(&data->progress.ul.rlimit);
874
23.1k
}
875
876
bool Curl_xfer_recv_is_paused(struct Curl_easy *data)
877
152k
{
878
152k
  return Curl_rlimit_is_blocked(&data->progress.dl.rlimit);
879
152k
}
880
881
CURLcode Curl_xfer_pause_send(struct Curl_easy *data, bool enable)
882
128
{
883
128
  CURLcode result = CURLE_OK;
884
128
  Curl_rlimit_block(&data->progress.ul.rlimit, enable, Curl_pgrs_now(data));
885
128
  if(!enable && Curl_creader_is_paused(data))
886
0
    result = Curl_creader_unpause(data);
887
128
  Curl_pgrsSendPause(data, enable);
888
128
  return result;
889
128
}
890
891
CURLcode Curl_xfer_pause_recv(struct Curl_easy *data, bool enable)
892
589
{
893
589
  CURLcode result = CURLE_OK;
894
589
  Curl_rlimit_block(&data->progress.dl.rlimit, enable, Curl_pgrs_now(data));
895
589
  if(!enable && Curl_cwriter_is_paused(data))
896
211
    result = Curl_cwriter_unpause(data);
897
589
  Curl_conn_ev_data_pause(data, enable);
898
589
  Curl_pgrsRecvPause(data, enable);
899
589
  return result;
900
589
}
901
902
bool Curl_xfer_is_secure(struct Curl_easy *data)
903
58.2k
{
904
58.2k
#ifndef CURL_DISABLE_PROXY
905
58.2k
  if(data->conn && data->conn->bits.origin_is_proxy) {
906
    /* talking to a forward proxy, not secure. we do not use
907
     * a forward proxy for https: and other 's' URLs. Let's just check that
908
     * this did not fail somewhere. */
909
0
    DEBUGASSERT(!(data->state.origin->scheme->flags & PROTOPT_SSL));
910
0
    return FALSE;
911
0
  }
912
58.2k
#endif
913
58.2k
  return (data->state.origin->scheme->flags & PROTOPT_SSL);
914
58.2k
}