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