• 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. "len" is not allowed to be 0.
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(len);
625   DEBUGASSERT(type <= 3);
626 
627   /* FTP data may need conversion. */
628   if((type & CLIENTWRITE_BODY) &&
629     (conn->handler->protocol & PROTO_FAMILY_FTP) &&
630     conn->proto.ftpc.transfertype == 'A') {
631     /* convert from the network encoding */
632     CURLcode result = Curl_convert_from_network(data, ptr, len);
633     /* Curl_convert_from_network calls failf if unsuccessful */
634     if(result)
635       return result;
636 
637 #ifdef CURL_DO_LINEEND_CONV
638     /* convert end-of-line markers */
639     len = convert_lineends(data, ptr, len);
640 #endif /* CURL_DO_LINEEND_CONV */
641     }
642 
643   return chop_write(data, type, ptr, len);
644 }
645 
Curl_read_plain(curl_socket_t sockfd,char * buf,size_t bytesfromsocket,ssize_t * n)646 CURLcode Curl_read_plain(curl_socket_t sockfd,
647                          char *buf,
648                          size_t bytesfromsocket,
649                          ssize_t *n)
650 {
651   ssize_t nread = sread(sockfd, buf, bytesfromsocket);
652 
653   if(-1 == nread) {
654     const int err = SOCKERRNO;
655     const bool return_error =
656 #ifdef USE_WINSOCK
657       WSAEWOULDBLOCK == err
658 #else
659       EWOULDBLOCK == err || EAGAIN == err || EINTR == err
660 #endif
661       ;
662     *n = 0; /* no data returned */
663     if(return_error)
664       return CURLE_AGAIN;
665     return CURLE_RECV_ERROR;
666   }
667 
668   *n = nread;
669   return CURLE_OK;
670 }
671 
672 /*
673  * Internal read-from-socket function. This is meant to deal with plain
674  * sockets, SSL sockets and kerberos sockets.
675  *
676  * Returns a regular CURLcode value.
677  */
Curl_read(struct Curl_easy * data,curl_socket_t sockfd,char * buf,size_t sizerequested,ssize_t * n)678 CURLcode Curl_read(struct Curl_easy *data,   /* transfer */
679                    curl_socket_t sockfd,     /* read from this socket */
680                    char *buf,                /* store read data here */
681                    size_t sizerequested,     /* max amount to read */
682                    ssize_t *n)               /* amount bytes read */
683 {
684   CURLcode result = CURLE_RECV_ERROR;
685   ssize_t nread = 0;
686   size_t bytesfromsocket = 0;
687   char *buffertofill = NULL;
688   struct connectdata *conn = data->conn;
689 
690   /* Set 'num' to 0 or 1, depending on which socket that has been sent here.
691      If it is the second socket, we set num to 1. Otherwise to 0. This lets
692      us use the correct ssl handle. */
693   int num = (sockfd == conn->sock[SECONDARYSOCKET]);
694 
695   *n = 0; /* reset amount to zero */
696 
697   bytesfromsocket = CURLMIN(sizerequested, (size_t)data->set.buffer_size);
698   buffertofill = buf;
699 
700   nread = conn->recv[num](data, num, buffertofill, bytesfromsocket, &result);
701   if(nread < 0)
702     return result;
703 
704   *n += nread;
705 
706   return CURLE_OK;
707 }
708 
709 /* return 0 on success */
Curl_debug(struct Curl_easy * data,curl_infotype type,char * ptr,size_t size)710 int Curl_debug(struct Curl_easy *data, curl_infotype type,
711                char *ptr, size_t size)
712 {
713   int rc = 0;
714   if(data->set.verbose) {
715     static const char s_infotype[CURLINFO_END][3] = {
716       "* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
717 
718 #ifdef CURL_DOES_CONVERSIONS
719     char *buf = NULL;
720     size_t conv_size = 0;
721 
722     switch(type) {
723     case CURLINFO_HEADER_OUT:
724       buf = Curl_memdup(ptr, size);
725       if(!buf)
726         return 1;
727       conv_size = size;
728 
729       /* Special processing is needed for this block if it
730        * contains both headers and data (separated by CRLFCRLF).
731        * We want to convert just the headers, leaving the data as-is.
732        */
733       if(size > 4) {
734         size_t i;
735         for(i = 0; i < size-4; i++) {
736           if(memcmp(&buf[i], "\x0d\x0a\x0d\x0a", 4) == 0) {
737             /* convert everything through this CRLFCRLF but no further */
738             conv_size = i + 4;
739             break;
740           }
741         }
742       }
743 
744       Curl_convert_from_network(data, buf, conv_size);
745       /* Curl_convert_from_network calls failf if unsuccessful */
746       /* we might as well continue even if it fails...   */
747       ptr = buf; /* switch pointer to use my buffer instead */
748       break;
749     default:
750       /* leave everything else as-is */
751       break;
752     }
753 #endif /* CURL_DOES_CONVERSIONS */
754 
755     if(data->set.fdebug) {
756       Curl_set_in_callback(data, true);
757       rc = (*data->set.fdebug)(data, type, ptr, size, data->set.debugdata);
758       Curl_set_in_callback(data, false);
759     }
760     else {
761       switch(type) {
762       case CURLINFO_TEXT:
763       case CURLINFO_HEADER_OUT:
764       case CURLINFO_HEADER_IN:
765         fwrite(s_infotype[type], 2, 1, data->set.err);
766         fwrite(ptr, size, 1, data->set.err);
767 #ifdef CURL_DOES_CONVERSIONS
768         if(size != conv_size) {
769           /* we had untranslated data so we need an explicit newline */
770           fwrite("\n", 1, 1, data->set.err);
771         }
772 #endif
773         break;
774       default: /* nada */
775         break;
776       }
777     }
778 #ifdef CURL_DOES_CONVERSIONS
779     free(buf);
780 #endif
781   }
782   return rc;
783 }
784