1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
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.
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.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ***************************************************************************/
23 #include "curl_setup.h"
25 #ifdef HAVE_NETINET_IN_H
26 #include <netinet/in.h>
29 #ifdef HAVE_LINUX_TCP_H
30 #include <linux/tcp.h>
31 #elif defined(HAVE_NETINET_TCP_H)
32 #include <netinet/tcp.h>
35 #include <curl/curl.h>
40 #include "vtls/vtls.h"
50 /* The last 3 #include files should be in this order */
51 #include "curl_printf.h"
52 #include "curl_memory.h"
55 #ifdef CURL_DO_LINEEND_CONV
57 * convert_lineends() changes CRLF (\r\n) end-of-line markers to a single LF
58 * (\n), with special processing for CRLF sequences that are split between two
59 * blocks of data. Remaining, bare CRs are changed to LFs. The possibly new
60 * size of the data is returned.
62 static size_t convert_lineends(struct Curl_easy *data,
63 char *startPtr, size_t size)
68 if(!startPtr || (size < 1)) {
72 if(data->state.prev_block_had_trailing_cr) {
73 /* The previous block of incoming data
74 had a trailing CR, which was turned into a LF. */
75 if(*startPtr == '\n') {
76 /* This block of incoming data starts with the
77 previous block's LF so get rid of it */
78 memmove(startPtr, startPtr + 1, size-1);
80 /* and it wasn't a bare CR but a CRLF conversion instead */
81 data->state.crlf_conversions++;
83 data->state.prev_block_had_trailing_cr = FALSE; /* reset the flag */
86 /* find 1st CR, if any */
87 inPtr = outPtr = memchr(startPtr, '\r', size);
89 /* at least one CR, now look for CRLF */
90 while(inPtr < (startPtr + size-1)) {
91 /* note that it's size-1, so we'll never look past the last byte */
92 if(memcmp(inPtr, "\r\n", 2) == 0) {
93 /* CRLF found, bump past the CR and copy the NL */
96 /* keep track of how many CRLFs we converted */
97 data->state.crlf_conversions++;
101 /* lone CR, move LF instead */
105 /* not a CRLF nor a CR, just copy whatever it is */
111 } /* end of while loop */
113 if(inPtr < startPtr + size) {
114 /* handle last byte */
116 /* deal with a CR at the end of the buffer */
117 *outPtr = '\n'; /* copy a NL instead */
118 /* note that a CRLF might be split across two blocks */
119 data->state.prev_block_had_trailing_cr = TRUE;
127 if(outPtr < startPtr + size)
128 /* tidy up by null terminating the now shorter data */
131 return (outPtr - startPtr);
135 #endif /* CURL_DO_LINEEND_CONV */
137 #ifdef USE_RECV_BEFORE_SEND_WORKAROUND
138 bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex)
140 struct postponed_data * const psnd = &(conn->postponed[sockindex]);
141 return psnd->buffer && psnd->allocated_size &&
142 psnd->recv_size > psnd->recv_processed;
145 static CURLcode pre_receive_plain(struct Curl_easy *data,
146 struct connectdata *conn, int num)
148 const curl_socket_t sockfd = conn->sock[num];
149 struct postponed_data * const psnd = &(conn->postponed[num]);
150 size_t bytestorecv = psnd->allocated_size - psnd->recv_size;
151 /* WinSock will destroy unread received data if send() is
153 To avoid lossage of received data, recv() must be
154 performed before every send() if any incoming data is
155 available. However, skip this, if buffer is already full. */
156 if((conn->handler->protocol&PROTO_FAMILY_HTTP) != 0 &&
157 conn->recv[num] == Curl_recv_plain &&
158 (!psnd->buffer || bytestorecv)) {
159 const int readymask = Curl_socket_check(sockfd, CURL_SOCKET_BAD,
161 if(readymask != -1 && (readymask & CURL_CSELECT_IN) != 0) {
162 /* Have some incoming data */
164 /* Use buffer double default size for intermediate buffer */
165 psnd->allocated_size = 2 * data->set.buffer_size;
166 psnd->buffer = malloc(psnd->allocated_size);
168 return CURLE_OUT_OF_MEMORY;
170 psnd->recv_processed = 0;
172 psnd->bindsock = sockfd; /* Used only for DEBUGASSERT */
173 #endif /* DEBUGBUILD */
174 bytestorecv = psnd->allocated_size;
178 DEBUGASSERT(psnd->bindsock == sockfd);
179 recvedbytes = sread(sockfd, psnd->buffer + psnd->recv_size,
182 psnd->recv_size += recvedbytes;
185 psnd->allocated_size = 0;
191 static ssize_t get_pre_recved(struct connectdata *conn, int num, char *buf,
194 struct postponed_data * const psnd = &(conn->postponed[num]);
199 DEBUGASSERT(psnd->allocated_size > 0);
200 DEBUGASSERT(psnd->recv_size <= psnd->allocated_size);
201 DEBUGASSERT(psnd->recv_processed <= psnd->recv_size);
202 /* Check and process data that already received and storied in internal
203 intermediate buffer */
204 if(psnd->recv_size > psnd->recv_processed) {
205 DEBUGASSERT(psnd->bindsock == conn->sock[num]);
206 copysize = CURLMIN(len, psnd->recv_size - psnd->recv_processed);
207 memcpy(buf, psnd->buffer + psnd->recv_processed, copysize);
208 psnd->recv_processed += copysize;
211 copysize = 0; /* buffer was allocated, but nothing was received */
213 /* Free intermediate buffer if it has no unprocessed data */
214 if(psnd->recv_processed == psnd->recv_size) {
217 psnd->allocated_size = 0;
219 psnd->recv_processed = 0;
221 psnd->bindsock = CURL_SOCKET_BAD;
222 #endif /* DEBUGBUILD */
224 return (ssize_t)copysize;
226 #else /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
227 /* Use "do-nothing" macros instead of functions when workaround not used */
228 bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex)
234 #define pre_receive_plain(d,c,n) CURLE_OK
235 #define get_pre_recved(c,n,b,l) 0
236 #endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
238 /* Curl_infof() is for info message along the way */
241 void Curl_infof(struct Curl_easy *data, const char *fmt, ...)
243 DEBUGASSERT(!strchr(fmt, '\n'));
244 if(data && data->set.verbose) {
247 char buffer[MAXINFO + 2];
249 len = mvsnprintf(buffer, MAXINFO, fmt, ap);
251 buffer[len++] = '\n';
253 Curl_debug(data, CURLINFO_TEXT, buffer, len);
257 /* Curl_failf() is for messages stating why we failed.
258 * The message SHALL NOT include any LF or CR.
261 void Curl_failf(struct Curl_easy *data, const char *fmt, ...)
263 DEBUGASSERT(!strchr(fmt, '\n'));
264 if(data->set.verbose || data->set.errorbuffer) {
267 char error[CURL_ERROR_SIZE + 2];
269 len = mvsnprintf(error, CURL_ERROR_SIZE, fmt, ap);
271 if(data->set.errorbuffer && !data->state.errorbuf) {
272 strcpy(data->set.errorbuffer, error);
273 data->state.errorbuf = TRUE; /* wrote error string */
277 Curl_debug(data, CURLINFO_TEXT, error, len);
283 * Curl_write() is an internal write function that sends data to the
284 * server. Works with plain sockets, SCP, SSL or kerberos.
286 * If the write would block (CURLE_AGAIN), we return CURLE_OK and
287 * (*written == 0). Otherwise we return regular CURLcode value.
289 CURLcode Curl_write(struct Curl_easy *data,
290 curl_socket_t sockfd,
295 ssize_t bytes_written;
296 CURLcode result = CURLE_OK;
297 struct connectdata *conn;
300 DEBUGASSERT(data->conn);
302 num = (sockfd == conn->sock[SECONDARYSOCKET]);
306 /* Allow debug builds to override this logic to force short sends
308 char *p = getenv("CURL_SMALLSENDS");
310 size_t altsize = (size_t)strtoul(p, NULL, 10);
312 len = CURLMIN(len, altsize);
316 bytes_written = conn->send[num](data, num, mem, len, &result);
318 *written = bytes_written;
319 if(bytes_written >= 0)
320 /* we completely ignore the curlcode value when subzero is not returned */
323 /* handle CURLE_AGAIN or a send failure */
330 /* general send failure */
331 return CURLE_SEND_ERROR;
334 /* we got a specific curlcode, forward it */
339 ssize_t Curl_send_plain(struct Curl_easy *data, int num,
340 const void *mem, size_t len, CURLcode *code)
342 struct connectdata *conn;
343 curl_socket_t sockfd;
344 ssize_t bytes_written;
347 DEBUGASSERT(data->conn);
349 sockfd = conn->sock[num];
350 /* WinSock will destroy unread received data if send() is
352 To avoid lossage of received data, recv() must be
353 performed before every send() if any incoming data is
355 if(pre_receive_plain(data, conn, num)) {
356 *code = CURLE_OUT_OF_MEMORY;
360 #if defined(MSG_FASTOPEN) && !defined(TCP_FASTOPEN_CONNECT) /* Linux */
361 if(conn->bits.tcp_fastopen) {
362 bytes_written = sendto(sockfd, mem, len, MSG_FASTOPEN,
363 conn->ip_addr->ai_addr, conn->ip_addr->ai_addrlen);
364 conn->bits.tcp_fastopen = FALSE;
368 bytes_written = swrite(sockfd, mem, len);
371 if(-1 == bytes_written) {
375 #ifdef WSAEWOULDBLOCK
376 /* This is how Windows does it */
377 (WSAEWOULDBLOCK == err)
379 /* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned
380 due to its inability to send off data without blocking. We therefore
381 treat both error codes the same here */
382 (EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err) ||
386 /* this is just a case of EWOULDBLOCK */
391 char buffer[STRERROR_LEN];
392 failf(data, "Send failure: %s",
393 Curl_strerror(err, buffer, sizeof(buffer)));
394 data->state.os_errno = err;
395 *code = CURLE_SEND_ERROR;
398 return bytes_written;
402 * Curl_write_plain() is an internal write function that sends data to the
403 * server using plain sockets only. Otherwise meant to have the exact same
404 * proto as Curl_write()
406 CURLcode Curl_write_plain(struct Curl_easy *data,
407 curl_socket_t sockfd,
413 struct connectdata *conn = data->conn;
416 num = (sockfd == conn->sock[SECONDARYSOCKET]);
418 *written = Curl_send_plain(data, num, mem, len, &result);
423 ssize_t Curl_recv_plain(struct Curl_easy *data, int num, char *buf,
424 size_t len, CURLcode *code)
426 struct connectdata *conn;
427 curl_socket_t sockfd;
430 DEBUGASSERT(data->conn);
432 sockfd = conn->sock[num];
433 /* Check and return data that already received and storied in internal
434 intermediate buffer */
435 nread = get_pre_recved(conn, num, buf, len);
441 nread = sread(sockfd, buf, len);
448 #ifdef WSAEWOULDBLOCK
449 /* This is how Windows does it */
450 (WSAEWOULDBLOCK == err)
452 /* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned
453 due to its inability to send off data without blocking. We therefore
454 treat both error codes the same here */
455 (EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err)
458 /* this is just a case of EWOULDBLOCK */
462 char buffer[STRERROR_LEN];
463 failf(data, "Recv failure: %s",
464 Curl_strerror(err, buffer, sizeof(buffer)));
465 data->state.os_errno = err;
466 *code = CURLE_RECV_ERROR;
472 static CURLcode pausewrite(struct Curl_easy *data,
473 int type, /* what type of data */
477 /* signalled to pause sending on this connection, but since we have data
478 we want to send we need to dup it to save a copy for when the sending
480 struct SingleRequest *k = &data->req;
481 struct UrlState *s = &data->state;
485 /* If this transfers over HTTP/2, pause the stream! */
486 Curl_http2_stream_pause(data, TRUE);
489 for(i = 0; i< s->tempcount; i++) {
490 if(s->tempwrite[i].type == type) {
491 /* data for this type exists */
502 /* store this information in the state struct for later use */
503 Curl_dyn_init(&s->tempwrite[i].b, DYN_PAUSE_BUFFER);
504 s->tempwrite[i].type = type;
508 if(Curl_dyn_addn(&s->tempwrite[i].b, (unsigned char *)ptr, len))
509 return CURLE_OUT_OF_MEMORY;
511 /* mark the connection as RECV paused */
512 k->keepon |= KEEP_RECV_PAUSE;
518 /* chop_write() writes chunks of data not larger than CURL_MAX_WRITE_SIZE via
519 * client write callback(s) and takes care of pause requests from the
522 static CURLcode chop_write(struct Curl_easy *data,
527 struct connectdata *conn = data->conn;
528 curl_write_callback writeheader = NULL;
529 curl_write_callback writebody = NULL;
536 /* If reading is paused, append this data to the already held data for this
538 if(data->req.keepon & KEEP_RECV_PAUSE)
539 return pausewrite(data, type, ptr, len);
541 /* Determine the callback(s) to use. */
542 if(type & CLIENTWRITE_BODY)
543 writebody = data->set.fwrite_func;
544 if((type & CLIENTWRITE_HEADER) &&
545 (data->set.fwrite_header || data->set.writeheader)) {
547 * Write headers to the same callback or to the especially setup
548 * header callback function (added after version 7.7.1).
551 data->set.fwrite_header? data->set.fwrite_header: data->set.fwrite_func;
554 /* Chop data, write chunks. */
556 size_t chunklen = len <= CURL_MAX_WRITE_SIZE? len: CURL_MAX_WRITE_SIZE;
560 Curl_set_in_callback(data, true);
561 wrote = writebody(ptr, 1, chunklen, data->set.out);
562 Curl_set_in_callback(data, false);
564 if(CURL_WRITEFUNC_PAUSE == wrote) {
565 if(conn->handler->flags & PROTOPT_NONETWORK) {
566 /* Protocols that work without network cannot be paused. This is
567 actually only FILE:// just now, and it can't pause since the
568 transfer isn't done using the "normal" procedure. */
569 failf(data, "Write callback asked for PAUSE when not supported");
570 return CURLE_WRITE_ERROR;
572 return pausewrite(data, type, ptr, len);
574 if(wrote != chunklen) {
575 failf(data, "Failure writing output to destination");
576 return CURLE_WRITE_ERROR;
584 /* HTTP header, but not status-line */
585 if((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
586 (type & CLIENTWRITE_HEADER) && !(type & CLIENTWRITE_STATUS) ) {
588 Curl_headers_push(data, optr,
589 type & CLIENTWRITE_CONNECT ? CURLH_CONNECT :
590 (type & CLIENTWRITE_1XX ? CURLH_1XX :
591 (type & CLIENTWRITE_TRAILER ? CURLH_TRAILER :
600 Curl_set_in_callback(data, true);
601 wrote = writeheader(optr, 1, olen, data->set.writeheader);
602 Curl_set_in_callback(data, false);
604 if(CURL_WRITEFUNC_PAUSE == wrote)
605 /* here we pass in the HEADER bit only since if this was body as well
606 then it was passed already and clearly that didn't trigger the
607 pause, so this is saved for later with the HEADER bit only */
608 return pausewrite(data, CLIENTWRITE_HEADER, optr, olen);
611 failf(data, "Failed writing header");
612 return CURLE_WRITE_ERROR;
620 /* Curl_client_write() sends data to the write callback(s)
622 The bit pattern defines to what "streams" to write to. Body and/or header.
623 The defines are in sendf.h of course.
625 If CURL_DO_LINEEND_CONV is enabled, data is converted IN PLACE to the
626 local character encoding. This is a problem and should be changed in
627 the future to leave the original data alone.
629 CURLcode Curl_client_write(struct Curl_easy *data,
634 struct connectdata *conn = data->conn;
639 /* FTP data may need conversion. */
640 if((type & CLIENTWRITE_BODY) &&
641 (conn->handler->protocol & PROTO_FAMILY_FTP) &&
642 conn->proto.ftpc.transfertype == 'A') {
644 #ifdef CURL_DO_LINEEND_CONV
645 /* convert end-of-line markers */
646 len = convert_lineends(data, ptr, len);
647 #endif /* CURL_DO_LINEEND_CONV */
650 return chop_write(data, type, ptr, len);
653 CURLcode Curl_read_plain(curl_socket_t sockfd,
655 size_t bytesfromsocket,
658 ssize_t nread = sread(sockfd, buf, bytesfromsocket);
661 const int err = SOCKERRNO;
662 const bool return_error =
664 WSAEWOULDBLOCK == err
666 EWOULDBLOCK == err || EAGAIN == err || EINTR == err
669 *n = 0; /* no data returned */
672 return CURLE_RECV_ERROR;
680 * Internal read-from-socket function. This is meant to deal with plain
681 * sockets, SSL sockets and kerberos sockets.
683 * Returns a regular CURLcode value.
685 CURLcode Curl_read(struct Curl_easy *data, /* transfer */
686 curl_socket_t sockfd, /* read from this socket */
687 char *buf, /* store read data here */
688 size_t sizerequested, /* max amount to read */
689 ssize_t *n) /* amount bytes read */
691 CURLcode result = CURLE_RECV_ERROR;
693 size_t bytesfromsocket = 0;
694 char *buffertofill = NULL;
695 struct connectdata *conn = data->conn;
697 /* Set 'num' to 0 or 1, depending on which socket that has been sent here.
698 If it is the second socket, we set num to 1. Otherwise to 0. This lets
699 us use the correct ssl handle. */
700 int num = (sockfd == conn->sock[SECONDARYSOCKET]);
702 *n = 0; /* reset amount to zero */
704 bytesfromsocket = CURLMIN(sizerequested, (size_t)data->set.buffer_size);
707 nread = conn->recv[num](data, num, buffertofill, bytesfromsocket, &result);
716 /* return 0 on success */
717 int Curl_debug(struct Curl_easy *data, curl_infotype type,
718 char *ptr, size_t size)
721 if(data->set.verbose) {
722 static const char s_infotype[CURLINFO_END][3] = {
723 "* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
724 if(data->set.fdebug) {
725 Curl_set_in_callback(data, true);
726 rc = (*data->set.fdebug)(data, type, ptr, size, data->set.debugdata);
727 Curl_set_in_callback(data, false);
732 case CURLINFO_HEADER_OUT:
733 case CURLINFO_HEADER_IN:
734 fwrite(s_infotype[type], 2, 1, data->set.err);
735 fwrite(ptr, size, 1, data->set.err);