quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

transfer.c (31548B)


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