1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2010, 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>
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"
61 #include "easyif.h" /* for the Curl_convert_from_network prototype */
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 */
237 static ssize_t send_plain(struct connectdata *conn,
242 curl_socket_t sockfd = conn->sock[num];
243 ssize_t bytes_written = swrite(sockfd, mem, len);
245 if(-1 == bytes_written) {
249 #ifdef WSAEWOULDBLOCK
250 /* This is how Windows does it */
251 (WSAEWOULDBLOCK == err)
253 /* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned
254 due to its inability to send off data without blocking. We therefor
255 treat both error codes the same here */
256 (EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err)
259 /* this is just a case of EWOULDBLOCK */
262 failf(conn->data, "Send failure: %s",
263 Curl_strerror(conn, err));
265 return bytes_written;
269 * Curl_write() is an internal write function that sends data to the
270 * server. Works with plain sockets, SCP, SSL or kerberos.
272 CURLcode Curl_write(struct connectdata *conn,
273 curl_socket_t sockfd,
278 ssize_t bytes_written;
280 int num = (sockfd == conn->sock[SECONDARYSOCKET]);
282 if(conn->ssl[num].state == ssl_connection_complete)
283 bytes_written = Curl_ssl_send(conn, num, mem, len);
284 else if(Curl_ssh_enabled(conn, PROT_SCP))
285 bytes_written = Curl_scp_send(conn, num, mem, len);
286 else if(Curl_ssh_enabled(conn, PROT_SFTP))
287 bytes_written = Curl_sftp_send(conn, num, mem, len);
288 else if(conn->sec_complete)
289 bytes_written = Curl_sec_send(conn, num, mem, len);
291 bytes_written = send_plain(conn, num, mem, len);
293 *written = bytes_written;
294 retcode = (-1 != bytes_written)?CURLE_OK:CURLE_SEND_ERROR;
300 * Curl_write_plain() is an internal write function that sends data to the
301 * server using plain sockets only. Otherwise meant to have the exact same
302 * proto as Curl_write()
304 CURLcode Curl_write_plain(struct connectdata *conn,
305 curl_socket_t sockfd,
310 ssize_t bytes_written;
312 int num = (sockfd == conn->sock[SECONDARYSOCKET]);
314 bytes_written = send_plain(conn, num, mem, len);
316 *written = bytes_written;
317 retcode = (-1 != bytes_written)?CURLE_OK:CURLE_SEND_ERROR;
322 static CURLcode pausewrite(struct SessionHandle *data,
323 int type, /* what type of data */
327 /* signalled to pause sending on this connection, but since we have data
328 we want to send we need to dup it to save a copy for when the sending
330 struct SingleRequest *k = &data->req;
331 char *dupl = malloc(len);
333 return CURLE_OUT_OF_MEMORY;
335 memcpy(dupl, ptr, len);
337 /* store this information in the state struct for later use */
338 data->state.tempwrite = dupl;
339 data->state.tempwritesize = len;
340 data->state.tempwritetype = type;
342 /* mark the connection as RECV paused */
343 k->keepon |= KEEP_RECV_PAUSE;
345 DEBUGF(infof(data, "Pausing with %zu bytes in buffer for type %02x\n",
352 /* Curl_client_write() sends data to the write callback(s)
354 The bit pattern defines to what "streams" to write to. Body and/or header.
355 The defines are in sendf.h of course.
357 If CURL_DO_LINEEND_CONV is enabled, data is converted IN PLACE to the
358 local character encoding. This is a problem and should be changed in
359 the future to leave the original data alone.
361 CURLcode Curl_client_write(struct connectdata *conn,
366 struct SessionHandle *data = conn->data;
372 /* If reading is actually paused, we're forced to append this chunk of data
373 to the already held data, but only if it is the same type as otherwise it
374 can't work and it'll return error instead. */
375 if(data->req.keepon & KEEP_RECV_PAUSE) {
378 if(type != data->state.tempwritetype)
379 /* major internal confusion */
380 return CURLE_RECV_ERROR;
382 DEBUGASSERT(data->state.tempwrite);
384 /* figure out the new size of the data to save */
385 newlen = len + data->state.tempwritesize;
386 /* allocate the new memory area */
387 newptr = realloc(data->state.tempwrite, newlen);
389 return CURLE_OUT_OF_MEMORY;
390 /* copy the new data to the end of the new area */
391 memcpy(newptr + data->state.tempwritesize, ptr, len);
392 /* update the pointer and the size */
393 data->state.tempwrite = newptr;
394 data->state.tempwritesize = newlen;
399 if(type & CLIENTWRITE_BODY) {
400 if((conn->protocol&PROT_FTP) && conn->proto.ftpc.transfertype == 'A') {
401 #ifdef CURL_DOES_CONVERSIONS
402 /* convert from the network encoding */
404 rc = Curl_convert_from_network(data, ptr, len);
405 /* Curl_convert_from_network calls failf if unsuccessful */
408 #endif /* CURL_DOES_CONVERSIONS */
410 #ifdef CURL_DO_LINEEND_CONV
411 /* convert end-of-line markers */
412 len = convert_lineends(data, ptr, len);
413 #endif /* CURL_DO_LINEEND_CONV */
415 /* If the previous block of data ended with CR and this block of data is
416 just a NL, then the length might be zero */
418 wrote = data->set.fwrite_func(ptr, 1, len, data->set.out);
424 if(CURL_WRITEFUNC_PAUSE == wrote)
425 return pausewrite(data, type, ptr, len);
428 failf(data, "Failed writing body (%zu != %zu)", wrote, len);
429 return CURLE_WRITE_ERROR;
433 if((type & CLIENTWRITE_HEADER) &&
434 (data->set.fwrite_header || data->set.writeheader) ) {
436 * Write headers to the same callback or to the especially setup
437 * header callback function (added after version 7.7.1).
439 curl_write_callback writeit=
440 data->set.fwrite_header?data->set.fwrite_header:data->set.fwrite_func;
442 /* Note: The header is in the host encoding
443 regardless of the ftp transfer mode (ASCII/Image) */
445 wrote = writeit(ptr, 1, len, data->set.writeheader);
446 if(CURL_WRITEFUNC_PAUSE == wrote)
447 /* here we pass in the HEADER bit only since if this was body as well
448 then it was passed already and clearly that didn't trigger the pause,
449 so this is saved for later with the HEADER bit only */
450 return pausewrite(data, CLIENTWRITE_HEADER, ptr, len);
453 failf (data, "Failed writing header");
454 return CURLE_WRITE_ERROR;
461 int Curl_read_plain(curl_socket_t sockfd,
463 size_t bytesfromsocket,
466 ssize_t nread = sread(sockfd, buf, bytesfromsocket);
471 if(WSAEWOULDBLOCK == err)
473 if((EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err))
477 return CURLE_RECV_ERROR;
480 /* we only return number of bytes read when we return OK */
486 * Internal read-from-socket function. This is meant to deal with plain
487 * sockets, SSL sockets and kerberos sockets.
489 * If the read would block (EWOULDBLOCK) we return -1. Otherwise we return
490 * a regular CURLcode value.
492 int Curl_read(struct connectdata *conn, /* connection data */
493 curl_socket_t sockfd, /* read from this socket */
494 char *buf, /* store read data here */
495 size_t sizerequested, /* max amount to read */
496 ssize_t *n) /* amount bytes read */
499 size_t bytesfromsocket = 0;
500 char *buffertofill = NULL;
501 bool pipelining = (bool)(conn->data->multi &&
502 Curl_multi_canPipeline(conn->data->multi));
504 /* Set 'num' to 0 or 1, depending on which socket that has been sent here.
505 If it is the second socket, we set num to 1. Otherwise to 0. This lets
506 us use the correct ssl handle. */
507 int num = (sockfd == conn->sock[SECONDARYSOCKET]);
509 *n=0; /* reset amount to zero */
511 /* If session can pipeline, check connection buffer */
513 size_t bytestocopy = CURLMIN(conn->buf_len - conn->read_pos,
516 /* Copy from our master buffer first if we have some unread data there*/
517 if(bytestocopy > 0) {
518 memcpy(buf, conn->master_buffer + conn->read_pos, bytestocopy);
519 conn->read_pos += bytestocopy;
520 conn->bits.stream_was_rewound = FALSE;
522 *n = (ssize_t)bytestocopy;
525 /* If we come here, it means that there is no data to read from the buffer,
526 * so we read from the socket */
527 bytesfromsocket = CURLMIN(sizerequested, BUFSIZE * sizeof (char));
528 buffertofill = conn->master_buffer;
531 bytesfromsocket = CURLMIN((long)sizerequested,
532 conn->data->set.buffer_size ?
533 conn->data->set.buffer_size : BUFSIZE);
537 if(conn->ssl[num].state == ssl_connection_complete) {
538 nread = Curl_ssl_recv(conn, num, buffertofill, bytesfromsocket);
541 return -1; /* -1 from Curl_ssl_recv() means EWOULDBLOCK */
543 /* -2 from Curl_ssl_recv() means a true error, not EWOULDBLOCK */
544 return CURLE_RECV_ERROR;
546 else if(Curl_ssh_enabled(conn, (PROT_SCP|PROT_SFTP))) {
547 if(conn->protocol & PROT_SCP)
548 nread = Curl_scp_recv(conn, num, buffertofill, bytesfromsocket);
549 else if(conn->protocol & PROT_SFTP)
550 nread = Curl_sftp_recv(conn, num, buffertofill, bytesfromsocket);
551 #ifdef LIBSSH2CHANNEL_EAGAIN
552 if((nread == LIBSSH2CHANNEL_EAGAIN) || (nread == 0))
557 /* since it is negative and not EAGAIN, it was a protocol-layer error */
558 return CURLE_RECV_ERROR;
561 if(conn->sec_complete)
562 nread = Curl_sec_read(conn, sockfd, buffertofill,
564 /* TODO: Need to handle EAGAIN here somehow, similar to how it
565 * is done in Curl_read_plain, either right here or in Curl_sec_read
568 int ret = Curl_read_plain(sockfd, buffertofill, bytesfromsocket,
576 memcpy(buf, conn->master_buffer, nread);
577 conn->buf_len = nread;
578 conn->read_pos = nread;
587 /* return 0 on success */
588 static int showit(struct SessionHandle *data, curl_infotype type,
589 char *ptr, size_t size)
591 static const char s_infotype[CURLINFO_END][3] = {
592 "* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
594 #ifdef CURL_DOES_CONVERSIONS
596 size_t conv_size = 0;
599 case CURLINFO_HEADER_OUT:
600 /* assume output headers are ASCII */
601 /* copy the data into my buffer so the original is unchanged */
603 size = BUFSIZE; /* truncate if necessary */
607 memcpy(buf, ptr, size);
608 /* Special processing is needed for this block if it
609 * contains both headers and data (separated by CRLFCRLF).
610 * We want to convert just the headers, leaving the data as-is.
614 for(i = 0; i < size-4; i++) {
615 if(memcmp(&buf[i], "\x0d\x0a\x0d\x0a", 4) == 0) {
616 /* convert everthing through this CRLFCRLF but no further */
623 Curl_convert_from_network(data, buf, conv_size);
624 /* Curl_convert_from_network calls failf if unsuccessful */
625 /* we might as well continue even if it fails... */
626 ptr = buf; /* switch pointer to use my buffer instead */
629 /* leave everything else as-is */
632 #endif /* CURL_DOES_CONVERSIONS */
635 return (*data->set.fdebug)(data, type, ptr, size,
636 data->set.debugdata);
640 case CURLINFO_HEADER_OUT:
641 case CURLINFO_HEADER_IN:
642 fwrite(s_infotype[type], 2, 1, data->set.err);
643 fwrite(ptr, size, 1, data->set.err);
644 #ifdef CURL_DOES_CONVERSIONS
645 if(size != conv_size) {
646 /* we had untranslated data so we need an explicit newline */
647 fwrite("\n", 1, 1, data->set.err);
657 int Curl_debug(struct SessionHandle *data, curl_infotype type,
658 char *ptr, size_t size,
659 struct connectdata *conn)
662 if(data->set.printhost && conn && conn->host.dispname) {
665 const char *w="Data";
667 case CURLINFO_HEADER_IN:
669 case CURLINFO_DATA_IN:
672 case CURLINFO_HEADER_OUT:
674 case CURLINFO_DATA_OUT:
682 snprintf(buffer, sizeof(buffer), "[%s %s %s]", w, t,
683 conn->host.dispname);
684 rc = showit(data, CURLINFO_TEXT, buffer, strlen(buffer));
689 rc = showit(data, type, ptr, size);