1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2006, 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_TYPES_H
32 #include <sys/types.h>
35 #ifdef HAVE_SYS_SOCKET_H
36 #include <sys/socket.h> /* required for send() & recv() prototypes */
43 #include <curl/curl.h>
46 #include "connect.h" /* for the Curl_sockerrno() proto */
49 #define _MPRINTF_REPLACE /* use the internal *printf() functions */
50 #include <curl/mprintf.h>
55 #define Curl_sec_write(a,b,c,d) -1
56 #define Curl_sec_read(a,b,c,d) -1
62 #include "easyif.h" /* for the Curl_convert_from_network prototype */
63 /* The last #include file should be: */
66 /* returns last node in linked list */
67 static struct curl_slist *slist_get_last(struct curl_slist *list)
69 struct curl_slist *item;
71 /* if caller passed us a NULL, return now */
75 /* loop through to find the last item */
84 * curl_slist_append() appends a string to the linked list. It always retunrs
85 * the address of the first record, so that you can sure this function as an
86 * initialization function as well as an append function. If you find this
87 * bothersome, then simply create a separate _init function and call it
88 * appropriately from within the proram.
90 struct curl_slist *curl_slist_append(struct curl_slist *list,
93 struct curl_slist *last;
94 struct curl_slist *new_item;
96 new_item = (struct curl_slist *) malloc(sizeof(struct curl_slist));
98 char *dup = strdup(data);
100 new_item->next = NULL;
101 new_item->data = dup;
112 last = slist_get_last(list);
113 last->next = new_item;
117 /* if this is the first item, then new_item *is* the list */
121 /* be nice and clean up resources */
122 void curl_slist_free_all(struct curl_slist *list)
124 struct curl_slist *next;
125 struct curl_slist *item;
142 #ifdef CURL_DO_LINEEND_CONV
144 * convert_lineends() changes CRLF (\r\n) end-of-line markers to a single LF
145 * (\n), with special processing for CRLF sequences that are split between two
146 * blocks of data. Remaining, bare CRs are changed to LFs. The possibly new
147 * size of the data is returned.
149 static size_t convert_lineends(struct SessionHandle *data,
150 char *startPtr, size_t size)
152 char *inPtr, *outPtr;
155 if ((startPtr == NULL) || (size < 1)) {
159 if (data->state.prev_block_had_trailing_cr == TRUE) {
160 /* The previous block of incoming data
161 had a trailing CR, which was turned into a LF. */
162 if (*startPtr == '\n') {
163 /* This block of incoming data starts with the
164 previous block's LF so get rid of it */
165 memcpy(startPtr, startPtr+1, size-1);
167 /* and it wasn't a bare CR but a CRLF conversion instead */
168 data->state.crlf_conversions++;
170 data->state.prev_block_had_trailing_cr = FALSE; /* reset the flag */
173 /* find 1st CR, if any */
174 inPtr = outPtr = memchr(startPtr, '\r', size);
176 /* at least one CR, now look for CRLF */
177 while (inPtr < (startPtr+size-1)) {
178 /* note that it's size-1, so we'll never look past the last byte */
179 if (memcmp(inPtr, "\r\n", 2) == 0) {
180 /* CRLF found, bump past the CR and copy the NL */
183 /* keep track of how many CRLFs we converted */
184 data->state.crlf_conversions++;
187 if (*inPtr == '\r') {
188 /* lone CR, move LF instead */
192 /* not a CRLF nor a CR, just copy whatever it is */
198 } /* end of while loop */
200 if (inPtr < startPtr+size) {
201 /* handle last byte */
202 if (*inPtr == '\r') {
203 /* deal with a CR at the end of the buffer */
204 *outPtr = '\n'; /* copy a NL instead */
205 /* note that a CRLF might be split across two blocks */
206 data->state.prev_block_had_trailing_cr = TRUE;
215 if (outPtr < startPtr+size) {
216 /* tidy up by null terminating the now shorter data */
219 return(outPtr - startPtr);
223 #endif /* CURL_DO_LINEEND_CONV */
225 /* Curl_infof() is for info message along the way */
227 void Curl_infof(struct SessionHandle *data, const char *fmt, ...)
229 if(data && data->set.verbose) {
232 char print_buffer[1024 + 1];
234 vsnprintf(print_buffer, 1024, fmt, ap);
236 len = strlen(print_buffer);
237 Curl_debug(data, CURLINFO_TEXT, print_buffer, len, NULL);
241 /* Curl_failf() is for messages stating why we failed.
242 * The message SHALL NOT include any LF or CR.
245 void Curl_failf(struct SessionHandle *data, const char *fmt, ...)
251 vsnprintf(data->state.buffer, BUFSIZE, fmt, ap);
253 if(data->set.errorbuffer && !data->state.errorbuf) {
254 snprintf(data->set.errorbuffer, CURL_ERROR_SIZE, "%s", data->state.buffer);
255 data->state.errorbuf = TRUE; /* wrote error string */
257 if(data->set.verbose) {
258 len = strlen(data->state.buffer);
259 if(len < BUFSIZE - 1) {
260 data->state.buffer[len] = '\n';
261 data->state.buffer[++len] = '\0';
263 Curl_debug(data, CURLINFO_TEXT, data->state.buffer, len, NULL);
269 /* Curl_sendf() sends formated data to the server */
270 CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *conn,
271 const char *fmt, ...)
273 struct SessionHandle *data = conn->data;
274 ssize_t bytes_written;
276 CURLcode res = CURLE_OK;
281 s = vaprintf(fmt, ap); /* returns an allocated string */
284 return CURLE_OUT_OF_MEMORY; /* failure */
287 write_len = strlen(s);
291 /* Write the buffer to the socket */
292 res = Curl_write(conn, sockfd, sptr, write_len, &bytes_written);
297 if(data->set.verbose)
298 Curl_debug(data, CURLINFO_DATA_OUT, sptr, (size_t)bytes_written, conn);
300 if((size_t)bytes_written != write_len) {
301 /* if not all was written at once, we must advance the pointer, decrease
302 the size left and try again! */
303 write_len -= bytes_written;
304 sptr += bytes_written;
310 free(s); /* free the output string */
316 * Curl_write() is an internal write function that sends plain (binary) data
317 * to the server. Works with plain sockets, SSL or kerberos.
319 CURLcode Curl_write(struct connectdata *conn,
320 curl_socket_t sockfd,
325 ssize_t bytes_written;
327 int num = (sockfd == conn->sock[SECONDARYSOCKET]);
329 if (conn->ssl[num].use)
330 /* only TRUE if SSL enabled */
331 bytes_written = Curl_ssl_send(conn, num, mem, len);
333 if(conn->sec_complete)
334 /* only TRUE if krb4 enabled */
335 bytes_written = Curl_sec_write(conn, sockfd, mem, len);
337 bytes_written = swrite(sockfd, mem, len);
339 if(-1 == bytes_written) {
340 int err = Curl_sockerrno();
343 #ifdef WSAEWOULDBLOCK
344 /* This is how Windows does it */
345 (WSAEWOULDBLOCK == err)
347 /* As pointed out by Christophe Demory on March 11 2003, errno
348 may be EWOULDBLOCK or on some systems EAGAIN when it returned
349 due to its inability to send off data without blocking. We
350 therefor treat both error codes the same here */
351 (EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err)
354 /* this is just a case of EWOULDBLOCK */
357 failf(conn->data, "Send failure: %s",
358 Curl_strerror(conn, err));
361 *written = bytes_written;
362 retcode = (-1 != bytes_written)?CURLE_OK:CURLE_SEND_ERROR;
367 /* client_write() sends data to the write callback(s)
369 The bit pattern defines to what "streams" to write to. Body and/or header.
370 The defines are in sendf.h of course.
372 CURLcode Curl_client_write(struct connectdata *conn,
377 struct SessionHandle *data = conn->data;
380 if (data->state.cancelled) {
381 /* We just suck everything into a black hole */
388 if(type & CLIENTWRITE_BODY) {
389 if((conn->protocol&PROT_FTP) && conn->proto.ftpc.transfertype == 'A') {
390 #ifdef CURL_DOES_CONVERSIONS
391 /* convert from the network encoding */
393 rc = Curl_convert_from_network(data, ptr, len);
394 /* Curl_convert_from_network calls failf if unsuccessful */
397 #endif /* CURL_DOES_CONVERSIONS */
399 #ifdef CURL_DO_LINEEND_CONV
400 /* convert end-of-line markers */
401 len = convert_lineends(data, ptr, len);
402 #endif /* CURL_DO_LINEEND_CONV */
404 /* If the previous block of data ended with CR and this block of data is
405 just a NL, then the length might be zero */
407 wrote = data->set.fwrite(ptr, 1, len, data->set.out);
414 failf (data, "Failed writing body");
415 return CURLE_WRITE_ERROR;
419 if((type & CLIENTWRITE_HEADER) &&
420 (data->set.fwrite_header || data->set.writeheader) ) {
422 * Write headers to the same callback or to the especially setup
423 * header callback function (added after version 7.7.1).
425 curl_write_callback writeit=
426 data->set.fwrite_header?data->set.fwrite_header:data->set.fwrite;
428 /* Note: The header is in the host encoding
429 regardless of the ftp transfer mode (ASCII/Image) */
431 wrote = writeit(ptr, 1, len, data->set.writeheader);
433 failf (data, "Failed writing header");
434 return CURLE_WRITE_ERROR;
441 void Curl_read_rewind(struct connectdata *conn,
442 size_t extraBytesRead)
444 conn->read_pos -= extraBytesRead;
445 conn->bits.stream_was_rewound = TRUE;
448 #define MIN(a,b) (a < b ? a : b)
451 * Internal read-from-socket function. This is meant to deal with plain
452 * sockets, SSL sockets and kerberos sockets.
454 * If the read would block (EWOULDBLOCK) we return -1. Otherwise we return
455 * a regular CURLcode value.
457 int Curl_read(struct connectdata *conn, /* connection data */
458 curl_socket_t sockfd, /* read from this socket */
459 char *buf, /* store read data here */
460 size_t buffersize, /* max amount to read */
461 ssize_t *n) /* amount bytes read */
464 size_t bytestocopy = MIN(conn->buf_len - conn->read_pos, buffersize);
465 size_t bytesremaining = buffersize - bytestocopy;
467 /* Set 'num' to 0 or 1, depending on which socket that has been sent here.
468 If it is the second socket, we set num to 1. Otherwise to 0. This lets
469 us use the correct ssl handle. */
470 int num = (sockfd == conn->sock[SECONDARYSOCKET]);
472 *n=0; /* reset amount to zero */
474 bytesremaining = MIN(bytesremaining, sizeof(conn->master_buffer));
476 /* Copy from our master buffer first */
477 memcpy(buf, conn->master_buffer + conn->read_pos, bytestocopy);
478 conn->read_pos += bytestocopy;
480 conn->bits.stream_was_rewound = FALSE;
482 *n = (ssize_t)bytestocopy;
484 if (bytesremaining == 0) {
488 if(conn->ssl[num].use) {
489 nread = Curl_ssl_recv(conn, num, conn->master_buffer, bytesremaining);
491 if(nread == -1 && bytestocopy == 0) {
492 return -1; /* -1 from Curl_ssl_recv() means EWOULDBLOCK */
496 if(conn->sec_complete)
497 nread = Curl_sec_read(conn, sockfd, conn->master_buffer, bytesremaining);
499 nread = sread(sockfd, conn->master_buffer, bytesremaining);
501 if(-1 == nread && bytestocopy == 0) {
502 int err = Curl_sockerrno();
504 if(WSAEWOULDBLOCK == err)
506 if((EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err))
513 memcpy(buf, conn->master_buffer, nread);
515 conn->buf_len = nread;
516 conn->read_pos = nread;
523 /* return 0 on success */
524 static int showit(struct SessionHandle *data, curl_infotype type,
525 char *ptr, size_t size)
527 static const char * const s_infotype[CURLINFO_END] = {
528 "* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
530 #ifdef CURL_DOES_CONVERSIONS
534 case CURLINFO_HEADER_OUT:
535 /* assume output headers are ASCII */
536 /* copy the data into my buffer so the original is unchanged */
537 if (size > BUFSIZE) {
538 size = BUFSIZE; /* truncate if necessary */
541 memcpy(buf, ptr, size);
542 Curl_convert_from_network(data, buf, size);
543 /* Curl_convert_from_network calls failf if unsuccessful */
544 /* we might as well continue even if it fails... */
545 ptr = buf; /* switch pointer to use my buffer instead */
548 /* leave everything else as-is */
551 #endif /* CURL_DOES_CONVERSIONS */
554 return (*data->set.fdebug)(data, type, ptr, size,
555 data->set.debugdata);
559 case CURLINFO_HEADER_OUT:
560 case CURLINFO_HEADER_IN:
561 fwrite(s_infotype[type], 2, 1, data->set.err);
562 fwrite(ptr, size, 1, data->set.err);
570 int Curl_debug(struct SessionHandle *data, curl_infotype type,
571 char *ptr, size_t size,
572 struct connectdata *conn)
575 if(data->set.printhost && conn && conn->host.dispname) {
578 const char *w="Data";
580 case CURLINFO_HEADER_IN:
582 case CURLINFO_DATA_IN:
585 case CURLINFO_HEADER_OUT:
587 case CURLINFO_DATA_OUT:
595 snprintf(buffer, sizeof(buffer), "[%s %s %s]", w, t,
596 conn->host.dispname);
597 rc = showit(data, CURLINFO_TEXT, buffer, strlen(buffer));
602 rc = showit(data, type, ptr, size);