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