Resync
[CMakeLuaTailorHgBridge.git] / CMakeLua / Utilities / cmcurl-7.19.0 / lib / sendf.c
blobe8f33de2ea3831f1a1ea50541fa8f0655943a418
1 /***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
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.
21 * $Id: sendf.c,v 1.1.1.1 2008-09-23 16:32:05 hoffman Exp $
22 ***************************************************************************/
24 #include "setup.h"
26 #include <stdio.h>
27 #include <stdarg.h>
28 #include <stdlib.h>
29 #include <errno.h>
31 #ifdef HAVE_SYS_SOCKET_H
32 #include <sys/socket.h> /* required for send() & recv() prototypes */
33 #endif
35 #ifdef HAVE_UNISTD_H
36 #include <unistd.h>
37 #endif
39 #include <curl/curl.h>
40 #include "urldata.h"
41 #include "sendf.h"
42 #include "connect.h"
43 #include "sslgen.h"
44 #include "ssh.h"
45 #include "multiif.h"
47 #define _MPRINTF_REPLACE /* use the internal *printf() functions */
48 #include <curl/mprintf.h>
50 #if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
51 #include "krb4.h"
52 #else
53 #define Curl_sec_send(a,b,c,d) -1
54 #define Curl_sec_read(a,b,c,d) -1
55 #endif
57 #include <string.h>
58 #include "memory.h"
59 #include "strerror.h"
60 #include "easyif.h" /* for the Curl_convert_from_network prototype */
61 /* The last #include file should be: */
62 #include "memdebug.h"
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 */
70 if(!list)
71 return NULL;
73 /* loop through to find the last item */
74 item = list;
75 while(item->next) {
76 item = item->next;
78 return 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,
89 const char *data)
91 struct curl_slist *last;
92 struct curl_slist *new_item;
94 new_item = (struct curl_slist *) malloc(sizeof(struct curl_slist));
95 if(new_item) {
96 char *dupdata = strdup(data);
97 if(dupdata) {
98 new_item->next = NULL;
99 new_item->data = dupdata;
101 else {
102 free(new_item);
103 return NULL;
106 else
107 return NULL;
109 if(list) {
110 last = slist_get_last(list);
111 last->next = new_item;
112 return list;
115 /* if this is the first item, then new_item *is* the list */
116 return new_item;
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;
125 if(!list)
126 return;
128 item = list;
129 do {
130 next = item->next;
132 if(item->data) {
133 free(item->data);
135 free(item);
136 item = next;
137 } while(next);
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;
152 /* sanity check */
153 if((startPtr == NULL) || (size < 1)) {
154 return(size);
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);
164 size--;
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);
173 if(inPtr) {
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 */
179 inPtr++;
180 *outPtr = *inPtr;
181 /* keep track of how many CRLFs we converted */
182 data->state.crlf_conversions++;
184 else {
185 if(*inPtr == '\r') {
186 /* lone CR, move LF instead */
187 *outPtr = '\n';
189 else {
190 /* not a CRLF nor a CR, just copy whatever it is */
191 *outPtr = *inPtr;
194 outPtr++;
195 inPtr++;
196 } /* end of while loop */
198 if(inPtr < startPtr+size) {
199 /* handle last byte */
200 if(*inPtr == '\r') {
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;
206 else {
207 /* copy last byte */
208 *outPtr = *inPtr;
210 outPtr++;
211 inPtr++;
213 if(outPtr < startPtr+size) {
214 /* tidy up by null terminating the now shorter data */
215 *outPtr = '\0';
217 return(outPtr - startPtr);
219 return(size);
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) {
228 va_list ap;
229 size_t len;
230 char print_buffer[1024 + 1];
231 va_start(ap, fmt);
232 vsnprintf(print_buffer, 1024, fmt, ap);
233 va_end(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, ...)
245 va_list ap;
246 size_t len;
247 va_start(ap, 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);
264 va_end(ap);
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;
273 size_t write_len;
274 CURLcode res = CURLE_OK;
275 char *s;
276 char *sptr;
277 va_list ap;
278 va_start(ap, fmt);
279 s = vaprintf(fmt, ap); /* returns an allocated string */
280 va_end(ap);
281 if(!s)
282 return CURLE_OUT_OF_MEMORY; /* failure */
284 bytes_written=0;
285 write_len = strlen(s);
286 sptr = s;
288 while(1) {
289 /* Write the buffer to the socket */
290 res = Curl_write(conn, sockfd, sptr, write_len, &bytes_written);
292 if(CURLE_OK != res)
293 break;
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;
304 else
305 break;
308 free(s); /* free the output string */
310 return res;
313 static ssize_t send_plain(struct connectdata *conn,
314 int num,
315 const void *mem,
316 size_t len)
318 curl_socket_t sockfd = conn->sock[num];
319 ssize_t bytes_written = swrite(sockfd, mem, len);
321 if(-1 == bytes_written) {
322 int err = SOCKERRNO;
325 #ifdef WSAEWOULDBLOCK
326 /* This is how Windows does it */
327 (WSAEWOULDBLOCK == err)
328 #else
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)
333 #endif
335 /* this is just a case of EWOULDBLOCK */
336 bytes_written=0;
337 else
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,
350 const void *mem,
351 size_t len,
352 ssize_t *written)
354 ssize_t bytes_written;
355 CURLcode retcode;
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);
366 else
367 bytes_written = send_plain(conn, num, mem, len);
369 *written = bytes_written;
370 retcode = (-1 != bytes_written)?CURLE_OK:CURLE_SEND_ERROR;
372 return retcode;
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,
382 const void *mem,
383 size_t len,
384 ssize_t *written)
386 ssize_t bytes_written;
387 CURLcode retcode;
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;
395 return retcode;
398 static CURLcode pausewrite(struct SessionHandle *data,
399 int type, /* what type of data */
400 char *ptr,
401 size_t len)
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
405 is again enabled */
406 struct SingleRequest *k = &data->req;
407 char *dupl = malloc(len);
408 if(!dupl)
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",
422 (int)len, type));
424 return CURLE_OK;
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 CURLcode Curl_client_write(struct connectdata *conn,
434 int type,
435 char *ptr,
436 size_t len)
438 struct SessionHandle *data = conn->data;
439 size_t wrote;
441 /* If reading is actually paused, we're forced to append this chunk of data
442 to the already held data, but only if it is the same type as otherwise it
443 can't work and it'll return error instead. */
444 if(data->req.keepon & KEEP_READ_PAUSE) {
445 size_t newlen;
446 char *newptr;
447 if(type != data->state.tempwritetype)
448 /* major internal confusion */
449 return CURLE_RECV_ERROR;
451 /* figure out the new size of the data to save */
452 newlen = len + data->state.tempwritesize;
453 /* allocate the new memory area */
454 newptr = malloc(newlen);
455 if(!newptr)
456 return CURLE_OUT_OF_MEMORY;
457 /* copy the previously held data to the new area */
458 memcpy(newptr, data->state.tempwrite, data->state.tempwritesize);
459 /* copy the new data to the end of the new area */
460 memcpy(newptr + data->state.tempwritesize, ptr, len);
461 /* free the old data */
462 free(data->state.tempwrite);
463 /* update the pointer and the size */
464 data->state.tempwrite = newptr;
465 data->state.tempwritesize = newlen;
467 return CURLE_OK;
470 if(0 == len)
471 len = strlen(ptr);
473 if(type & CLIENTWRITE_BODY) {
474 if((conn->protocol&PROT_FTP) && conn->proto.ftpc.transfertype == 'A') {
475 #ifdef CURL_DOES_CONVERSIONS
476 /* convert from the network encoding */
477 size_t rc;
478 rc = Curl_convert_from_network(data, ptr, len);
479 /* Curl_convert_from_network calls failf if unsuccessful */
480 if(rc != CURLE_OK)
481 return rc;
482 #endif /* CURL_DOES_CONVERSIONS */
484 #ifdef CURL_DO_LINEEND_CONV
485 /* convert end-of-line markers */
486 len = convert_lineends(data, ptr, len);
487 #endif /* CURL_DO_LINEEND_CONV */
489 /* If the previous block of data ended with CR and this block of data is
490 just a NL, then the length might be zero */
491 if(len) {
492 wrote = data->set.fwrite_func(ptr, 1, len, data->set.out);
494 else {
495 wrote = len;
498 if(CURL_WRITEFUNC_PAUSE == wrote)
499 return pausewrite(data, type, ptr, len);
501 if(wrote != len) {
502 failf(data, "Failed writing body (%d != %d)", (int)wrote, (int)len);
503 return CURLE_WRITE_ERROR;
507 if((type & CLIENTWRITE_HEADER) &&
508 (data->set.fwrite_header || data->set.writeheader) ) {
510 * Write headers to the same callback or to the especially setup
511 * header callback function (added after version 7.7.1).
513 curl_write_callback writeit=
514 data->set.fwrite_header?data->set.fwrite_header:data->set.fwrite_func;
516 /* Note: The header is in the host encoding
517 regardless of the ftp transfer mode (ASCII/Image) */
519 wrote = writeit(ptr, 1, len, data->set.writeheader);
520 if(CURL_WRITEFUNC_PAUSE == wrote)
521 /* here we pass in the HEADER bit only since if this was body as well
522 then it was passed already and clearly that didn't trigger the pause,
523 so this is saved for later with the HEADER bit only */
524 return pausewrite(data, CLIENTWRITE_HEADER, ptr, len);
526 if(wrote != len) {
527 failf (data, "Failed writing header");
528 return CURLE_WRITE_ERROR;
532 return CURLE_OK;
535 #ifndef MIN
536 #define MIN(a,b) ((a) < (b) ? (a) : (b))
537 #endif
540 * Internal read-from-socket function. This is meant to deal with plain
541 * sockets, SSL sockets and kerberos sockets.
543 * If the read would block (EWOULDBLOCK) we return -1. Otherwise we return
544 * a regular CURLcode value.
546 int Curl_read(struct connectdata *conn, /* connection data */
547 curl_socket_t sockfd, /* read from this socket */
548 char *buf, /* store read data here */
549 size_t sizerequested, /* max amount to read */
550 ssize_t *n) /* amount bytes read */
552 ssize_t nread = 0;
553 size_t bytesfromsocket = 0;
554 char *buffertofill = NULL;
555 bool pipelining = (bool)(conn->data->multi &&
556 Curl_multi_canPipeline(conn->data->multi));
558 /* Set 'num' to 0 or 1, depending on which socket that has been sent here.
559 If it is the second socket, we set num to 1. Otherwise to 0. This lets
560 us use the correct ssl handle. */
561 int num = (sockfd == conn->sock[SECONDARYSOCKET]);
563 *n=0; /* reset amount to zero */
565 /* If session can pipeline, check connection buffer */
566 if(pipelining) {
567 size_t bytestocopy = MIN(conn->buf_len - conn->read_pos, sizerequested);
569 /* Copy from our master buffer first if we have some unread data there*/
570 if(bytestocopy > 0) {
571 memcpy(buf, conn->master_buffer + conn->read_pos, bytestocopy);
572 conn->read_pos += bytestocopy;
573 conn->bits.stream_was_rewound = FALSE;
575 *n = (ssize_t)bytestocopy;
576 return CURLE_OK;
578 /* If we come here, it means that there is no data to read from the buffer,
579 * so we read from the socket */
580 bytesfromsocket = MIN(sizerequested, BUFSIZE * sizeof (char));
581 buffertofill = conn->master_buffer;
583 else {
584 bytesfromsocket = MIN((long)sizerequested, conn->data->set.buffer_size ?
585 conn->data->set.buffer_size : BUFSIZE);
586 buffertofill = buf;
589 if(conn->ssl[num].state == ssl_connection_complete) {
590 nread = Curl_ssl_recv(conn, num, buffertofill, bytesfromsocket);
592 if(nread == -1) {
593 return -1; /* -1 from Curl_ssl_recv() means EWOULDBLOCK */
596 else if(Curl_ssh_enabled(conn, (PROT_SCP|PROT_SFTP))) {
597 if(conn->protocol & PROT_SCP)
598 nread = Curl_scp_recv(conn, num, buffertofill, bytesfromsocket);
599 else if(conn->protocol & PROT_SFTP)
600 nread = Curl_sftp_recv(conn, num, buffertofill, bytesfromsocket);
601 #ifdef LIBSSH2CHANNEL_EAGAIN
602 if((nread == LIBSSH2CHANNEL_EAGAIN) || (nread == 0))
603 /* EWOULDBLOCK */
604 return -1;
605 #endif
606 if(nread < 0)
607 /* since it is negative and not EGAIN, it was a protocol-layer error */
608 return CURLE_RECV_ERROR;
610 else {
611 if(conn->sec_complete)
612 nread = Curl_sec_read(conn, sockfd, buffertofill,
613 bytesfromsocket);
614 else
615 nread = sread(sockfd, buffertofill, bytesfromsocket);
617 if(-1 == nread) {
618 int err = SOCKERRNO;
619 #ifdef USE_WINSOCK
620 if(WSAEWOULDBLOCK == err)
621 #else
622 if((EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err))
623 #endif
624 return -1;
628 if(nread >= 0) {
629 if(pipelining) {
630 memcpy(buf, conn->master_buffer, nread);
631 conn->buf_len = nread;
632 conn->read_pos = nread;
635 *n += nread;
638 return CURLE_OK;
641 /* return 0 on success */
642 static int showit(struct SessionHandle *data, curl_infotype type,
643 char *ptr, size_t size)
645 static const char * const s_infotype[CURLINFO_END] = {
646 "* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
648 #ifdef CURL_DOES_CONVERSIONS
649 char buf[BUFSIZE+1];
650 size_t conv_size = 0;
652 switch(type) {
653 case CURLINFO_HEADER_OUT:
654 /* assume output headers are ASCII */
655 /* copy the data into my buffer so the original is unchanged */
656 if(size > BUFSIZE) {
657 size = BUFSIZE; /* truncate if necessary */
658 buf[BUFSIZE] = '\0';
660 conv_size = size;
661 memcpy(buf, ptr, size);
662 /* Special processing is needed for this block if it
663 * contains both headers and data (separated by CRLFCRLF).
664 * We want to convert just the headers, leaving the data as-is.
666 if(size > 4) {
667 size_t i;
668 for(i = 0; i < size-4; i++) {
669 if(memcmp(&buf[i], "\x0d\x0a\x0d\x0a", 4) == 0) {
670 /* convert everthing through this CRLFCRLF but no further */
671 conv_size = i + 4;
672 break;
677 Curl_convert_from_network(data, buf, conv_size);
678 /* Curl_convert_from_network calls failf if unsuccessful */
679 /* we might as well continue even if it fails... */
680 ptr = buf; /* switch pointer to use my buffer instead */
681 break;
682 default:
683 /* leave everything else as-is */
684 break;
686 #endif /* CURL_DOES_CONVERSIONS */
688 if(data->set.fdebug)
689 return (*data->set.fdebug)(data, type, ptr, size,
690 data->set.debugdata);
692 switch(type) {
693 case CURLINFO_TEXT:
694 case CURLINFO_HEADER_OUT:
695 case CURLINFO_HEADER_IN:
696 fwrite(s_infotype[type], 2, 1, data->set.err);
697 fwrite(ptr, size, 1, data->set.err);
698 #ifdef CURL_DOES_CONVERSIONS
699 if(size != conv_size) {
700 /* we had untranslated data so we need an explicit newline */
701 fwrite("\n", 1, 1, data->set.err);
703 #endif
704 break;
705 default: /* nada */
706 break;
708 return 0;
711 int Curl_debug(struct SessionHandle *data, curl_infotype type,
712 char *ptr, size_t size,
713 struct connectdata *conn)
715 int rc;
716 if(data->set.printhost && conn && conn->host.dispname) {
717 char buffer[160];
718 const char *t=NULL;
719 const char *w="Data";
720 switch (type) {
721 case CURLINFO_HEADER_IN:
722 w = "Header";
723 case CURLINFO_DATA_IN:
724 t = "from";
725 break;
726 case CURLINFO_HEADER_OUT:
727 w = "Header";
728 case CURLINFO_DATA_OUT:
729 t = "to";
730 break;
731 default:
732 break;
735 if(t) {
736 snprintf(buffer, sizeof(buffer), "[%s %s %s]", w, t,
737 conn->host.dispname);
738 rc = showit(data, CURLINFO_TEXT, buffer, strlen(buffer));
739 if(rc)
740 return rc;
743 rc = showit(data, type, ptr, size);
744 return rc;