1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2011, 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 ***************************************************************************/
25 #ifdef HAVE_SYS_SOCKET_H
26 #include <sys/socket.h> /* required for send() & recv() prototypes */
33 #include <curl/curl.h>
40 #include "non-ascii.h"
42 #define _MPRINTF_REPLACE /* use the internal *printf() functions */
43 #include <curl/mprintf.h>
45 /* the krb4 functions only exists for FTP and if krb4 or gssapi is defined */
46 #if !defined(CURL_DISABLE_FTP) && (defined(HAVE_KRB4) || defined(HAVE_GSSAPI))
49 #define Curl_sec_send(a,b,c,d) -1
50 #define Curl_sec_read(a,b,c,d) -1
53 #include "curl_memory.h"
56 /* The last #include file should be: */
59 #ifdef CURL_DO_LINEEND_CONV
61 * convert_lineends() changes CRLF (\r\n) end-of-line markers to a single LF
62 * (\n), with special processing for CRLF sequences that are split between two
63 * blocks of data. Remaining, bare CRs are changed to LFs. The possibly new
64 * size of the data is returned.
66 static size_t convert_lineends(struct SessionHandle *data,
67 char *startPtr, size_t size)
72 if((startPtr == NULL) || (size < 1)) {
76 if(data->state.prev_block_had_trailing_cr) {
77 /* The previous block of incoming data
78 had a trailing CR, which was turned into a LF. */
79 if(*startPtr == '\n') {
80 /* This block of incoming data starts with the
81 previous block's LF so get rid of it */
82 memmove(startPtr, startPtr+1, size-1);
84 /* and it wasn't a bare CR but a CRLF conversion instead */
85 data->state.crlf_conversions++;
87 data->state.prev_block_had_trailing_cr = FALSE; /* reset the flag */
90 /* find 1st CR, if any */
91 inPtr = outPtr = memchr(startPtr, '\r', size);
93 /* at least one CR, now look for CRLF */
94 while(inPtr < (startPtr+size-1)) {
95 /* note that it's size-1, so we'll never look past the last byte */
96 if(memcmp(inPtr, "\r\n", 2) == 0) {
97 /* CRLF found, bump past the CR and copy the NL */
100 /* keep track of how many CRLFs we converted */
101 data->state.crlf_conversions++;
105 /* lone CR, move LF instead */
109 /* not a CRLF nor a CR, just copy whatever it is */
115 } /* end of while loop */
117 if(inPtr < startPtr+size) {
118 /* handle last byte */
120 /* deal with a CR at the end of the buffer */
121 *outPtr = '\n'; /* copy a NL instead */
122 /* note that a CRLF might be split across two blocks */
123 data->state.prev_block_had_trailing_cr = TRUE;
131 if(outPtr < startPtr+size)
132 /* tidy up by null terminating the now shorter data */
135 return(outPtr - startPtr);
139 #endif /* CURL_DO_LINEEND_CONV */
141 /* Curl_infof() is for info message along the way */
143 void Curl_infof(struct SessionHandle *data, const char *fmt, ...)
145 if(data && data->set.verbose) {
148 char print_buffer[2048 + 1];
150 vsnprintf(print_buffer, sizeof(print_buffer), fmt, ap);
152 len = strlen(print_buffer);
153 Curl_debug(data, CURLINFO_TEXT, print_buffer, len, NULL);
157 /* Curl_failf() is for messages stating why we failed.
158 * The message SHALL NOT include any LF or CR.
161 void Curl_failf(struct SessionHandle *data, const char *fmt, ...)
167 vsnprintf(data->state.buffer, BUFSIZE, fmt, ap);
169 if(data->set.errorbuffer && !data->state.errorbuf) {
170 snprintf(data->set.errorbuffer, CURL_ERROR_SIZE, "%s", data->state.buffer);
171 data->state.errorbuf = TRUE; /* wrote error string */
173 if(data->set.verbose) {
174 len = strlen(data->state.buffer);
175 if(len < BUFSIZE - 1) {
176 data->state.buffer[len] = '\n';
177 data->state.buffer[++len] = '\0';
179 Curl_debug(data, CURLINFO_TEXT, data->state.buffer, len, NULL);
185 /* Curl_sendf() sends formated data to the server */
186 CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *conn,
187 const char *fmt, ...)
189 struct SessionHandle *data = conn->data;
190 ssize_t bytes_written;
192 CURLcode res = CURLE_OK;
197 s = vaprintf(fmt, ap); /* returns an allocated string */
200 return CURLE_OUT_OF_MEMORY; /* failure */
203 write_len = strlen(s);
207 /* Write the buffer to the socket */
208 res = Curl_write(conn, sockfd, sptr, write_len, &bytes_written);
213 if(data->set.verbose)
214 Curl_debug(data, CURLINFO_DATA_OUT, sptr, (size_t)bytes_written, conn);
216 if((size_t)bytes_written != write_len) {
217 /* if not all was written at once, we must advance the pointer, decrease
218 the size left and try again! */
219 write_len -= bytes_written;
220 sptr += bytes_written;
226 free(s); /* free the output string */
232 * Curl_write() is an internal write function that sends data to the
233 * server. Works with plain sockets, SCP, SSL or kerberos.
235 * If the write would block (CURLE_AGAIN), we return CURLE_OK and
236 * (*written == 0). Otherwise we return regular CURLcode value.
238 CURLcode Curl_write(struct connectdata *conn,
239 curl_socket_t sockfd,
244 ssize_t bytes_written;
245 CURLcode curlcode = CURLE_OK;
246 int num = (sockfd == conn->sock[SECONDARYSOCKET]);
248 bytes_written = conn->send[num](conn, num, mem, len, &curlcode);
250 *written = bytes_written;
251 if(bytes_written >= 0)
252 /* we completely ignore the curlcode value when subzero is not returned */
255 /* handle CURLE_AGAIN or a send failure */
262 /* general send failure */
263 return CURLE_SEND_ERROR;
266 /* we got a specific curlcode, forward it */
271 ssize_t Curl_send_plain(struct connectdata *conn, int num,
272 const void *mem, size_t len, CURLcode *code)
274 curl_socket_t sockfd = conn->sock[num];
275 ssize_t bytes_written = swrite(sockfd, mem, len);
278 if(-1 == bytes_written) {
282 #ifdef WSAEWOULDBLOCK
283 /* This is how Windows does it */
284 (WSAEWOULDBLOCK == err)
286 /* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned
287 due to its inability to send off data without blocking. We therefor
288 treat both error codes the same here */
289 (EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err)
292 /* this is just a case of EWOULDBLOCK */
297 failf(conn->data, "Send failure: %s",
298 Curl_strerror(conn, err));
299 conn->data->state.os_errno = err;
300 *code = CURLE_SEND_ERROR;
303 return bytes_written;
307 * Curl_write_plain() is an internal write function that sends data to the
308 * server using plain sockets only. Otherwise meant to have the exact same
309 * proto as Curl_write()
311 CURLcode Curl_write_plain(struct connectdata *conn,
312 curl_socket_t sockfd,
317 ssize_t bytes_written;
319 int num = (sockfd == conn->sock[SECONDARYSOCKET]);
321 bytes_written = Curl_send_plain(conn, num, mem, len, &retcode);
323 *written = bytes_written;
328 ssize_t Curl_recv_plain(struct connectdata *conn, int num, char *buf,
329 size_t len, CURLcode *code)
331 curl_socket_t sockfd = conn->sock[num];
332 ssize_t nread = sread(sockfd, buf, len);
339 #ifdef WSAEWOULDBLOCK
340 /* This is how Windows does it */
341 (WSAEWOULDBLOCK == err)
343 /* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned
344 due to its inability to send off data without blocking. We therefor
345 treat both error codes the same here */
346 (EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err)
349 /* this is just a case of EWOULDBLOCK */
353 failf(conn->data, "Recv failure: %s",
354 Curl_strerror(conn, err));
355 conn->data->state.os_errno = err;
356 *code = CURLE_RECV_ERROR;
362 static CURLcode pausewrite(struct SessionHandle *data,
363 int type, /* what type of data */
367 /* signalled to pause sending on this connection, but since we have data
368 we want to send we need to dup it to save a copy for when the sending
370 struct SingleRequest *k = &data->req;
371 char *dupl = malloc(len);
373 return CURLE_OUT_OF_MEMORY;
375 memcpy(dupl, ptr, len);
377 /* store this information in the state struct for later use */
378 data->state.tempwrite = dupl;
379 data->state.tempwritesize = len;
380 data->state.tempwritetype = type;
382 /* mark the connection as RECV paused */
383 k->keepon |= KEEP_RECV_PAUSE;
385 DEBUGF(infof(data, "Pausing with %zu bytes in buffer for type %02x\n",
392 /* Curl_client_write() sends data to the write callback(s)
394 The bit pattern defines to what "streams" to write to. Body and/or header.
395 The defines are in sendf.h of course.
397 If CURL_DO_LINEEND_CONV is enabled, data is converted IN PLACE to the
398 local character encoding. This is a problem and should be changed in
399 the future to leave the original data alone.
401 CURLcode Curl_client_write(struct connectdata *conn,
406 struct SessionHandle *data = conn->data;
412 /* If reading is actually paused, we're forced to append this chunk of data
413 to the already held data, but only if it is the same type as otherwise it
414 can't work and it'll return error instead. */
415 if(data->req.keepon & KEEP_RECV_PAUSE) {
418 if(type != data->state.tempwritetype)
419 /* major internal confusion */
420 return CURLE_RECV_ERROR;
422 DEBUGASSERT(data->state.tempwrite);
424 /* figure out the new size of the data to save */
425 newlen = len + data->state.tempwritesize;
426 /* allocate the new memory area */
427 newptr = realloc(data->state.tempwrite, newlen);
429 return CURLE_OUT_OF_MEMORY;
430 /* copy the new data to the end of the new area */
431 memcpy(newptr + data->state.tempwritesize, ptr, len);
432 /* update the pointer and the size */
433 data->state.tempwrite = newptr;
434 data->state.tempwritesize = newlen;
439 if(type & CLIENTWRITE_BODY) {
440 if((conn->handler->protocol&CURLPROTO_FTP) &&
441 conn->proto.ftpc.transfertype == 'A') {
442 /* convert from the network encoding */
443 CURLcode rc = Curl_convert_from_network(data, ptr, len);
444 /* Curl_convert_from_network calls failf if unsuccessful */
448 #ifdef CURL_DO_LINEEND_CONV
449 /* convert end-of-line markers */
450 len = convert_lineends(data, ptr, len);
451 #endif /* CURL_DO_LINEEND_CONV */
453 /* If the previous block of data ended with CR and this block of data is
454 just a NL, then the length might be zero */
456 wrote = data->set.fwrite_func(ptr, 1, len, data->set.out);
462 if(CURL_WRITEFUNC_PAUSE == wrote)
463 return pausewrite(data, type, ptr, len);
466 failf(data, "Failed writing body (%zu != %zu)", wrote, len);
467 return CURLE_WRITE_ERROR;
471 if((type & CLIENTWRITE_HEADER) &&
472 (data->set.fwrite_header || data->set.writeheader) ) {
474 * Write headers to the same callback or to the especially setup
475 * header callback function (added after version 7.7.1).
477 curl_write_callback writeit=
478 data->set.fwrite_header?data->set.fwrite_header:data->set.fwrite_func;
480 /* Note: The header is in the host encoding
481 regardless of the ftp transfer mode (ASCII/Image) */
483 wrote = writeit(ptr, 1, len, data->set.writeheader);
484 if(CURL_WRITEFUNC_PAUSE == wrote)
485 /* here we pass in the HEADER bit only since if this was body as well
486 then it was passed already and clearly that didn't trigger the pause,
487 so this is saved for later with the HEADER bit only */
488 return pausewrite(data, CLIENTWRITE_HEADER, ptr, len);
491 failf (data, "Failed writing header");
492 return CURLE_WRITE_ERROR;
499 CURLcode Curl_read_plain(curl_socket_t sockfd,
501 size_t bytesfromsocket,
504 ssize_t nread = sread(sockfd, buf, bytesfromsocket);
509 if(WSAEWOULDBLOCK == err)
511 if((EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err))
515 return CURLE_RECV_ERROR;
518 /* we only return number of bytes read when we return OK */
524 * Internal read-from-socket function. This is meant to deal with plain
525 * sockets, SSL sockets and kerberos sockets.
527 * Returns a regular CURLcode value.
529 CURLcode Curl_read(struct connectdata *conn, /* connection data */
530 curl_socket_t sockfd, /* read from this socket */
531 char *buf, /* store read data here */
532 size_t sizerequested, /* max amount to read */
533 ssize_t *n) /* amount bytes read */
535 CURLcode curlcode = CURLE_RECV_ERROR;
537 size_t bytesfromsocket = 0;
538 char *buffertofill = NULL;
539 bool pipelining = (conn->data->multi &&
540 Curl_multi_canPipeline(conn->data->multi)) ? TRUE : FALSE;
542 /* Set 'num' to 0 or 1, depending on which socket that has been sent here.
543 If it is the second socket, we set num to 1. Otherwise to 0. This lets
544 us use the correct ssl handle. */
545 int num = (sockfd == conn->sock[SECONDARYSOCKET]);
547 *n=0; /* reset amount to zero */
549 /* If session can pipeline, check connection buffer */
551 size_t bytestocopy = CURLMIN(conn->buf_len - conn->read_pos,
554 /* Copy from our master buffer first if we have some unread data there*/
555 if(bytestocopy > 0) {
556 memcpy(buf, conn->master_buffer + conn->read_pos, bytestocopy);
557 conn->read_pos += bytestocopy;
558 conn->bits.stream_was_rewound = FALSE;
560 *n = (ssize_t)bytestocopy;
563 /* If we come here, it means that there is no data to read from the buffer,
564 * so we read from the socket */
565 bytesfromsocket = CURLMIN(sizerequested, BUFSIZE * sizeof (char));
566 buffertofill = conn->master_buffer;
569 bytesfromsocket = CURLMIN((long)sizerequested,
570 conn->data->set.buffer_size ?
571 conn->data->set.buffer_size : BUFSIZE);
575 nread = conn->recv[num](conn, num, buffertofill, bytesfromsocket, &curlcode);
580 memcpy(buf, conn->master_buffer, nread);
581 conn->buf_len = nread;
582 conn->read_pos = nread;
590 /* return 0 on success */
591 static int showit(struct SessionHandle *data, curl_infotype type,
592 char *ptr, size_t size)
594 static const char s_infotype[CURLINFO_END][3] = {
595 "* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
597 #ifdef CURL_DOES_CONVERSIONS
599 size_t conv_size = 0;
602 case CURLINFO_HEADER_OUT:
603 /* assume output headers are ASCII */
604 /* copy the data into my buffer so the original is unchanged */
606 size = BUFSIZE; /* truncate if necessary */
610 memcpy(buf, ptr, size);
611 /* Special processing is needed for this block if it
612 * contains both headers and data (separated by CRLFCRLF).
613 * We want to convert just the headers, leaving the data as-is.
617 for(i = 0; i < size-4; i++) {
618 if(memcmp(&buf[i], "\x0d\x0a\x0d\x0a", 4) == 0) {
619 /* convert everything through this CRLFCRLF but no further */
626 Curl_convert_from_network(data, buf, conv_size);
627 /* Curl_convert_from_network calls failf if unsuccessful */
628 /* we might as well continue even if it fails... */
629 ptr = buf; /* switch pointer to use my buffer instead */
632 /* leave everything else as-is */
635 #endif /* CURL_DOES_CONVERSIONS */
638 return (*data->set.fdebug)(data, type, ptr, size,
639 data->set.debugdata);
643 case CURLINFO_HEADER_OUT:
644 case CURLINFO_HEADER_IN:
645 fwrite(s_infotype[type], 2, 1, data->set.err);
646 fwrite(ptr, size, 1, data->set.err);
647 #ifdef CURL_DOES_CONVERSIONS
648 if(size != conv_size) {
649 /* we had untranslated data so we need an explicit newline */
650 fwrite("\n", 1, 1, data->set.err);
660 int Curl_debug(struct SessionHandle *data, curl_infotype type,
661 char *ptr, size_t size,
662 struct connectdata *conn)
665 if(data->set.printhost && conn && conn->host.dispname) {
668 const char *w="Data";
670 case CURLINFO_HEADER_IN:
672 case CURLINFO_DATA_IN:
675 case CURLINFO_HEADER_OUT:
677 case CURLINFO_DATA_OUT:
685 snprintf(buffer, sizeof(buffer), "[%s %s %s]", w, t,
686 conn->host.dispname);
687 rc = showit(data, CURLINFO_TEXT, buffer, strlen(buffer));
692 rc = showit(data, type, ptr, size);