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