1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2014, 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 http://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"
35 #define _MPRINTF_REPLACE /* use the internal *printf() functions */
36 #include <curl/mprintf.h>
38 #include "curl_memory.h"
41 /* The last #include file should be: */
44 #ifdef CURL_DO_LINEEND_CONV
46 * convert_lineends() changes CRLF (\r\n) end-of-line markers to a single LF
47 * (\n), with special processing for CRLF sequences that are split between two
48 * blocks of data. Remaining, bare CRs are changed to LFs. The possibly new
49 * size of the data is returned.
51 static size_t convert_lineends(struct SessionHandle *data,
52 char *startPtr, size_t size)
57 if((startPtr == NULL) || (size < 1)) {
61 if(data->state.prev_block_had_trailing_cr) {
62 /* The previous block of incoming data
63 had a trailing CR, which was turned into a LF. */
64 if(*startPtr == '\n') {
65 /* This block of incoming data starts with the
66 previous block's LF so get rid of it */
67 memmove(startPtr, startPtr+1, size-1);
69 /* and it wasn't a bare CR but a CRLF conversion instead */
70 data->state.crlf_conversions++;
72 data->state.prev_block_had_trailing_cr = FALSE; /* reset the flag */
75 /* find 1st CR, if any */
76 inPtr = outPtr = memchr(startPtr, '\r', size);
78 /* at least one CR, now look for CRLF */
79 while(inPtr < (startPtr+size-1)) {
80 /* note that it's size-1, so we'll never look past the last byte */
81 if(memcmp(inPtr, "\r\n", 2) == 0) {
82 /* CRLF found, bump past the CR and copy the NL */
85 /* keep track of how many CRLFs we converted */
86 data->state.crlf_conversions++;
90 /* lone CR, move LF instead */
94 /* not a CRLF nor a CR, just copy whatever it is */
100 } /* end of while loop */
102 if(inPtr < startPtr+size) {
103 /* handle last byte */
105 /* deal with a CR at the end of the buffer */
106 *outPtr = '\n'; /* copy a NL instead */
107 /* note that a CRLF might be split across two blocks */
108 data->state.prev_block_had_trailing_cr = TRUE;
116 if(outPtr < startPtr+size)
117 /* tidy up by null terminating the now shorter data */
120 return(outPtr - startPtr);
124 #endif /* CURL_DO_LINEEND_CONV */
126 /* Curl_infof() is for info message along the way */
128 void Curl_infof(struct SessionHandle *data, const char *fmt, ...)
130 if(data && data->set.verbose) {
133 char print_buffer[2048 + 1];
135 vsnprintf(print_buffer, sizeof(print_buffer), fmt, ap);
137 len = strlen(print_buffer);
138 Curl_debug(data, CURLINFO_TEXT, print_buffer, len, NULL);
142 /* Curl_failf() is for messages stating why we failed.
143 * The message SHALL NOT include any LF or CR.
146 void Curl_failf(struct SessionHandle *data, const char *fmt, ...)
152 vsnprintf(data->state.buffer, BUFSIZE, fmt, ap);
154 if(data->set.errorbuffer && !data->state.errorbuf) {
155 snprintf(data->set.errorbuffer, CURL_ERROR_SIZE, "%s", data->state.buffer);
156 data->state.errorbuf = TRUE; /* wrote error string */
158 if(data->set.verbose) {
159 len = strlen(data->state.buffer);
160 if(len < BUFSIZE - 1) {
161 data->state.buffer[len] = '\n';
162 data->state.buffer[++len] = '\0';
164 Curl_debug(data, CURLINFO_TEXT, data->state.buffer, len, NULL);
170 /* Curl_sendf() sends formated data to the server */
171 CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *conn,
172 const char *fmt, ...)
174 struct SessionHandle *data = conn->data;
175 ssize_t bytes_written;
177 CURLcode result = CURLE_OK;
182 s = vaprintf(fmt, ap); /* returns an allocated string */
185 return CURLE_OUT_OF_MEMORY; /* failure */
188 write_len = strlen(s);
192 /* Write the buffer to the socket */
193 result = Curl_write(conn, sockfd, sptr, write_len, &bytes_written);
198 if(data->set.verbose)
199 Curl_debug(data, CURLINFO_DATA_OUT, sptr, (size_t)bytes_written, conn);
201 if((size_t)bytes_written != write_len) {
202 /* if not all was written at once, we must advance the pointer, decrease
203 the size left and try again! */
204 write_len -= bytes_written;
205 sptr += bytes_written;
211 free(s); /* free the output string */
217 * Curl_write() is an internal write function that sends data to the
218 * server. Works with plain sockets, SCP, SSL or kerberos.
220 * If the write would block (CURLE_AGAIN), we return CURLE_OK and
221 * (*written == 0). Otherwise we return regular CURLcode value.
223 CURLcode Curl_write(struct connectdata *conn,
224 curl_socket_t sockfd,
229 ssize_t bytes_written;
230 CURLcode result = CURLE_OK;
231 int num = (sockfd == conn->sock[SECONDARYSOCKET]);
233 bytes_written = conn->send[num](conn, num, mem, len, &result);
235 *written = bytes_written;
236 if(bytes_written >= 0)
237 /* we completely ignore the curlcode value when subzero is not returned */
240 /* handle CURLE_AGAIN or a send failure */
247 /* general send failure */
248 return CURLE_SEND_ERROR;
251 /* we got a specific curlcode, forward it */
256 ssize_t Curl_send_plain(struct connectdata *conn, int num,
257 const void *mem, size_t len, CURLcode *code)
259 curl_socket_t sockfd = conn->sock[num];
260 ssize_t bytes_written = swrite(sockfd, mem, len);
263 if(-1 == bytes_written) {
267 #ifdef WSAEWOULDBLOCK
268 /* This is how Windows does it */
269 (WSAEWOULDBLOCK == err)
271 /* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned
272 due to its inability to send off data without blocking. We therefor
273 treat both error codes the same here */
274 (EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err)
277 /* this is just a case of EWOULDBLOCK */
282 failf(conn->data, "Send failure: %s",
283 Curl_strerror(conn, err));
284 conn->data->state.os_errno = err;
285 *code = CURLE_SEND_ERROR;
288 return bytes_written;
292 * Curl_write_plain() is an internal write function that sends data to the
293 * server using plain sockets only. Otherwise meant to have the exact same
294 * proto as Curl_write()
296 CURLcode Curl_write_plain(struct connectdata *conn,
297 curl_socket_t sockfd,
302 ssize_t bytes_written;
304 int num = (sockfd == conn->sock[SECONDARYSOCKET]);
306 bytes_written = Curl_send_plain(conn, num, mem, len, &result);
308 *written = bytes_written;
313 ssize_t Curl_recv_plain(struct connectdata *conn, int num, char *buf,
314 size_t len, CURLcode *code)
316 curl_socket_t sockfd = conn->sock[num];
317 ssize_t nread = sread(sockfd, buf, len);
324 #ifdef WSAEWOULDBLOCK
325 /* This is how Windows does it */
326 (WSAEWOULDBLOCK == err)
328 /* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned
329 due to its inability to send off data without blocking. We therefor
330 treat both error codes the same here */
331 (EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err)
334 /* this is just a case of EWOULDBLOCK */
338 failf(conn->data, "Recv failure: %s",
339 Curl_strerror(conn, err));
340 conn->data->state.os_errno = err;
341 *code = CURLE_RECV_ERROR;
347 static CURLcode pausewrite(struct SessionHandle *data,
348 int type, /* what type of data */
352 /* signalled to pause sending on this connection, but since we have data
353 we want to send we need to dup it to save a copy for when the sending
355 struct SingleRequest *k = &data->req;
356 char *dupl = malloc(len);
358 return CURLE_OUT_OF_MEMORY;
360 memcpy(dupl, ptr, len);
362 /* store this information in the state struct for later use */
363 data->state.tempwrite = dupl;
364 data->state.tempwritesize = len;
365 data->state.tempwritetype = type;
367 /* mark the connection as RECV paused */
368 k->keepon |= KEEP_RECV_PAUSE;
370 DEBUGF(infof(data, "Pausing with %zu bytes in buffer for type %02x\n",
377 /* Curl_client_chop_write() writes chunks of data not larger than
378 * CURL_MAX_WRITE_SIZE via client write callback(s) and
379 * takes care of pause requests from the callbacks.
381 CURLcode Curl_client_chop_write(struct connectdata *conn,
386 struct SessionHandle *data = conn->data;
387 curl_write_callback writeheader = NULL;
388 curl_write_callback writebody = NULL;
393 /* If reading is actually paused, we're forced to append this chunk of data
394 to the already held data, but only if it is the same type as otherwise it
395 can't work and it'll return error instead. */
396 if(data->req.keepon & KEEP_RECV_PAUSE) {
399 if(type != data->state.tempwritetype)
400 /* major internal confusion */
401 return CURLE_RECV_ERROR;
403 DEBUGASSERT(data->state.tempwrite);
405 /* figure out the new size of the data to save */
406 newlen = len + data->state.tempwritesize;
407 /* allocate the new memory area */
408 newptr = realloc(data->state.tempwrite, newlen);
410 return CURLE_OUT_OF_MEMORY;
411 /* copy the new data to the end of the new area */
412 memcpy(newptr + data->state.tempwritesize, ptr, len);
413 /* update the pointer and the size */
414 data->state.tempwrite = newptr;
415 data->state.tempwritesize = newlen;
419 /* Determine the callback(s) to use. */
420 if(type & CLIENTWRITE_BODY)
421 writebody = data->set.fwrite_func;
422 if((type & CLIENTWRITE_HEADER) &&
423 (data->set.fwrite_header || data->set.writeheader)) {
425 * Write headers to the same callback or to the especially setup
426 * header callback function (added after version 7.7.1).
429 data->set.fwrite_header? data->set.fwrite_header: data->set.fwrite_func;
432 /* Chop data, write chunks. */
434 size_t chunklen = len <= CURL_MAX_WRITE_SIZE? len: CURL_MAX_WRITE_SIZE;
437 size_t wrote = writebody(ptr, 1, chunklen, data->set.out);
439 if(CURL_WRITEFUNC_PAUSE == wrote) {
440 if(conn->handler->flags & PROTOPT_NONETWORK) {
441 /* Protocols that work without network cannot be paused. This is
442 actually only FILE:// just now, and it can't pause since the
443 transfer isn't done using the "normal" procedure. */
444 failf(data, "Write callback asked for PAUSE when not supported!");
445 return CURLE_WRITE_ERROR;
448 return pausewrite(data, type, ptr, len);
450 else if(wrote != chunklen) {
451 failf(data, "Failed writing body (%zu != %zu)", wrote, chunklen);
452 return CURLE_WRITE_ERROR;
457 size_t wrote = writeheader(ptr, 1, chunklen, data->set.writeheader);
459 if(CURL_WRITEFUNC_PAUSE == wrote)
460 /* here we pass in the HEADER bit only since if this was body as well
461 then it was passed already and clearly that didn't trigger the
462 pause, so this is saved for later with the HEADER bit only */
463 return pausewrite(data, CLIENTWRITE_HEADER, ptr, len);
465 if(wrote != chunklen) {
466 failf (data, "Failed writing header");
467 return CURLE_WRITE_ERROR;
479 /* Curl_client_write() sends data to the write callback(s)
481 The bit pattern defines to what "streams" to write to. Body and/or header.
482 The defines are in sendf.h of course.
484 If CURL_DO_LINEEND_CONV is enabled, data is converted IN PLACE to the
485 local character encoding. This is a problem and should be changed in
486 the future to leave the original data alone.
488 CURLcode Curl_client_write(struct connectdata *conn,
493 struct SessionHandle *data = conn->data;
498 /* FTP data may need conversion. */
499 if((type & CLIENTWRITE_BODY) &&
500 (conn->handler->protocol & PROTO_FAMILY_FTP) &&
501 conn->proto.ftpc.transfertype == 'A') {
502 /* convert from the network encoding */
503 CURLcode result = Curl_convert_from_network(data, ptr, len);
504 /* Curl_convert_from_network calls failf if unsuccessful */
508 #ifdef CURL_DO_LINEEND_CONV
509 /* convert end-of-line markers */
510 len = convert_lineends(data, ptr, len);
511 #endif /* CURL_DO_LINEEND_CONV */
514 return Curl_client_chop_write(conn, type, ptr, len);
517 CURLcode Curl_read_plain(curl_socket_t sockfd,
519 size_t bytesfromsocket,
522 ssize_t nread = sread(sockfd, buf, bytesfromsocket);
527 if(WSAEWOULDBLOCK == err)
529 if((EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err))
533 return CURLE_RECV_ERROR;
536 /* we only return number of bytes read when we return OK */
542 * Internal read-from-socket function. This is meant to deal with plain
543 * sockets, SSL sockets and kerberos sockets.
545 * Returns a regular CURLcode value.
547 CURLcode Curl_read(struct connectdata *conn, /* connection data */
548 curl_socket_t sockfd, /* read from this socket */
549 char *buf, /* store read data here */
550 size_t sizerequested, /* max amount to read */
551 ssize_t *n) /* amount bytes read */
553 CURLcode result = CURLE_RECV_ERROR;
555 size_t bytesfromsocket = 0;
556 char *buffertofill = NULL;
557 bool pipelining = Curl_multi_pipeline_enabled(conn->data->multi);
559 /* Set 'num' to 0 or 1, depending on which socket that has been sent here.
560 If it is the second socket, we set num to 1. Otherwise to 0. This lets
561 us use the correct ssl handle. */
562 int num = (sockfd == conn->sock[SECONDARYSOCKET]);
564 *n=0; /* reset amount to zero */
566 /* If session can pipeline, check connection buffer */
568 size_t bytestocopy = CURLMIN(conn->buf_len - conn->read_pos,
571 /* Copy from our master buffer first if we have some unread data there*/
572 if(bytestocopy > 0) {
573 memcpy(buf, conn->master_buffer + conn->read_pos, bytestocopy);
574 conn->read_pos += bytestocopy;
575 conn->bits.stream_was_rewound = FALSE;
577 *n = (ssize_t)bytestocopy;
580 /* If we come here, it means that there is no data to read from the buffer,
581 * so we read from the socket */
582 bytesfromsocket = CURLMIN(sizerequested, BUFSIZE * sizeof (char));
583 buffertofill = conn->master_buffer;
586 bytesfromsocket = CURLMIN((long)sizerequested,
587 conn->data->set.buffer_size ?
588 conn->data->set.buffer_size : BUFSIZE);
592 nread = conn->recv[num](conn, num, buffertofill, bytesfromsocket, &result);
597 memcpy(buf, conn->master_buffer, nread);
598 conn->buf_len = nread;
599 conn->read_pos = nread;
607 /* return 0 on success */
608 static int showit(struct SessionHandle *data, curl_infotype type,
609 char *ptr, size_t size)
611 static const char s_infotype[CURLINFO_END][3] = {
612 "* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
614 #ifdef CURL_DOES_CONVERSIONS
616 size_t conv_size = 0;
619 case CURLINFO_HEADER_OUT:
620 /* assume output headers are ASCII */
621 /* copy the data into my buffer so the original is unchanged */
623 size = BUFSIZE; /* truncate if necessary */
627 memcpy(buf, ptr, size);
628 /* Special processing is needed for this block if it
629 * contains both headers and data (separated by CRLFCRLF).
630 * We want to convert just the headers, leaving the data as-is.
634 for(i = 0; i < size-4; i++) {
635 if(memcmp(&buf[i], "\x0d\x0a\x0d\x0a", 4) == 0) {
636 /* convert everything through this CRLFCRLF but no further */
643 Curl_convert_from_network(data, buf, conv_size);
644 /* Curl_convert_from_network calls failf if unsuccessful */
645 /* we might as well continue even if it fails... */
646 ptr = buf; /* switch pointer to use my buffer instead */
649 /* leave everything else as-is */
652 #endif /* CURL_DOES_CONVERSIONS */
655 return (*data->set.fdebug)(data, type, ptr, size,
656 data->set.debugdata);
660 case CURLINFO_HEADER_OUT:
661 case CURLINFO_HEADER_IN:
662 fwrite(s_infotype[type], 2, 1, data->set.err);
663 fwrite(ptr, size, 1, data->set.err);
664 #ifdef CURL_DOES_CONVERSIONS
665 if(size != conv_size) {
666 /* we had untranslated data so we need an explicit newline */
667 fwrite("\n", 1, 1, data->set.err);
677 int Curl_debug(struct SessionHandle *data, curl_infotype type,
678 char *ptr, size_t size,
679 struct connectdata *conn)
682 if(data->set.printhost && conn && conn->host.dispname) {
685 const char *w="Data";
687 case CURLINFO_HEADER_IN:
690 case CURLINFO_DATA_IN:
693 case CURLINFO_HEADER_OUT:
696 case CURLINFO_DATA_OUT:
704 snprintf(buffer, sizeof(buffer), "[%s %s %s]", w, t,
705 conn->host.dispname);
706 rc = showit(data, CURLINFO_TEXT, buffer, strlen(buffer));
711 rc = showit(data, type, ptr, size);