1 /***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2016, 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 https://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 "curl_setup.h"
24
25 #include <curl/curl.h>
26
27 #include "urldata.h"
28 #include "sendf.h"
29 #include "connect.h"
30 #include "vtls/vtls.h"
31 #include "ssh.h"
32 #include "multiif.h"
33 #include "non-ascii.h"
34 #include "strerror.h"
35 #include "select.h"
36
37 /* The last 3 #include files should be in this order */
38 #include "curl_printf.h"
39 #include "curl_memory.h"
40 #include "memdebug.h"
41
42 #ifdef CURL_DO_LINEEND_CONV
43 /*
44 * convert_lineends() changes CRLF (\r\n) end-of-line markers to a single LF
45 * (\n), with special processing for CRLF sequences that are split between two
46 * blocks of data. Remaining, bare CRs are changed to LFs. The possibly new
47 * size of the data is returned.
48 */
convert_lineends(struct Curl_easy * data,char * startPtr,size_t size)49 static size_t convert_lineends(struct Curl_easy *data,
50 char *startPtr, size_t size)
51 {
52 char *inPtr, *outPtr;
53
54 /* sanity check */
55 if((startPtr == NULL) || (size < 1)) {
56 return size;
57 }
58
59 if(data->state.prev_block_had_trailing_cr) {
60 /* The previous block of incoming data
61 had a trailing CR, which was turned into a LF. */
62 if(*startPtr == '\n') {
63 /* This block of incoming data starts with the
64 previous block's LF so get rid of it */
65 memmove(startPtr, startPtr+1, size-1);
66 size--;
67 /* and it wasn't a bare CR but a CRLF conversion instead */
68 data->state.crlf_conversions++;
69 }
70 data->state.prev_block_had_trailing_cr = FALSE; /* reset the flag */
71 }
72
73 /* find 1st CR, if any */
74 inPtr = outPtr = memchr(startPtr, '\r', size);
75 if(inPtr) {
76 /* at least one CR, now look for CRLF */
77 while(inPtr < (startPtr+size-1)) {
78 /* note that it's size-1, so we'll never look past the last byte */
79 if(memcmp(inPtr, "\r\n", 2) == 0) {
80 /* CRLF found, bump past the CR and copy the NL */
81 inPtr++;
82 *outPtr = *inPtr;
83 /* keep track of how many CRLFs we converted */
84 data->state.crlf_conversions++;
85 }
86 else {
87 if(*inPtr == '\r') {
88 /* lone CR, move LF instead */
89 *outPtr = '\n';
90 }
91 else {
92 /* not a CRLF nor a CR, just copy whatever it is */
93 *outPtr = *inPtr;
94 }
95 }
96 outPtr++;
97 inPtr++;
98 } /* end of while loop */
99
100 if(inPtr < startPtr+size) {
101 /* handle last byte */
102 if(*inPtr == '\r') {
103 /* deal with a CR at the end of the buffer */
104 *outPtr = '\n'; /* copy a NL instead */
105 /* note that a CRLF might be split across two blocks */
106 data->state.prev_block_had_trailing_cr = TRUE;
107 }
108 else {
109 /* copy last byte */
110 *outPtr = *inPtr;
111 }
112 outPtr++;
113 }
114 if(outPtr < startPtr+size)
115 /* tidy up by null terminating the now shorter data */
116 *outPtr = '\0';
117
118 return (outPtr - startPtr);
119 }
120 return size;
121 }
122 #endif /* CURL_DO_LINEEND_CONV */
123
124 #ifdef USE_RECV_BEFORE_SEND_WORKAROUND
Curl_recv_has_postponed_data(struct connectdata * conn,int sockindex)125 bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex)
126 {
127 struct postponed_data * const psnd = &(conn->postponed[sockindex]);
128 return psnd->buffer && psnd->allocated_size &&
129 psnd->recv_size > psnd->recv_processed;
130 }
131
pre_receive_plain(struct connectdata * conn,int num)132 static void pre_receive_plain(struct connectdata *conn, int num)
133 {
134 const curl_socket_t sockfd = conn->sock[num];
135 struct postponed_data * const psnd = &(conn->postponed[num]);
136 size_t bytestorecv = psnd->allocated_size - psnd->recv_size;
137 /* WinSock will destroy unread received data if send() is
138 failed.
139 To avoid lossage of received data, recv() must be
140 performed before every send() if any incoming data is
141 available. However, skip this, if buffer is already full. */
142 if((conn->handler->protocol&PROTO_FAMILY_HTTP) != 0 &&
143 conn->recv[num] == Curl_recv_plain &&
144 (!psnd->buffer || bytestorecv)) {
145 const int readymask = Curl_socket_check(sockfd, CURL_SOCKET_BAD,
146 CURL_SOCKET_BAD, 0);
147 if(readymask != -1 && (readymask & CURL_CSELECT_IN) != 0) {
148 /* Have some incoming data */
149 if(!psnd->buffer) {
150 /* Use buffer double default size for intermediate buffer */
151 psnd->allocated_size = 2 * BUFSIZE;
152 psnd->buffer = malloc(psnd->allocated_size);
153 psnd->recv_size = 0;
154 psnd->recv_processed = 0;
155 #ifdef DEBUGBUILD
156 psnd->bindsock = sockfd; /* Used only for DEBUGASSERT */
157 #endif /* DEBUGBUILD */
158 bytestorecv = psnd->allocated_size;
159 }
160 if(psnd->buffer) {
161 ssize_t recvedbytes;
162 DEBUGASSERT(psnd->bindsock == sockfd);
163 recvedbytes = sread(sockfd, psnd->buffer + psnd->recv_size,
164 bytestorecv);
165 if(recvedbytes > 0)
166 psnd->recv_size += recvedbytes;
167 }
168 else
169 psnd->allocated_size = 0;
170 }
171 }
172 }
173
get_pre_recved(struct connectdata * conn,int num,char * buf,size_t len)174 static ssize_t get_pre_recved(struct connectdata *conn, int num, char *buf,
175 size_t len)
176 {
177 struct postponed_data * const psnd = &(conn->postponed[num]);
178 size_t copysize;
179 if(!psnd->buffer)
180 return 0;
181
182 DEBUGASSERT(psnd->allocated_size > 0);
183 DEBUGASSERT(psnd->recv_size <= psnd->allocated_size);
184 DEBUGASSERT(psnd->recv_processed <= psnd->recv_size);
185 /* Check and process data that already received and storied in internal
186 intermediate buffer */
187 if(psnd->recv_size > psnd->recv_processed) {
188 DEBUGASSERT(psnd->bindsock == conn->sock[num]);
189 copysize = CURLMIN(len, psnd->recv_size - psnd->recv_processed);
190 memcpy(buf, psnd->buffer + psnd->recv_processed, copysize);
191 psnd->recv_processed += copysize;
192 }
193 else
194 copysize = 0; /* buffer was allocated, but nothing was received */
195
196 /* Free intermediate buffer if it has no unprocessed data */
197 if(psnd->recv_processed == psnd->recv_size) {
198 free(psnd->buffer);
199 psnd->buffer = NULL;
200 psnd->allocated_size = 0;
201 psnd->recv_size = 0;
202 psnd->recv_processed = 0;
203 #ifdef DEBUGBUILD
204 psnd->bindsock = CURL_SOCKET_BAD;
205 #endif /* DEBUGBUILD */
206 }
207 return (ssize_t)copysize;
208 }
209 #else /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
210 /* Use "do-nothing" macros instead of functions when workaround not used */
Curl_recv_has_postponed_data(struct connectdata * conn,int sockindex)211 bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex)
212 {
213 (void)conn;
214 (void)sockindex;
215 return false;
216 }
217 #define pre_receive_plain(c,n) do {} WHILE_FALSE
218 #define get_pre_recved(c,n,b,l) 0
219 #endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
220
221 /* Curl_infof() is for info message along the way */
222
Curl_infof(struct Curl_easy * data,const char * fmt,...)223 void Curl_infof(struct Curl_easy *data, const char *fmt, ...)
224 {
225 if(data && data->set.verbose) {
226 va_list ap;
227 size_t len;
228 char print_buffer[2048 + 1];
229 va_start(ap, fmt);
230 vsnprintf(print_buffer, sizeof(print_buffer), fmt, ap);
231 va_end(ap);
232 len = strlen(print_buffer);
233 Curl_debug(data, CURLINFO_TEXT, print_buffer, len, NULL);
234 }
235 }
236
237 /* Curl_failf() is for messages stating why we failed.
238 * The message SHALL NOT include any LF or CR.
239 */
240
Curl_failf(struct Curl_easy * data,const char * fmt,...)241 void Curl_failf(struct Curl_easy *data, const char *fmt, ...)
242 {
243 va_list ap;
244 size_t len;
245 va_start(ap, fmt);
246
247 vsnprintf(data->state.buffer, BUFSIZE, fmt, ap);
248
249 if(data->set.errorbuffer && !data->state.errorbuf) {
250 snprintf(data->set.errorbuffer, CURL_ERROR_SIZE, "%s", data->state.buffer);
251 data->state.errorbuf = TRUE; /* wrote error string */
252 }
253 if(data->set.verbose) {
254 len = strlen(data->state.buffer);
255 if(len < BUFSIZE - 1) {
256 data->state.buffer[len] = '\n';
257 data->state.buffer[++len] = '\0';
258 }
259 Curl_debug(data, CURLINFO_TEXT, data->state.buffer, len, NULL);
260 }
261
262 va_end(ap);
263 }
264
265 /* Curl_sendf() sends formated data to the server */
Curl_sendf(curl_socket_t sockfd,struct connectdata * conn,const char * fmt,...)266 CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *conn,
267 const char *fmt, ...)
268 {
269 struct Curl_easy *data = conn->data;
270 ssize_t bytes_written;
271 size_t write_len;
272 CURLcode result = CURLE_OK;
273 char *s;
274 char *sptr;
275 va_list ap;
276 va_start(ap, fmt);
277 s = vaprintf(fmt, ap); /* returns an allocated string */
278 va_end(ap);
279 if(!s)
280 return CURLE_OUT_OF_MEMORY; /* failure */
281
282 bytes_written=0;
283 write_len = strlen(s);
284 sptr = s;
285
286 for(;;) {
287 /* Write the buffer to the socket */
288 result = Curl_write(conn, sockfd, sptr, write_len, &bytes_written);
289
290 if(result)
291 break;
292
293 if(data->set.verbose)
294 Curl_debug(data, CURLINFO_DATA_OUT, sptr, (size_t)bytes_written, conn);
295
296 if((size_t)bytes_written != write_len) {
297 /* if not all was written at once, we must advance the pointer, decrease
298 the size left and try again! */
299 write_len -= bytes_written;
300 sptr += bytes_written;
301 }
302 else
303 break;
304 }
305
306 free(s); /* free the output string */
307
308 return result;
309 }
310
311 /*
312 * Curl_write() is an internal write function that sends data to the
313 * server. Works with plain sockets, SCP, SSL or kerberos.
314 *
315 * If the write would block (CURLE_AGAIN), we return CURLE_OK and
316 * (*written == 0). Otherwise we return regular CURLcode value.
317 */
Curl_write(struct connectdata * conn,curl_socket_t sockfd,const void * mem,size_t len,ssize_t * written)318 CURLcode Curl_write(struct connectdata *conn,
319 curl_socket_t sockfd,
320 const void *mem,
321 size_t len,
322 ssize_t *written)
323 {
324 ssize_t bytes_written;
325 CURLcode result = CURLE_OK;
326 int num = (sockfd == conn->sock[SECONDARYSOCKET]);
327
328 bytes_written = conn->send[num](conn, num, mem, len, &result);
329
330 *written = bytes_written;
331 if(bytes_written >= 0)
332 /* we completely ignore the curlcode value when subzero is not returned */
333 return CURLE_OK;
334
335 /* handle CURLE_AGAIN or a send failure */
336 switch(result) {
337 case CURLE_AGAIN:
338 *written = 0;
339 return CURLE_OK;
340
341 case CURLE_OK:
342 /* general send failure */
343 return CURLE_SEND_ERROR;
344
345 default:
346 /* we got a specific curlcode, forward it */
347 return result;
348 }
349 }
350
Curl_send_plain(struct connectdata * conn,int num,const void * mem,size_t len,CURLcode * code)351 ssize_t Curl_send_plain(struct connectdata *conn, int num,
352 const void *mem, size_t len, CURLcode *code)
353 {
354 curl_socket_t sockfd = conn->sock[num];
355 ssize_t bytes_written;
356 /* WinSock will destroy unread received data if send() is
357 failed.
358 To avoid lossage of received data, recv() must be
359 performed before every send() if any incoming data is
360 available. */
361 pre_receive_plain(conn, num);
362
363 #ifdef MSG_FASTOPEN /* Linux */
364 if(conn->bits.tcp_fastopen) {
365 bytes_written = sendto(sockfd, mem, len, MSG_FASTOPEN,
366 conn->ip_addr->ai_addr, conn->ip_addr->ai_addrlen);
367 conn->bits.tcp_fastopen = FALSE;
368 }
369 else
370 #endif
371 bytes_written = swrite(sockfd, mem, len);
372
373 *code = CURLE_OK;
374 if(-1 == bytes_written) {
375 int err = SOCKERRNO;
376
377 if(
378 #ifdef WSAEWOULDBLOCK
379 /* This is how Windows does it */
380 (WSAEWOULDBLOCK == err)
381 #else
382 /* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned
383 due to its inability to send off data without blocking. We therefor
384 treat both error codes the same here */
385 (EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err) ||
386 (EINPROGRESS == err)
387 #endif
388 ) {
389 /* this is just a case of EWOULDBLOCK */
390 bytes_written=0;
391 *code = CURLE_AGAIN;
392 }
393 else {
394 failf(conn->data, "Send failure: %s",
395 Curl_strerror(conn, err));
396 conn->data->state.os_errno = err;
397 *code = CURLE_SEND_ERROR;
398 }
399 }
400 return bytes_written;
401 }
402
403 /*
404 * Curl_write_plain() is an internal write function that sends data to the
405 * server using plain sockets only. Otherwise meant to have the exact same
406 * proto as Curl_write()
407 */
Curl_write_plain(struct connectdata * conn,curl_socket_t sockfd,const void * mem,size_t len,ssize_t * written)408 CURLcode Curl_write_plain(struct connectdata *conn,
409 curl_socket_t sockfd,
410 const void *mem,
411 size_t len,
412 ssize_t *written)
413 {
414 ssize_t bytes_written;
415 CURLcode result;
416 int num = (sockfd == conn->sock[SECONDARYSOCKET]);
417
418 bytes_written = Curl_send_plain(conn, num, mem, len, &result);
419
420 *written = bytes_written;
421
422 return result;
423 }
424
Curl_recv_plain(struct connectdata * conn,int num,char * buf,size_t len,CURLcode * code)425 ssize_t Curl_recv_plain(struct connectdata *conn, int num, char *buf,
426 size_t len, CURLcode *code)
427 {
428 curl_socket_t sockfd = conn->sock[num];
429 ssize_t nread;
430 /* Check and return data that already received and storied in internal
431 intermediate buffer */
432 nread = get_pre_recved(conn, num, buf, len);
433 if(nread > 0) {
434 *code = CURLE_OK;
435 return nread;
436 }
437
438 nread = sread(sockfd, buf, len);
439
440 *code = CURLE_OK;
441 if(-1 == nread) {
442 int err = SOCKERRNO;
443
444 if(
445 #ifdef WSAEWOULDBLOCK
446 /* This is how Windows does it */
447 (WSAEWOULDBLOCK == err)
448 #else
449 /* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned
450 due to its inability to send off data without blocking. We therefor
451 treat both error codes the same here */
452 (EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err)
453 #endif
454 ) {
455 /* this is just a case of EWOULDBLOCK */
456 *code = CURLE_AGAIN;
457 }
458 else {
459 failf(conn->data, "Recv failure: %s",
460 Curl_strerror(conn, err));
461 conn->data->state.os_errno = err;
462 *code = CURLE_RECV_ERROR;
463 }
464 }
465 return nread;
466 }
467
pausewrite(struct Curl_easy * data,int type,const char * ptr,size_t len)468 static CURLcode pausewrite(struct Curl_easy *data,
469 int type, /* what type of data */
470 const char *ptr,
471 size_t len)
472 {
473 /* signalled to pause sending on this connection, but since we have data
474 we want to send we need to dup it to save a copy for when the sending
475 is again enabled */
476 struct SingleRequest *k = &data->req;
477 char *dupl = malloc(len);
478 if(!dupl)
479 return CURLE_OUT_OF_MEMORY;
480
481 memcpy(dupl, ptr, len);
482
483 /* store this information in the state struct for later use */
484 data->state.tempwrite = dupl;
485 data->state.tempwritesize = len;
486 data->state.tempwritetype = type;
487
488 /* mark the connection as RECV paused */
489 k->keepon |= KEEP_RECV_PAUSE;
490
491 DEBUGF(infof(data, "Pausing with %zu bytes in buffer for type %02x\n",
492 len, type));
493
494 return CURLE_OK;
495 }
496
497
498 /* Curl_client_chop_write() writes chunks of data not larger than
499 * CURL_MAX_WRITE_SIZE via client write callback(s) and
500 * takes care of pause requests from the callbacks.
501 */
Curl_client_chop_write(struct connectdata * conn,int type,char * ptr,size_t len)502 CURLcode Curl_client_chop_write(struct connectdata *conn,
503 int type,
504 char *ptr,
505 size_t len)
506 {
507 struct Curl_easy *data = conn->data;
508 curl_write_callback writeheader = NULL;
509 curl_write_callback writebody = NULL;
510
511 if(!len)
512 return CURLE_OK;
513
514 /* If reading is actually paused, we're forced to append this chunk of data
515 to the already held data, but only if it is the same type as otherwise it
516 can't work and it'll return error instead. */
517 if(data->req.keepon & KEEP_RECV_PAUSE) {
518 size_t newlen;
519 char *newptr;
520 if(type != data->state.tempwritetype)
521 /* major internal confusion */
522 return CURLE_RECV_ERROR;
523
524 DEBUGASSERT(data->state.tempwrite);
525
526 /* figure out the new size of the data to save */
527 newlen = len + data->state.tempwritesize;
528 /* allocate the new memory area */
529 newptr = realloc(data->state.tempwrite, newlen);
530 if(!newptr)
531 return CURLE_OUT_OF_MEMORY;
532 /* copy the new data to the end of the new area */
533 memcpy(newptr + data->state.tempwritesize, ptr, len);
534 /* update the pointer and the size */
535 data->state.tempwrite = newptr;
536 data->state.tempwritesize = newlen;
537 return CURLE_OK;
538 }
539
540 /* Determine the callback(s) to use. */
541 if(type & CLIENTWRITE_BODY)
542 writebody = data->set.fwrite_func;
543 if((type & CLIENTWRITE_HEADER) &&
544 (data->set.fwrite_header || data->set.writeheader)) {
545 /*
546 * Write headers to the same callback or to the especially setup
547 * header callback function (added after version 7.7.1).
548 */
549 writeheader =
550 data->set.fwrite_header? data->set.fwrite_header: data->set.fwrite_func;
551 }
552
553 /* Chop data, write chunks. */
554 while(len) {
555 size_t chunklen = len <= CURL_MAX_WRITE_SIZE? len: CURL_MAX_WRITE_SIZE;
556
557 if(writebody) {
558 size_t wrote = writebody(ptr, 1, chunklen, data->set.out);
559
560 if(CURL_WRITEFUNC_PAUSE == wrote) {
561 if(conn->handler->flags & PROTOPT_NONETWORK) {
562 /* Protocols that work without network cannot be paused. This is
563 actually only FILE:// just now, and it can't pause since the
564 transfer isn't done using the "normal" procedure. */
565 failf(data, "Write callback asked for PAUSE when not supported!");
566 return CURLE_WRITE_ERROR;
567 }
568 else
569 return pausewrite(data, type, ptr, len);
570 }
571 else if(wrote != chunklen) {
572 failf(data, "Failed writing body (%zu != %zu)", wrote, chunklen);
573 return CURLE_WRITE_ERROR;
574 }
575 }
576
577 if(writeheader) {
578 size_t wrote = writeheader(ptr, 1, chunklen, data->set.writeheader);
579
580 if(CURL_WRITEFUNC_PAUSE == wrote)
581 /* here we pass in the HEADER bit only since if this was body as well
582 then it was passed already and clearly that didn't trigger the
583 pause, so this is saved for later with the HEADER bit only */
584 return pausewrite(data, CLIENTWRITE_HEADER, ptr, len);
585
586 if(wrote != chunklen) {
587 failf(data, "Failed writing header");
588 return CURLE_WRITE_ERROR;
589 }
590 }
591
592 ptr += chunklen;
593 len -= chunklen;
594 }
595
596 return CURLE_OK;
597 }
598
599
600 /* Curl_client_write() sends data to the write callback(s)
601
602 The bit pattern defines to what "streams" to write to. Body and/or header.
603 The defines are in sendf.h of course.
604
605 If CURL_DO_LINEEND_CONV is enabled, data is converted IN PLACE to the
606 local character encoding. This is a problem and should be changed in
607 the future to leave the original data alone.
608 */
Curl_client_write(struct connectdata * conn,int type,char * ptr,size_t len)609 CURLcode Curl_client_write(struct connectdata *conn,
610 int type,
611 char *ptr,
612 size_t len)
613 {
614 struct Curl_easy *data = conn->data;
615
616 if(0 == len)
617 len = strlen(ptr);
618
619 /* FTP data may need conversion. */
620 if((type & CLIENTWRITE_BODY) &&
621 (conn->handler->protocol & PROTO_FAMILY_FTP) &&
622 conn->proto.ftpc.transfertype == 'A') {
623 /* convert from the network encoding */
624 CURLcode result = Curl_convert_from_network(data, ptr, len);
625 /* Curl_convert_from_network calls failf if unsuccessful */
626 if(result)
627 return result;
628
629 #ifdef CURL_DO_LINEEND_CONV
630 /* convert end-of-line markers */
631 len = convert_lineends(data, ptr, len);
632 #endif /* CURL_DO_LINEEND_CONV */
633 }
634
635 return Curl_client_chop_write(conn, type, ptr, len);
636 }
637
Curl_read_plain(curl_socket_t sockfd,char * buf,size_t bytesfromsocket,ssize_t * n)638 CURLcode Curl_read_plain(curl_socket_t sockfd,
639 char *buf,
640 size_t bytesfromsocket,
641 ssize_t *n)
642 {
643 ssize_t nread = sread(sockfd, buf, bytesfromsocket);
644
645 if(-1 == nread) {
646 int err = SOCKERRNO;
647 int return_error;
648 #ifdef USE_WINSOCK
649 return_error = WSAEWOULDBLOCK == err;
650 #else
651 return_error = EWOULDBLOCK == err || EAGAIN == err || EINTR == err;
652 #endif
653 if(return_error)
654 return CURLE_AGAIN;
655 else
656 return CURLE_RECV_ERROR;
657 }
658
659 /* we only return number of bytes read when we return OK */
660 *n = nread;
661 return CURLE_OK;
662 }
663
664 /*
665 * Internal read-from-socket function. This is meant to deal with plain
666 * sockets, SSL sockets and kerberos sockets.
667 *
668 * Returns a regular CURLcode value.
669 */
Curl_read(struct connectdata * conn,curl_socket_t sockfd,char * buf,size_t sizerequested,ssize_t * n)670 CURLcode Curl_read(struct connectdata *conn, /* connection data */
671 curl_socket_t sockfd, /* read from this socket */
672 char *buf, /* store read data here */
673 size_t sizerequested, /* max amount to read */
674 ssize_t *n) /* amount bytes read */
675 {
676 CURLcode result = CURLE_RECV_ERROR;
677 ssize_t nread = 0;
678 size_t bytesfromsocket = 0;
679 char *buffertofill = NULL;
680
681 /* if HTTP/1 pipelining is both wanted and possible */
682 bool pipelining = Curl_pipeline_wanted(conn->data->multi, CURLPIPE_HTTP1) &&
683 (conn->bundle->multiuse == BUNDLE_PIPELINING);
684
685 /* Set 'num' to 0 or 1, depending on which socket that has been sent here.
686 If it is the second socket, we set num to 1. Otherwise to 0. This lets
687 us use the correct ssl handle. */
688 int num = (sockfd == conn->sock[SECONDARYSOCKET]);
689
690 *n=0; /* reset amount to zero */
691
692 /* If session can pipeline, check connection buffer */
693 if(pipelining) {
694 size_t bytestocopy = CURLMIN(conn->buf_len - conn->read_pos,
695 sizerequested);
696
697 /* Copy from our master buffer first if we have some unread data there*/
698 if(bytestocopy > 0) {
699 memcpy(buf, conn->master_buffer + conn->read_pos, bytestocopy);
700 conn->read_pos += bytestocopy;
701 conn->bits.stream_was_rewound = FALSE;
702
703 *n = (ssize_t)bytestocopy;
704 return CURLE_OK;
705 }
706 /* If we come here, it means that there is no data to read from the buffer,
707 * so we read from the socket */
708 bytesfromsocket = CURLMIN(sizerequested, BUFSIZE * sizeof(char));
709 buffertofill = conn->master_buffer;
710 }
711 else {
712 bytesfromsocket = CURLMIN((long)sizerequested,
713 conn->data->set.buffer_size ?
714 conn->data->set.buffer_size : BUFSIZE);
715 buffertofill = buf;
716 }
717
718 nread = conn->recv[num](conn, num, buffertofill, bytesfromsocket, &result);
719 if(nread < 0)
720 return result;
721
722 if(pipelining) {
723 memcpy(buf, conn->master_buffer, nread);
724 conn->buf_len = nread;
725 conn->read_pos = nread;
726 }
727
728 *n += nread;
729
730 return CURLE_OK;
731 }
732
733 /* return 0 on success */
showit(struct Curl_easy * data,curl_infotype type,char * ptr,size_t size)734 static int showit(struct Curl_easy *data, curl_infotype type,
735 char *ptr, size_t size)
736 {
737 static const char s_infotype[CURLINFO_END][3] = {
738 "* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
739
740 #ifdef CURL_DOES_CONVERSIONS
741 char buf[BUFSIZE+1];
742 size_t conv_size = 0;
743
744 switch(type) {
745 case CURLINFO_HEADER_OUT:
746 /* assume output headers are ASCII */
747 /* copy the data into my buffer so the original is unchanged */
748 if(size > BUFSIZE) {
749 size = BUFSIZE; /* truncate if necessary */
750 buf[BUFSIZE] = '\0';
751 }
752 conv_size = size;
753 memcpy(buf, ptr, size);
754 /* Special processing is needed for this block if it
755 * contains both headers and data (separated by CRLFCRLF).
756 * We want to convert just the headers, leaving the data as-is.
757 */
758 if(size > 4) {
759 size_t i;
760 for(i = 0; i < size-4; i++) {
761 if(memcmp(&buf[i], "\x0d\x0a\x0d\x0a", 4) == 0) {
762 /* convert everything through this CRLFCRLF but no further */
763 conv_size = i + 4;
764 break;
765 }
766 }
767 }
768
769 Curl_convert_from_network(data, buf, conv_size);
770 /* Curl_convert_from_network calls failf if unsuccessful */
771 /* we might as well continue even if it fails... */
772 ptr = buf; /* switch pointer to use my buffer instead */
773 break;
774 default:
775 /* leave everything else as-is */
776 break;
777 }
778 #endif /* CURL_DOES_CONVERSIONS */
779
780 if(data->set.fdebug)
781 return (*data->set.fdebug)(data, type, ptr, size,
782 data->set.debugdata);
783
784 switch(type) {
785 case CURLINFO_TEXT:
786 case CURLINFO_HEADER_OUT:
787 case CURLINFO_HEADER_IN:
788 fwrite(s_infotype[type], 2, 1, data->set.err);
789 fwrite(ptr, size, 1, data->set.err);
790 #ifdef CURL_DOES_CONVERSIONS
791 if(size != conv_size) {
792 /* we had untranslated data so we need an explicit newline */
793 fwrite("\n", 1, 1, data->set.err);
794 }
795 #endif
796 break;
797 default: /* nada */
798 break;
799 }
800 return 0;
801 }
802
Curl_debug(struct Curl_easy * data,curl_infotype type,char * ptr,size_t size,struct connectdata * conn)803 int Curl_debug(struct Curl_easy *data, curl_infotype type,
804 char *ptr, size_t size,
805 struct connectdata *conn)
806 {
807 int rc;
808 if(data->set.printhost && conn && conn->host.dispname) {
809 char buffer[160];
810 const char *t=NULL;
811 const char *w="Data";
812 switch(type) {
813 case CURLINFO_HEADER_IN:
814 w = "Header";
815 /* FALLTHROUGH */
816 case CURLINFO_DATA_IN:
817 t = "from";
818 break;
819 case CURLINFO_HEADER_OUT:
820 w = "Header";
821 /* FALLTHROUGH */
822 case CURLINFO_DATA_OUT:
823 t = "to";
824 break;
825 default:
826 break;
827 }
828
829 if(t) {
830 snprintf(buffer, sizeof(buffer), "[%s %s %s]", w, t,
831 conn->host.dispname);
832 rc = showit(data, CURLINFO_TEXT, buffer, strlen(buffer));
833 if(rc)
834 return rc;
835 }
836 }
837 rc = showit(data, type, ptr, size);
838 return rc;
839 }
840