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