Coverage Report

Created: 2025-11-15 08:43

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