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