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 ***************************************************************************/
30 #ifdef HAVE_SYS_SOCKET_H
31 #include <sys/socket.h> /* required for send() & recv() prototypes */
38 #include <curl/curl.h>
45 #include "non-ascii.h"
47 #define _MPRINTF_REPLACE /* use the internal *printf() functions */
48 #include <curl/mprintf.h>
50 /* the krb4 functions only exists for FTP and if krb4 or gssapi is defined */
51 #if !defined(CURL_DISABLE_FTP) && (defined(HAVE_KRB4) || defined(HAVE_GSSAPI))
54 #define Curl_sec_send(a,b,c,d) -1
55 #define Curl_sec_read(a,b,c,d) -1
59 #include "curl_memory.h"
62 /* The last #include file should be: */
65 #ifdef CURL_DO_LINEEND_CONV
67 * convert_lineends() changes CRLF (\r\n) end-of-line markers to a single LF
68 * (\n), with special processing for CRLF sequences that are split between two
69 * blocks of data. Remaining, bare CRs are changed to LFs. The possibly new
70 * size of the data is returned.
72 static size_t convert_lineends(struct SessionHandle *data,
73 char *startPtr, size_t size)
78 if((startPtr == NULL) || (size < 1)) {
82 if(data->state.prev_block_had_trailing_cr == TRUE) {
83 /* The previous block of incoming data
84 had a trailing CR, which was turned into a LF. */
85 if(*startPtr == '\n') {
86 /* This block of incoming data starts with the
87 previous block's LF so get rid of it */
88 memmove(startPtr, startPtr+1, size-1);
90 /* and it wasn't a bare CR but a CRLF conversion instead */
91 data->state.crlf_conversions++;
93 data->state.prev_block_had_trailing_cr = FALSE; /* reset the flag */
96 /* find 1st CR, if any */
97 inPtr = outPtr = memchr(startPtr, '\r', size);
99 /* at least one CR, now look for CRLF */
100 while(inPtr < (startPtr+size-1)) {
101 /* note that it's size-1, so we'll never look past the last byte */
102 if(memcmp(inPtr, "\r\n", 2) == 0) {
103 /* CRLF found, bump past the CR and copy the NL */
106 /* keep track of how many CRLFs we converted */
107 data->state.crlf_conversions++;
111 /* lone CR, move LF instead */
115 /* not a CRLF nor a CR, just copy whatever it is */
121 } /* end of while loop */
123 if(inPtr < startPtr+size) {
124 /* handle last byte */
126 /* deal with a CR at the end of the buffer */
127 *outPtr = '\n'; /* copy a NL instead */
128 /* note that a CRLF might be split across two blocks */
129 data->state.prev_block_had_trailing_cr = TRUE;
137 if(outPtr < startPtr+size)
138 /* tidy up by null terminating the now shorter data */
141 return(outPtr - startPtr);
145 #endif /* CURL_DO_LINEEND_CONV */
147 /* Curl_infof() is for info message along the way */
149 void Curl_infof(struct SessionHandle *data, const char *fmt, ...)
151 if(data && data->set.verbose) {
154 char print_buffer[2048 + 1];
156 vsnprintf(print_buffer, sizeof(print_buffer), fmt, ap);
158 len = strlen(print_buffer);
159 Curl_debug(data, CURLINFO_TEXT, print_buffer, len, NULL);
163 /* Curl_failf() is for messages stating why we failed.
164 * The message SHALL NOT include any LF or CR.
167 void Curl_failf(struct SessionHandle *data, const char *fmt, ...)
173 vsnprintf(data->state.buffer, BUFSIZE, fmt, ap);
175 if(data->set.errorbuffer && !data->state.errorbuf) {
176 snprintf(data->set.errorbuffer, CURL_ERROR_SIZE, "%s", data->state.buffer);
177 data->state.errorbuf = TRUE; /* wrote error string */
179 if(data->set.verbose) {
180 len = strlen(data->state.buffer);
181 if(len < BUFSIZE - 1) {
182 data->state.buffer[len] = '\n';
183 data->state.buffer[++len] = '\0';
185 Curl_debug(data, CURLINFO_TEXT, data->state.buffer, len, NULL);
191 /* Curl_sendf() sends formated data to the server */
192 CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *conn,
193 const char *fmt, ...)
195 struct SessionHandle *data = conn->data;
196 ssize_t bytes_written;
198 CURLcode res = CURLE_OK;
203 s = vaprintf(fmt, ap); /* returns an allocated string */
206 return CURLE_OUT_OF_MEMORY; /* failure */
209 write_len = strlen(s);
213 /* Write the buffer to the socket */
214 res = Curl_write(conn, sockfd, sptr, write_len, &bytes_written);
219 if(data->set.verbose)
220 Curl_debug(data, CURLINFO_DATA_OUT, sptr, (size_t)bytes_written, conn);
222 if((size_t)bytes_written != write_len) {
223 /* if not all was written at once, we must advance the pointer, decrease
224 the size left and try again! */
225 write_len -= bytes_written;
226 sptr += bytes_written;
232 free(s); /* free the output string */
238 * Curl_write() is an internal write function that sends data to the
239 * server. Works with plain sockets, SCP, SSL or kerberos.
241 * If the write would block (CURLE_AGAIN), we return CURLE_OK and
242 * (*written == 0). Otherwise we return regular CURLcode value.
244 CURLcode Curl_write(struct connectdata *conn,
245 curl_socket_t sockfd,
250 ssize_t bytes_written;
251 CURLcode curlcode = CURLE_OK;
252 int num = (sockfd == conn->sock[SECONDARYSOCKET]);
254 bytes_written = conn->send[num](conn, num, mem, len, &curlcode);
256 *written = bytes_written;
257 if(bytes_written >= 0)
258 /* we completely ignore the curlcode value when subzero is not returned */
261 /* handle CURLE_AGAIN or a send failure */
268 /* general send failure */
269 return CURLE_SEND_ERROR;
272 /* we got a specific curlcode, forward it */
273 return (CURLcode)curlcode;
277 ssize_t Curl_send_plain(struct connectdata *conn, int num,
278 const void *mem, size_t len, CURLcode *code)
280 curl_socket_t sockfd = conn->sock[num];
281 ssize_t bytes_written = swrite(sockfd, mem, len);
284 if(-1 == bytes_written) {
288 #ifdef WSAEWOULDBLOCK
289 /* This is how Windows does it */
290 (WSAEWOULDBLOCK == err)
292 /* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned
293 due to its inability to send off data without blocking. We therefor
294 treat both error codes the same here */
295 (EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err)
298 /* this is just a case of EWOULDBLOCK */
303 failf(conn->data, "Send failure: %s",
304 Curl_strerror(conn, err));
305 conn->data->state.os_errno = err;
306 *code = CURLE_SEND_ERROR;
309 return bytes_written;
313 * Curl_write_plain() is an internal write function that sends data to the
314 * server using plain sockets only. Otherwise meant to have the exact same
315 * proto as Curl_write()
317 CURLcode Curl_write_plain(struct connectdata *conn,
318 curl_socket_t sockfd,
323 ssize_t bytes_written;
325 int num = (sockfd == conn->sock[SECONDARYSOCKET]);
327 bytes_written = Curl_send_plain(conn, num, mem, len, &retcode);
329 *written = bytes_written;
334 ssize_t Curl_recv_plain(struct connectdata *conn, int num, char *buf,
335 size_t len, CURLcode *code)
337 curl_socket_t sockfd = conn->sock[num];
338 ssize_t nread = sread(sockfd, buf, len);
345 #ifdef WSAEWOULDBLOCK
346 /* This is how Windows does it */
347 (WSAEWOULDBLOCK == err)
349 /* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned
350 due to its inability to send off data without blocking. We therefor
351 treat both error codes the same here */
352 (EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err)
355 /* this is just a case of EWOULDBLOCK */
359 failf(conn->data, "Recv failure: %s",
360 Curl_strerror(conn, err));
361 conn->data->state.os_errno = err;
362 *code = CURLE_RECV_ERROR;
368 static CURLcode pausewrite(struct SessionHandle *data,
369 int type, /* what type of data */
373 /* signalled to pause sending on this connection, but since we have data
374 we want to send we need to dup it to save a copy for when the sending
376 struct SingleRequest *k = &data->req;
377 char *dupl = malloc(len);
379 return CURLE_OUT_OF_MEMORY;
381 memcpy(dupl, ptr, len);
383 /* store this information in the state struct for later use */
384 data->state.tempwrite = dupl;
385 data->state.tempwritesize = len;
386 data->state.tempwritetype = type;
388 /* mark the connection as RECV paused */
389 k->keepon |= KEEP_RECV_PAUSE;
391 DEBUGF(infof(data, "Pausing with %zu bytes in buffer for type %02x\n",
398 /* Curl_client_write() sends data to the write callback(s)
400 The bit pattern defines to what "streams" to write to. Body and/or header.
401 The defines are in sendf.h of course.
403 If CURL_DO_LINEEND_CONV is enabled, data is converted IN PLACE to the
404 local character encoding. This is a problem and should be changed in
405 the future to leave the original data alone.
407 CURLcode Curl_client_write(struct connectdata *conn,
412 struct SessionHandle *data = conn->data;
418 /* If reading is actually paused, we're forced to append this chunk of data
419 to the already held data, but only if it is the same type as otherwise it
420 can't work and it'll return error instead. */
421 if(data->req.keepon & KEEP_RECV_PAUSE) {
424 if(type != data->state.tempwritetype)
425 /* major internal confusion */
426 return CURLE_RECV_ERROR;
428 DEBUGASSERT(data->state.tempwrite);
430 /* figure out the new size of the data to save */
431 newlen = len + data->state.tempwritesize;
432 /* allocate the new memory area */
433 newptr = realloc(data->state.tempwrite, newlen);
435 return CURLE_OUT_OF_MEMORY;
436 /* copy the new data to the end of the new area */
437 memcpy(newptr + data->state.tempwritesize, ptr, len);
438 /* update the pointer and the size */
439 data->state.tempwrite = newptr;
440 data->state.tempwritesize = newlen;
445 if(type & CLIENTWRITE_BODY) {
446 if((conn->handler->protocol&CURLPROTO_FTP) &&
447 conn->proto.ftpc.transfertype == 'A') {
448 /* convert from the network encoding */
449 CURLcode rc = Curl_convert_from_network(data, ptr, len);
450 /* Curl_convert_from_network calls failf if unsuccessful */
454 #ifdef CURL_DO_LINEEND_CONV
455 /* convert end-of-line markers */
456 len = convert_lineends(data, ptr, len);
457 #endif /* CURL_DO_LINEEND_CONV */
459 /* If the previous block of data ended with CR and this block of data is
460 just a NL, then the length might be zero */
462 wrote = data->set.fwrite_func(ptr, 1, len, data->set.out);
468 if(CURL_WRITEFUNC_PAUSE == wrote)
469 return pausewrite(data, type, ptr, len);
472 failf(data, "Failed writing body (%zu != %zu)", wrote, len);
473 return CURLE_WRITE_ERROR;
477 if((type & CLIENTWRITE_HEADER) &&
478 (data->set.fwrite_header || data->set.writeheader) ) {
480 * Write headers to the same callback or to the especially setup
481 * header callback function (added after version 7.7.1).
483 curl_write_callback writeit=
484 data->set.fwrite_header?data->set.fwrite_header:data->set.fwrite_func;
486 /* Note: The header is in the host encoding
487 regardless of the ftp transfer mode (ASCII/Image) */
489 wrote = writeit(ptr, 1, len, data->set.writeheader);
490 if(CURL_WRITEFUNC_PAUSE == wrote)
491 /* here we pass in the HEADER bit only since if this was body as well
492 then it was passed already and clearly that didn't trigger the pause,
493 so this is saved for later with the HEADER bit only */
494 return pausewrite(data, CLIENTWRITE_HEADER, ptr, len);
497 failf (data, "Failed writing header");
498 return CURLE_WRITE_ERROR;
505 CURLcode Curl_read_plain(curl_socket_t sockfd,
507 size_t bytesfromsocket,
510 ssize_t nread = sread(sockfd, buf, bytesfromsocket);
515 if(WSAEWOULDBLOCK == err)
517 if((EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err))
521 return CURLE_RECV_ERROR;
524 /* we only return number of bytes read when we return OK */
530 * Internal read-from-socket function. This is meant to deal with plain
531 * sockets, SSL sockets and kerberos sockets.
533 * Returns a regular CURLcode value.
535 CURLcode Curl_read(struct connectdata *conn, /* connection data */
536 curl_socket_t sockfd, /* read from this socket */
537 char *buf, /* store read data here */
538 size_t sizerequested, /* max amount to read */
539 ssize_t *n) /* amount bytes read */
541 CURLcode curlcode = CURLE_RECV_ERROR;
543 size_t bytesfromsocket = 0;
544 char *buffertofill = NULL;
545 bool pipelining = (bool)(conn->data->multi &&
546 Curl_multi_canPipeline(conn->data->multi));
548 /* Set 'num' to 0 or 1, depending on which socket that has been sent here.
549 If it is the second socket, we set num to 1. Otherwise to 0. This lets
550 us use the correct ssl handle. */
551 int num = (sockfd == conn->sock[SECONDARYSOCKET]);
553 *n=0; /* reset amount to zero */
555 /* If session can pipeline, check connection buffer */
557 size_t bytestocopy = CURLMIN(conn->buf_len - conn->read_pos,
560 /* Copy from our master buffer first if we have some unread data there*/
561 if(bytestocopy > 0) {
562 memcpy(buf, conn->master_buffer + conn->read_pos, bytestocopy);
563 conn->read_pos += bytestocopy;
564 conn->bits.stream_was_rewound = FALSE;
566 *n = (ssize_t)bytestocopy;
569 /* If we come here, it means that there is no data to read from the buffer,
570 * so we read from the socket */
571 bytesfromsocket = CURLMIN(sizerequested, BUFSIZE * sizeof (char));
572 buffertofill = conn->master_buffer;
575 bytesfromsocket = CURLMIN((long)sizerequested,
576 conn->data->set.buffer_size ?
577 conn->data->set.buffer_size : BUFSIZE);
581 nread = conn->recv[num](conn, num, buffertofill, bytesfromsocket, &curlcode);
586 memcpy(buf, conn->master_buffer, nread);
587 conn->buf_len = nread;
588 conn->read_pos = nread;
596 /* return 0 on success */
597 static int showit(struct SessionHandle *data, curl_infotype type,
598 char *ptr, size_t size)
600 static const char s_infotype[CURLINFO_END][3] = {
601 "* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
603 #ifdef CURL_DOES_CONVERSIONS
605 size_t conv_size = 0;
608 case CURLINFO_HEADER_OUT:
609 /* assume output headers are ASCII */
610 /* copy the data into my buffer so the original is unchanged */
612 size = BUFSIZE; /* truncate if necessary */
616 memcpy(buf, ptr, size);
617 /* Special processing is needed for this block if it
618 * contains both headers and data (separated by CRLFCRLF).
619 * We want to convert just the headers, leaving the data as-is.
623 for(i = 0; i < size-4; i++) {
624 if(memcmp(&buf[i], "\x0d\x0a\x0d\x0a", 4) == 0) {
625 /* convert everything through this CRLFCRLF but no further */
632 Curl_convert_from_network(data, buf, conv_size);
633 /* Curl_convert_from_network calls failf if unsuccessful */
634 /* we might as well continue even if it fails... */
635 ptr = buf; /* switch pointer to use my buffer instead */
638 /* leave everything else as-is */
641 #endif /* CURL_DOES_CONVERSIONS */
644 return (*data->set.fdebug)(data, type, ptr, size,
645 data->set.debugdata);
649 case CURLINFO_HEADER_OUT:
650 case CURLINFO_HEADER_IN:
651 fwrite(s_infotype[type], 2, 1, data->set.err);
652 fwrite(ptr, size, 1, data->set.err);
653 #ifdef CURL_DOES_CONVERSIONS
654 if(size != conv_size) {
655 /* we had untranslated data so we need an explicit newline */
656 fwrite("\n", 1, 1, data->set.err);
666 int Curl_debug(struct SessionHandle *data, curl_infotype type,
667 char *ptr, size_t size,
668 struct connectdata *conn)
671 if(data->set.printhost && conn && conn->host.dispname) {
674 const char *w="Data";
676 case CURLINFO_HEADER_IN:
678 case CURLINFO_DATA_IN:
681 case CURLINFO_HEADER_OUT:
683 case CURLINFO_DATA_OUT:
691 snprintf(buffer, sizeof(buffer), "[%s %s %s]", w, t,
692 conn->host.dispname);
693 rc = showit(data, CURLINFO_TEXT, buffer, strlen(buffer));
698 rc = showit(data, type, ptr, size);