sendf.c
Go to the documentation of this file.
00001 /***************************************************************************
00002  *                                  _   _ ____  _
00003  *  Project                     ___| | | |  _ \| |
00004  *                             / __| | | | |_) | |
00005  *                            | (__| |_| |  _ <| |___
00006  *                             \___|\___/|_| \_\_____|
00007  *
00008  * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
00009  *
00010  * This software is licensed as described in the file COPYING, which
00011  * you should have received as part of this distribution. The terms
00012  * are also available at https://curl.haxx.se/docs/copyright.html.
00013  *
00014  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
00015  * copies of the Software, and permit persons to whom the Software is
00016  * furnished to do so, under the terms of the COPYING file.
00017  *
00018  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
00019  * KIND, either express or implied.
00020  *
00021  ***************************************************************************/
00022 
00023 #include "curl_setup.h"
00024 
00025 #include <curl/curl.h>
00026 
00027 #include "urldata.h"
00028 #include "sendf.h"
00029 #include "connect.h"
00030 #include "vtls/vtls.h"
00031 #include "ssh.h"
00032 #include "multiif.h"
00033 #include "non-ascii.h"
00034 #include "strerror.h"
00035 #include "select.h"
00036 
00037 /* The last 3 #include files should be in this order */
00038 #include "curl_printf.h"
00039 #include "curl_memory.h"
00040 #include "memdebug.h"
00041 
00042 #ifdef CURL_DO_LINEEND_CONV
00043 /*
00044  * convert_lineends() changes CRLF (\r\n) end-of-line markers to a single LF
00045  * (\n), with special processing for CRLF sequences that are split between two
00046  * blocks of data.  Remaining, bare CRs are changed to LFs.  The possibly new
00047  * size of the data is returned.
00048  */
00049 static size_t convert_lineends(struct Curl_easy *data,
00050                                char *startPtr, size_t size)
00051 {
00052   char *inPtr, *outPtr;
00053 
00054   /* sanity check */
00055   if((startPtr == NULL) || (size < 1)) {
00056     return size;
00057   }
00058 
00059   if(data->state.prev_block_had_trailing_cr) {
00060     /* The previous block of incoming data
00061        had a trailing CR, which was turned into a LF. */
00062     if(*startPtr == '\n') {
00063       /* This block of incoming data starts with the
00064          previous block's LF so get rid of it */
00065       memmove(startPtr, startPtr+1, size-1);
00066       size--;
00067       /* and it wasn't a bare CR but a CRLF conversion instead */
00068       data->state.crlf_conversions++;
00069     }
00070     data->state.prev_block_had_trailing_cr = FALSE; /* reset the flag */
00071   }
00072 
00073   /* find 1st CR, if any */
00074   inPtr = outPtr = memchr(startPtr, '\r', size);
00075   if(inPtr) {
00076     /* at least one CR, now look for CRLF */
00077     while(inPtr < (startPtr+size-1)) {
00078       /* note that it's size-1, so we'll never look past the last byte */
00079       if(memcmp(inPtr, "\r\n", 2) == 0) {
00080         /* CRLF found, bump past the CR and copy the NL */
00081         inPtr++;
00082         *outPtr = *inPtr;
00083         /* keep track of how many CRLFs we converted */
00084         data->state.crlf_conversions++;
00085       }
00086       else {
00087         if(*inPtr == '\r') {
00088           /* lone CR, move LF instead */
00089           *outPtr = '\n';
00090         }
00091         else {
00092           /* not a CRLF nor a CR, just copy whatever it is */
00093           *outPtr = *inPtr;
00094         }
00095       }
00096       outPtr++;
00097       inPtr++;
00098     } /* end of while loop */
00099 
00100     if(inPtr < startPtr+size) {
00101       /* handle last byte */
00102       if(*inPtr == '\r') {
00103         /* deal with a CR at the end of the buffer */
00104         *outPtr = '\n'; /* copy a NL instead */
00105         /* note that a CRLF might be split across two blocks */
00106         data->state.prev_block_had_trailing_cr = TRUE;
00107       }
00108       else {
00109         /* copy last byte */
00110         *outPtr = *inPtr;
00111       }
00112       outPtr++;
00113     }
00114     if(outPtr < startPtr+size)
00115       /* tidy up by null terminating the now shorter data */
00116       *outPtr = '\0';
00117 
00118     return (outPtr - startPtr);
00119   }
00120   return size;
00121 }
00122 #endif /* CURL_DO_LINEEND_CONV */
00123 
00124 #ifdef USE_RECV_BEFORE_SEND_WORKAROUND
00125 bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex)
00126 {
00127   struct postponed_data * const psnd = &(conn->postponed[sockindex]);
00128   return psnd->buffer && psnd->allocated_size &&
00129          psnd->recv_size > psnd->recv_processed;
00130 }
00131 
00132 static void pre_receive_plain(struct connectdata *conn, int num)
00133 {
00134   const curl_socket_t sockfd = conn->sock[num];
00135   struct postponed_data * const psnd = &(conn->postponed[num]);
00136   size_t bytestorecv = psnd->allocated_size - psnd->recv_size;
00137   /* WinSock will destroy unread received data if send() is
00138      failed.
00139      To avoid lossage of received data, recv() must be
00140      performed before every send() if any incoming data is
00141      available. However, skip this, if buffer is already full. */
00142   if((conn->handler->protocol&PROTO_FAMILY_HTTP) != 0 &&
00143      conn->recv[num] == Curl_recv_plain &&
00144      (!psnd->buffer || bytestorecv)) {
00145     const int readymask = Curl_socket_check(sockfd, CURL_SOCKET_BAD,
00146                                             CURL_SOCKET_BAD, 0);
00147     if(readymask != -1 && (readymask & CURL_CSELECT_IN) != 0) {
00148       /* Have some incoming data */
00149       if(!psnd->buffer) {
00150         /* Use buffer double default size for intermediate buffer */
00151         psnd->allocated_size = 2 * BUFSIZE;
00152         psnd->buffer = malloc(psnd->allocated_size);
00153         psnd->recv_size = 0;
00154         psnd->recv_processed = 0;
00155 #ifdef DEBUGBUILD
00156         psnd->bindsock = sockfd; /* Used only for DEBUGASSERT */
00157 #endif /* DEBUGBUILD */
00158         bytestorecv = psnd->allocated_size;
00159       }
00160       if(psnd->buffer) {
00161         ssize_t recvedbytes;
00162         DEBUGASSERT(psnd->bindsock == sockfd);
00163         recvedbytes = sread(sockfd, psnd->buffer + psnd->recv_size,
00164                             bytestorecv);
00165         if(recvedbytes > 0)
00166           psnd->recv_size += recvedbytes;
00167       }
00168       else
00169         psnd->allocated_size = 0;
00170     }
00171   }
00172 }
00173 
00174 static ssize_t get_pre_recved(struct connectdata *conn, int num, char *buf,
00175                               size_t len)
00176 {
00177   struct postponed_data * const psnd = &(conn->postponed[num]);
00178   size_t copysize;
00179   if(!psnd->buffer)
00180     return 0;
00181 
00182   DEBUGASSERT(psnd->allocated_size > 0);
00183   DEBUGASSERT(psnd->recv_size <= psnd->allocated_size);
00184   DEBUGASSERT(psnd->recv_processed <= psnd->recv_size);
00185   /* Check and process data that already received and storied in internal
00186      intermediate buffer */
00187   if(psnd->recv_size > psnd->recv_processed) {
00188     DEBUGASSERT(psnd->bindsock == conn->sock[num]);
00189     copysize = CURLMIN(len, psnd->recv_size - psnd->recv_processed);
00190     memcpy(buf, psnd->buffer + psnd->recv_processed, copysize);
00191     psnd->recv_processed += copysize;
00192   }
00193   else
00194     copysize = 0; /* buffer was allocated, but nothing was received */
00195 
00196   /* Free intermediate buffer if it has no unprocessed data */
00197   if(psnd->recv_processed == psnd->recv_size) {
00198     free(psnd->buffer);
00199     psnd->buffer = NULL;
00200     psnd->allocated_size = 0;
00201     psnd->recv_size = 0;
00202     psnd->recv_processed = 0;
00203 #ifdef DEBUGBUILD
00204     psnd->bindsock = CURL_SOCKET_BAD;
00205 #endif /* DEBUGBUILD */
00206   }
00207   return (ssize_t)copysize;
00208 }
00209 #else  /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
00210 /* Use "do-nothing" macros instead of functions when workaround not used */
00211 bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex)
00212 {
00213   (void)conn;
00214   (void)sockindex;
00215   return false;
00216 }
00217 #define pre_receive_plain(c,n) do {} WHILE_FALSE
00218 #define get_pre_recved(c,n,b,l) 0
00219 #endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
00220 
00221 /* Curl_infof() is for info message along the way */
00222 
00223 void Curl_infof(struct Curl_easy *data, const char *fmt, ...)
00224 {
00225   if(data && data->set.verbose) {
00226     va_list ap;
00227     size_t len;
00228     char print_buffer[2048 + 1];
00229     va_start(ap, fmt);
00230     vsnprintf(print_buffer, sizeof(print_buffer), fmt, ap);
00231     va_end(ap);
00232     len = strlen(print_buffer);
00233     Curl_debug(data, CURLINFO_TEXT, print_buffer, len, NULL);
00234   }
00235 }
00236 
00237 /* Curl_failf() is for messages stating why we failed.
00238  * The message SHALL NOT include any LF or CR.
00239  */
00240 
00241 void Curl_failf(struct Curl_easy *data, const char *fmt, ...)
00242 {
00243   va_list ap;
00244   size_t len;
00245   va_start(ap, fmt);
00246 
00247   vsnprintf(data->state.buffer, BUFSIZE, fmt, ap);
00248 
00249   if(data->set.errorbuffer && !data->state.errorbuf) {
00250     snprintf(data->set.errorbuffer, CURL_ERROR_SIZE, "%s", data->state.buffer);
00251     data->state.errorbuf = TRUE; /* wrote error string */
00252   }
00253   if(data->set.verbose) {
00254     len = strlen(data->state.buffer);
00255     if(len < BUFSIZE - 1) {
00256       data->state.buffer[len] = '\n';
00257       data->state.buffer[++len] = '\0';
00258     }
00259     Curl_debug(data, CURLINFO_TEXT, data->state.buffer, len, NULL);
00260   }
00261 
00262   va_end(ap);
00263 }
00264 
00265 /* Curl_sendf() sends formated data to the server */
00266 CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *conn,
00267                     const char *fmt, ...)
00268 {
00269   struct Curl_easy *data = conn->data;
00270   ssize_t bytes_written;
00271   size_t write_len;
00272   CURLcode result = CURLE_OK;
00273   char *s;
00274   char *sptr;
00275   va_list ap;
00276   va_start(ap, fmt);
00277   s = vaprintf(fmt, ap); /* returns an allocated string */
00278   va_end(ap);
00279   if(!s)
00280     return CURLE_OUT_OF_MEMORY; /* failure */
00281 
00282   bytes_written=0;
00283   write_len = strlen(s);
00284   sptr = s;
00285 
00286   for(;;) {
00287     /* Write the buffer to the socket */
00288     result = Curl_write(conn, sockfd, sptr, write_len, &bytes_written);
00289 
00290     if(result)
00291       break;
00292 
00293     if(data->set.verbose)
00294       Curl_debug(data, CURLINFO_DATA_OUT, sptr, (size_t)bytes_written, conn);
00295 
00296     if((size_t)bytes_written != write_len) {
00297       /* if not all was written at once, we must advance the pointer, decrease
00298          the size left and try again! */
00299       write_len -= bytes_written;
00300       sptr += bytes_written;
00301     }
00302     else
00303       break;
00304   }
00305 
00306   free(s); /* free the output string */
00307 
00308   return result;
00309 }
00310 
00311 /*
00312  * Curl_write() is an internal write function that sends data to the
00313  * server. Works with plain sockets, SCP, SSL or kerberos.
00314  *
00315  * If the write would block (CURLE_AGAIN), we return CURLE_OK and
00316  * (*written == 0). Otherwise we return regular CURLcode value.
00317  */
00318 CURLcode Curl_write(struct connectdata *conn,
00319                     curl_socket_t sockfd,
00320                     const void *mem,
00321                     size_t len,
00322                     ssize_t *written)
00323 {
00324   ssize_t bytes_written;
00325   CURLcode result = CURLE_OK;
00326   int num = (sockfd == conn->sock[SECONDARYSOCKET]);
00327 
00328   bytes_written = conn->send[num](conn, num, mem, len, &result);
00329 
00330   *written = bytes_written;
00331   if(bytes_written >= 0)
00332     /* we completely ignore the curlcode value when subzero is not returned */
00333     return CURLE_OK;
00334 
00335   /* handle CURLE_AGAIN or a send failure */
00336   switch(result) {
00337   case CURLE_AGAIN:
00338     *written = 0;
00339     return CURLE_OK;
00340 
00341   case CURLE_OK:
00342     /* general send failure */
00343     return CURLE_SEND_ERROR;
00344 
00345   default:
00346     /* we got a specific curlcode, forward it */
00347     return result;
00348   }
00349 }
00350 
00351 ssize_t Curl_send_plain(struct connectdata *conn, int num,
00352                         const void *mem, size_t len, CURLcode *code)
00353 {
00354   curl_socket_t sockfd = conn->sock[num];
00355   ssize_t bytes_written;
00356   /* WinSock will destroy unread received data if send() is
00357      failed.
00358      To avoid lossage of received data, recv() must be
00359      performed before every send() if any incoming data is
00360      available. */
00361   pre_receive_plain(conn, num);
00362 
00363 #ifdef MSG_FASTOPEN /* Linux */
00364   if(conn->bits.tcp_fastopen) {
00365     bytes_written = sendto(sockfd, mem, len, MSG_FASTOPEN,
00366                            conn->ip_addr->ai_addr, conn->ip_addr->ai_addrlen);
00367     conn->bits.tcp_fastopen = FALSE;
00368   }
00369   else
00370 #endif
00371     bytes_written = swrite(sockfd, mem, len);
00372 
00373   *code = CURLE_OK;
00374   if(-1 == bytes_written) {
00375     int err = SOCKERRNO;
00376 
00377     if(
00378 #ifdef WSAEWOULDBLOCK
00379       /* This is how Windows does it */
00380       (WSAEWOULDBLOCK == err)
00381 #else
00382       /* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned
00383          due to its inability to send off data without blocking. We therefor
00384          treat both error codes the same here */
00385       (EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err) ||
00386       (EINPROGRESS == err)
00387 #endif
00388       ) {
00389       /* this is just a case of EWOULDBLOCK */
00390       bytes_written=0;
00391       *code = CURLE_AGAIN;
00392     }
00393     else {
00394       failf(conn->data, "Send failure: %s",
00395             Curl_strerror(conn, err));
00396       conn->data->state.os_errno = err;
00397       *code = CURLE_SEND_ERROR;
00398     }
00399   }
00400   return bytes_written;
00401 }
00402 
00403 /*
00404  * Curl_write_plain() is an internal write function that sends data to the
00405  * server using plain sockets only. Otherwise meant to have the exact same
00406  * proto as Curl_write()
00407  */
00408 CURLcode Curl_write_plain(struct connectdata *conn,
00409                           curl_socket_t sockfd,
00410                           const void *mem,
00411                           size_t len,
00412                           ssize_t *written)
00413 {
00414   ssize_t bytes_written;
00415   CURLcode result;
00416   int num = (sockfd == conn->sock[SECONDARYSOCKET]);
00417 
00418   bytes_written = Curl_send_plain(conn, num, mem, len, &result);
00419 
00420   *written = bytes_written;
00421 
00422   return result;
00423 }
00424 
00425 ssize_t Curl_recv_plain(struct connectdata *conn, int num, char *buf,
00426                         size_t len, CURLcode *code)
00427 {
00428   curl_socket_t sockfd = conn->sock[num];
00429   ssize_t nread;
00430   /* Check and return data that already received and storied in internal
00431      intermediate buffer */
00432   nread = get_pre_recved(conn, num, buf, len);
00433   if(nread > 0) {
00434     *code = CURLE_OK;
00435     return nread;
00436   }
00437 
00438   nread = sread(sockfd, buf, len);
00439 
00440   *code = CURLE_OK;
00441   if(-1 == nread) {
00442     int err = SOCKERRNO;
00443 
00444     if(
00445 #ifdef WSAEWOULDBLOCK
00446       /* This is how Windows does it */
00447       (WSAEWOULDBLOCK == err)
00448 #else
00449       /* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned
00450          due to its inability to send off data without blocking. We therefor
00451          treat both error codes the same here */
00452       (EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err)
00453 #endif
00454       ) {
00455       /* this is just a case of EWOULDBLOCK */
00456       *code = CURLE_AGAIN;
00457     }
00458     else {
00459       failf(conn->data, "Recv failure: %s",
00460             Curl_strerror(conn, err));
00461       conn->data->state.os_errno = err;
00462       *code = CURLE_RECV_ERROR;
00463     }
00464   }
00465   return nread;
00466 }
00467 
00468 static CURLcode pausewrite(struct Curl_easy *data,
00469                            int type, /* what type of data */
00470                            const char *ptr,
00471                            size_t len)
00472 {
00473   /* signalled to pause sending on this connection, but since we have data
00474      we want to send we need to dup it to save a copy for when the sending
00475      is again enabled */
00476   struct SingleRequest *k = &data->req;
00477   char *dupl = malloc(len);
00478   if(!dupl)
00479     return CURLE_OUT_OF_MEMORY;
00480 
00481   memcpy(dupl, ptr, len);
00482 
00483   /* store this information in the state struct for later use */
00484   data->state.tempwrite = dupl;
00485   data->state.tempwritesize = len;
00486   data->state.tempwritetype = type;
00487 
00488   /* mark the connection as RECV paused */
00489   k->keepon |= KEEP_RECV_PAUSE;
00490 
00491   DEBUGF(infof(data, "Pausing with %zu bytes in buffer for type %02x\n",
00492                len, type));
00493 
00494   return CURLE_OK;
00495 }
00496 
00497 
00498 /* Curl_client_chop_write() writes chunks of data not larger than
00499  * CURL_MAX_WRITE_SIZE via client write callback(s) and
00500  * takes care of pause requests from the callbacks.
00501  */
00502 CURLcode Curl_client_chop_write(struct connectdata *conn,
00503                                 int type,
00504                                 char *ptr,
00505                                 size_t len)
00506 {
00507   struct Curl_easy *data = conn->data;
00508   curl_write_callback writeheader = NULL;
00509   curl_write_callback writebody = NULL;
00510 
00511   if(!len)
00512     return CURLE_OK;
00513 
00514   /* If reading is actually paused, we're forced to append this chunk of data
00515      to the already held data, but only if it is the same type as otherwise it
00516      can't work and it'll return error instead. */
00517   if(data->req.keepon & KEEP_RECV_PAUSE) {
00518     size_t newlen;
00519     char *newptr;
00520     if(type != data->state.tempwritetype)
00521       /* major internal confusion */
00522       return CURLE_RECV_ERROR;
00523 
00524     DEBUGASSERT(data->state.tempwrite);
00525 
00526     /* figure out the new size of the data to save */
00527     newlen = len + data->state.tempwritesize;
00528     /* allocate the new memory area */
00529     newptr = realloc(data->state.tempwrite, newlen);
00530     if(!newptr)
00531       return CURLE_OUT_OF_MEMORY;
00532     /* copy the new data to the end of the new area */
00533     memcpy(newptr + data->state.tempwritesize, ptr, len);
00534     /* update the pointer and the size */
00535     data->state.tempwrite = newptr;
00536     data->state.tempwritesize = newlen;
00537     return CURLE_OK;
00538   }
00539 
00540   /* Determine the callback(s) to use. */
00541   if(type & CLIENTWRITE_BODY)
00542     writebody = data->set.fwrite_func;
00543   if((type & CLIENTWRITE_HEADER) &&
00544      (data->set.fwrite_header || data->set.writeheader)) {
00545     /*
00546      * Write headers to the same callback or to the especially setup
00547      * header callback function (added after version 7.7.1).
00548      */
00549     writeheader =
00550       data->set.fwrite_header? data->set.fwrite_header: data->set.fwrite_func;
00551   }
00552 
00553   /* Chop data, write chunks. */
00554   while(len) {
00555     size_t chunklen = len <= CURL_MAX_WRITE_SIZE? len: CURL_MAX_WRITE_SIZE;
00556 
00557     if(writebody) {
00558       size_t wrote = writebody(ptr, 1, chunklen, data->set.out);
00559 
00560       if(CURL_WRITEFUNC_PAUSE == wrote) {
00561         if(conn->handler->flags & PROTOPT_NONETWORK) {
00562           /* Protocols that work without network cannot be paused. This is
00563              actually only FILE:// just now, and it can't pause since the
00564              transfer isn't done using the "normal" procedure. */
00565           failf(data, "Write callback asked for PAUSE when not supported!");
00566           return CURLE_WRITE_ERROR;
00567         }
00568         else
00569           return pausewrite(data, type, ptr, len);
00570       }
00571       else if(wrote != chunklen) {
00572         failf(data, "Failed writing body (%zu != %zu)", wrote, chunklen);
00573         return CURLE_WRITE_ERROR;
00574       }
00575     }
00576 
00577     if(writeheader) {
00578       size_t wrote = writeheader(ptr, 1, chunklen, data->set.writeheader);
00579 
00580       if(CURL_WRITEFUNC_PAUSE == wrote)
00581         /* here we pass in the HEADER bit only since if this was body as well
00582            then it was passed already and clearly that didn't trigger the
00583            pause, so this is saved for later with the HEADER bit only */
00584         return pausewrite(data, CLIENTWRITE_HEADER, ptr, len);
00585 
00586       if(wrote != chunklen) {
00587         failf(data, "Failed writing header");
00588         return CURLE_WRITE_ERROR;
00589       }
00590     }
00591 
00592     ptr += chunklen;
00593     len -= chunklen;
00594   }
00595 
00596   return CURLE_OK;
00597 }
00598 
00599 
00600 /* Curl_client_write() sends data to the write callback(s)
00601 
00602    The bit pattern defines to what "streams" to write to. Body and/or header.
00603    The defines are in sendf.h of course.
00604 
00605    If CURL_DO_LINEEND_CONV is enabled, data is converted IN PLACE to the
00606    local character encoding.  This is a problem and should be changed in
00607    the future to leave the original data alone.
00608  */
00609 CURLcode Curl_client_write(struct connectdata *conn,
00610                            int type,
00611                            char *ptr,
00612                            size_t len)
00613 {
00614   struct Curl_easy *data = conn->data;
00615 
00616   if(0 == len)
00617     len = strlen(ptr);
00618 
00619   /* FTP data may need conversion. */
00620   if((type & CLIENTWRITE_BODY) &&
00621     (conn->handler->protocol & PROTO_FAMILY_FTP) &&
00622     conn->proto.ftpc.transfertype == 'A') {
00623     /* convert from the network encoding */
00624     CURLcode result = Curl_convert_from_network(data, ptr, len);
00625     /* Curl_convert_from_network calls failf if unsuccessful */
00626     if(result)
00627       return result;
00628 
00629 #ifdef CURL_DO_LINEEND_CONV
00630     /* convert end-of-line markers */
00631     len = convert_lineends(data, ptr, len);
00632 #endif /* CURL_DO_LINEEND_CONV */
00633     }
00634 
00635   return Curl_client_chop_write(conn, type, ptr, len);
00636 }
00637 
00638 CURLcode Curl_read_plain(curl_socket_t sockfd,
00639                          char *buf,
00640                          size_t bytesfromsocket,
00641                          ssize_t *n)
00642 {
00643   ssize_t nread = sread(sockfd, buf, bytesfromsocket);
00644 
00645   if(-1 == nread) {
00646     int err = SOCKERRNO;
00647     int return_error;
00648 #ifdef USE_WINSOCK
00649     return_error = WSAEWOULDBLOCK == err;
00650 #else
00651     return_error = EWOULDBLOCK == err || EAGAIN == err || EINTR == err;
00652 #endif
00653     if(return_error)
00654       return CURLE_AGAIN;
00655     else
00656       return CURLE_RECV_ERROR;
00657   }
00658 
00659   /* we only return number of bytes read when we return OK */
00660   *n = nread;
00661   return CURLE_OK;
00662 }
00663 
00664 /*
00665  * Internal read-from-socket function. This is meant to deal with plain
00666  * sockets, SSL sockets and kerberos sockets.
00667  *
00668  * Returns a regular CURLcode value.
00669  */
00670 CURLcode Curl_read(struct connectdata *conn, /* connection data */
00671                    curl_socket_t sockfd,     /* read from this socket */
00672                    char *buf,                /* store read data here */
00673                    size_t sizerequested,     /* max amount to read */
00674                    ssize_t *n)               /* amount bytes read */
00675 {
00676   CURLcode result = CURLE_RECV_ERROR;
00677   ssize_t nread = 0;
00678   size_t bytesfromsocket = 0;
00679   char *buffertofill = NULL;
00680 
00681   /* if HTTP/1 pipelining is both wanted and possible */
00682   bool pipelining = Curl_pipeline_wanted(conn->data->multi, CURLPIPE_HTTP1) &&
00683     (conn->bundle->multiuse == BUNDLE_PIPELINING);
00684 
00685   /* Set 'num' to 0 or 1, depending on which socket that has been sent here.
00686      If it is the second socket, we set num to 1. Otherwise to 0. This lets
00687      us use the correct ssl handle. */
00688   int num = (sockfd == conn->sock[SECONDARYSOCKET]);
00689 
00690   *n=0; /* reset amount to zero */
00691 
00692   /* If session can pipeline, check connection buffer  */
00693   if(pipelining) {
00694     size_t bytestocopy = CURLMIN(conn->buf_len - conn->read_pos,
00695                                  sizerequested);
00696 
00697     /* Copy from our master buffer first if we have some unread data there*/
00698     if(bytestocopy > 0) {
00699       memcpy(buf, conn->master_buffer + conn->read_pos, bytestocopy);
00700       conn->read_pos += bytestocopy;
00701       conn->bits.stream_was_rewound = FALSE;
00702 
00703       *n = (ssize_t)bytestocopy;
00704       return CURLE_OK;
00705     }
00706     /* If we come here, it means that there is no data to read from the buffer,
00707      * so we read from the socket */
00708     bytesfromsocket = CURLMIN(sizerequested, BUFSIZE * sizeof(char));
00709     buffertofill = conn->master_buffer;
00710   }
00711   else {
00712     bytesfromsocket = CURLMIN((long)sizerequested,
00713                               conn->data->set.buffer_size ?
00714                               conn->data->set.buffer_size : BUFSIZE);
00715     buffertofill = buf;
00716   }
00717 
00718   nread = conn->recv[num](conn, num, buffertofill, bytesfromsocket, &result);
00719   if(nread < 0)
00720     return result;
00721 
00722   if(pipelining) {
00723     memcpy(buf, conn->master_buffer, nread);
00724     conn->buf_len = nread;
00725     conn->read_pos = nread;
00726   }
00727 
00728   *n += nread;
00729 
00730   return CURLE_OK;
00731 }
00732 
00733 /* return 0 on success */
00734 static int showit(struct Curl_easy *data, curl_infotype type,
00735                   char *ptr, size_t size)
00736 {
00737   static const char s_infotype[CURLINFO_END][3] = {
00738     "* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
00739 
00740 #ifdef CURL_DOES_CONVERSIONS
00741   char buf[BUFSIZE+1];
00742   size_t conv_size = 0;
00743 
00744   switch(type) {
00745   case CURLINFO_HEADER_OUT:
00746     /* assume output headers are ASCII */
00747     /* copy the data into my buffer so the original is unchanged */
00748     if(size > BUFSIZE) {
00749       size = BUFSIZE; /* truncate if necessary */
00750       buf[BUFSIZE] = '\0';
00751     }
00752     conv_size = size;
00753     memcpy(buf, ptr, size);
00754     /* Special processing is needed for this block if it
00755      * contains both headers and data (separated by CRLFCRLF).
00756      * We want to convert just the headers, leaving the data as-is.
00757      */
00758     if(size > 4) {
00759       size_t i;
00760       for(i = 0; i < size-4; i++) {
00761         if(memcmp(&buf[i], "\x0d\x0a\x0d\x0a", 4) == 0) {
00762           /* convert everything through this CRLFCRLF but no further */
00763           conv_size = i + 4;
00764           break;
00765         }
00766       }
00767     }
00768 
00769     Curl_convert_from_network(data, buf, conv_size);
00770     /* Curl_convert_from_network calls failf if unsuccessful */
00771     /* we might as well continue even if it fails...   */
00772     ptr = buf; /* switch pointer to use my buffer instead */
00773     break;
00774   default:
00775     /* leave everything else as-is */
00776     break;
00777   }
00778 #endif /* CURL_DOES_CONVERSIONS */
00779 
00780   if(data->set.fdebug)
00781     return (*data->set.fdebug)(data, type, ptr, size,
00782                                data->set.debugdata);
00783 
00784   switch(type) {
00785   case CURLINFO_TEXT:
00786   case CURLINFO_HEADER_OUT:
00787   case CURLINFO_HEADER_IN:
00788     fwrite(s_infotype[type], 2, 1, data->set.err);
00789     fwrite(ptr, size, 1, data->set.err);
00790 #ifdef CURL_DOES_CONVERSIONS
00791     if(size != conv_size) {
00792       /* we had untranslated data so we need an explicit newline */
00793       fwrite("\n", 1, 1, data->set.err);
00794     }
00795 #endif
00796     break;
00797   default: /* nada */
00798     break;
00799   }
00800   return 0;
00801 }
00802 
00803 int Curl_debug(struct Curl_easy *data, curl_infotype type,
00804                char *ptr, size_t size,
00805                struct connectdata *conn)
00806 {
00807   int rc;
00808   if(data->set.printhost && conn && conn->host.dispname) {
00809     char buffer[160];
00810     const char *t=NULL;
00811     const char *w="Data";
00812     switch(type) {
00813     case CURLINFO_HEADER_IN:
00814       w = "Header";
00815       /* FALLTHROUGH */
00816     case CURLINFO_DATA_IN:
00817       t = "from";
00818       break;
00819     case CURLINFO_HEADER_OUT:
00820       w = "Header";
00821       /* FALLTHROUGH */
00822     case CURLINFO_DATA_OUT:
00823       t = "to";
00824       break;
00825     default:
00826       break;
00827     }
00828 
00829     if(t) {
00830       snprintf(buffer, sizeof(buffer), "[%s %s %s]", w, t,
00831                conn->host.dispname);
00832       rc = showit(data, CURLINFO_TEXT, buffer, strlen(buffer));
00833       if(rc)
00834         return rc;
00835     }
00836   }
00837   rc = showit(data, type, ptr, size);
00838   return rc;
00839 }


rc_visard_driver
Author(s): Heiko Hirschmueller , Christian Emmerich , Felix Ruess
autogenerated on Thu Jun 6 2019 20:43:06