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