1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2008, 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>
47 #define _MPRINTF_REPLACE /* use the internal *printf() functions */
48 #include <curl/mprintf.h>
50 #if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
53 #define Curl_sec_send(a,b,c,d) -1
54 #define Curl_sec_read(a,b,c,d) -1
60 #include "easyif.h" /* for the Curl_convert_from_network prototype */
61 /* The last #include file should be: */
64 /* returns last node in linked list */
65 static struct curl_slist *slist_get_last(struct curl_slist *list)
67 struct curl_slist *item;
69 /* if caller passed us a NULL, return now */
73 /* loop through to find the last item */
82 * curl_slist_append() appends a string to the linked list. It always returns
83 * the address of the first record, so that you can use this function as an
84 * initialization function as well as an append function. If you find this
85 * bothersome, then simply create a separate _init function and call it
86 * appropriately from within the program.
88 struct curl_slist *curl_slist_append(struct curl_slist *list,
91 struct curl_slist *last;
92 struct curl_slist *new_item;
94 new_item = (struct curl_slist *) malloc(sizeof(struct curl_slist));
96 char *dupdata = strdup(data);
98 new_item->next = NULL;
99 new_item->data = dupdata;
110 last = slist_get_last(list);
111 last->next = new_item;
115 /* if this is the first item, then new_item *is* the list */
119 /* be nice and clean up resources */
120 void curl_slist_free_all(struct curl_slist *list)
122 struct curl_slist *next;
123 struct curl_slist *item;
140 #ifdef CURL_DO_LINEEND_CONV
142 * convert_lineends() changes CRLF (\r\n) end-of-line markers to a single LF
143 * (\n), with special processing for CRLF sequences that are split between two
144 * blocks of data. Remaining, bare CRs are changed to LFs. The possibly new
145 * size of the data is returned.
147 static size_t convert_lineends(struct SessionHandle *data,
148 char *startPtr, size_t size)
150 char *inPtr, *outPtr;
153 if((startPtr == NULL) || (size < 1)) {
157 if(data->state.prev_block_had_trailing_cr == TRUE) {
158 /* The previous block of incoming data
159 had a trailing CR, which was turned into a LF. */
160 if(*startPtr == '\n') {
161 /* This block of incoming data starts with the
162 previous block's LF so get rid of it */
163 memmove(startPtr, startPtr+1, size-1);
165 /* and it wasn't a bare CR but a CRLF conversion instead */
166 data->state.crlf_conversions++;
168 data->state.prev_block_had_trailing_cr = FALSE; /* reset the flag */
171 /* find 1st CR, if any */
172 inPtr = outPtr = memchr(startPtr, '\r', size);
174 /* at least one CR, now look for CRLF */
175 while(inPtr < (startPtr+size-1)) {
176 /* note that it's size-1, so we'll never look past the last byte */
177 if(memcmp(inPtr, "\r\n", 2) == 0) {
178 /* CRLF found, bump past the CR and copy the NL */
181 /* keep track of how many CRLFs we converted */
182 data->state.crlf_conversions++;
186 /* lone CR, move LF instead */
190 /* not a CRLF nor a CR, just copy whatever it is */
196 } /* end of while loop */
198 if(inPtr < startPtr+size) {
199 /* handle last byte */
201 /* deal with a CR at the end of the buffer */
202 *outPtr = '\n'; /* copy a NL instead */
203 /* note that a CRLF might be split across two blocks */
204 data->state.prev_block_had_trailing_cr = TRUE;
213 if(outPtr < startPtr+size) {
214 /* tidy up by null terminating the now shorter data */
217 return(outPtr - startPtr);
221 #endif /* CURL_DO_LINEEND_CONV */
223 /* Curl_infof() is for info message along the way */
225 void Curl_infof(struct SessionHandle *data, const char *fmt, ...)
227 if(data && data->set.verbose) {
230 char print_buffer[2048 + 1];
232 vsnprintf(print_buffer, sizeof(print_buffer), fmt, ap);
234 len = strlen(print_buffer);
235 Curl_debug(data, CURLINFO_TEXT, print_buffer, len, NULL);
239 /* Curl_failf() is for messages stating why we failed.
240 * The message SHALL NOT include any LF or CR.
243 void Curl_failf(struct SessionHandle *data, const char *fmt, ...)
249 vsnprintf(data->state.buffer, BUFSIZE, fmt, ap);
251 if(data->set.errorbuffer && !data->state.errorbuf) {
252 snprintf(data->set.errorbuffer, CURL_ERROR_SIZE, "%s", data->state.buffer);
253 data->state.errorbuf = TRUE; /* wrote error string */
255 if(data->set.verbose) {
256 len = strlen(data->state.buffer);
257 if(len < BUFSIZE - 1) {
258 data->state.buffer[len] = '\n';
259 data->state.buffer[++len] = '\0';
261 Curl_debug(data, CURLINFO_TEXT, data->state.buffer, len, NULL);
267 /* Curl_sendf() sends formated data to the server */
268 CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *conn,
269 const char *fmt, ...)
271 struct SessionHandle *data = conn->data;
272 ssize_t bytes_written;
274 CURLcode res = CURLE_OK;
279 s = vaprintf(fmt, ap); /* returns an allocated string */
282 return CURLE_OUT_OF_MEMORY; /* failure */
285 write_len = strlen(s);
289 /* Write the buffer to the socket */
290 res = Curl_write(conn, sockfd, sptr, write_len, &bytes_written);
295 if(data->set.verbose)
296 Curl_debug(data, CURLINFO_DATA_OUT, sptr, (size_t)bytes_written, conn);
298 if((size_t)bytes_written != write_len) {
299 /* if not all was written at once, we must advance the pointer, decrease
300 the size left and try again! */
301 write_len -= bytes_written;
302 sptr += bytes_written;
308 free(s); /* free the output string */
313 static ssize_t send_plain(struct connectdata *conn,
318 curl_socket_t sockfd = conn->sock[num];
319 ssize_t bytes_written = swrite(sockfd, mem, len);
321 if(-1 == bytes_written) {
325 #ifdef WSAEWOULDBLOCK
326 /* This is how Windows does it */
327 (WSAEWOULDBLOCK == err)
329 /* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned
330 due to its inability to send off data without blocking. We therefor
331 treat both error codes the same here */
332 (EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err)
335 /* this is just a case of EWOULDBLOCK */
338 failf(conn->data, "Send failure: %s",
339 Curl_strerror(conn, err));
341 return bytes_written;
345 * Curl_write() is an internal write function that sends data to the
346 * server. Works with plain sockets, SCP, SSL or kerberos.
348 CURLcode Curl_write(struct connectdata *conn,
349 curl_socket_t sockfd,
354 ssize_t bytes_written;
356 int num = (sockfd == conn->sock[SECONDARYSOCKET]);
358 if(conn->ssl[num].state == ssl_connection_complete)
359 bytes_written = Curl_ssl_send(conn, num, mem, len);
360 else if(Curl_ssh_enabled(conn, PROT_SCP))
361 bytes_written = Curl_scp_send(conn, num, mem, len);
362 else if(Curl_ssh_enabled(conn, PROT_SFTP))
363 bytes_written = Curl_sftp_send(conn, num, mem, len);
364 else if(conn->sec_complete)
365 bytes_written = Curl_sec_send(conn, num, mem, len);
367 bytes_written = send_plain(conn, num, mem, len);
369 *written = bytes_written;
370 retcode = (-1 != bytes_written)?CURLE_OK:CURLE_SEND_ERROR;
376 * Curl_write_plain() is an internal write function that sends data to the
377 * server using plain sockets only. Otherwise meant to have the exact same
378 * proto as Curl_write()
380 CURLcode Curl_write_plain(struct connectdata *conn,
381 curl_socket_t sockfd,
386 ssize_t bytes_written;
388 int num = (sockfd == conn->sock[SECONDARYSOCKET]);
390 bytes_written = send_plain(conn, num, mem, len);
392 *written = bytes_written;
393 retcode = (-1 != bytes_written)?CURLE_OK:CURLE_SEND_ERROR;
398 static CURLcode pausewrite(struct SessionHandle *data,
399 int type, /* what type of data */
403 /* signalled to pause sending on this connection, but since we have data
404 we want to send we need to dup it to save a copy for when the sending
406 struct SingleRequest *k = &data->req;
407 char *dupl = malloc(len);
409 return CURLE_OUT_OF_MEMORY;
411 memcpy(dupl, ptr, len);
413 /* store this information in the state struct for later use */
414 data->state.tempwrite = dupl;
415 data->state.tempwritesize = len;
416 data->state.tempwritetype = type;
418 /* mark the connection as RECV paused */
419 k->keepon |= KEEP_READ_PAUSE;
421 DEBUGF(infof(data, "Pausing with %d bytes in buffer for type %02x\n",
428 /* client_write() sends data to the write callback(s)
430 The bit pattern defines to what "streams" to write to. Body and/or header.
431 The defines are in sendf.h of course.
433 If CURL_DO_LINEEND_CONV is enabled, data is converted IN PLACE to the
434 local character encoding. This is a problem and should be changed in
435 the future to leave the original data alone.
437 CURLcode Curl_client_write(struct connectdata *conn,
442 struct SessionHandle *data = conn->data;
445 /* If reading is actually paused, we're forced to append this chunk of data
446 to the already held data, but only if it is the same type as otherwise it
447 can't work and it'll return error instead. */
448 if(data->req.keepon & KEEP_READ_PAUSE) {
451 if(type != data->state.tempwritetype)
452 /* major internal confusion */
453 return CURLE_RECV_ERROR;
455 /* figure out the new size of the data to save */
456 newlen = len + data->state.tempwritesize;
457 /* allocate the new memory area */
458 newptr = malloc(newlen);
460 return CURLE_OUT_OF_MEMORY;
461 /* copy the previously held data to the new area */
462 memcpy(newptr, data->state.tempwrite, data->state.tempwritesize);
463 /* copy the new data to the end of the new area */
464 memcpy(newptr + data->state.tempwritesize, ptr, len);
465 /* free the old data */
466 free(data->state.tempwrite);
467 /* update the pointer and the size */
468 data->state.tempwrite = newptr;
469 data->state.tempwritesize = newlen;
477 if(type & CLIENTWRITE_BODY) {
478 if((conn->protocol&PROT_FTP) && conn->proto.ftpc.transfertype == 'A') {
479 #ifdef CURL_DOES_CONVERSIONS
480 /* convert from the network encoding */
482 rc = Curl_convert_from_network(data, ptr, len);
483 /* Curl_convert_from_network calls failf if unsuccessful */
486 #endif /* CURL_DOES_CONVERSIONS */
488 #ifdef CURL_DO_LINEEND_CONV
489 /* convert end-of-line markers */
490 len = convert_lineends(data, ptr, len);
491 #endif /* CURL_DO_LINEEND_CONV */
493 /* If the previous block of data ended with CR and this block of data is
494 just a NL, then the length might be zero */
496 wrote = data->set.fwrite_func(ptr, 1, len, data->set.out);
502 if(CURL_WRITEFUNC_PAUSE == wrote)
503 return pausewrite(data, type, ptr, len);
506 failf(data, "Failed writing body (%d != %d)", (int)wrote, (int)len);
507 return CURLE_WRITE_ERROR;
511 if((type & CLIENTWRITE_HEADER) &&
512 (data->set.fwrite_header || data->set.writeheader) ) {
514 * Write headers to the same callback or to the especially setup
515 * header callback function (added after version 7.7.1).
517 curl_write_callback writeit=
518 data->set.fwrite_header?data->set.fwrite_header:data->set.fwrite_func;
520 /* Note: The header is in the host encoding
521 regardless of the ftp transfer mode (ASCII/Image) */
523 wrote = writeit(ptr, 1, len, data->set.writeheader);
524 if(CURL_WRITEFUNC_PAUSE == wrote)
525 /* here we pass in the HEADER bit only since if this was body as well
526 then it was passed already and clearly that didn't trigger the pause,
527 so this is saved for later with the HEADER bit only */
528 return pausewrite(data, CLIENTWRITE_HEADER, ptr, len);
531 failf (data, "Failed writing header");
532 return CURLE_WRITE_ERROR;
540 #define MIN(a,b) ((a) < (b) ? (a) : (b))
544 * Internal read-from-socket function. This is meant to deal with plain
545 * sockets, SSL sockets and kerberos sockets.
547 * If the read would block (EWOULDBLOCK) we return -1. Otherwise we return
548 * a regular CURLcode value.
550 int Curl_read(struct connectdata *conn, /* connection data */
551 curl_socket_t sockfd, /* read from this socket */
552 char *buf, /* store read data here */
553 size_t sizerequested, /* max amount to read */
554 ssize_t *n) /* amount bytes read */
557 size_t bytesfromsocket = 0;
558 char *buffertofill = NULL;
559 bool pipelining = (bool)(conn->data->multi &&
560 Curl_multi_canPipeline(conn->data->multi));
562 /* Set 'num' to 0 or 1, depending on which socket that has been sent here.
563 If it is the second socket, we set num to 1. Otherwise to 0. This lets
564 us use the correct ssl handle. */
565 int num = (sockfd == conn->sock[SECONDARYSOCKET]);
567 *n=0; /* reset amount to zero */
569 /* If session can pipeline, check connection buffer */
571 size_t bytestocopy = MIN(conn->buf_len - conn->read_pos, sizerequested);
573 /* Copy from our master buffer first if we have some unread data there*/
574 if(bytestocopy > 0) {
575 memcpy(buf, conn->master_buffer + conn->read_pos, bytestocopy);
576 conn->read_pos += bytestocopy;
577 conn->bits.stream_was_rewound = FALSE;
579 *n = (ssize_t)bytestocopy;
582 /* If we come here, it means that there is no data to read from the buffer,
583 * so we read from the socket */
584 bytesfromsocket = MIN(sizerequested, BUFSIZE * sizeof (char));
585 buffertofill = conn->master_buffer;
588 bytesfromsocket = MIN((long)sizerequested, conn->data->set.buffer_size ?
589 conn->data->set.buffer_size : BUFSIZE);
593 if(conn->ssl[num].state == ssl_connection_complete) {
594 nread = Curl_ssl_recv(conn, num, buffertofill, bytesfromsocket);
597 return -1; /* -1 from Curl_ssl_recv() means EWOULDBLOCK */
600 else if(Curl_ssh_enabled(conn, (PROT_SCP|PROT_SFTP))) {
601 if(conn->protocol & PROT_SCP)
602 nread = Curl_scp_recv(conn, num, buffertofill, bytesfromsocket);
603 else if(conn->protocol & PROT_SFTP)
604 nread = Curl_sftp_recv(conn, num, buffertofill, bytesfromsocket);
605 #ifdef LIBSSH2CHANNEL_EAGAIN
606 if((nread == LIBSSH2CHANNEL_EAGAIN) || (nread == 0))
611 /* since it is negative and not EGAIN, it was a protocol-layer error */
612 return CURLE_RECV_ERROR;
615 if(conn->sec_complete)
616 nread = Curl_sec_read(conn, sockfd, buffertofill,
619 nread = sread(sockfd, buffertofill, bytesfromsocket);
624 if(WSAEWOULDBLOCK == err)
626 if((EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err))
634 memcpy(buf, conn->master_buffer, nread);
635 conn->buf_len = nread;
636 conn->read_pos = nread;
645 /* return 0 on success */
646 static int showit(struct SessionHandle *data, curl_infotype type,
647 char *ptr, size_t size)
649 static const char * const s_infotype[CURLINFO_END] = {
650 "* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
652 #ifdef CURL_DOES_CONVERSIONS
654 size_t conv_size = 0;
657 case CURLINFO_HEADER_OUT:
658 /* assume output headers are ASCII */
659 /* copy the data into my buffer so the original is unchanged */
661 size = BUFSIZE; /* truncate if necessary */
665 memcpy(buf, ptr, size);
666 /* Special processing is needed for this block if it
667 * contains both headers and data (separated by CRLFCRLF).
668 * We want to convert just the headers, leaving the data as-is.
672 for(i = 0; i < size-4; i++) {
673 if(memcmp(&buf[i], "\x0d\x0a\x0d\x0a", 4) == 0) {
674 /* convert everthing through this CRLFCRLF but no further */
681 Curl_convert_from_network(data, buf, conv_size);
682 /* Curl_convert_from_network calls failf if unsuccessful */
683 /* we might as well continue even if it fails... */
684 ptr = buf; /* switch pointer to use my buffer instead */
687 /* leave everything else as-is */
690 #endif /* CURL_DOES_CONVERSIONS */
693 return (*data->set.fdebug)(data, type, ptr, size,
694 data->set.debugdata);
698 case CURLINFO_HEADER_OUT:
699 case CURLINFO_HEADER_IN:
700 fwrite(s_infotype[type], 2, 1, data->set.err);
701 fwrite(ptr, size, 1, data->set.err);
702 #ifdef CURL_DOES_CONVERSIONS
703 if(size != conv_size) {
704 /* we had untranslated data so we need an explicit newline */
705 fwrite("\n", 1, 1, data->set.err);
715 int Curl_debug(struct SessionHandle *data, curl_infotype type,
716 char *ptr, size_t size,
717 struct connectdata *conn)
720 if(data->set.printhost && conn && conn->host.dispname) {
723 const char *w="Data";
725 case CURLINFO_HEADER_IN:
727 case CURLINFO_DATA_IN:
730 case CURLINFO_HEADER_OUT:
732 case CURLINFO_DATA_OUT:
740 snprintf(buffer, sizeof(buffer), "[%s %s %s]", w, t,
741 conn->host.dispname);
742 rc = showit(data, CURLINFO_TEXT, buffer, strlen(buffer));
747 rc = showit(data, type, ptr, size);