xref: /curl/lib/transfer.c (revision cfae354a)
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 #include "strtoofft.h"
27 
28 #ifdef HAVE_NETINET_IN_H
29 #include <netinet/in.h>
30 #endif
31 #ifdef HAVE_NETDB_H
32 #include <netdb.h>
33 #endif
34 #ifdef HAVE_ARPA_INET_H
35 #include <arpa/inet.h>
36 #endif
37 #ifdef HAVE_NET_IF_H
38 #include <net/if.h>
39 #endif
40 #ifdef HAVE_SYS_IOCTL_H
41 #include <sys/ioctl.h>
42 #endif
43 #include <signal.h>
44 
45 #ifdef HAVE_SYS_PARAM_H
46 #include <sys/param.h>
47 #endif
48 
49 #ifdef HAVE_SYS_SELECT_H
50 #include <sys/select.h>
51 #elif defined(HAVE_UNISTD_H)
52 #include <unistd.h>
53 #endif
54 
55 #ifndef HAVE_SOCKET
56 #error "We cannot compile without socket() support!"
57 #endif
58 
59 #include "urldata.h"
60 #include <curl/curl.h>
61 #include "netrc.h"
62 
63 #include "content_encoding.h"
64 #include "hostip.h"
65 #include "cfilters.h"
66 #include "cw-out.h"
67 #include "transfer.h"
68 #include "sendf.h"
69 #include "speedcheck.h"
70 #include "progress.h"
71 #include "http.h"
72 #include "url.h"
73 #include "getinfo.h"
74 #include "vtls/vtls.h"
75 #include "vquic/vquic.h"
76 #include "select.h"
77 #include "multiif.h"
78 #include "connect.h"
79 #include "http2.h"
80 #include "mime.h"
81 #include "strcase.h"
82 #include "urlapi-int.h"
83 #include "hsts.h"
84 #include "setopt.h"
85 #include "headers.h"
86 
87 /* The last 3 #include files should be in this order */
88 #include "curl_printf.h"
89 #include "curl_memory.h"
90 #include "memdebug.h"
91 
92 #if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_SMTP) || \
93     !defined(CURL_DISABLE_IMAP)
94 /*
95  * checkheaders() checks the linked list of custom headers for a
96  * particular header (prefix). Provide the prefix without colon!
97  *
98  * Returns a pointer to the first matching header or NULL if none matched.
99  */
Curl_checkheaders(const struct Curl_easy * data,const char * thisheader,const size_t thislen)100 char *Curl_checkheaders(const struct Curl_easy *data,
101                         const char *thisheader,
102                         const size_t thislen)
103 {
104   struct curl_slist *head;
105   DEBUGASSERT(thislen);
106   DEBUGASSERT(thisheader[thislen-1] != ':');
107 
108   for(head = data->set.headers; head; head = head->next) {
109     if(strncasecompare(head->data, thisheader, thislen) &&
110        Curl_headersep(head->data[thislen]) )
111       return head->data;
112   }
113 
114   return NULL;
115 }
116 #endif
117 
data_pending(struct Curl_easy * data)118 static int data_pending(struct Curl_easy *data)
119 {
120   struct connectdata *conn = data->conn;
121 
122   if(conn->handler->protocol&PROTO_FAMILY_FTP)
123     return Curl_conn_data_pending(data, SECONDARYSOCKET);
124 
125   /* in the case of libssh2, we can never be really sure that we have emptied
126      its internal buffers so we MUST always try until we get EAGAIN back */
127   return 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  */
Curl_meets_timecondition(struct Curl_easy * data,time_t timeofdoc)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 
xfer_recv_shutdown(struct Curl_easy * data,bool * done)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 
xfer_recv_shutdown_started(struct Curl_easy * data)175 static bool xfer_recv_shutdown_started(struct Curl_easy *data)
176 {
177   int sockindex;
178 
179   if(!data || !data->conn)
180     return CURLE_FAILED_INIT;
181   if(data->conn->sockfd == CURL_SOCKET_BAD)
182     return CURLE_FAILED_INIT;
183   sockindex = (data->conn->sockfd == data->conn->sock[SECONDARYSOCKET]);
184   return Curl_shutdown_started(data, sockindex);
185 }
186 
Curl_xfer_send_shutdown(struct Curl_easy * data,bool * done)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  */
Curl_xfer_recv_resp(struct Curl_easy * data,char * buf,size_t blen,bool eos_reliable,CURLcode * err)208 static ssize_t Curl_xfer_recv_resp(struct Curl_easy *data,
209                                    char *buf, size_t blen,
210                                    bool eos_reliable,
211                                    CURLcode *err)
212 {
213   ssize_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   DEBUGASSERT(nread >= 0);
255   return nread;
256 }
257 
258 /*
259  * Go ahead and do a read if we have a readable socket or if
260  * the stream was rewound (in which case we have data in a
261  * buffer)
262  */
sendrecv_dl(struct Curl_easy * data,struct SingleRequest * k,int * didwhat)263 static CURLcode sendrecv_dl(struct Curl_easy *data,
264                             struct SingleRequest *k,
265                             int *didwhat)
266 {
267   struct connectdata *conn = data->conn;
268   CURLcode result = CURLE_OK;
269   char *buf, *xfer_buf;
270   size_t blen, xfer_blen;
271   int maxloops = 10;
272   curl_off_t total_received = 0;
273   bool is_multiplex = 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     nread = Curl_xfer_recv_resp(data, buf, bytestoread,
307                                 is_multiplex, &result);
308     if(nread < 0) {
309       if(CURLE_AGAIN != result)
310         goto out; /* real error */
311       result = CURLE_OK;
312       if(data->req.download_done && data->req.no_body &&
313          !data->req.resp_trailer) {
314         DEBUGF(infof(data, "EAGAIN, download done, no trailer announced, "
315                "not waiting for EOS"));
316         nread = 0;
317         /* continue as if we read the EOS */
318       }
319       else
320         break; /* get out of loop */
321     }
322 
323     /* We only get a 0-length read on EndOfStream */
324     blen = (size_t)nread;
325     is_eos = (blen == 0);
326     *didwhat |= KEEP_RECV;
327 
328     if(!blen) {
329       /* if we receive 0 or less here, either the data transfer is done or the
330          server closed the connection and we bail out from this! */
331       if(is_multiplex)
332         DEBUGF(infof(data, "nread == 0, stream closed, bailing"));
333       else
334         DEBUGF(infof(data, "nread <= 0, server closed connection, bailing"));
335       result = Curl_req_stop_send_recv(data);
336       if(result)
337         goto out;
338       if(k->eos_written) /* already did write this to client, leave */
339         break;
340     }
341     total_received += blen;
342 
343     result = Curl_xfer_write_resp(data, buf, blen, is_eos);
344     if(result || data->req.done)
345       goto out;
346 
347     /* if we are done, we stop receiving. On multiplexed connections,
348      * we should read the EOS. Which may arrive as meta data after
349      * the bytes. Not taking it in might lead to RST of streams. */
350     if((!is_multiplex && data->req.download_done) || is_eos) {
351       data->req.keepon &= ~KEEP_RECV;
352     }
353     /* if we are PAUSEd or stopped receiving, leave the loop */
354     if((k->keepon & KEEP_RECV_PAUSE) || !(k->keepon & KEEP_RECV))
355       break;
356 
357   } while(maxloops--);
358 
359   if((maxloops <= 0) || data_pending(data)) {
360     /* did not read until EAGAIN or there is still pending data, mark as
361        read-again-please */
362     data->state.select_bits = CURL_CSELECT_IN;
363     if((k->keepon & KEEP_SENDBITS) == KEEP_SEND)
364       data->state.select_bits |= CURL_CSELECT_OUT;
365   }
366 
367   if(((k->keepon & (KEEP_RECV|KEEP_SEND)) == KEEP_SEND) &&
368      (conn->bits.close || is_multiplex)) {
369     /* When we have read the entire thing and the close bit is set, the server
370        may now close the connection. If there is now any kind of sending going
371        on from our side, we need to stop that immediately. */
372     infof(data, "we are done reading and this is set to close, stop send");
373     Curl_req_abort_sending(data);
374   }
375 
376 out:
377   Curl_multi_xfer_buf_release(data, xfer_buf);
378   if(result)
379     DEBUGF(infof(data, "sendrecv_dl() -> %d", result));
380   return result;
381 }
382 
383 /*
384  * Send data to upload to the server, when the socket is writable.
385  */
sendrecv_ul(struct Curl_easy * data,int * didwhat)386 static CURLcode sendrecv_ul(struct Curl_easy *data, int *didwhat)
387 {
388   /* We should not get here when the sending is already done. It
389    * probably means that someone set `data-req.keepon |= KEEP_SEND`
390    * when it should not. */
391   DEBUGASSERT(!Curl_req_done_sending(data));
392 
393   if(!Curl_req_done_sending(data)) {
394     *didwhat |= KEEP_SEND;
395     return Curl_req_send_more(data);
396   }
397   return CURLE_OK;
398 }
399 
select_bits_paused(struct Curl_easy * data,int select_bits)400 static int select_bits_paused(struct Curl_easy *data, int select_bits)
401 {
402   /* See issue #11982: we really need to be careful not to progress
403    * a transfer direction when that direction is paused. Not all parts
404    * of our state machine are handling PAUSED transfers correctly. So, we
405    * do not want to go there.
406    * NOTE: we are only interested in PAUSE, not HOLD. */
407 
408   /* if there is data in a direction not paused, return false */
409   if(((select_bits & CURL_CSELECT_IN) &&
410       !(data->req.keepon & KEEP_RECV_PAUSE)) ||
411      ((select_bits & CURL_CSELECT_OUT) &&
412       !(data->req.keepon & KEEP_SEND_PAUSE)))
413     return FALSE;
414 
415   return (data->req.keepon & (KEEP_RECV_PAUSE|KEEP_SEND_PAUSE));
416 }
417 
418 /*
419  * Curl_sendrecv() is the low-level function to be called when data is to
420  * be read and written to/from the connection.
421  */
Curl_sendrecv(struct Curl_easy * data,struct curltime * nowp)422 CURLcode Curl_sendrecv(struct Curl_easy *data, struct curltime *nowp)
423 {
424   struct SingleRequest *k = &data->req;
425   CURLcode result = CURLE_OK;
426   int didwhat = 0;
427 
428   DEBUGASSERT(nowp);
429   if(data->state.select_bits) {
430     if(select_bits_paused(data, data->state.select_bits)) {
431       /* leave the bits unchanged, so they'll tell us what to do when
432        * this transfer gets unpaused. */
433       result = CURLE_OK;
434       goto out;
435     }
436     data->state.select_bits = 0;
437   }
438 
439 #ifdef USE_HYPER
440   if(data->conn->datastream) {
441     result = data->conn->datastream(data, data->conn, &didwhat,
442                                     CURL_CSELECT_OUT|CURL_CSELECT_IN);
443     if(result || data->req.done)
444       goto out;
445   }
446   else {
447 #endif
448   /* We go ahead and do a read if we have a readable socket or if the stream
449      was rewound (in which case we have data in a buffer) */
450   if(k->keepon & KEEP_RECV) {
451     result = sendrecv_dl(data, k, &didwhat);
452     if(result || data->req.done)
453       goto out;
454   }
455 
456   /* If we still have writing to do, we check if we have a writable socket. */
457   if(Curl_req_want_send(data) || (data->req.keepon & KEEP_SEND_TIMED)) {
458     result = sendrecv_ul(data, &didwhat);
459     if(result)
460       goto out;
461   }
462 #ifdef USE_HYPER
463   }
464 #endif
465 
466   if(!didwhat) {
467     /* Transfer wanted to send/recv, but nothing was possible. */
468     result = Curl_conn_ev_data_idle(data);
469     if(result)
470       goto out;
471   }
472 
473   if(Curl_pgrsUpdate(data))
474     result = CURLE_ABORTED_BY_CALLBACK;
475   else
476     result = Curl_speedcheck(data, *nowp);
477   if(result)
478     goto out;
479 
480   if(k->keepon) {
481     if(0 > Curl_timeleft(data, nowp, FALSE)) {
482       if(k->size != -1) {
483         failf(data, "Operation timed out after %" FMT_TIMEDIFF_T
484               " milliseconds with %" FMT_OFF_T " out of %"
485               FMT_OFF_T " bytes received",
486               Curl_timediff(*nowp, data->progress.t_startsingle),
487               k->bytecount, k->size);
488       }
489       else {
490         failf(data, "Operation timed out after %" FMT_TIMEDIFF_T
491               " milliseconds with %" FMT_OFF_T " bytes received",
492               Curl_timediff(*nowp, data->progress.t_startsingle),
493               k->bytecount);
494       }
495       result = CURLE_OPERATION_TIMEDOUT;
496       goto out;
497     }
498   }
499   else {
500     /*
501      * The transfer has been performed. Just make some general checks before
502      * returning.
503      */
504     if(!(data->req.no_body) && (k->size != -1) &&
505        (k->bytecount != k->size) && !k->newurl) {
506       failf(data, "transfer closed with %" FMT_OFF_T
507             " bytes remaining to read", k->size - k->bytecount);
508       result = CURLE_PARTIAL_FILE;
509       goto out;
510     }
511     if(Curl_pgrsUpdate(data)) {
512       result = CURLE_ABORTED_BY_CALLBACK;
513       goto out;
514     }
515   }
516 
517   /* If there is nothing more to send/recv, the request is done */
518   if(0 == (k->keepon&(KEEP_RECVBITS|KEEP_SENDBITS)))
519     data->req.done = TRUE;
520 
521 out:
522   if(result)
523     DEBUGF(infof(data, "Curl_sendrecv() -> %d", result));
524   return result;
525 }
526 
527 /* Curl_init_CONNECT() gets called each time the handle switches to CONNECT
528    which means this gets called once for each subsequent redirect etc */
Curl_init_CONNECT(struct Curl_easy * data)529 void Curl_init_CONNECT(struct Curl_easy *data)
530 {
531   data->state.fread_func = data->set.fread_func_set;
532   data->state.in = data->set.in_set;
533   data->state.upload = (data->state.httpreq == HTTPREQ_PUT);
534 }
535 
536 /*
537  * Curl_pretransfer() is called immediately before a transfer starts, and only
538  * once for one transfer no matter if it has redirects or do multi-pass
539  * authentication etc.
540  */
Curl_pretransfer(struct Curl_easy * data)541 CURLcode Curl_pretransfer(struct Curl_easy *data)
542 {
543   CURLcode result;
544 
545   if(!data->state.url && !data->set.uh) {
546     /* we cannot do anything without URL */
547     failf(data, "No URL set");
548     return CURLE_URL_MALFORMAT;
549   }
550 
551   /* since the URL may have been redirected in a previous use of this handle */
552   if(data->state.url_alloc) {
553     /* the already set URL is allocated, free it first! */
554     Curl_safefree(data->state.url);
555     data->state.url_alloc = FALSE;
556   }
557 
558   if(!data->state.url && data->set.uh) {
559     CURLUcode uc;
560     free(data->set.str[STRING_SET_URL]);
561     uc = curl_url_get(data->set.uh,
562                       CURLUPART_URL, &data->set.str[STRING_SET_URL], 0);
563     if(uc) {
564       failf(data, "No URL set");
565       return CURLE_URL_MALFORMAT;
566     }
567   }
568 
569   if(data->set.postfields && data->set.set_resume_from) {
570     /* we cannot */
571     failf(data, "cannot mix POSTFIELDS with RESUME_FROM");
572     return CURLE_BAD_FUNCTION_ARGUMENT;
573   }
574 
575   data->state.prefer_ascii = data->set.prefer_ascii;
576 #ifdef CURL_LIST_ONLY_PROTOCOL
577   data->state.list_only = data->set.list_only;
578 #endif
579   data->state.httpreq = data->set.method;
580   data->state.url = data->set.str[STRING_SET_URL];
581 
582   /* Init the SSL session ID cache here. We do it here since we want to do it
583      after the *_setopt() calls (that could specify the size of the cache) but
584      before any transfer takes place. */
585   result = Curl_ssl_initsessions(data, data->set.general_ssl.max_ssl_sessions);
586   if(result)
587     return result;
588 
589   data->state.requests = 0;
590   data->state.followlocation = 0; /* reset the location-follow counter */
591   data->state.this_is_a_follow = FALSE; /* reset this */
592   data->state.errorbuf = FALSE; /* no error has occurred */
593   data->state.httpwant = data->set.httpwant;
594   data->state.httpversion = 0;
595   data->state.authproblem = FALSE;
596   data->state.authhost.want = data->set.httpauth;
597   data->state.authproxy.want = data->set.proxyauth;
598   Curl_safefree(data->info.wouldredirect);
599   Curl_data_priority_clear_state(data);
600 
601   if(data->state.httpreq == HTTPREQ_PUT)
602     data->state.infilesize = data->set.filesize;
603   else if((data->state.httpreq != HTTPREQ_GET) &&
604           (data->state.httpreq != HTTPREQ_HEAD)) {
605     data->state.infilesize = data->set.postfieldsize;
606     if(data->set.postfields && (data->state.infilesize == -1))
607       data->state.infilesize = (curl_off_t)strlen(data->set.postfields);
608   }
609   else
610     data->state.infilesize = 0;
611 
612   /* If there is a list of cookie files to read, do it now! */
613   Curl_cookie_loadfiles(data);
614 
615   /* If there is a list of host pairs to deal with */
616   if(data->state.resolve)
617     result = Curl_loadhostpairs(data);
618 
619   /* If there is a list of hsts files to read */
620   Curl_hsts_loadfiles(data);
621 
622   if(!result) {
623     /* Allow data->set.use_port to set which port to use. This needs to be
624      * disabled for example when we follow Location: headers to URLs using
625      * different ports! */
626     data->state.allow_port = TRUE;
627 
628 #if defined(HAVE_SIGNAL) && defined(SIGPIPE) && !defined(HAVE_MSG_NOSIGNAL)
629     /*************************************************************
630      * Tell signal handler to ignore SIGPIPE
631      *************************************************************/
632     if(!data->set.no_signal)
633       data->state.prev_signal = signal(SIGPIPE, SIG_IGN);
634 #endif
635 
636     Curl_initinfo(data); /* reset session-specific information "variables" */
637     Curl_pgrsResetTransferSizes(data);
638     Curl_pgrsStartNow(data);
639 
640     /* In case the handle is reused and an authentication method was picked
641        in the session we need to make sure we only use the one(s) we now
642        consider to be fine */
643     data->state.authhost.picked &= data->state.authhost.want;
644     data->state.authproxy.picked &= data->state.authproxy.want;
645 
646 #ifndef CURL_DISABLE_FTP
647     data->state.wildcardmatch = data->set.wildcard_enabled;
648     if(data->state.wildcardmatch) {
649       struct WildcardData *wc;
650       if(!data->wildcard) {
651         data->wildcard = calloc(1, sizeof(struct WildcardData));
652         if(!data->wildcard)
653           return CURLE_OUT_OF_MEMORY;
654       }
655       wc = data->wildcard;
656       if(wc->state < CURLWC_INIT) {
657         if(wc->ftpwc)
658           wc->dtor(wc->ftpwc);
659         Curl_safefree(wc->pattern);
660         Curl_safefree(wc->path);
661         result = Curl_wildcard_init(wc); /* init wildcard structures */
662         if(result)
663           return CURLE_OUT_OF_MEMORY;
664       }
665     }
666 #endif
667     result = Curl_hsts_loadcb(data, data->hsts);
668   }
669 
670   /*
671    * Set user-agent. Used for HTTP, but since we can attempt to tunnel
672    * basically anything through an HTTP proxy we cannot limit this based on
673    * protocol.
674    */
675   if(data->set.str[STRING_USERAGENT]) {
676     Curl_safefree(data->state.aptr.uagent);
677     data->state.aptr.uagent =
678       aprintf("User-Agent: %s\r\n", data->set.str[STRING_USERAGENT]);
679     if(!data->state.aptr.uagent)
680       return CURLE_OUT_OF_MEMORY;
681   }
682 
683   if(!result)
684     result = Curl_setstropt(&data->state.aptr.user,
685                             data->set.str[STRING_USERNAME]);
686   if(!result)
687     result = Curl_setstropt(&data->state.aptr.passwd,
688                             data->set.str[STRING_PASSWORD]);
689 #ifndef CURL_DISABLE_PROXY
690   if(!result)
691     result = Curl_setstropt(&data->state.aptr.proxyuser,
692                             data->set.str[STRING_PROXYUSERNAME]);
693   if(!result)
694     result = Curl_setstropt(&data->state.aptr.proxypasswd,
695                             data->set.str[STRING_PROXYPASSWORD]);
696 #endif
697 
698   data->req.headerbytecount = 0;
699   Curl_headers_cleanup(data);
700   return result;
701 }
702 
703 /*
704  * Curl_follow() handles the URL redirect magic. Pass in the 'newurl' string
705  * as given by the remote server and set up the new URL to request.
706  *
707  * This function DOES NOT FREE the given url.
708  */
Curl_follow(struct Curl_easy * data,char * newurl,followtype type)709 CURLcode Curl_follow(struct Curl_easy *data,
710                      char *newurl,    /* the Location: string */
711                      followtype type) /* see transfer.h */
712 {
713 #ifdef CURL_DISABLE_HTTP
714   (void)data;
715   (void)newurl;
716   (void)type;
717   /* Location: following will not happen when HTTP is disabled */
718   return CURLE_TOO_MANY_REDIRECTS;
719 #else
720 
721   /* Location: redirect */
722   bool disallowport = FALSE;
723   bool reachedmax = FALSE;
724   CURLUcode uc;
725 
726   DEBUGASSERT(type != FOLLOW_NONE);
727 
728   if(type != FOLLOW_FAKE)
729     data->state.requests++; /* count all real follows */
730   if(type == FOLLOW_REDIR) {
731     if((data->set.maxredirs != -1) &&
732        (data->state.followlocation >= data->set.maxredirs)) {
733       reachedmax = TRUE;
734       type = FOLLOW_FAKE; /* switch to fake to store the would-be-redirected
735                              to URL */
736     }
737     else {
738       data->state.followlocation++; /* count redirect-followings, including
739                                        auth reloads */
740 
741       if(data->set.http_auto_referer) {
742         CURLU *u;
743         char *referer = NULL;
744 
745         /* We are asked to automatically set the previous URL as the referer
746            when we get the next URL. We pick the ->url field, which may or may
747            not be 100% correct */
748 
749         if(data->state.referer_alloc) {
750           Curl_safefree(data->state.referer);
751           data->state.referer_alloc = FALSE;
752         }
753 
754         /* Make a copy of the URL without credentials and fragment */
755         u = curl_url();
756         if(!u)
757           return CURLE_OUT_OF_MEMORY;
758 
759         uc = curl_url_set(u, CURLUPART_URL, data->state.url, 0);
760         if(!uc)
761           uc = curl_url_set(u, CURLUPART_FRAGMENT, NULL, 0);
762         if(!uc)
763           uc = curl_url_set(u, CURLUPART_USER, NULL, 0);
764         if(!uc)
765           uc = curl_url_set(u, CURLUPART_PASSWORD, NULL, 0);
766         if(!uc)
767           uc = curl_url_get(u, CURLUPART_URL, &referer, 0);
768 
769         curl_url_cleanup(u);
770 
771         if(uc || !referer)
772           return CURLE_OUT_OF_MEMORY;
773 
774         data->state.referer = referer;
775         data->state.referer_alloc = TRUE; /* yes, free this later */
776       }
777     }
778   }
779 
780   if((type != FOLLOW_RETRY) &&
781      (data->req.httpcode != 401) && (data->req.httpcode != 407) &&
782      Curl_is_absolute_url(newurl, NULL, 0, FALSE)) {
783     /* If this is not redirect due to a 401 or 407 response and an absolute
784        URL: do not allow a custom port number */
785     disallowport = TRUE;
786   }
787 
788   DEBUGASSERT(data->state.uh);
789   uc = curl_url_set(data->state.uh, CURLUPART_URL, newurl, (unsigned int)
790                     ((type == FOLLOW_FAKE) ? CURLU_NON_SUPPORT_SCHEME :
791                      ((type == FOLLOW_REDIR) ? CURLU_URLENCODE : 0) |
792                      CURLU_ALLOW_SPACE |
793                      (data->set.path_as_is ? CURLU_PATH_AS_IS : 0)));
794   if(uc) {
795     if(type != FOLLOW_FAKE) {
796       failf(data, "The redirect target URL could not be parsed: %s",
797             curl_url_strerror(uc));
798       return Curl_uc_to_curlcode(uc);
799     }
800 
801     /* the URL could not be parsed for some reason, but since this is FAKE
802        mode, just duplicate the field as-is */
803     newurl = strdup(newurl);
804     if(!newurl)
805       return CURLE_OUT_OF_MEMORY;
806   }
807   else {
808     uc = curl_url_get(data->state.uh, CURLUPART_URL, &newurl, 0);
809     if(uc)
810       return Curl_uc_to_curlcode(uc);
811 
812     /* Clear auth if this redirects to a different port number or protocol,
813        unless permitted */
814     if(!data->set.allow_auth_to_other_hosts && (type != FOLLOW_FAKE)) {
815       char *portnum;
816       int port;
817       bool clear = FALSE;
818 
819       if(data->set.use_port && data->state.allow_port)
820         /* a custom port is used */
821         port = (int)data->set.use_port;
822       else {
823         uc = curl_url_get(data->state.uh, CURLUPART_PORT, &portnum,
824                           CURLU_DEFAULT_PORT);
825         if(uc) {
826           free(newurl);
827           return Curl_uc_to_curlcode(uc);
828         }
829         port = atoi(portnum);
830         free(portnum);
831       }
832       if(port != data->info.conn_remote_port) {
833         infof(data, "Clear auth, redirects to port from %u to %u",
834               data->info.conn_remote_port, port);
835         clear = TRUE;
836       }
837       else {
838         char *scheme;
839         const struct Curl_handler *p;
840         uc = curl_url_get(data->state.uh, CURLUPART_SCHEME, &scheme, 0);
841         if(uc) {
842           free(newurl);
843           return Curl_uc_to_curlcode(uc);
844         }
845 
846         p = Curl_get_scheme_handler(scheme);
847         if(p && (p->protocol != data->info.conn_protocol)) {
848           infof(data, "Clear auth, redirects scheme from %s to %s",
849                 data->info.conn_scheme, scheme);
850           clear = TRUE;
851         }
852         free(scheme);
853       }
854       if(clear) {
855         Curl_safefree(data->state.aptr.user);
856         Curl_safefree(data->state.aptr.passwd);
857       }
858     }
859   }
860 
861   if(type == FOLLOW_FAKE) {
862     /* we are only figuring out the new URL if we would have followed locations
863        but now we are done so we can get out! */
864     data->info.wouldredirect = newurl;
865 
866     if(reachedmax) {
867       failf(data, "Maximum (%ld) redirects followed", data->set.maxredirs);
868       return CURLE_TOO_MANY_REDIRECTS;
869     }
870     return CURLE_OK;
871   }
872 
873   if(disallowport)
874     data->state.allow_port = FALSE;
875 
876   if(data->state.url_alloc)
877     Curl_safefree(data->state.url);
878 
879   data->state.url = newurl;
880   data->state.url_alloc = TRUE;
881   Curl_req_soft_reset(&data->req, data);
882   infof(data, "Issue another request to this URL: '%s'", data->state.url);
883 
884   /*
885    * We get here when the HTTP code is 300-399 (and 401). We need to perform
886    * differently based on exactly what return code there was.
887    *
888    * News from 7.10.6: we can also get here on a 401 or 407, in case we act on
889    * an HTTP (proxy-) authentication scheme other than Basic.
890    */
891   switch(data->info.httpcode) {
892     /* 401 - Act on a WWW-Authenticate, we keep on moving and do the
893        Authorization: XXXX header in the HTTP request code snippet */
894     /* 407 - Act on a Proxy-Authenticate, we keep on moving and do the
895        Proxy-Authorization: XXXX header in the HTTP request code snippet */
896     /* 300 - Multiple Choices */
897     /* 306 - Not used */
898     /* 307 - Temporary Redirect */
899   default:  /* for all above (and the unknown ones) */
900     /* Some codes are explicitly mentioned since I have checked RFC2616 and
901      * they seem to be OK to POST to.
902      */
903     break;
904   case 301: /* Moved Permanently */
905     /* (quote from RFC7231, section 6.4.2)
906      *
907      * Note: For historical reasons, a user agent MAY change the request
908      * method from POST to GET for the subsequent request. If this
909      * behavior is undesired, the 307 (Temporary Redirect) status code
910      * can be used instead.
911      *
912      * ----
913      *
914      * Many webservers expect this, so these servers often answers to a POST
915      * request with an error page. To be sure that libcurl gets the page that
916      * most user agents would get, libcurl has to force GET.
917      *
918      * This behavior is forbidden by RFC1945 and the obsolete RFC2616, and
919      * can be overridden with CURLOPT_POSTREDIR.
920      */
921     if((data->state.httpreq == HTTPREQ_POST
922         || data->state.httpreq == HTTPREQ_POST_FORM
923         || data->state.httpreq == HTTPREQ_POST_MIME)
924        && !(data->set.keep_post & CURL_REDIR_POST_301)) {
925       infof(data, "Switch from POST to GET");
926       data->state.httpreq = HTTPREQ_GET;
927       Curl_creader_set_rewind(data, FALSE);
928     }
929     break;
930   case 302: /* Found */
931     /* (quote from RFC7231, section 6.4.3)
932      *
933      * Note: For historical reasons, a user agent MAY change the request
934      * method from POST to GET for the subsequent request. If this
935      * behavior is undesired, the 307 (Temporary Redirect) status code
936      * can be used instead.
937      *
938      * ----
939      *
940      * Many webservers expect this, so these servers often answers to a POST
941      * request with an error page. To be sure that libcurl gets the page that
942      * most user agents would get, libcurl has to force GET.
943      *
944      * This behavior is forbidden by RFC1945 and the obsolete RFC2616, and
945      * can be overridden with CURLOPT_POSTREDIR.
946      */
947     if((data->state.httpreq == HTTPREQ_POST
948         || data->state.httpreq == HTTPREQ_POST_FORM
949         || data->state.httpreq == HTTPREQ_POST_MIME)
950        && !(data->set.keep_post & CURL_REDIR_POST_302)) {
951       infof(data, "Switch from POST to GET");
952       data->state.httpreq = HTTPREQ_GET;
953       Curl_creader_set_rewind(data, FALSE);
954     }
955     break;
956 
957   case 303: /* See Other */
958     /* 'See Other' location is not the resource but a substitute for the
959      * resource. In this case we switch the method to GET/HEAD, unless the
960      * method is POST and the user specified to keep it as POST.
961      * https://github.com/curl/curl/issues/5237#issuecomment-614641049
962      */
963     if(data->state.httpreq != HTTPREQ_GET &&
964        ((data->state.httpreq != HTTPREQ_POST &&
965          data->state.httpreq != HTTPREQ_POST_FORM &&
966          data->state.httpreq != HTTPREQ_POST_MIME) ||
967         !(data->set.keep_post & CURL_REDIR_POST_303))) {
968       data->state.httpreq = HTTPREQ_GET;
969       infof(data, "Switch to %s",
970             data->req.no_body ? "HEAD" : "GET");
971     }
972     break;
973   case 304: /* Not Modified */
974     /* 304 means we did a conditional request and it was "Not modified".
975      * We should not get any Location: header in this response!
976      */
977     break;
978   case 305: /* Use Proxy */
979     /* (quote from RFC2616, section 10.3.6):
980      * "The requested resource MUST be accessed through the proxy given
981      * by the Location field. The Location field gives the URI of the
982      * proxy. The recipient is expected to repeat this single request
983      * via the proxy. 305 responses MUST only be generated by origin
984      * servers."
985      */
986     break;
987   }
988   Curl_pgrsTime(data, TIMER_REDIRECT);
989   Curl_pgrsResetTransferSizes(data);
990 
991   return CURLE_OK;
992 #endif /* CURL_DISABLE_HTTP */
993 }
994 
995 /* Returns CURLE_OK *and* sets '*url' if a request retry is wanted.
996 
997    NOTE: that the *url is malloc()ed. */
Curl_retry_request(struct Curl_easy * data,char ** url)998 CURLcode Curl_retry_request(struct Curl_easy *data, char **url)
999 {
1000   struct connectdata *conn = data->conn;
1001   bool retry = FALSE;
1002   *url = NULL;
1003 
1004   /* if we are talking upload, we cannot do the checks below, unless the
1005      protocol is HTTP as when uploading over HTTP we will still get a
1006      response */
1007   if(data->state.upload &&
1008      !(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP)))
1009     return CURLE_OK;
1010 
1011   if((data->req.bytecount + data->req.headerbytecount == 0) &&
1012      conn->bits.reuse &&
1013      (!data->req.no_body || (conn->handler->protocol & PROTO_FAMILY_HTTP))
1014 #ifndef CURL_DISABLE_RTSP
1015      && (data->set.rtspreq != RTSPREQ_RECEIVE)
1016 #endif
1017     )
1018     /* We got no data, we attempted to reuse a connection. For HTTP this
1019        can be a retry so we try again regardless if we expected a body.
1020        For other protocols we only try again only if we expected a body.
1021 
1022        This might happen if the connection was left alive when we were
1023        done using it before, but that was closed when we wanted to read from
1024        it again. Bad luck. Retry the same request on a fresh connect! */
1025     retry = TRUE;
1026   else if(data->state.refused_stream &&
1027           (data->req.bytecount + data->req.headerbytecount == 0) ) {
1028     /* This was sent on a refused stream, safe to rerun. A refused stream
1029        error can typically only happen on HTTP/2 level if the stream is safe
1030        to issue again, but the nghttp2 API can deliver the message to other
1031        streams as well, which is why this adds the check the data counters
1032        too. */
1033     infof(data, "REFUSED_STREAM, retrying a fresh connect");
1034     data->state.refused_stream = FALSE; /* clear again */
1035     retry = TRUE;
1036   }
1037   if(retry) {
1038 #define CONN_MAX_RETRIES 5
1039     if(data->state.retrycount++ >= CONN_MAX_RETRIES) {
1040       failf(data, "Connection died, tried %d times before giving up",
1041             CONN_MAX_RETRIES);
1042       data->state.retrycount = 0;
1043       return CURLE_SEND_ERROR;
1044     }
1045     infof(data, "Connection died, retrying a fresh connect (retry count: %d)",
1046           data->state.retrycount);
1047     *url = strdup(data->state.url);
1048     if(!*url)
1049       return CURLE_OUT_OF_MEMORY;
1050 
1051     connclose(conn, "retry"); /* close this connection */
1052     conn->bits.retry = TRUE; /* mark this as a connection we are about
1053                                 to retry. Marking it this way should
1054                                 prevent i.e HTTP transfers to return
1055                                 error just because nothing has been
1056                                 transferred! */
1057     Curl_creader_set_rewind(data, TRUE);
1058   }
1059   return CURLE_OK;
1060 }
1061 
1062 /*
1063  * xfer_setup() is called to setup basic properties for the transfer.
1064  */
xfer_setup(struct Curl_easy * data,int sockindex,curl_off_t size,bool getheader,int writesockindex,bool shutdown,bool shutdown_err_ignore)1065 static void xfer_setup(
1066   struct Curl_easy *data,   /* transfer */
1067   int sockindex,            /* socket index to read from or -1 */
1068   curl_off_t size,          /* -1 if unknown at this point */
1069   bool getheader,           /* TRUE if header parsing is wanted */
1070   int writesockindex,       /* socket index to write to, it may very well be
1071                                the same we read from. -1 disables */
1072   bool shutdown,            /* shutdown connection at transfer end. Only
1073                              * supported when sending OR receiving. */
1074   bool shutdown_err_ignore  /* errors during shutdown do not fail the
1075                              * transfer */
1076   )
1077 {
1078   struct SingleRequest *k = &data->req;
1079   struct connectdata *conn = data->conn;
1080   bool want_send = Curl_req_want_send(data);
1081 
1082   DEBUGASSERT(conn != NULL);
1083   DEBUGASSERT((sockindex <= 1) && (sockindex >= -1));
1084   DEBUGASSERT((writesockindex <= 1) && (writesockindex >= -1));
1085   DEBUGASSERT(!shutdown || (sockindex == -1) || (writesockindex == -1));
1086 
1087   if(conn->bits.multiplex || conn->httpversion >= 20 || want_send) {
1088     /* when multiplexing, the read/write sockets need to be the same! */
1089     conn->sockfd = sockindex == -1 ?
1090       ((writesockindex == -1 ? CURL_SOCKET_BAD : conn->sock[writesockindex])) :
1091       conn->sock[sockindex];
1092     conn->writesockfd = conn->sockfd;
1093     if(want_send)
1094       /* special and very HTTP-specific */
1095       writesockindex = FIRSTSOCKET;
1096   }
1097   else {
1098     conn->sockfd = sockindex == -1 ?
1099       CURL_SOCKET_BAD : conn->sock[sockindex];
1100     conn->writesockfd = writesockindex == -1 ?
1101       CURL_SOCKET_BAD : conn->sock[writesockindex];
1102   }
1103 
1104   k->getheader = getheader;
1105   k->size = size;
1106   k->shutdown = shutdown;
1107   k->shutdown_err_ignore = shutdown_err_ignore;
1108 
1109   /* The code sequence below is placed in this function just because all
1110      necessary input is not always known in do_complete() as this function may
1111      be called after that */
1112 
1113   if(!k->getheader) {
1114     k->header = FALSE;
1115     if(size > 0)
1116       Curl_pgrsSetDownloadSize(data, size);
1117   }
1118   /* we want header and/or body, if neither then do not do this! */
1119   if(k->getheader || !data->req.no_body) {
1120 
1121     if(sockindex != -1)
1122       k->keepon |= KEEP_RECV;
1123 
1124     if(writesockindex != -1)
1125       k->keepon |= KEEP_SEND;
1126   } /* if(k->getheader || !data->req.no_body) */
1127 
1128 }
1129 
Curl_xfer_setup_nop(struct Curl_easy * data)1130 void Curl_xfer_setup_nop(struct Curl_easy *data)
1131 {
1132   xfer_setup(data, -1, -1, FALSE, -1, FALSE, FALSE);
1133 }
1134 
Curl_xfer_setup1(struct Curl_easy * data,int send_recv,curl_off_t recv_size,bool getheader)1135 void Curl_xfer_setup1(struct Curl_easy *data,
1136                       int send_recv,
1137                       curl_off_t recv_size,
1138                       bool getheader)
1139 {
1140   int recv_index = (send_recv & CURL_XFER_RECV) ? FIRSTSOCKET : -1;
1141   int send_index = (send_recv & CURL_XFER_SEND) ? FIRSTSOCKET : -1;
1142   DEBUGASSERT((recv_index >= 0) || (recv_size == -1));
1143   xfer_setup(data, recv_index, recv_size, getheader, send_index, FALSE, FALSE);
1144 }
1145 
Curl_xfer_setup2(struct Curl_easy * data,int send_recv,curl_off_t recv_size,bool shutdown,bool shutdown_err_ignore)1146 void Curl_xfer_setup2(struct Curl_easy *data,
1147                       int send_recv,
1148                       curl_off_t recv_size,
1149                       bool shutdown,
1150                       bool shutdown_err_ignore)
1151 {
1152   int recv_index = (send_recv & CURL_XFER_RECV) ? SECONDARYSOCKET : -1;
1153   int send_index = (send_recv & CURL_XFER_SEND) ? SECONDARYSOCKET : -1;
1154   DEBUGASSERT((recv_index >= 0) || (recv_size == -1));
1155   xfer_setup(data, recv_index, recv_size, FALSE, send_index,
1156              shutdown, shutdown_err_ignore);
1157 }
1158 
Curl_xfer_write_resp(struct Curl_easy * data,const char * buf,size_t blen,bool is_eos)1159 CURLcode Curl_xfer_write_resp(struct Curl_easy *data,
1160                               const char *buf, size_t blen,
1161                               bool is_eos)
1162 {
1163   CURLcode result = CURLE_OK;
1164 
1165   if(data->conn->handler->write_resp) {
1166     /* protocol handlers offering this function take full responsibility
1167      * for writing all received download data to the client. */
1168     result = data->conn->handler->write_resp(data, buf, blen, is_eos);
1169   }
1170   else {
1171     /* No special handling by protocol handler, write all received data
1172      * as BODY to the client. */
1173     if(blen || is_eos) {
1174       int cwtype = CLIENTWRITE_BODY;
1175       if(is_eos)
1176         cwtype |= CLIENTWRITE_EOS;
1177       result = Curl_client_write(data, cwtype, buf, blen);
1178     }
1179   }
1180 
1181   if(!result && is_eos) {
1182     /* If we wrote the EOS, we are definitely done */
1183     data->req.eos_written = TRUE;
1184     data->req.download_done = TRUE;
1185   }
1186   CURL_TRC_WRITE(data, "xfer_write_resp(len=%zu, eos=%d) -> %d",
1187                  blen, is_eos, result);
1188   return result;
1189 }
1190 
Curl_xfer_write_resp_hd(struct Curl_easy * data,const char * hd0,size_t hdlen,bool is_eos)1191 CURLcode Curl_xfer_write_resp_hd(struct Curl_easy *data,
1192                                  const char *hd0, size_t hdlen, bool is_eos)
1193 {
1194   if(data->conn->handler->write_resp_hd) {
1195     /* protocol handlers offering this function take full responsibility
1196      * for writing all received download data to the client. */
1197     return data->conn->handler->write_resp_hd(data, hd0, hdlen, is_eos);
1198   }
1199   /* No special handling by protocol handler, write as response bytes */
1200   return Curl_xfer_write_resp(data, hd0, hdlen, is_eos);
1201 }
1202 
Curl_xfer_write_done(struct Curl_easy * data,bool premature)1203 CURLcode Curl_xfer_write_done(struct Curl_easy *data, bool premature)
1204 {
1205   (void)premature;
1206   return Curl_cw_out_done(data);
1207 }
1208 
Curl_xfer_needs_flush(struct Curl_easy * data)1209 bool Curl_xfer_needs_flush(struct Curl_easy *data)
1210 {
1211   int sockindex;
1212   sockindex = ((data->conn->writesockfd != CURL_SOCKET_BAD) &&
1213                (data->conn->writesockfd == data->conn->sock[SECONDARYSOCKET]));
1214   return Curl_conn_needs_flush(data, sockindex);
1215 }
1216 
Curl_xfer_flush(struct Curl_easy * data)1217 CURLcode Curl_xfer_flush(struct Curl_easy *data)
1218 {
1219   int sockindex;
1220   sockindex = ((data->conn->writesockfd != CURL_SOCKET_BAD) &&
1221                (data->conn->writesockfd == data->conn->sock[SECONDARYSOCKET]));
1222   return Curl_conn_flush(data, sockindex);
1223 }
1224 
Curl_xfer_send(struct Curl_easy * data,const void * buf,size_t blen,bool eos,size_t * pnwritten)1225 CURLcode Curl_xfer_send(struct Curl_easy *data,
1226                         const void *buf, size_t blen, bool eos,
1227                         size_t *pnwritten)
1228 {
1229   CURLcode result;
1230   int sockindex;
1231 
1232   DEBUGASSERT(data);
1233   DEBUGASSERT(data->conn);
1234 
1235   sockindex = ((data->conn->writesockfd != CURL_SOCKET_BAD) &&
1236                (data->conn->writesockfd == data->conn->sock[SECONDARYSOCKET]));
1237   result = Curl_conn_send(data, sockindex, buf, blen, eos, pnwritten);
1238   if(result == CURLE_AGAIN) {
1239     result = CURLE_OK;
1240     *pnwritten = 0;
1241   }
1242   else if(!result && *pnwritten)
1243     data->info.request_size += *pnwritten;
1244 
1245   DEBUGF(infof(data, "Curl_xfer_send(len=%zu, eos=%d) -> %d, %zu",
1246                blen, eos, result, *pnwritten));
1247   return result;
1248 }
1249 
Curl_xfer_recv(struct Curl_easy * data,char * buf,size_t blen,ssize_t * pnrcvd)1250 CURLcode Curl_xfer_recv(struct Curl_easy *data,
1251                         char *buf, size_t blen,
1252                         ssize_t *pnrcvd)
1253 {
1254   int sockindex;
1255 
1256   DEBUGASSERT(data);
1257   DEBUGASSERT(data->conn);
1258   DEBUGASSERT(data->set.buffer_size > 0);
1259 
1260   sockindex = ((data->conn->sockfd != CURL_SOCKET_BAD) &&
1261                (data->conn->sockfd == data->conn->sock[SECONDARYSOCKET]));
1262   if((size_t)data->set.buffer_size < blen)
1263     blen = (size_t)data->set.buffer_size;
1264   return Curl_conn_recv(data, sockindex, buf, blen, pnrcvd);
1265 }
1266 
Curl_xfer_send_close(struct Curl_easy * data)1267 CURLcode Curl_xfer_send_close(struct Curl_easy *data)
1268 {
1269   Curl_conn_ev_data_done_send(data);
1270   return CURLE_OK;
1271 }
1272 
Curl_xfer_is_blocked(struct Curl_easy * data)1273 bool Curl_xfer_is_blocked(struct Curl_easy *data)
1274 {
1275   bool want_send = ((data)->req.keepon & KEEP_SEND);
1276   bool want_recv = ((data)->req.keepon & KEEP_RECV);
1277   if(!want_send)
1278     return (want_recv && Curl_cwriter_is_paused(data));
1279   else if(!want_recv)
1280     return (want_send && Curl_creader_is_paused(data));
1281   else
1282     return Curl_creader_is_paused(data) && Curl_cwriter_is_paused(data);
1283 }
1284