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.
22 ***************************************************************************/
31 #ifdef HAVE_SYS_SOCKET_H
32 #include <sys/socket.h> /* required for send() & recv() prototypes */
39 #include <curl/curl.h>
48 #define _MPRINTF_REPLACE /* use the internal *printf() functions */
49 #include <curl/mprintf.h>
51 /* the krb4 functions only exists for FTP and if krb4 or gssapi is defined */
52 #if !defined(CURL_DISABLE_FTP) && (defined(HAVE_KRB4) || defined(HAVE_GSSAPI))
55 #define Curl_sec_send(a,b,c,d) -1
56 #define Curl_sec_read(a,b,c,d) -1
60 #include "curl_memory.h"
62 #include "easyif.h" /* for the Curl_convert_from_network prototype */
63 /* The last #include file should be: */
66 #ifdef CURL_DO_LINEEND_CONV
68 * convert_lineends() changes CRLF (\r\n) end-of-line markers to a single LF
69 * (\n), with special processing for CRLF sequences that are split between two
70 * blocks of data. Remaining, bare CRs are changed to LFs. The possibly new
71 * size of the data is returned.
73 static size_t convert_lineends(struct SessionHandle *data,
74 char *startPtr, size_t size)
79 if((startPtr == NULL) || (size < 1)) {
83 if(data->state.prev_block_had_trailing_cr == TRUE) {
84 /* The previous block of incoming data
85 had a trailing CR, which was turned into a LF. */
86 if(*startPtr == '\n') {
87 /* This block of incoming data starts with the
88 previous block's LF so get rid of it */
89 memmove(startPtr, startPtr+1, size-1);
91 /* and it wasn't a bare CR but a CRLF conversion instead */
92 data->state.crlf_conversions++;
94 data->state.prev_block_had_trailing_cr = FALSE; /* reset the flag */
97 /* find 1st CR, if any */
98 inPtr = outPtr = memchr(startPtr, '\r', size);
100 /* at least one CR, now look for CRLF */
101 while(inPtr < (startPtr+size-1)) {
102 /* note that it's size-1, so we'll never look past the last byte */
103 if(memcmp(inPtr, "\r\n", 2) == 0) {
104 /* CRLF found, bump past the CR and copy the NL */
107 /* keep track of how many CRLFs we converted */
108 data->state.crlf_conversions++;
112 /* lone CR, move LF instead */
116 /* not a CRLF nor a CR, just copy whatever it is */
122 } /* end of while loop */
124 if(inPtr < startPtr+size) {
125 /* handle last byte */
127 /* deal with a CR at the end of the buffer */
128 *outPtr = '\n'; /* copy a NL instead */
129 /* note that a CRLF might be split across two blocks */
130 data->state.prev_block_had_trailing_cr = TRUE;
138 if(outPtr < startPtr+size)
139 /* tidy up by null terminating the now shorter data */
142 return(outPtr - startPtr);
146 #endif /* CURL_DO_LINEEND_CONV */
148 /* Curl_infof() is for info message along the way */
150 void Curl_infof(struct SessionHandle *data, const char *fmt, ...)
152 if(data && data->set.verbose) {
155 char print_buffer[2048 + 1];
157 vsnprintf(print_buffer, sizeof(print_buffer), fmt, ap);
159 len = strlen(print_buffer);
160 Curl_debug(data, CURLINFO_TEXT, print_buffer, len, NULL);
164 /* Curl_failf() is for messages stating why we failed.
165 * The message SHALL NOT include any LF or CR.
168 void Curl_failf(struct SessionHandle *data, const char *fmt, ...)
174 vsnprintf(data->state.buffer, BUFSIZE, fmt, ap);
176 if(data->set.errorbuffer && !data->state.errorbuf) {
177 snprintf(data->set.errorbuffer, CURL_ERROR_SIZE, "%s", data->state.buffer);
178 data->state.errorbuf = TRUE; /* wrote error string */
180 if(data->set.verbose) {
181 len = strlen(data->state.buffer);
182 if(len < BUFSIZE - 1) {
183 data->state.buffer[len] = '\n';
184 data->state.buffer[++len] = '\0';
186 Curl_debug(data, CURLINFO_TEXT, data->state.buffer, len, NULL);
192 /* Curl_sendf() sends formated data to the server */
193 CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *conn,
194 const char *fmt, ...)
196 struct SessionHandle *data = conn->data;
197 ssize_t bytes_written;
199 CURLcode res = CURLE_OK;
204 s = vaprintf(fmt, ap); /* returns an allocated string */
207 return CURLE_OUT_OF_MEMORY; /* failure */
210 write_len = strlen(s);
214 /* Write the buffer to the socket */
215 res = Curl_write(conn, sockfd, sptr, write_len, &bytes_written);
220 if(data->set.verbose)
221 Curl_debug(data, CURLINFO_DATA_OUT, sptr, (size_t)bytes_written, conn);
223 if((size_t)bytes_written != write_len) {
224 /* if not all was written at once, we must advance the pointer, decrease
225 the size left and try again! */
226 write_len -= bytes_written;
227 sptr += bytes_written;
233 free(s); /* free the output string */
238 static ssize_t send_plain(struct connectdata *conn,
243 curl_socket_t sockfd = conn->sock[num];
244 ssize_t bytes_written = swrite(sockfd, mem, len);
246 if(-1 == bytes_written) {
250 #ifdef WSAEWOULDBLOCK
251 /* This is how Windows does it */
252 (WSAEWOULDBLOCK == err)
254 /* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned
255 due to its inability to send off data without blocking. We therefor
256 treat both error codes the same here */
257 (EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err)
260 /* this is just a case of EWOULDBLOCK */
263 failf(conn->data, "Send failure: %s",
264 Curl_strerror(conn, err));
266 return bytes_written;
270 * Curl_write() is an internal write function that sends data to the
271 * server. Works with plain sockets, SCP, SSL or kerberos.
273 CURLcode Curl_write(struct connectdata *conn,
274 curl_socket_t sockfd,
279 ssize_t bytes_written;
281 int num = (sockfd == conn->sock[SECONDARYSOCKET]);
283 if(conn->ssl[num].state == ssl_connection_complete)
284 bytes_written = Curl_ssl_send(conn, num, mem, len);
285 else if(Curl_ssh_enabled(conn, PROT_SCP))
286 bytes_written = Curl_scp_send(conn, num, mem, len);
287 else if(Curl_ssh_enabled(conn, PROT_SFTP))
288 bytes_written = Curl_sftp_send(conn, num, mem, len);
289 else if(conn->sec_complete)
290 bytes_written = Curl_sec_send(conn, num, mem, len);
292 bytes_written = send_plain(conn, num, mem, len);
294 *written = bytes_written;
295 retcode = (-1 != bytes_written)?CURLE_OK:CURLE_SEND_ERROR;
301 * Curl_write_plain() is an internal write function that sends data to the
302 * server using plain sockets only. Otherwise meant to have the exact same
303 * proto as Curl_write()
305 CURLcode Curl_write_plain(struct connectdata *conn,
306 curl_socket_t sockfd,
311 ssize_t bytes_written;
313 int num = (sockfd == conn->sock[SECONDARYSOCKET]);
315 bytes_written = send_plain(conn, num, mem, len);
317 *written = bytes_written;
318 retcode = (-1 != bytes_written)?CURLE_OK:CURLE_SEND_ERROR;
323 static CURLcode pausewrite(struct SessionHandle *data,
324 int type, /* what type of data */
328 /* signalled to pause sending on this connection, but since we have data
329 we want to send we need to dup it to save a copy for when the sending
331 struct SingleRequest *k = &data->req;
332 char *dupl = malloc(len);
334 return CURLE_OUT_OF_MEMORY;
336 memcpy(dupl, ptr, len);
338 /* store this information in the state struct for later use */
339 data->state.tempwrite = dupl;
340 data->state.tempwritesize = len;
341 data->state.tempwritetype = type;
343 /* mark the connection as RECV paused */
344 k->keepon |= KEEP_RECV_PAUSE;
346 DEBUGF(infof(data, "Pausing with %d bytes in buffer for type %02x\n",
353 /* Curl_client_write() sends data to the write callback(s)
355 The bit pattern defines to what "streams" to write to. Body and/or header.
356 The defines are in sendf.h of course.
358 If CURL_DO_LINEEND_CONV is enabled, data is converted IN PLACE to the
359 local character encoding. This is a problem and should be changed in
360 the future to leave the original data alone.
362 CURLcode Curl_client_write(struct connectdata *conn,
367 struct SessionHandle *data = conn->data;
373 /* If reading is actually paused, we're forced to append this chunk of data
374 to the already held data, but only if it is the same type as otherwise it
375 can't work and it'll return error instead. */
376 if(data->req.keepon & KEEP_RECV_PAUSE) {
379 if(type != data->state.tempwritetype)
380 /* major internal confusion */
381 return CURLE_RECV_ERROR;
383 DEBUGASSERT(data->state.tempwrite);
385 /* figure out the new size of the data to save */
386 newlen = len + data->state.tempwritesize;
387 /* allocate the new memory area */
388 newptr = realloc(data->state.tempwrite, newlen);
390 return CURLE_OUT_OF_MEMORY;
391 /* copy the new data to the end of the new area */
392 memcpy(newptr + data->state.tempwritesize, ptr, len);
393 /* update the pointer and the size */
394 data->state.tempwrite = newptr;
395 data->state.tempwritesize = newlen;
400 if(type & CLIENTWRITE_BODY) {
401 if((conn->protocol&PROT_FTP) && conn->proto.ftpc.transfertype == 'A') {
402 #ifdef CURL_DOES_CONVERSIONS
403 /* convert from the network encoding */
405 rc = Curl_convert_from_network(data, ptr, len);
406 /* Curl_convert_from_network calls failf if unsuccessful */
409 #endif /* CURL_DOES_CONVERSIONS */
411 #ifdef CURL_DO_LINEEND_CONV
412 /* convert end-of-line markers */
413 len = convert_lineends(data, ptr, len);
414 #endif /* CURL_DO_LINEEND_CONV */
416 /* If the previous block of data ended with CR and this block of data is
417 just a NL, then the length might be zero */
419 wrote = data->set.fwrite_func(ptr, 1, len, data->set.out);
425 if(CURL_WRITEFUNC_PAUSE == wrote)
426 return pausewrite(data, type, ptr, len);
429 failf(data, "Failed writing body (%d != %d)", (int)wrote, (int)len);
430 return CURLE_WRITE_ERROR;
434 if((type & CLIENTWRITE_HEADER) &&
435 (data->set.fwrite_header || data->set.writeheader) ) {
437 * Write headers to the same callback or to the especially setup
438 * header callback function (added after version 7.7.1).
440 curl_write_callback writeit=
441 data->set.fwrite_header?data->set.fwrite_header:data->set.fwrite_func;
443 /* Note: The header is in the host encoding
444 regardless of the ftp transfer mode (ASCII/Image) */
446 wrote = writeit(ptr, 1, len, data->set.writeheader);
447 if(CURL_WRITEFUNC_PAUSE == wrote)
448 /* here we pass in the HEADER bit only since if this was body as well
449 then it was passed already and clearly that didn't trigger the pause,
450 so this is saved for later with the HEADER bit only */
451 return pausewrite(data, CLIENTWRITE_HEADER, ptr, len);
454 failf (data, "Failed writing header");
455 return CURLE_WRITE_ERROR;
462 int Curl_read_plain(curl_socket_t sockfd,
464 size_t bytesfromsocket,
467 ssize_t nread = sread(sockfd, buf, bytesfromsocket);
472 if(WSAEWOULDBLOCK == err)
474 if((EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err))
478 return CURLE_RECV_ERROR;
481 /* we only return number of bytes read when we return OK */
487 * Internal read-from-socket function. This is meant to deal with plain
488 * sockets, SSL sockets and kerberos sockets.
490 * If the read would block (EWOULDBLOCK) we return -1. Otherwise we return
491 * a regular CURLcode value.
493 int Curl_read(struct connectdata *conn, /* connection data */
494 curl_socket_t sockfd, /* read from this socket */
495 char *buf, /* store read data here */
496 size_t sizerequested, /* max amount to read */
497 ssize_t *n) /* amount bytes read */
500 size_t bytesfromsocket = 0;
501 char *buffertofill = NULL;
502 bool pipelining = (bool)(conn->data->multi &&
503 Curl_multi_canPipeline(conn->data->multi));
505 /* Set 'num' to 0 or 1, depending on which socket that has been sent here.
506 If it is the second socket, we set num to 1. Otherwise to 0. This lets
507 us use the correct ssl handle. */
508 int num = (sockfd == conn->sock[SECONDARYSOCKET]);
510 *n=0; /* reset amount to zero */
512 /* If session can pipeline, check connection buffer */
514 size_t bytestocopy = CURLMIN(conn->buf_len - conn->read_pos,
517 /* Copy from our master buffer first if we have some unread data there*/
518 if(bytestocopy > 0) {
519 memcpy(buf, conn->master_buffer + conn->read_pos, bytestocopy);
520 conn->read_pos += bytestocopy;
521 conn->bits.stream_was_rewound = FALSE;
523 *n = (ssize_t)bytestocopy;
526 /* If we come here, it means that there is no data to read from the buffer,
527 * so we read from the socket */
528 bytesfromsocket = CURLMIN(sizerequested, BUFSIZE * sizeof (char));
529 buffertofill = conn->master_buffer;
532 bytesfromsocket = CURLMIN((long)sizerequested,
533 conn->data->set.buffer_size ?
534 conn->data->set.buffer_size : BUFSIZE);
538 if(conn->ssl[num].state == ssl_connection_complete) {
539 nread = Curl_ssl_recv(conn, num, buffertofill, bytesfromsocket);
542 return -1; /* -1 from Curl_ssl_recv() means EWOULDBLOCK */
545 else if(Curl_ssh_enabled(conn, (PROT_SCP|PROT_SFTP))) {
546 if(conn->protocol & PROT_SCP)
547 nread = Curl_scp_recv(conn, num, buffertofill, bytesfromsocket);
548 else if(conn->protocol & PROT_SFTP)
549 nread = Curl_sftp_recv(conn, num, buffertofill, bytesfromsocket);
550 #ifdef LIBSSH2CHANNEL_EAGAIN
551 if((nread == LIBSSH2CHANNEL_EAGAIN) || (nread == 0))
556 /* since it is negative and not EAGAIN, it was a protocol-layer error */
557 return CURLE_RECV_ERROR;
560 if(conn->sec_complete)
561 nread = Curl_sec_read(conn, sockfd, buffertofill,
563 /* TODO: Need to handle EAGAIN here somehow, similar to how it
564 * is done in Curl_read_plain, either right here or in Curl_sec_read
567 int ret = Curl_read_plain(sockfd, buffertofill, bytesfromsocket,
575 memcpy(buf, conn->master_buffer, nread);
576 conn->buf_len = nread;
577 conn->read_pos = nread;
586 /* return 0 on success */
587 static int showit(struct SessionHandle *data, curl_infotype type,
588 char *ptr, size_t size)
590 static const char s_infotype[CURLINFO_END][3] = {
591 "* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
593 #ifdef CURL_DOES_CONVERSIONS
595 size_t conv_size = 0;
598 case CURLINFO_HEADER_OUT:
599 /* assume output headers are ASCII */
600 /* copy the data into my buffer so the original is unchanged */
602 size = BUFSIZE; /* truncate if necessary */
606 memcpy(buf, ptr, size);
607 /* Special processing is needed for this block if it
608 * contains both headers and data (separated by CRLFCRLF).
609 * We want to convert just the headers, leaving the data as-is.
613 for(i = 0; i < size-4; i++) {
614 if(memcmp(&buf[i], "\x0d\x0a\x0d\x0a", 4) == 0) {
615 /* convert everthing through this CRLFCRLF but no further */
622 Curl_convert_from_network(data, buf, conv_size);
623 /* Curl_convert_from_network calls failf if unsuccessful */
624 /* we might as well continue even if it fails... */
625 ptr = buf; /* switch pointer to use my buffer instead */
628 /* leave everything else as-is */
631 #endif /* CURL_DOES_CONVERSIONS */
634 return (*data->set.fdebug)(data, type, ptr, size,
635 data->set.debugdata);
639 case CURLINFO_HEADER_OUT:
640 case CURLINFO_HEADER_IN:
641 fwrite(s_infotype[type], 2, 1, data->set.err);
642 fwrite(ptr, size, 1, data->set.err);
643 #ifdef CURL_DOES_CONVERSIONS
644 if(size != conv_size) {
645 /* we had untranslated data so we need an explicit newline */
646 fwrite("\n", 1, 1, data->set.err);
656 int Curl_debug(struct SessionHandle *data, curl_infotype type,
657 char *ptr, size_t size,
658 struct connectdata *conn)
661 if(data->set.printhost && conn && conn->host.dispname) {
664 const char *w="Data";
666 case CURLINFO_HEADER_IN:
668 case CURLINFO_DATA_IN:
671 case CURLINFO_HEADER_OUT:
673 case CURLINFO_DATA_OUT:
681 snprintf(buffer, sizeof(buffer), "[%s %s %s]", w, t,
682 conn->host.dispname);
683 rc = showit(data, CURLINFO_TEXT, buffer, strlen(buffer));
688 rc = showit(data, type, ptr, size);