1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2016, 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.haxx.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 #include <curl/curl.h>
30 #include "vtls/vtls.h"
33 #include "non-ascii.h"
34 #include "curl_printf.h"
37 /* The last #include files should be: */
38 #include "curl_memory.h"
41 #ifdef CURL_DO_LINEEND_CONV
43 * convert_lineends() changes CRLF (\r\n) end-of-line markers to a single LF
44 * (\n), with special processing for CRLF sequences that are split between two
45 * blocks of data. Remaining, bare CRs are changed to LFs. The possibly new
46 * size of the data is returned.
48 static size_t convert_lineends(struct SessionHandle *data,
49 char *startPtr, size_t size)
54 if((startPtr == NULL) || (size < 1)) {
58 if(data->state.prev_block_had_trailing_cr) {
59 /* The previous block of incoming data
60 had a trailing CR, which was turned into a LF. */
61 if(*startPtr == '\n') {
62 /* This block of incoming data starts with the
63 previous block's LF so get rid of it */
64 memmove(startPtr, startPtr+1, size-1);
66 /* and it wasn't a bare CR but a CRLF conversion instead */
67 data->state.crlf_conversions++;
69 data->state.prev_block_had_trailing_cr = FALSE; /* reset the flag */
72 /* find 1st CR, if any */
73 inPtr = outPtr = memchr(startPtr, '\r', size);
75 /* at least one CR, now look for CRLF */
76 while(inPtr < (startPtr+size-1)) {
77 /* note that it's size-1, so we'll never look past the last byte */
78 if(memcmp(inPtr, "\r\n", 2) == 0) {
79 /* CRLF found, bump past the CR and copy the NL */
82 /* keep track of how many CRLFs we converted */
83 data->state.crlf_conversions++;
87 /* lone CR, move LF instead */
91 /* not a CRLF nor a CR, just copy whatever it is */
97 } /* end of while loop */
99 if(inPtr < startPtr+size) {
100 /* handle last byte */
102 /* deal with a CR at the end of the buffer */
103 *outPtr = '\n'; /* copy a NL instead */
104 /* note that a CRLF might be split across two blocks */
105 data->state.prev_block_had_trailing_cr = TRUE;
113 if(outPtr < startPtr+size)
114 /* tidy up by null terminating the now shorter data */
117 return (outPtr - startPtr);
121 #endif /* CURL_DO_LINEEND_CONV */
123 /* Curl_infof() is for info message along the way */
125 void Curl_infof(struct SessionHandle *data, const char *fmt, ...)
127 if(data && data->set.verbose) {
130 char print_buffer[2048 + 1];
132 vsnprintf(print_buffer, sizeof(print_buffer), fmt, ap);
134 len = strlen(print_buffer);
135 Curl_debug(data, CURLINFO_TEXT, print_buffer, len, NULL);
139 /* Curl_failf() is for messages stating why we failed.
140 * The message SHALL NOT include any LF or CR.
143 void Curl_failf(struct SessionHandle *data, const char *fmt, ...)
149 vsnprintf(data->state.buffer, BUFSIZE, fmt, ap);
151 if(data->set.errorbuffer && !data->state.errorbuf) {
152 snprintf(data->set.errorbuffer, CURL_ERROR_SIZE, "%s", data->state.buffer);
153 data->state.errorbuf = TRUE; /* wrote error string */
155 if(data->set.verbose) {
156 len = strlen(data->state.buffer);
157 if(len < BUFSIZE - 1) {
158 data->state.buffer[len] = '\n';
159 data->state.buffer[++len] = '\0';
161 Curl_debug(data, CURLINFO_TEXT, data->state.buffer, len, NULL);
167 /* Curl_sendf() sends formated data to the server */
168 CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *conn,
169 const char *fmt, ...)
171 struct SessionHandle *data = conn->data;
172 ssize_t bytes_written;
174 CURLcode result = CURLE_OK;
179 s = vaprintf(fmt, ap); /* returns an allocated string */
182 return CURLE_OUT_OF_MEMORY; /* failure */
185 write_len = strlen(s);
189 /* Write the buffer to the socket */
190 result = Curl_write(conn, sockfd, sptr, write_len, &bytes_written);
195 if(data->set.verbose)
196 Curl_debug(data, CURLINFO_DATA_OUT, sptr, (size_t)bytes_written, conn);
198 if((size_t)bytes_written != write_len) {
199 /* if not all was written at once, we must advance the pointer, decrease
200 the size left and try again! */
201 write_len -= bytes_written;
202 sptr += bytes_written;
208 free(s); /* free the output string */
214 * Curl_write() is an internal write function that sends data to the
215 * server. Works with plain sockets, SCP, SSL or kerberos.
217 * If the write would block (CURLE_AGAIN), we return CURLE_OK and
218 * (*written == 0). Otherwise we return regular CURLcode value.
220 CURLcode Curl_write(struct connectdata *conn,
221 curl_socket_t sockfd,
226 ssize_t bytes_written;
227 CURLcode result = CURLE_OK;
228 int num = (sockfd == conn->sock[SECONDARYSOCKET]);
230 bytes_written = conn->send[num](conn, num, mem, len, &result);
232 *written = bytes_written;
233 if(bytes_written >= 0)
234 /* we completely ignore the curlcode value when subzero is not returned */
237 /* handle CURLE_AGAIN or a send failure */
244 /* general send failure */
245 return CURLE_SEND_ERROR;
248 /* we got a specific curlcode, forward it */
253 ssize_t Curl_send_plain(struct connectdata *conn, int num,
254 const void *mem, size_t len, CURLcode *code)
256 curl_socket_t sockfd = conn->sock[num];
257 ssize_t bytes_written = swrite(sockfd, mem, len);
260 if(-1 == bytes_written) {
264 #ifdef WSAEWOULDBLOCK
265 /* This is how Windows does it */
266 (WSAEWOULDBLOCK == err)
268 /* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned
269 due to its inability to send off data without blocking. We therefor
270 treat both error codes the same here */
271 (EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err)
274 /* this is just a case of EWOULDBLOCK */
279 failf(conn->data, "Send failure: %s",
280 Curl_strerror(conn, err));
281 conn->data->state.os_errno = err;
282 *code = CURLE_SEND_ERROR;
285 return bytes_written;
289 * Curl_write_plain() is an internal write function that sends data to the
290 * server using plain sockets only. Otherwise meant to have the exact same
291 * proto as Curl_write()
293 CURLcode Curl_write_plain(struct connectdata *conn,
294 curl_socket_t sockfd,
299 ssize_t bytes_written;
301 int num = (sockfd == conn->sock[SECONDARYSOCKET]);
303 bytes_written = Curl_send_plain(conn, num, mem, len, &result);
305 *written = bytes_written;
310 ssize_t Curl_recv_plain(struct connectdata *conn, int num, char *buf,
311 size_t len, CURLcode *code)
313 curl_socket_t sockfd = conn->sock[num];
314 ssize_t nread = sread(sockfd, buf, len);
321 #ifdef WSAEWOULDBLOCK
322 /* This is how Windows does it */
323 (WSAEWOULDBLOCK == err)
325 /* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned
326 due to its inability to send off data without blocking. We therefor
327 treat both error codes the same here */
328 (EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err)
331 /* this is just a case of EWOULDBLOCK */
335 failf(conn->data, "Recv failure: %s",
336 Curl_strerror(conn, err));
337 conn->data->state.os_errno = err;
338 *code = CURLE_RECV_ERROR;
344 static CURLcode pausewrite(struct SessionHandle *data,
345 int type, /* what type of data */
349 /* signalled to pause sending on this connection, but since we have data
350 we want to send we need to dup it to save a copy for when the sending
352 struct SingleRequest *k = &data->req;
353 char *dupl = malloc(len);
355 return CURLE_OUT_OF_MEMORY;
357 memcpy(dupl, ptr, len);
359 /* store this information in the state struct for later use */
360 data->state.tempwrite = dupl;
361 data->state.tempwritesize = len;
362 data->state.tempwritetype = type;
364 /* mark the connection as RECV paused */
365 k->keepon |= KEEP_RECV_PAUSE;
367 DEBUGF(infof(data, "Pausing with %zu bytes in buffer for type %02x\n",
374 /* Curl_client_chop_write() writes chunks of data not larger than
375 * CURL_MAX_WRITE_SIZE via client write callback(s) and
376 * takes care of pause requests from the callbacks.
378 CURLcode Curl_client_chop_write(struct connectdata *conn,
383 struct SessionHandle *data = conn->data;
384 curl_write_callback writeheader = NULL;
385 curl_write_callback writebody = NULL;
390 /* If reading is actually paused, we're forced to append this chunk of data
391 to the already held data, but only if it is the same type as otherwise it
392 can't work and it'll return error instead. */
393 if(data->req.keepon & KEEP_RECV_PAUSE) {
396 if(type != data->state.tempwritetype)
397 /* major internal confusion */
398 return CURLE_RECV_ERROR;
400 DEBUGASSERT(data->state.tempwrite);
402 /* figure out the new size of the data to save */
403 newlen = len + data->state.tempwritesize;
404 /* allocate the new memory area */
405 newptr = realloc(data->state.tempwrite, newlen);
407 return CURLE_OUT_OF_MEMORY;
408 /* copy the new data to the end of the new area */
409 memcpy(newptr + data->state.tempwritesize, ptr, len);
410 /* update the pointer and the size */
411 data->state.tempwrite = newptr;
412 data->state.tempwritesize = newlen;
416 /* Determine the callback(s) to use. */
417 if(type & CLIENTWRITE_BODY)
418 writebody = data->set.fwrite_func;
419 if((type & CLIENTWRITE_HEADER) &&
420 (data->set.fwrite_header || data->set.writeheader)) {
422 * Write headers to the same callback or to the especially setup
423 * header callback function (added after version 7.7.1).
426 data->set.fwrite_header? data->set.fwrite_header: data->set.fwrite_func;
429 /* Chop data, write chunks. */
431 size_t chunklen = len <= CURL_MAX_WRITE_SIZE? len: CURL_MAX_WRITE_SIZE;
434 size_t wrote = writebody(ptr, 1, chunklen, data->set.out);
436 if(CURL_WRITEFUNC_PAUSE == wrote) {
437 if(conn->handler->flags & PROTOPT_NONETWORK) {
438 /* Protocols that work without network cannot be paused. This is
439 actually only FILE:// just now, and it can't pause since the
440 transfer isn't done using the "normal" procedure. */
441 failf(data, "Write callback asked for PAUSE when not supported!");
442 return CURLE_WRITE_ERROR;
445 return pausewrite(data, type, ptr, len);
447 else if(wrote != chunklen) {
448 failf(data, "Failed writing body (%zu != %zu)", wrote, chunklen);
449 return CURLE_WRITE_ERROR;
454 size_t wrote = writeheader(ptr, 1, chunklen, data->set.writeheader);
456 if(CURL_WRITEFUNC_PAUSE == wrote)
457 /* here we pass in the HEADER bit only since if this was body as well
458 then it was passed already and clearly that didn't trigger the
459 pause, so this is saved for later with the HEADER bit only */
460 return pausewrite(data, CLIENTWRITE_HEADER, ptr, len);
462 if(wrote != chunklen) {
463 failf (data, "Failed writing header");
464 return CURLE_WRITE_ERROR;
476 /* Curl_client_write() sends data to the write callback(s)
478 The bit pattern defines to what "streams" to write to. Body and/or header.
479 The defines are in sendf.h of course.
481 If CURL_DO_LINEEND_CONV is enabled, data is converted IN PLACE to the
482 local character encoding. This is a problem and should be changed in
483 the future to leave the original data alone.
485 CURLcode Curl_client_write(struct connectdata *conn,
490 struct SessionHandle *data = conn->data;
495 /* FTP data may need conversion. */
496 if((type & CLIENTWRITE_BODY) &&
497 (conn->handler->protocol & PROTO_FAMILY_FTP) &&
498 conn->proto.ftpc.transfertype == 'A') {
499 /* convert from the network encoding */
500 CURLcode result = Curl_convert_from_network(data, ptr, len);
501 /* Curl_convert_from_network calls failf if unsuccessful */
505 #ifdef CURL_DO_LINEEND_CONV
506 /* convert end-of-line markers */
507 len = convert_lineends(data, ptr, len);
508 #endif /* CURL_DO_LINEEND_CONV */
511 return Curl_client_chop_write(conn, type, ptr, len);
514 CURLcode Curl_read_plain(curl_socket_t sockfd,
516 size_t bytesfromsocket,
519 ssize_t nread = sread(sockfd, buf, bytesfromsocket);
525 return_error = WSAEWOULDBLOCK == err;
527 return_error = EWOULDBLOCK == err || EAGAIN == err || EINTR == err;
532 return CURLE_RECV_ERROR;
535 /* we only return number of bytes read when we return OK */
541 * Internal read-from-socket function. This is meant to deal with plain
542 * sockets, SSL sockets and kerberos sockets.
544 * Returns a regular CURLcode value.
546 CURLcode Curl_read(struct connectdata *conn, /* connection data */
547 curl_socket_t sockfd, /* read from this socket */
548 char *buf, /* store read data here */
549 size_t sizerequested, /* max amount to read */
550 ssize_t *n) /* amount bytes read */
552 CURLcode result = CURLE_RECV_ERROR;
554 size_t bytesfromsocket = 0;
555 char *buffertofill = NULL;
557 /* if HTTP/1 pipelining is both wanted and possible */
558 bool pipelining = Curl_pipeline_wanted(conn->data->multi, CURLPIPE_HTTP1) &&
559 (conn->bundle->multiuse == BUNDLE_PIPELINING);
561 /* Set 'num' to 0 or 1, depending on which socket that has been sent here.
562 If it is the second socket, we set num to 1. Otherwise to 0. This lets
563 us use the correct ssl handle. */
564 int num = (sockfd == conn->sock[SECONDARYSOCKET]);
566 *n=0; /* reset amount to zero */
568 /* If session can pipeline, check connection buffer */
570 size_t bytestocopy = CURLMIN(conn->buf_len - conn->read_pos,
573 /* Copy from our master buffer first if we have some unread data there*/
574 if(bytestocopy > 0) {
575 memcpy(buf, conn->master_buffer + conn->read_pos, bytestocopy);
576 conn->read_pos += bytestocopy;
577 conn->bits.stream_was_rewound = FALSE;
579 *n = (ssize_t)bytestocopy;
582 /* If we come here, it means that there is no data to read from the buffer,
583 * so we read from the socket */
584 bytesfromsocket = CURLMIN(sizerequested, BUFSIZE * sizeof (char));
585 buffertofill = conn->master_buffer;
588 bytesfromsocket = CURLMIN((long)sizerequested,
589 conn->data->set.buffer_size ?
590 conn->data->set.buffer_size : BUFSIZE);
594 nread = conn->recv[num](conn, num, buffertofill, bytesfromsocket, &result);
599 memcpy(buf, conn->master_buffer, nread);
600 conn->buf_len = nread;
601 conn->read_pos = nread;
609 /* return 0 on success */
610 static int showit(struct SessionHandle *data, curl_infotype type,
611 char *ptr, size_t size)
613 static const char s_infotype[CURLINFO_END][3] = {
614 "* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
616 #ifdef CURL_DOES_CONVERSIONS
618 size_t conv_size = 0;
621 case CURLINFO_HEADER_OUT:
622 /* assume output headers are ASCII */
623 /* copy the data into my buffer so the original is unchanged */
625 size = BUFSIZE; /* truncate if necessary */
629 memcpy(buf, ptr, size);
630 /* Special processing is needed for this block if it
631 * contains both headers and data (separated by CRLFCRLF).
632 * We want to convert just the headers, leaving the data as-is.
636 for(i = 0; i < size-4; i++) {
637 if(memcmp(&buf[i], "\x0d\x0a\x0d\x0a", 4) == 0) {
638 /* convert everything through this CRLFCRLF but no further */
645 Curl_convert_from_network(data, buf, conv_size);
646 /* Curl_convert_from_network calls failf if unsuccessful */
647 /* we might as well continue even if it fails... */
648 ptr = buf; /* switch pointer to use my buffer instead */
651 /* leave everything else as-is */
654 #endif /* CURL_DOES_CONVERSIONS */
657 return (*data->set.fdebug)(data, type, ptr, size,
658 data->set.debugdata);
662 case CURLINFO_HEADER_OUT:
663 case CURLINFO_HEADER_IN:
664 fwrite(s_infotype[type], 2, 1, data->set.err);
665 fwrite(ptr, size, 1, data->set.err);
666 #ifdef CURL_DOES_CONVERSIONS
667 if(size != conv_size) {
668 /* we had untranslated data so we need an explicit newline */
669 fwrite("\n", 1, 1, data->set.err);
679 int Curl_debug(struct SessionHandle *data, curl_infotype type,
680 char *ptr, size_t size,
681 struct connectdata *conn)
684 if(data->set.printhost && conn && conn->host.dispname) {
687 const char *w="Data";
689 case CURLINFO_HEADER_IN:
692 case CURLINFO_DATA_IN:
695 case CURLINFO_HEADER_OUT:
698 case CURLINFO_DATA_OUT:
706 snprintf(buffer, sizeof(buffer), "[%s %s %s]", w, t,
707 conn->host.dispname);
708 rc = showit(data, CURLINFO_TEXT, buffer, strlen(buffer));
713 rc = showit(data, type, ptr, size);