blob: d04371f84e4402ae985fc9c29c75a7739d72644f [file] [log] [blame]
9487f7f2011-08-03 07:05:30 -07001/***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
9 *
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.
13 *
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.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ***************************************************************************/
22
23#include "setup.h"
24
25#include <stdio.h>
26#include <stdarg.h>
27#include <stdlib.h>
28#include <errno.h>
29
30#ifdef HAVE_SYS_SOCKET_H
31#include <sys/socket.h> /* required for send() & recv() prototypes */
32#endif
33
34#ifdef HAVE_UNISTD_H
35#include <unistd.h>
36#endif
37
38#include <curl/curl.h>
39#include "urldata.h"
40#include "sendf.h"
41#include "connect.h"
42#include "sslgen.h"
43#include "ssh.h"
44#include "multiif.h"
45#include "rtsp.h"
46
47#define _MPRINTF_REPLACE /* use the internal *printf() functions */
48#include <curl/mprintf.h>
49
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))
52#include "krb4.h"
53#else
54#define Curl_sec_send(a,b,c,d) -1
55#define Curl_sec_read(a,b,c,d) -1
56#endif
57
58#include <string.h>
59#include "curl_memory.h"
60#include "strerror.h"
61#include "easyif.h" /* for the Curl_convert_from_network prototype */
62/* The last #include file should be: */
63#include "memdebug.h"
64
65#ifdef CURL_DO_LINEEND_CONV
66/*
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.
71 */
72static size_t convert_lineends(struct SessionHandle *data,
73 char *startPtr, size_t size)
74{
75 char *inPtr, *outPtr;
76
77 /* sanity check */
78 if((startPtr == NULL) || (size < 1)) {
79 return(size);
80 }
81
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);
89 size--;
90 /* and it wasn't a bare CR but a CRLF conversion instead */
91 data->state.crlf_conversions++;
92 }
93 data->state.prev_block_had_trailing_cr = FALSE; /* reset the flag */
94 }
95
96 /* find 1st CR, if any */
97 inPtr = outPtr = memchr(startPtr, '\r', size);
98 if(inPtr) {
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 */
104 inPtr++;
105 *outPtr = *inPtr;
106 /* keep track of how many CRLFs we converted */
107 data->state.crlf_conversions++;
108 }
109 else {
110 if(*inPtr == '\r') {
111 /* lone CR, move LF instead */
112 *outPtr = '\n';
113 }
114 else {
115 /* not a CRLF nor a CR, just copy whatever it is */
116 *outPtr = *inPtr;
117 }
118 }
119 outPtr++;
120 inPtr++;
121 } /* end of while loop */
122
123 if(inPtr < startPtr+size) {
124 /* handle last byte */
125 if(*inPtr == '\r') {
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;
130 }
131 else {
132 /* copy last byte */
133 *outPtr = *inPtr;
134 }
135 outPtr++;
136 }
137 if(outPtr < startPtr+size)
138 /* tidy up by null terminating the now shorter data */
139 *outPtr = '\0';
140
141 return(outPtr - startPtr);
142 }
143 return(size);
144}
145#endif /* CURL_DO_LINEEND_CONV */
146
147/* Curl_infof() is for info message along the way */
148
149void Curl_infof(struct SessionHandle *data, const char *fmt, ...)
150{
151 if(data && data->set.verbose) {
152 va_list ap;
153 size_t len;
154 char print_buffer[2048 + 1];
155 va_start(ap, fmt);
156 vsnprintf(print_buffer, sizeof(print_buffer), fmt, ap);
157 va_end(ap);
158 len = strlen(print_buffer);
159 Curl_debug(data, CURLINFO_TEXT, print_buffer, len, NULL);
160 }
161}
162
163/* Curl_failf() is for messages stating why we failed.
164 * The message SHALL NOT include any LF or CR.
165 */
166
167void Curl_failf(struct SessionHandle *data, const char *fmt, ...)
168{
169 va_list ap;
170 size_t len;
171 va_start(ap, fmt);
172
173 vsnprintf(data->state.buffer, BUFSIZE, fmt, ap);
174
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 */
178 }
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';
184 }
185 Curl_debug(data, CURLINFO_TEXT, data->state.buffer, len, NULL);
186 }
187
188 va_end(ap);
189}
190
191/* Curl_sendf() sends formated data to the server */
192CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *conn,
193 const char *fmt, ...)
194{
195 struct SessionHandle *data = conn->data;
196 ssize_t bytes_written;
197 size_t write_len;
198 CURLcode res = CURLE_OK;
199 char *s;
200 char *sptr;
201 va_list ap;
202 va_start(ap, fmt);
203 s = vaprintf(fmt, ap); /* returns an allocated string */
204 va_end(ap);
205 if(!s)
206 return CURLE_OUT_OF_MEMORY; /* failure */
207
208 bytes_written=0;
209 write_len = strlen(s);
210 sptr = s;
211
212 for(;;) {
213 /* Write the buffer to the socket */
214 res = Curl_write(conn, sockfd, sptr, write_len, &bytes_written);
215
216 if(CURLE_OK != res)
217 break;
218
219 if(data->set.verbose)
220 Curl_debug(data, CURLINFO_DATA_OUT, sptr, (size_t)bytes_written, conn);
221
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;
227 }
228 else
229 break;
230 }
231
232 free(s); /* free the output string */
233
234 return res;
235}
236
237/*
238 * Curl_write() is an internal write function that sends data to the
239 * server. Works with plain sockets, SCP, SSL or kerberos.
240 *
241 * If the write would block (CURLE_AGAIN), we return CURLE_OK and
242 * (*written == 0). Otherwise we return regular CURLcode value.
243 */
244CURLcode Curl_write(struct connectdata *conn,
245 curl_socket_t sockfd,
246 const void *mem,
247 size_t len,
248 ssize_t *written)
249{
250 ssize_t bytes_written;
251 CURLcode curlcode = CURLE_OK;
252 int num = (sockfd == conn->sock[SECONDARYSOCKET]);
253
254 bytes_written = conn->send[num](conn, num, mem, len, &curlcode);
255
256 *written = bytes_written;
257 if(bytes_written >= 0)
258 /* we completely ignore the curlcode value when subzero is not returned */
259 return CURLE_OK;
260
261 /* handle CURLE_AGAIN or a send failure */
262 switch(curlcode) {
263 case CURLE_AGAIN:
264 *written = 0;
265 return CURLE_OK;
266
267 case CURLE_OK:
268 /* general send failure */
269 return CURLE_SEND_ERROR;
270
271 default:
272 /* we got a specific curlcode, forward it */
273 return (CURLcode)curlcode;
274 }
275}
276
277ssize_t Curl_send_plain(struct connectdata *conn, int num,
278 const void *mem, size_t len, CURLcode *code)
279{
280 curl_socket_t sockfd = conn->sock[num];
281 ssize_t bytes_written = swrite(sockfd, mem, len);
282
283 *code = CURLE_OK;
284 if(-1 == bytes_written) {
285 int err = SOCKERRNO;
286
287 if(
288#ifdef WSAEWOULDBLOCK
289 /* This is how Windows does it */
290 (WSAEWOULDBLOCK == err)
291#else
292 /* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned
293 due to its inability to send off data without blocking. We therefor
294 treat both error codes the same here */
295 (EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err)
296#endif
297 ) {
298 /* this is just a case of EWOULDBLOCK */
299 bytes_written=0;
300 *code = CURLE_AGAIN;
301 } else {
302 failf(conn->data, "Send failure: %s",
303 Curl_strerror(conn, err));
304 conn->data->state.os_errno = err;
305 *code = CURLE_SEND_ERROR;
306 }
307 }
308 return bytes_written;
309}
310
311/*
312 * Curl_write_plain() is an internal write function that sends data to the
313 * server using plain sockets only. Otherwise meant to have the exact same
314 * proto as Curl_write()
315 */
316CURLcode Curl_write_plain(struct connectdata *conn,
317 curl_socket_t sockfd,
318 const void *mem,
319 size_t len,
320 ssize_t *written)
321{
322 ssize_t bytes_written;
323 CURLcode retcode;
324 int num = (sockfd == conn->sock[SECONDARYSOCKET]);
325
326 bytes_written = Curl_send_plain(conn, num, mem, len, &retcode);
327
328 *written = bytes_written;
329
330 return retcode;
331}
332
333ssize_t Curl_recv_plain(struct connectdata *conn, int num, char *buf,
334 size_t len, CURLcode *code)
335{
336 curl_socket_t sockfd = conn->sock[num];
337 ssize_t nread = sread(sockfd, buf, len);
338
339 *code = CURLE_OK;
340 if(-1 == nread) {
341 int err = SOCKERRNO;
342
343 if(
344#ifdef WSAEWOULDBLOCK
345 /* This is how Windows does it */
346 (WSAEWOULDBLOCK == err)
347#else
348 /* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned
349 due to its inability to send off data without blocking. We therefor
350 treat both error codes the same here */
351 (EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err)
352#endif
353 ) {
354 /* this is just a case of EWOULDBLOCK */
355 *code = CURLE_AGAIN;
356 } else {
357 failf(conn->data, "Recv failure: %s",
358 Curl_strerror(conn, err));
359 conn->data->state.os_errno = err;
360 *code = CURLE_RECV_ERROR;
361 }
362 }
363 return nread;
364}
365
366static CURLcode pausewrite(struct SessionHandle *data,
367 int type, /* what type of data */
368 const char *ptr,
369 size_t len)
370{
371 /* signalled to pause sending on this connection, but since we have data
372 we want to send we need to dup it to save a copy for when the sending
373 is again enabled */
374 struct SingleRequest *k = &data->req;
375 char *dupl = malloc(len);
376 if(!dupl)
377 return CURLE_OUT_OF_MEMORY;
378
379 memcpy(dupl, ptr, len);
380
381 /* store this information in the state struct for later use */
382 data->state.tempwrite = dupl;
383 data->state.tempwritesize = len;
384 data->state.tempwritetype = type;
385
386 /* mark the connection as RECV paused */
387 k->keepon |= KEEP_RECV_PAUSE;
388
389 DEBUGF(infof(data, "Pausing with %zu bytes in buffer for type %02x\n",
390 len, type));
391
392 return CURLE_OK;
393}
394
395
396/* Curl_client_write() sends data to the write callback(s)
397
398 The bit pattern defines to what "streams" to write to. Body and/or header.
399 The defines are in sendf.h of course.
400
401 If CURL_DO_LINEEND_CONV is enabled, data is converted IN PLACE to the
402 local character encoding. This is a problem and should be changed in
403 the future to leave the original data alone.
404 */
405CURLcode Curl_client_write(struct connectdata *conn,
406 int type,
407 char *ptr,
408 size_t len)
409{
410 struct SessionHandle *data = conn->data;
411 size_t wrote;
412
413 if(0 == len)
414 len = strlen(ptr);
415
416 /* If reading is actually paused, we're forced to append this chunk of data
417 to the already held data, but only if it is the same type as otherwise it
418 can't work and it'll return error instead. */
419 if(data->req.keepon & KEEP_RECV_PAUSE) {
420 size_t newlen;
421 char *newptr;
422 if(type != data->state.tempwritetype)
423 /* major internal confusion */
424 return CURLE_RECV_ERROR;
425
426 DEBUGASSERT(data->state.tempwrite);
427
428 /* figure out the new size of the data to save */
429 newlen = len + data->state.tempwritesize;
430 /* allocate the new memory area */
431 newptr = realloc(data->state.tempwrite, newlen);
432 if(!newptr)
433 return CURLE_OUT_OF_MEMORY;
434 /* copy the new data to the end of the new area */
435 memcpy(newptr + data->state.tempwritesize, ptr, len);
436 /* update the pointer and the size */
437 data->state.tempwrite = newptr;
438 data->state.tempwritesize = newlen;
439
440 return CURLE_OK;
441 }
442
443 if(type & CLIENTWRITE_BODY) {
444 if((conn->protocol&PROT_FTP) && conn->proto.ftpc.transfertype == 'A') {
445#ifdef CURL_DOES_CONVERSIONS
446 /* convert from the network encoding */
447 size_t rc;
448 rc = Curl_convert_from_network(data, ptr, len);
449 /* Curl_convert_from_network calls failf if unsuccessful */
450 if(rc != CURLE_OK)
451 return rc;
452#endif /* CURL_DOES_CONVERSIONS */
453
454#ifdef CURL_DO_LINEEND_CONV
455 /* convert end-of-line markers */
456 len = convert_lineends(data, ptr, len);
457#endif /* CURL_DO_LINEEND_CONV */
458 }
459 /* If the previous block of data ended with CR and this block of data is
460 just a NL, then the length might be zero */
461 if(len) {
462 wrote = data->set.fwrite_func(ptr, 1, len, data->set.out);
463 }
464 else {
465 wrote = len;
466 }
467
468 if(CURL_WRITEFUNC_PAUSE == wrote)
469 return pausewrite(data, type, ptr, len);
470
471 if(wrote != len) {
472 failf(data, "Failed writing body (%zu != %zu)", wrote, len);
473 return CURLE_WRITE_ERROR;
474 }
475 }
476
477 if((type & CLIENTWRITE_HEADER) &&
478 (data->set.fwrite_header || data->set.writeheader) ) {
479 /*
480 * Write headers to the same callback or to the especially setup
481 * header callback function (added after version 7.7.1).
482 */
483 curl_write_callback writeit=
484 data->set.fwrite_header?data->set.fwrite_header:data->set.fwrite_func;
485
486 /* Note: The header is in the host encoding
487 regardless of the ftp transfer mode (ASCII/Image) */
488
489 wrote = writeit(ptr, 1, len, data->set.writeheader);
490 if(CURL_WRITEFUNC_PAUSE == wrote)
491 /* here we pass in the HEADER bit only since if this was body as well
492 then it was passed already and clearly that didn't trigger the pause,
493 so this is saved for later with the HEADER bit only */
494 return pausewrite(data, CLIENTWRITE_HEADER, ptr, len);
495
496 if(wrote != len) {
497 failf (data, "Failed writing header");
498 return CURLE_WRITE_ERROR;
499 }
500 }
501
502 return CURLE_OK;
503}
504
505CURLcode Curl_read_plain(curl_socket_t sockfd,
506 char *buf,
507 size_t bytesfromsocket,
508 ssize_t *n)
509{
510 ssize_t nread = sread(sockfd, buf, bytesfromsocket);
511
512 if(-1 == nread) {
513 int err = SOCKERRNO;
514#ifdef USE_WINSOCK
515 if(WSAEWOULDBLOCK == err)
516#else
517 if((EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err))
518#endif
519 return CURLE_AGAIN;
520 else
521 return CURLE_RECV_ERROR;
522 }
523
524 /* we only return number of bytes read when we return OK */
525 *n = nread;
526 return CURLE_OK;
527}
528
529/*
530 * Internal read-from-socket function. This is meant to deal with plain
531 * sockets, SSL sockets and kerberos sockets.
532 *
533 * Returns a regular CURLcode value.
534 */
535CURLcode Curl_read(struct connectdata *conn, /* connection data */
536 curl_socket_t sockfd, /* read from this socket */
537 char *buf, /* store read data here */
538 size_t sizerequested, /* max amount to read */
539 ssize_t *n) /* amount bytes read */
540{
541 CURLcode curlcode = CURLE_RECV_ERROR;
542 ssize_t nread = 0;
543 size_t bytesfromsocket = 0;
544 char *buffertofill = NULL;
545 bool pipelining = (bool)(conn->data->multi &&
546 Curl_multi_canPipeline(conn->data->multi));
547
548 /* Set 'num' to 0 or 1, depending on which socket that has been sent here.
549 If it is the second socket, we set num to 1. Otherwise to 0. This lets
550 us use the correct ssl handle. */
551 int num = (sockfd == conn->sock[SECONDARYSOCKET]);
552
553 *n=0; /* reset amount to zero */
554
555 /* If session can pipeline, check connection buffer */
556 if(pipelining) {
557 size_t bytestocopy = CURLMIN(conn->buf_len - conn->read_pos,
558 sizerequested);
559
560 /* Copy from our master buffer first if we have some unread data there*/
561 if(bytestocopy > 0) {
562 memcpy(buf, conn->master_buffer + conn->read_pos, bytestocopy);
563 conn->read_pos += bytestocopy;
564 conn->bits.stream_was_rewound = FALSE;
565
566 *n = (ssize_t)bytestocopy;
567 return CURLE_OK;
568 }
569 /* If we come here, it means that there is no data to read from the buffer,
570 * so we read from the socket */
571 bytesfromsocket = CURLMIN(sizerequested, BUFSIZE * sizeof (char));
572 buffertofill = conn->master_buffer;
573 }
574 else {
575 bytesfromsocket = CURLMIN((long)sizerequested,
576 conn->data->set.buffer_size ?
577 conn->data->set.buffer_size : BUFSIZE);
578 buffertofill = buf;
579 }
580
581 nread = conn->recv[num](conn, num, buffertofill, bytesfromsocket, &curlcode);
582 if(nread < 0)
583 return curlcode;
584
585 if(pipelining) {
586 memcpy(buf, conn->master_buffer, nread);
587 conn->buf_len = nread;
588 conn->read_pos = nread;
589 }
590
591 *n += nread;
592
593 return CURLE_OK;
594}
595
596/* return 0 on success */
597static int showit(struct SessionHandle *data, curl_infotype type,
598 char *ptr, size_t size)
599{
600 static const char s_infotype[CURLINFO_END][3] = {
601 "* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
602
603#ifdef CURL_DOES_CONVERSIONS
604 char buf[BUFSIZE+1];
605 size_t conv_size = 0;
606
607 switch(type) {
608 case CURLINFO_HEADER_OUT:
609 /* assume output headers are ASCII */
610 /* copy the data into my buffer so the original is unchanged */
611 if(size > BUFSIZE) {
612 size = BUFSIZE; /* truncate if necessary */
613 buf[BUFSIZE] = '\0';
614 }
615 conv_size = size;
616 memcpy(buf, ptr, size);
617 /* Special processing is needed for this block if it
618 * contains both headers and data (separated by CRLFCRLF).
619 * We want to convert just the headers, leaving the data as-is.
620 */
621 if(size > 4) {
622 size_t i;
623 for(i = 0; i < size-4; i++) {
624 if(memcmp(&buf[i], "\x0d\x0a\x0d\x0a", 4) == 0) {
625 /* convert everthing through this CRLFCRLF but no further */
626 conv_size = i + 4;
627 break;
628 }
629 }
630 }
631
632 Curl_convert_from_network(data, buf, conv_size);
633 /* Curl_convert_from_network calls failf if unsuccessful */
634 /* we might as well continue even if it fails... */
635 ptr = buf; /* switch pointer to use my buffer instead */
636 break;
637 default:
638 /* leave everything else as-is */
639 break;
640 }
641#endif /* CURL_DOES_CONVERSIONS */
642
643 if(data->set.fdebug)
644 return (*data->set.fdebug)(data, type, ptr, size,
645 data->set.debugdata);
646
647 switch(type) {
648 case CURLINFO_TEXT:
649 case CURLINFO_HEADER_OUT:
650 case CURLINFO_HEADER_IN:
651 fwrite(s_infotype[type], 2, 1, data->set.err);
652 fwrite(ptr, size, 1, data->set.err);
653#ifdef CURL_DOES_CONVERSIONS
654 if(size != conv_size) {
655 /* we had untranslated data so we need an explicit newline */
656 fwrite("\n", 1, 1, data->set.err);
657 }
658#endif
659 break;
660 default: /* nada */
661 break;
662 }
663 return 0;
664}
665
666int Curl_debug(struct SessionHandle *data, curl_infotype type,
667 char *ptr, size_t size,
668 struct connectdata *conn)
669{
670 int rc;
671 if(data->set.printhost && conn && conn->host.dispname) {
672 char buffer[160];
673 const char *t=NULL;
674 const char *w="Data";
675 switch (type) {
676 case CURLINFO_HEADER_IN:
677 w = "Header";
678 case CURLINFO_DATA_IN:
679 t = "from";
680 break;
681 case CURLINFO_HEADER_OUT:
682 w = "Header";
683 case CURLINFO_DATA_OUT:
684 t = "to";
685 break;
686 default:
687 break;
688 }
689
690 if(t) {
691 snprintf(buffer, sizeof(buffer), "[%s %s %s]", w, t,
692 conn->host.dispname);
693 rc = showit(data, CURLINFO_TEXT, buffer, strlen(buffer));
694 if(rc)
695 return rc;
696 }
697 }
698 rc = showit(data, type, ptr, size);
699 return rc;
700}