quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

sendf.c (39318B)


      1 /***************************************************************************
      2  *                                  _   _ ____  _
      3  *  Project                     ___| | | |  _ \| |
      4  *                             / __| | | | |_) | |
      5  *                            | (__| |_| |  _ <| |___
      6  *                             \___|\___/|_| \_\_____|
      7  *
      8  * Copyright (C) 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  * SPDX-License-Identifier: curl
     22  *
     23  ***************************************************************************/
     24 
     25 #include "curl_setup.h"
     26 
     27 #ifdef HAVE_NETINET_IN_H
     28 #include <netinet/in.h>
     29 #endif
     30 
     31 #ifdef HAVE_LINUX_TCP_H
     32 #include <linux/tcp.h>
     33 #elif defined(HAVE_NETINET_TCP_H)
     34 #include <netinet/tcp.h>
     35 #endif
     36 
     37 #include <curl/curl.h>
     38 
     39 #include "urldata.h"
     40 #include "sendf.h"
     41 #include "transfer.h"
     42 #include "cfilters.h"
     43 #include "connect.h"
     44 #include "content_encoding.h"
     45 #include "cw-out.h"
     46 #include "cw-pause.h"
     47 #include "vtls/vtls.h"
     48 #include "vssh/ssh.h"
     49 #include "easyif.h"
     50 #include "multiif.h"
     51 #include "strerror.h"
     52 #include "select.h"
     53 #include "strdup.h"
     54 #include "http2.h"
     55 #include "progress.h"
     56 #include "curlx/warnless.h"
     57 #include "ws.h"
     58 
     59 /* The last 3 #include files should be in this order */
     60 #include "curl_printf.h"
     61 #include "curl_memory.h"
     62 #include "memdebug.h"
     63 
     64 
     65 static CURLcode do_init_writer_stack(struct Curl_easy *data);
     66 
     67 /* Curl_client_write() sends data to the write callback(s)
     68 
     69    The bit pattern defines to what "streams" to write to. Body and/or header.
     70    The defines are in sendf.h of course.
     71  */
     72 CURLcode Curl_client_write(struct Curl_easy *data,
     73                            int type, const char *buf, size_t blen)
     74 {
     75   CURLcode result;
     76 
     77   /* it is one of those, at least */
     78   DEBUGASSERT(type & (CLIENTWRITE_BODY|CLIENTWRITE_HEADER|CLIENTWRITE_INFO));
     79   /* BODY is only BODY (with optional EOS) */
     80   DEBUGASSERT(!(type & CLIENTWRITE_BODY) ||
     81               ((type & ~(CLIENTWRITE_BODY|CLIENTWRITE_EOS)) == 0));
     82   /* INFO is only INFO (with optional EOS) */
     83   DEBUGASSERT(!(type & CLIENTWRITE_INFO) ||
     84               ((type & ~(CLIENTWRITE_INFO|CLIENTWRITE_EOS)) == 0));
     85 
     86   if(!data->req.writer_stack) {
     87     result = do_init_writer_stack(data);
     88     if(result)
     89       return result;
     90     DEBUGASSERT(data->req.writer_stack);
     91   }
     92 
     93   result = Curl_cwriter_write(data, data->req.writer_stack, type, buf, blen);
     94   CURL_TRC_WRITE(data, "client_write(type=%x, len=%zu) -> %d",
     95                  type, blen, result);
     96   return result;
     97 }
     98 
     99 static void cl_reset_writer(struct Curl_easy *data)
    100 {
    101   struct Curl_cwriter *writer = data->req.writer_stack;
    102   while(writer) {
    103     data->req.writer_stack = writer->next;
    104     writer->cwt->do_close(data, writer);
    105     free(writer);
    106     writer = data->req.writer_stack;
    107   }
    108 }
    109 
    110 static void cl_reset_reader(struct Curl_easy *data)
    111 {
    112   struct Curl_creader *reader = data->req.reader_stack;
    113   while(reader) {
    114     data->req.reader_stack = reader->next;
    115     reader->crt->do_close(data, reader);
    116     free(reader);
    117     reader = data->req.reader_stack;
    118   }
    119 }
    120 
    121 void Curl_client_cleanup(struct Curl_easy *data)
    122 {
    123   cl_reset_reader(data);
    124   cl_reset_writer(data);
    125 
    126   data->req.bytecount = 0;
    127   data->req.headerline = 0;
    128 }
    129 
    130 void Curl_client_reset(struct Curl_easy *data)
    131 {
    132   if(data->req.rewind_read) {
    133     /* already requested */
    134     CURL_TRC_READ(data, "client_reset, will rewind reader");
    135   }
    136   else {
    137     CURL_TRC_READ(data, "client_reset, clear readers");
    138     cl_reset_reader(data);
    139   }
    140   cl_reset_writer(data);
    141 
    142   data->req.bytecount = 0;
    143   data->req.headerline = 0;
    144 }
    145 
    146 CURLcode Curl_client_start(struct Curl_easy *data)
    147 {
    148   if(data->req.rewind_read) {
    149     struct Curl_creader *r = data->req.reader_stack;
    150     CURLcode result = CURLE_OK;
    151 
    152     CURL_TRC_READ(data, "client start, rewind readers");
    153     while(r) {
    154       result = r->crt->rewind(data, r);
    155       if(result) {
    156         failf(data, "rewind of client reader '%s' failed: %d",
    157               r->crt->name, result);
    158         return result;
    159       }
    160       r = r->next;
    161     }
    162     data->req.rewind_read = FALSE;
    163     cl_reset_reader(data);
    164   }
    165   return CURLE_OK;
    166 }
    167 
    168 bool Curl_creader_will_rewind(struct Curl_easy *data)
    169 {
    170   return data->req.rewind_read;
    171 }
    172 
    173 void Curl_creader_set_rewind(struct Curl_easy *data, bool enable)
    174 {
    175   data->req.rewind_read = !!enable;
    176 }
    177 
    178 /* Write data using an unencoding writer stack. */
    179 CURLcode Curl_cwriter_write(struct Curl_easy *data,
    180                             struct Curl_cwriter *writer, int type,
    181                             const char *buf, size_t nbytes)
    182 {
    183   if(!writer)
    184     return CURLE_WRITE_ERROR;
    185   return writer->cwt->do_write(data, writer, type, buf, nbytes);
    186 }
    187 
    188 CURLcode Curl_cwriter_def_init(struct Curl_easy *data,
    189                                struct Curl_cwriter *writer)
    190 {
    191   (void)data;
    192   (void)writer;
    193   return CURLE_OK;
    194 }
    195 
    196 CURLcode Curl_cwriter_def_write(struct Curl_easy *data,
    197                                 struct Curl_cwriter *writer, int type,
    198                                 const char *buf, size_t nbytes)
    199 {
    200   return Curl_cwriter_write(data, writer->next, type, buf, nbytes);
    201 }
    202 
    203 void Curl_cwriter_def_close(struct Curl_easy *data,
    204                             struct Curl_cwriter *writer)
    205 {
    206   (void) data;
    207   (void) writer;
    208 }
    209 
    210 static size_t get_max_body_write_len(struct Curl_easy *data, curl_off_t limit)
    211 {
    212   if(limit != -1) {
    213     /* How much more are we allowed to write? */
    214     curl_off_t remain_diff;
    215     remain_diff = limit - data->req.bytecount;
    216     if(remain_diff < 0) {
    217       /* already written too much! */
    218       return 0;
    219     }
    220 #if SIZEOF_CURL_OFF_T > SIZEOF_SIZE_T
    221     else if(remain_diff > SSIZE_T_MAX) {
    222       return SIZE_T_MAX;
    223     }
    224 #endif
    225     else {
    226       return (size_t)remain_diff;
    227     }
    228   }
    229   return SIZE_T_MAX;
    230 }
    231 
    232 struct cw_download_ctx {
    233   struct Curl_cwriter super;
    234   BIT(started_response);
    235 };
    236 /* Download client writer in phase CURL_CW_PROTOCOL that
    237  * sees the "real" download body data. */
    238 static CURLcode cw_download_write(struct Curl_easy *data,
    239                                   struct Curl_cwriter *writer, int type,
    240                                   const char *buf, size_t nbytes)
    241 {
    242   struct cw_download_ctx *ctx = writer->ctx;
    243   CURLcode result;
    244   size_t nwrite, excess_len = 0;
    245   bool is_connect = !!(type & CLIENTWRITE_CONNECT);
    246 
    247   if(!is_connect && !ctx->started_response) {
    248     Curl_pgrsTime(data, TIMER_STARTTRANSFER);
    249     ctx->started_response = TRUE;
    250   }
    251 
    252   if(!(type & CLIENTWRITE_BODY)) {
    253     if(is_connect && data->set.suppress_connect_headers)
    254       return CURLE_OK;
    255     result = Curl_cwriter_write(data, writer->next, type, buf, nbytes);
    256     CURL_TRC_WRITE(data, "download_write header(type=%x, blen=%zu) -> %d",
    257                    type, nbytes, result);
    258     return result;
    259   }
    260 
    261   /* Here, we deal with REAL BODY bytes. All filtering and transfer
    262    * encodings have been applied and only the true content, e.g. BODY,
    263    * bytes are passed here.
    264    * This allows us to check sizes, update stats, etc. independent
    265    * from the protocol in play. */
    266 
    267   if(data->req.no_body && nbytes > 0) {
    268     /* BODY arrives although we want none, bail out */
    269     streamclose(data->conn, "ignoring body");
    270     CURL_TRC_WRITE(data, "download_write body(type=%x, blen=%zu), "
    271                    "did not want a BODY", type, nbytes);
    272     data->req.download_done = TRUE;
    273     if(data->info.header_size)
    274       /* if headers have been received, this is fine */
    275       return CURLE_OK;
    276     return CURLE_WEIRD_SERVER_REPLY;
    277   }
    278 
    279   /* Determine if we see any bytes in excess to what is allowed.
    280    * We write the allowed bytes and handle excess further below.
    281    * This gives deterministic BODY writes on varying buffer receive
    282    * lengths. */
    283   nwrite = nbytes;
    284   if(-1 != data->req.maxdownload) {
    285     size_t wmax = get_max_body_write_len(data, data->req.maxdownload);
    286     if(nwrite > wmax) {
    287       excess_len = nbytes - wmax;
    288       nwrite = wmax;
    289     }
    290 
    291     if(nwrite == wmax) {
    292       data->req.download_done = TRUE;
    293     }
    294 
    295     if((type & CLIENTWRITE_EOS) && !data->req.no_body &&
    296        (data->req.maxdownload > data->req.bytecount)) {
    297       failf(data, "end of response with %" FMT_OFF_T " bytes missing",
    298             data->req.maxdownload - data->req.bytecount);
    299       return CURLE_PARTIAL_FILE;
    300     }
    301   }
    302 
    303   /* Error on too large filesize is handled below, after writing
    304    * the permitted bytes */
    305   if(data->set.max_filesize && !data->req.ignorebody) {
    306     size_t wmax = get_max_body_write_len(data, data->set.max_filesize);
    307     if(nwrite > wmax) {
    308       nwrite = wmax;
    309     }
    310   }
    311 
    312   if(!data->req.ignorebody && (nwrite || (type & CLIENTWRITE_EOS))) {
    313     result = Curl_cwriter_write(data, writer->next, type, buf, nwrite);
    314     CURL_TRC_WRITE(data, "download_write body(type=%x, blen=%zu) -> %d",
    315                    type, nbytes, result);
    316     if(result)
    317       return result;
    318   }
    319   /* Update stats, write and report progress */
    320   data->req.bytecount += nwrite;
    321   result = Curl_pgrsSetDownloadCounter(data, data->req.bytecount);
    322   if(result)
    323     return result;
    324 
    325   if(excess_len) {
    326     if(!data->req.ignorebody) {
    327       infof(data,
    328             "Excess found writing body:"
    329             " excess = %zu"
    330             ", size = %" FMT_OFF_T
    331             ", maxdownload = %" FMT_OFF_T
    332             ", bytecount = %" FMT_OFF_T,
    333             excess_len, data->req.size, data->req.maxdownload,
    334             data->req.bytecount);
    335       connclose(data->conn, "excess found in a read");
    336     }
    337   }
    338   else if((nwrite < nbytes) && !data->req.ignorebody) {
    339     failf(data, "Exceeded the maximum allowed file size "
    340           "(%" FMT_OFF_T ") with %" FMT_OFF_T " bytes",
    341           data->set.max_filesize, data->req.bytecount);
    342     return CURLE_FILESIZE_EXCEEDED;
    343   }
    344 
    345   return CURLE_OK;
    346 }
    347 
    348 static const struct Curl_cwtype cw_download = {
    349   "protocol",
    350   NULL,
    351   Curl_cwriter_def_init,
    352   cw_download_write,
    353   Curl_cwriter_def_close,
    354   sizeof(struct cw_download_ctx)
    355 };
    356 
    357 /* RAW client writer in phase CURL_CW_RAW that
    358  * enabled tracing of raw data. */
    359 static CURLcode cw_raw_write(struct Curl_easy *data,
    360                              struct Curl_cwriter *writer, int type,
    361                              const char *buf, size_t nbytes)
    362 {
    363   if(type & CLIENTWRITE_BODY && data->set.verbose && !data->req.ignorebody) {
    364     Curl_debug(data, CURLINFO_DATA_IN, buf, nbytes);
    365   }
    366   return Curl_cwriter_write(data, writer->next, type, buf, nbytes);
    367 }
    368 
    369 static const struct Curl_cwtype cw_raw = {
    370   "raw",
    371   NULL,
    372   Curl_cwriter_def_init,
    373   cw_raw_write,
    374   Curl_cwriter_def_close,
    375   sizeof(struct Curl_cwriter)
    376 };
    377 
    378 /* Create an unencoding writer stage using the given handler. */
    379 CURLcode Curl_cwriter_create(struct Curl_cwriter **pwriter,
    380                              struct Curl_easy *data,
    381                              const struct Curl_cwtype *cwt,
    382                              Curl_cwriter_phase phase)
    383 {
    384   struct Curl_cwriter *writer = NULL;
    385   CURLcode result = CURLE_OUT_OF_MEMORY;
    386   void *p;
    387 
    388   DEBUGASSERT(cwt->cwriter_size >= sizeof(struct Curl_cwriter));
    389   p = calloc(1, cwt->cwriter_size);
    390   if(!p)
    391     goto out;
    392 
    393   writer = (struct Curl_cwriter *)p;
    394   writer->cwt = cwt;
    395   writer->ctx = p;
    396   writer->phase = phase;
    397   result = cwt->do_init(data, writer);
    398 
    399 out:
    400   *pwriter = result ? NULL : writer;
    401   if(result)
    402     free(writer);
    403   return result;
    404 }
    405 
    406 void Curl_cwriter_free(struct Curl_easy *data,
    407                        struct Curl_cwriter *writer)
    408 {
    409   if(writer) {
    410     writer->cwt->do_close(data, writer);
    411     free(writer);
    412   }
    413 }
    414 
    415 size_t Curl_cwriter_count(struct Curl_easy *data, Curl_cwriter_phase phase)
    416 {
    417   struct Curl_cwriter *w;
    418   size_t n = 0;
    419 
    420   for(w = data->req.writer_stack; w; w = w->next) {
    421     if(w->phase == phase)
    422       ++n;
    423   }
    424   return n;
    425 }
    426 
    427 static CURLcode do_init_writer_stack(struct Curl_easy *data)
    428 {
    429   struct Curl_cwriter *writer;
    430   CURLcode result;
    431 
    432   DEBUGASSERT(!data->req.writer_stack);
    433   result = Curl_cwriter_create(&data->req.writer_stack,
    434                                data, &Curl_cwt_out, CURL_CW_CLIENT);
    435   if(result)
    436     return result;
    437 
    438   /* This places the "pause" writer behind the "download" writer that
    439    * is added below. Meaning the "download" can do checks on content length
    440    * and other things *before* write outs are buffered for paused transfers. */
    441   result = Curl_cwriter_create(&writer, data, &Curl_cwt_pause,
    442                                CURL_CW_PROTOCOL);
    443   if(!result) {
    444     result = Curl_cwriter_add(data, writer);
    445     if(result)
    446       Curl_cwriter_free(data, writer);
    447   }
    448   if(result)
    449     return result;
    450 
    451   result = Curl_cwriter_create(&writer, data, &cw_download, CURL_CW_PROTOCOL);
    452   if(!result) {
    453     result = Curl_cwriter_add(data, writer);
    454     if(result)
    455       Curl_cwriter_free(data, writer);
    456   }
    457   if(result)
    458     return result;
    459 
    460   result = Curl_cwriter_create(&writer, data, &cw_raw, CURL_CW_RAW);
    461   if(!result) {
    462     result = Curl_cwriter_add(data, writer);
    463     if(result)
    464       Curl_cwriter_free(data, writer);
    465   }
    466   if(result)
    467     return result;
    468 
    469   return result;
    470 }
    471 
    472 CURLcode Curl_cwriter_add(struct Curl_easy *data,
    473                           struct Curl_cwriter *writer)
    474 {
    475   CURLcode result;
    476   struct Curl_cwriter **anchor = &data->req.writer_stack;
    477 
    478   if(!*anchor) {
    479     result = do_init_writer_stack(data);
    480     if(result)
    481       return result;
    482   }
    483 
    484   /* Insert the writer as first in its phase.
    485    * Skip existing writers of lower phases. */
    486   while(*anchor && (*anchor)->phase < writer->phase)
    487     anchor = &((*anchor)->next);
    488   writer->next = *anchor;
    489   *anchor = writer;
    490   return CURLE_OK;
    491 }
    492 
    493 struct Curl_cwriter *Curl_cwriter_get_by_name(struct Curl_easy *data,
    494                                               const char *name)
    495 {
    496   struct Curl_cwriter *writer;
    497   for(writer = data->req.writer_stack; writer; writer = writer->next) {
    498     if(!strcmp(name, writer->cwt->name))
    499       return writer;
    500   }
    501   return NULL;
    502 }
    503 
    504 struct Curl_cwriter *Curl_cwriter_get_by_type(struct Curl_easy *data,
    505                                               const struct Curl_cwtype *cwt)
    506 {
    507   struct Curl_cwriter *writer;
    508   for(writer = data->req.writer_stack; writer; writer = writer->next) {
    509     if(writer->cwt == cwt)
    510       return writer;
    511   }
    512   return NULL;
    513 }
    514 
    515 bool Curl_cwriter_is_content_decoding(struct Curl_easy *data)
    516 {
    517   struct Curl_cwriter *writer;
    518   for(writer = data->req.writer_stack; writer; writer = writer->next) {
    519     if(writer->phase == CURL_CW_CONTENT_DECODE)
    520       return TRUE;
    521   }
    522   return FALSE;
    523 }
    524 
    525 bool Curl_cwriter_is_paused(struct Curl_easy *data)
    526 {
    527   return Curl_cw_out_is_paused(data);
    528 }
    529 
    530 CURLcode Curl_cwriter_unpause(struct Curl_easy *data)
    531 {
    532   return Curl_cw_out_unpause(data);
    533 }
    534 
    535 CURLcode Curl_creader_read(struct Curl_easy *data,
    536                            struct Curl_creader *reader,
    537                            char *buf, size_t blen, size_t *nread, bool *eos)
    538 {
    539   *nread = 0;
    540   *eos = FALSE;
    541   if(!reader)
    542     return CURLE_READ_ERROR;
    543   return reader->crt->do_read(data, reader, buf, blen, nread, eos);
    544 }
    545 
    546 CURLcode Curl_creader_def_init(struct Curl_easy *data,
    547                                struct Curl_creader *reader)
    548 {
    549   (void)data;
    550   (void)reader;
    551   return CURLE_OK;
    552 }
    553 
    554 void Curl_creader_def_close(struct Curl_easy *data,
    555                             struct Curl_creader *reader)
    556 {
    557   (void)data;
    558   (void)reader;
    559 }
    560 
    561 CURLcode Curl_creader_def_read(struct Curl_easy *data,
    562                                struct Curl_creader *reader,
    563                                char *buf, size_t blen,
    564                                size_t *nread, bool *eos)
    565 {
    566   if(reader->next)
    567     return reader->next->crt->do_read(data, reader->next, buf, blen,
    568                                       nread, eos);
    569   else {
    570     *nread = 0;
    571     *eos = FALSE;
    572     return CURLE_READ_ERROR;
    573   }
    574 }
    575 
    576 bool Curl_creader_def_needs_rewind(struct Curl_easy *data,
    577                                    struct Curl_creader *reader)
    578 {
    579   (void)data;
    580   (void)reader;
    581   return FALSE;
    582 }
    583 
    584 curl_off_t Curl_creader_def_total_length(struct Curl_easy *data,
    585                                          struct Curl_creader *reader)
    586 {
    587   return reader->next ?
    588          reader->next->crt->total_length(data, reader->next) : -1;
    589 }
    590 
    591 CURLcode Curl_creader_def_resume_from(struct Curl_easy *data,
    592                                       struct Curl_creader *reader,
    593                                       curl_off_t offset)
    594 {
    595   (void)data;
    596   (void)reader;
    597   (void)offset;
    598   return CURLE_READ_ERROR;
    599 }
    600 
    601 CURLcode Curl_creader_def_rewind(struct Curl_easy *data,
    602                                  struct Curl_creader *reader)
    603 {
    604   (void)data;
    605   (void)reader;
    606   return CURLE_OK;
    607 }
    608 
    609 CURLcode Curl_creader_def_unpause(struct Curl_easy *data,
    610                                   struct Curl_creader *reader)
    611 {
    612   (void)data;
    613   (void)reader;
    614   return CURLE_OK;
    615 }
    616 
    617 bool Curl_creader_def_is_paused(struct Curl_easy *data,
    618                                 struct Curl_creader *reader)
    619 {
    620   (void)data;
    621   (void)reader;
    622   return FALSE;
    623 }
    624 
    625 void Curl_creader_def_done(struct Curl_easy *data,
    626                            struct Curl_creader *reader, int premature)
    627 {
    628   (void)data;
    629   (void)reader;
    630   (void)premature;
    631 }
    632 
    633 struct cr_in_ctx {
    634   struct Curl_creader super;
    635   curl_read_callback read_cb;
    636   void *cb_user_data;
    637   curl_off_t total_len;
    638   curl_off_t read_len;
    639   CURLcode error_result;
    640   BIT(seen_eos);
    641   BIT(errored);
    642   BIT(has_used_cb);
    643   BIT(is_paused);
    644 };
    645 
    646 static CURLcode cr_in_init(struct Curl_easy *data, struct Curl_creader *reader)
    647 {
    648   struct cr_in_ctx *ctx = reader->ctx;
    649   (void)data;
    650   ctx->read_cb = data->state.fread_func;
    651   ctx->cb_user_data = data->state.in;
    652   ctx->total_len = -1;
    653   ctx->read_len = 0;
    654   return CURLE_OK;
    655 }
    656 
    657 /* Real client reader to installed client callbacks. */
    658 static CURLcode cr_in_read(struct Curl_easy *data,
    659                            struct Curl_creader *reader,
    660                            char *buf, size_t blen,
    661                            size_t *pnread, bool *peos)
    662 {
    663   struct cr_in_ctx *ctx = reader->ctx;
    664   CURLcode result = CURLE_OK;
    665   size_t nread;
    666 
    667   ctx->is_paused = FALSE;
    668 
    669   /* Once we have errored, we will return the same error forever */
    670   if(ctx->errored) {
    671     *pnread = 0;
    672     *peos = FALSE;
    673     return ctx->error_result;
    674   }
    675   if(ctx->seen_eos) {
    676     *pnread = 0;
    677     *peos = TRUE;
    678     return CURLE_OK;
    679   }
    680   /* respect length limitations */
    681   if(ctx->total_len >= 0) {
    682     curl_off_t remain = ctx->total_len - ctx->read_len;
    683     if(remain <= 0)
    684       blen = 0;
    685     else if(remain < (curl_off_t)blen)
    686       blen = (size_t)remain;
    687   }
    688   nread = 0;
    689   if(ctx->read_cb && blen) {
    690     Curl_set_in_callback(data, TRUE);
    691     nread = ctx->read_cb(buf, 1, blen, ctx->cb_user_data);
    692     Curl_set_in_callback(data, FALSE);
    693     ctx->has_used_cb = TRUE;
    694   }
    695 
    696   switch(nread) {
    697   case 0:
    698     if((ctx->total_len >= 0) && (ctx->read_len < ctx->total_len)) {
    699       failf(data, "client read function EOF fail, "
    700             "only %"FMT_OFF_T"/%"FMT_OFF_T " of needed bytes read",
    701             ctx->read_len, ctx->total_len);
    702       result = CURLE_READ_ERROR;
    703       break;
    704     }
    705     *pnread = 0;
    706     *peos = TRUE;
    707     ctx->seen_eos = TRUE;
    708     break;
    709 
    710   case CURL_READFUNC_ABORT:
    711     failf(data, "operation aborted by callback");
    712     *pnread = 0;
    713     *peos = FALSE;
    714     ctx->errored = TRUE;
    715     ctx->error_result = CURLE_ABORTED_BY_CALLBACK;
    716     result = CURLE_ABORTED_BY_CALLBACK;
    717     break;
    718 
    719   case CURL_READFUNC_PAUSE:
    720     if(data->conn->handler->flags & PROTOPT_NONETWORK) {
    721       /* protocols that work without network cannot be paused. This is
    722          actually only FILE:// just now, and it cannot pause since the transfer
    723          is not done using the "normal" procedure. */
    724       failf(data, "Read callback asked for PAUSE when not supported");
    725       result = CURLE_READ_ERROR;
    726       break;
    727     }
    728     /* CURL_READFUNC_PAUSE pauses read callbacks that feed socket writes */
    729     CURL_TRC_READ(data, "cr_in_read, callback returned CURL_READFUNC_PAUSE");
    730     ctx->is_paused = TRUE;
    731     *pnread = 0;
    732     *peos = FALSE;
    733     result = Curl_xfer_pause_send(data, TRUE);
    734     break; /* nothing was read */
    735 
    736   default:
    737     if(nread > blen) {
    738       /* the read function returned a too large value */
    739       failf(data, "read function returned funny value");
    740       *pnread = 0;
    741       *peos = FALSE;
    742       ctx->errored = TRUE;
    743       ctx->error_result = CURLE_READ_ERROR;
    744       result = CURLE_READ_ERROR;
    745       break;
    746     }
    747     ctx->read_len += nread;
    748     if(ctx->total_len >= 0)
    749       ctx->seen_eos = (ctx->read_len >= ctx->total_len);
    750     *pnread = nread;
    751     *peos = ctx->seen_eos;
    752     break;
    753   }
    754   CURL_TRC_READ(data, "cr_in_read(len=%zu, total=%"FMT_OFF_T
    755                 ", read=%"FMT_OFF_T") -> %d, nread=%zu, eos=%d",
    756                 blen, ctx->total_len, ctx->read_len, result,
    757                 *pnread, *peos);
    758   return result;
    759 }
    760 
    761 static bool cr_in_needs_rewind(struct Curl_easy *data,
    762                                struct Curl_creader *reader)
    763 {
    764   struct cr_in_ctx *ctx = reader->ctx;
    765   (void)data;
    766   return ctx->has_used_cb;
    767 }
    768 
    769 static curl_off_t cr_in_total_length(struct Curl_easy *data,
    770                                      struct Curl_creader *reader)
    771 {
    772   struct cr_in_ctx *ctx = reader->ctx;
    773   (void)data;
    774   return ctx->total_len;
    775 }
    776 
    777 static CURLcode cr_in_resume_from(struct Curl_easy *data,
    778                                   struct Curl_creader *reader,
    779                                   curl_off_t offset)
    780 {
    781   struct cr_in_ctx *ctx = reader->ctx;
    782   int seekerr = CURL_SEEKFUNC_CANTSEEK;
    783 
    784   DEBUGASSERT(data->conn);
    785   /* already started reading? */
    786   if(ctx->read_len)
    787     return CURLE_READ_ERROR;
    788 
    789   if(data->set.seek_func) {
    790     Curl_set_in_callback(data, TRUE);
    791     seekerr = data->set.seek_func(data->set.seek_client, offset, SEEK_SET);
    792     Curl_set_in_callback(data, FALSE);
    793   }
    794 
    795   if(seekerr != CURL_SEEKFUNC_OK) {
    796     curl_off_t passed = 0;
    797 
    798     if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
    799       failf(data, "Could not seek stream");
    800       return CURLE_READ_ERROR;
    801     }
    802     /* when seekerr == CURL_SEEKFUNC_CANTSEEK (cannot seek to offset) */
    803     do {
    804       char scratch[4*1024];
    805       size_t readthisamountnow =
    806         (offset - passed > (curl_off_t)sizeof(scratch)) ?
    807         sizeof(scratch) :
    808         curlx_sotouz(offset - passed);
    809       size_t actuallyread;
    810 
    811       Curl_set_in_callback(data, TRUE);
    812       actuallyread = ctx->read_cb(scratch, 1, readthisamountnow,
    813                                   ctx->cb_user_data);
    814       Curl_set_in_callback(data, FALSE);
    815 
    816       passed += actuallyread;
    817       if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
    818         /* this checks for greater-than only to make sure that the
    819            CURL_READFUNC_ABORT return code still aborts */
    820         failf(data, "Could only read %" FMT_OFF_T " bytes from the input",
    821               passed);
    822         return CURLE_READ_ERROR;
    823       }
    824     } while(passed < offset);
    825   }
    826 
    827   /* now, decrease the size of the read */
    828   if(ctx->total_len > 0) {
    829     ctx->total_len -= offset;
    830 
    831     if(ctx->total_len <= 0) {
    832       failf(data, "File already completely uploaded");
    833       return CURLE_PARTIAL_FILE;
    834     }
    835   }
    836   /* we have passed, proceed as normal */
    837   return CURLE_OK;
    838 }
    839 
    840 static CURLcode cr_in_rewind(struct Curl_easy *data,
    841                              struct Curl_creader *reader)
    842 {
    843   struct cr_in_ctx *ctx = reader->ctx;
    844 
    845   /* If we never invoked the callback, there is noting to rewind */
    846   if(!ctx->has_used_cb)
    847     return CURLE_OK;
    848 
    849   if(data->set.seek_func) {
    850     int err;
    851 
    852     Curl_set_in_callback(data, TRUE);
    853     err = (data->set.seek_func)(data->set.seek_client, 0, SEEK_SET);
    854     Curl_set_in_callback(data, FALSE);
    855     CURL_TRC_READ(data, "cr_in, rewind via set.seek_func -> %d", err);
    856     if(err) {
    857       failf(data, "seek callback returned error %d", (int)err);
    858       return CURLE_SEND_FAIL_REWIND;
    859     }
    860   }
    861   else if(data->set.ioctl_func) {
    862     curlioerr err;
    863 
    864     Curl_set_in_callback(data, TRUE);
    865     err = (data->set.ioctl_func)(data, CURLIOCMD_RESTARTREAD,
    866                                  data->set.ioctl_client);
    867     Curl_set_in_callback(data, FALSE);
    868     CURL_TRC_READ(data, "cr_in, rewind via set.ioctl_func -> %d", (int)err);
    869     if(err) {
    870       failf(data, "ioctl callback returned error %d", (int)err);
    871       return CURLE_SEND_FAIL_REWIND;
    872     }
    873   }
    874   else {
    875     /* If no CURLOPT_READFUNCTION is used, we know that we operate on a
    876        given FILE * stream and we can actually attempt to rewind that
    877        ourselves with fseek() */
    878     if(data->state.fread_func == (curl_read_callback)fread) {
    879       int err = fseek(data->state.in, 0, SEEK_SET);
    880       CURL_TRC_READ(data, "cr_in, rewind via fseek -> %d(%d)",
    881                     (int)err, (int)errno);
    882       if(-1 != err)
    883         /* successful rewind */
    884         return CURLE_OK;
    885     }
    886 
    887     /* no callback set or failure above, makes us fail at once */
    888     failf(data, "necessary data rewind was not possible");
    889     return CURLE_SEND_FAIL_REWIND;
    890   }
    891   return CURLE_OK;
    892 }
    893 
    894 static CURLcode cr_in_unpause(struct Curl_easy *data,
    895                               struct Curl_creader *reader)
    896 {
    897   struct cr_in_ctx *ctx = reader->ctx;
    898   (void)data;
    899   ctx->is_paused = FALSE;
    900   return CURLE_OK;
    901 }
    902 
    903 static bool cr_in_is_paused(struct Curl_easy *data,
    904                             struct Curl_creader *reader)
    905 {
    906   struct cr_in_ctx *ctx = reader->ctx;
    907   (void)data;
    908   return ctx->is_paused;
    909 }
    910 
    911 static const struct Curl_crtype cr_in = {
    912   "cr-in",
    913   cr_in_init,
    914   cr_in_read,
    915   Curl_creader_def_close,
    916   cr_in_needs_rewind,
    917   cr_in_total_length,
    918   cr_in_resume_from,
    919   cr_in_rewind,
    920   cr_in_unpause,
    921   cr_in_is_paused,
    922   Curl_creader_def_done,
    923   sizeof(struct cr_in_ctx)
    924 };
    925 
    926 CURLcode Curl_creader_create(struct Curl_creader **preader,
    927                              struct Curl_easy *data,
    928                              const struct Curl_crtype *crt,
    929                              Curl_creader_phase phase)
    930 {
    931   struct Curl_creader *reader = NULL;
    932   CURLcode result = CURLE_OUT_OF_MEMORY;
    933   void *p;
    934 
    935   DEBUGASSERT(crt->creader_size >= sizeof(struct Curl_creader));
    936   p = calloc(1, crt->creader_size);
    937   if(!p)
    938     goto out;
    939 
    940   reader = (struct Curl_creader *)p;
    941   reader->crt = crt;
    942   reader->ctx = p;
    943   reader->phase = phase;
    944   result = crt->do_init(data, reader);
    945 
    946 out:
    947   *preader = result ? NULL : reader;
    948   if(result)
    949     free(reader);
    950   return result;
    951 }
    952 
    953 void Curl_creader_free(struct Curl_easy *data, struct Curl_creader *reader)
    954 {
    955   if(reader) {
    956     reader->crt->do_close(data, reader);
    957     free(reader);
    958   }
    959 }
    960 
    961 struct cr_lc_ctx {
    962   struct Curl_creader super;
    963   struct bufq buf;
    964   BIT(read_eos);  /* we read an EOS from the next reader */
    965   BIT(eos);       /* we have returned an EOS */
    966   BIT(prev_cr);   /* the last byte was a CR */
    967 };
    968 
    969 static CURLcode cr_lc_init(struct Curl_easy *data, struct Curl_creader *reader)
    970 {
    971   struct cr_lc_ctx *ctx = reader->ctx;
    972   (void)data;
    973   Curl_bufq_init2(&ctx->buf, (16 * 1024), 1, BUFQ_OPT_SOFT_LIMIT);
    974   return CURLE_OK;
    975 }
    976 
    977 static void cr_lc_close(struct Curl_easy *data, struct Curl_creader *reader)
    978 {
    979   struct cr_lc_ctx *ctx = reader->ctx;
    980   (void)data;
    981   Curl_bufq_free(&ctx->buf);
    982 }
    983 
    984 /* client reader doing line end conversions. */
    985 static CURLcode cr_lc_read(struct Curl_easy *data,
    986                            struct Curl_creader *reader,
    987                            char *buf, size_t blen,
    988                            size_t *pnread, bool *peos)
    989 {
    990   struct cr_lc_ctx *ctx = reader->ctx;
    991   CURLcode result;
    992   size_t nread, i, start, n;
    993   bool eos;
    994 
    995   if(ctx->eos) {
    996     *pnread = 0;
    997     *peos = TRUE;
    998     return CURLE_OK;
    999   }
   1000 
   1001   if(Curl_bufq_is_empty(&ctx->buf)) {
   1002     if(ctx->read_eos) {
   1003       ctx->eos = TRUE;
   1004       *pnread = 0;
   1005       *peos = TRUE;
   1006       return CURLE_OK;
   1007     }
   1008     /* Still getting data form the next reader, ctx->buf is empty */
   1009     result = Curl_creader_read(data, reader->next, buf, blen, &nread, &eos);
   1010     if(result)
   1011       return result;
   1012     ctx->read_eos = eos;
   1013 
   1014     if(!nread || !memchr(buf, '\n', nread)) {
   1015       /* nothing to convert, return this right away */
   1016       if(ctx->read_eos)
   1017         ctx->eos = TRUE;
   1018       *pnread = nread;
   1019       *peos = ctx->eos;
   1020       goto out;
   1021     }
   1022 
   1023     /* at least one \n might need conversion to '\r\n', place into ctx->buf */
   1024     for(i = start = 0; i < nread; ++i) {
   1025       /* if this byte is not an LF character, or if the preceding character is
   1026          a CR (meaning this already is a CRLF pair), go to next */
   1027       if((buf[i] != '\n') || ctx->prev_cr) {
   1028         ctx->prev_cr = (buf[i] == '\r');
   1029         continue;
   1030       }
   1031       ctx->prev_cr = FALSE;
   1032       /* on a soft limit bufq, we do not need to check length */
   1033       result = Curl_bufq_cwrite(&ctx->buf, buf + start, i - start, &n);
   1034       if(!result)
   1035         result = Curl_bufq_cwrite(&ctx->buf, STRCONST("\r\n"), &n);
   1036       if(result)
   1037         return result;
   1038       start = i + 1;
   1039     }
   1040 
   1041     if(start < i) { /* leftover */
   1042       result = Curl_bufq_cwrite(&ctx->buf, buf + start, i - start, &n);
   1043       if(result)
   1044         return result;
   1045     }
   1046   }
   1047 
   1048   DEBUGASSERT(!Curl_bufq_is_empty(&ctx->buf));
   1049   *peos = FALSE;
   1050   result = Curl_bufq_cread(&ctx->buf, buf, blen, pnread);
   1051   if(!result && ctx->read_eos && Curl_bufq_is_empty(&ctx->buf)) {
   1052     /* no more data, read all, done. */
   1053     ctx->eos = TRUE;
   1054     *peos = TRUE;
   1055   }
   1056 
   1057 out:
   1058   CURL_TRC_READ(data, "cr_lc_read(len=%zu) -> %d, nread=%zu, eos=%d",
   1059                 blen, result, *pnread, *peos);
   1060   return result;
   1061 }
   1062 
   1063 static curl_off_t cr_lc_total_length(struct Curl_easy *data,
   1064                                      struct Curl_creader *reader)
   1065 {
   1066   /* this reader changes length depending on input */
   1067   (void)data;
   1068   (void)reader;
   1069   return -1;
   1070 }
   1071 
   1072 static const struct Curl_crtype cr_lc = {
   1073   "cr-lineconv",
   1074   cr_lc_init,
   1075   cr_lc_read,
   1076   cr_lc_close,
   1077   Curl_creader_def_needs_rewind,
   1078   cr_lc_total_length,
   1079   Curl_creader_def_resume_from,
   1080   Curl_creader_def_rewind,
   1081   Curl_creader_def_unpause,
   1082   Curl_creader_def_is_paused,
   1083   Curl_creader_def_done,
   1084   sizeof(struct cr_lc_ctx)
   1085 };
   1086 
   1087 static CURLcode cr_lc_add(struct Curl_easy *data)
   1088 {
   1089   struct Curl_creader *reader = NULL;
   1090   CURLcode result;
   1091 
   1092   result = Curl_creader_create(&reader, data, &cr_lc,
   1093                                CURL_CR_CONTENT_ENCODE);
   1094   if(!result)
   1095     result = Curl_creader_add(data, reader);
   1096 
   1097   if(result && reader)
   1098     Curl_creader_free(data, reader);
   1099   return result;
   1100 }
   1101 
   1102 static CURLcode do_init_reader_stack(struct Curl_easy *data,
   1103                                      struct Curl_creader *r)
   1104 {
   1105   CURLcode result = CURLE_OK;
   1106   curl_off_t clen;
   1107 
   1108   DEBUGASSERT(r);
   1109   DEBUGASSERT(r->crt);
   1110   DEBUGASSERT(r->phase == CURL_CR_CLIENT);
   1111   DEBUGASSERT(!data->req.reader_stack);
   1112 
   1113   data->req.reader_stack = r;
   1114   clen = r->crt->total_length(data, r);
   1115   /* if we do not have 0 length init, and crlf conversion is wanted,
   1116    * add the reader for it */
   1117   if(clen && (data->set.crlf
   1118 #ifdef CURL_PREFER_LF_LINEENDS
   1119      || data->state.prefer_ascii
   1120 #endif
   1121     )) {
   1122     result = cr_lc_add(data);
   1123     if(result)
   1124       return result;
   1125   }
   1126 
   1127   return result;
   1128 }
   1129 
   1130 CURLcode Curl_creader_set_fread(struct Curl_easy *data, curl_off_t len)
   1131 {
   1132   CURLcode result;
   1133   struct Curl_creader *r;
   1134   struct cr_in_ctx *ctx;
   1135 
   1136   result = Curl_creader_create(&r, data, &cr_in, CURL_CR_CLIENT);
   1137   if(result)
   1138     goto out;
   1139   ctx = r->ctx;
   1140   ctx->total_len = len;
   1141 
   1142   cl_reset_reader(data);
   1143   result = do_init_reader_stack(data, r);
   1144 out:
   1145   CURL_TRC_READ(data, "add fread reader, len=%"FMT_OFF_T " -> %d",
   1146                 len, result);
   1147   return result;
   1148 }
   1149 
   1150 CURLcode Curl_creader_add(struct Curl_easy *data,
   1151                           struct Curl_creader *reader)
   1152 {
   1153   CURLcode result;
   1154   struct Curl_creader **anchor = &data->req.reader_stack;
   1155 
   1156   if(!*anchor) {
   1157     result = Curl_creader_set_fread(data, data->state.infilesize);
   1158     if(result)
   1159       return result;
   1160   }
   1161 
   1162   /* Insert the writer as first in its phase.
   1163    * Skip existing readers of lower phases. */
   1164   while(*anchor && (*anchor)->phase < reader->phase)
   1165     anchor = &((*anchor)->next);
   1166   reader->next = *anchor;
   1167   *anchor = reader;
   1168   return CURLE_OK;
   1169 }
   1170 
   1171 CURLcode Curl_creader_set(struct Curl_easy *data, struct Curl_creader *r)
   1172 {
   1173   CURLcode result;
   1174 
   1175   DEBUGASSERT(r);
   1176   DEBUGASSERT(r->crt);
   1177   DEBUGASSERT(r->phase == CURL_CR_CLIENT);
   1178 
   1179   cl_reset_reader(data);
   1180   result = do_init_reader_stack(data, r);
   1181   if(result)
   1182     Curl_creader_free(data, r);
   1183   return result;
   1184 }
   1185 
   1186 CURLcode Curl_client_read(struct Curl_easy *data, char *buf, size_t blen,
   1187                           size_t *nread, bool *eos)
   1188 {
   1189   CURLcode result;
   1190 
   1191   DEBUGASSERT(buf);
   1192   DEBUGASSERT(blen);
   1193   DEBUGASSERT(nread);
   1194   DEBUGASSERT(eos);
   1195 
   1196   if(!data->req.reader_stack) {
   1197     result = Curl_creader_set_fread(data, data->state.infilesize);
   1198     if(result)
   1199       return result;
   1200     DEBUGASSERT(data->req.reader_stack);
   1201   }
   1202 
   1203   result = Curl_creader_read(data, data->req.reader_stack, buf, blen,
   1204                              nread, eos);
   1205   CURL_TRC_READ(data, "client_read(len=%zu) -> %d, nread=%zu, eos=%d",
   1206                 blen, result, *nread, *eos);
   1207   return result;
   1208 }
   1209 
   1210 bool Curl_creader_needs_rewind(struct Curl_easy *data)
   1211 {
   1212   struct Curl_creader *reader = data->req.reader_stack;
   1213   while(reader) {
   1214     if(reader->crt->needs_rewind(data, reader)) {
   1215       CURL_TRC_READ(data, "client reader needs rewind before next request");
   1216       return TRUE;
   1217     }
   1218     reader = reader->next;
   1219   }
   1220   return FALSE;
   1221 }
   1222 
   1223 static CURLcode cr_null_read(struct Curl_easy *data,
   1224                              struct Curl_creader *reader,
   1225                              char *buf, size_t blen,
   1226                              size_t *pnread, bool *peos)
   1227 {
   1228   (void)data;
   1229   (void)reader;
   1230   (void)buf;
   1231   (void)blen;
   1232   *pnread = 0;
   1233   *peos = TRUE;
   1234   return CURLE_OK;
   1235 }
   1236 
   1237 static curl_off_t cr_null_total_length(struct Curl_easy *data,
   1238                                        struct Curl_creader *reader)
   1239 {
   1240   /* this reader changes length depending on input */
   1241   (void)data;
   1242   (void)reader;
   1243   return 0;
   1244 }
   1245 
   1246 static const struct Curl_crtype cr_null = {
   1247   "cr-null",
   1248   Curl_creader_def_init,
   1249   cr_null_read,
   1250   Curl_creader_def_close,
   1251   Curl_creader_def_needs_rewind,
   1252   cr_null_total_length,
   1253   Curl_creader_def_resume_from,
   1254   Curl_creader_def_rewind,
   1255   Curl_creader_def_unpause,
   1256   Curl_creader_def_is_paused,
   1257   Curl_creader_def_done,
   1258   sizeof(struct Curl_creader)
   1259 };
   1260 
   1261 CURLcode Curl_creader_set_null(struct Curl_easy *data)
   1262 {
   1263   struct Curl_creader *r;
   1264   CURLcode result;
   1265 
   1266   result = Curl_creader_create(&r, data, &cr_null, CURL_CR_CLIENT);
   1267   if(result)
   1268     return result;
   1269 
   1270   cl_reset_reader(data);
   1271   return do_init_reader_stack(data, r);
   1272 }
   1273 
   1274 struct cr_buf_ctx {
   1275   struct Curl_creader super;
   1276   const char *buf;
   1277   size_t blen;
   1278   size_t index;
   1279 };
   1280 
   1281 static CURLcode cr_buf_read(struct Curl_easy *data,
   1282                             struct Curl_creader *reader,
   1283                             char *buf, size_t blen,
   1284                             size_t *pnread, bool *peos)
   1285 {
   1286   struct cr_buf_ctx *ctx = reader->ctx;
   1287   size_t nread = ctx->blen - ctx->index;
   1288 
   1289   (void)data;
   1290   if(!nread || !ctx->buf) {
   1291     *pnread = 0;
   1292     *peos = TRUE;
   1293   }
   1294   else {
   1295     if(nread > blen)
   1296       nread = blen;
   1297     memcpy(buf, ctx->buf + ctx->index, nread);
   1298     *pnread = nread;
   1299     ctx->index += nread;
   1300     *peos = (ctx->index == ctx->blen);
   1301   }
   1302   CURL_TRC_READ(data, "cr_buf_read(len=%zu) -> 0, nread=%zu, eos=%d",
   1303                 blen, *pnread, *peos);
   1304   return CURLE_OK;
   1305 }
   1306 
   1307 static bool cr_buf_needs_rewind(struct Curl_easy *data,
   1308                                 struct Curl_creader *reader)
   1309 {
   1310   struct cr_buf_ctx *ctx = reader->ctx;
   1311   (void)data;
   1312   return ctx->index > 0;
   1313 }
   1314 
   1315 static CURLcode cr_buf_rewind(struct Curl_easy *data,
   1316                               struct Curl_creader *reader)
   1317 {
   1318   struct cr_buf_ctx *ctx = reader->ctx;
   1319   (void)data;
   1320   ctx->index = 0;
   1321   return CURLE_OK;
   1322 }
   1323 
   1324 static curl_off_t cr_buf_total_length(struct Curl_easy *data,
   1325                                       struct Curl_creader *reader)
   1326 {
   1327   struct cr_buf_ctx *ctx = reader->ctx;
   1328   (void)data;
   1329   return (curl_off_t)ctx->blen;
   1330 }
   1331 
   1332 static CURLcode cr_buf_resume_from(struct Curl_easy *data,
   1333                                    struct Curl_creader *reader,
   1334                                    curl_off_t offset)
   1335 {
   1336   struct cr_buf_ctx *ctx = reader->ctx;
   1337   size_t boffset;
   1338 
   1339   (void)data;
   1340   DEBUGASSERT(data->conn);
   1341   /* already started reading? */
   1342   if(ctx->index)
   1343     return CURLE_READ_ERROR;
   1344   if(offset <= 0)
   1345     return CURLE_OK;
   1346   boffset = (size_t)offset;
   1347   if(boffset > ctx->blen)
   1348     return CURLE_READ_ERROR;
   1349 
   1350   ctx->buf += boffset;
   1351   ctx->blen -= boffset;
   1352   return CURLE_OK;
   1353 }
   1354 
   1355 static const struct Curl_crtype cr_buf = {
   1356   "cr-buf",
   1357   Curl_creader_def_init,
   1358   cr_buf_read,
   1359   Curl_creader_def_close,
   1360   cr_buf_needs_rewind,
   1361   cr_buf_total_length,
   1362   cr_buf_resume_from,
   1363   cr_buf_rewind,
   1364   Curl_creader_def_unpause,
   1365   Curl_creader_def_is_paused,
   1366   Curl_creader_def_done,
   1367   sizeof(struct cr_buf_ctx)
   1368 };
   1369 
   1370 CURLcode Curl_creader_set_buf(struct Curl_easy *data,
   1371                               const char *buf, size_t blen)
   1372 {
   1373   CURLcode result;
   1374   struct Curl_creader *r;
   1375   struct cr_buf_ctx *ctx;
   1376 
   1377   result = Curl_creader_create(&r, data, &cr_buf, CURL_CR_CLIENT);
   1378   if(result)
   1379     goto out;
   1380   ctx = r->ctx;
   1381   ctx->buf = buf;
   1382   ctx->blen = blen;
   1383   ctx->index = 0;
   1384 
   1385   cl_reset_reader(data);
   1386   result = do_init_reader_stack(data, r);
   1387 out:
   1388   CURL_TRC_READ(data, "add buf reader, len=%zu -> %d", blen, result);
   1389   return result;
   1390 }
   1391 
   1392 curl_off_t Curl_creader_total_length(struct Curl_easy *data)
   1393 {
   1394   struct Curl_creader *r = data->req.reader_stack;
   1395   return r ? r->crt->total_length(data, r) : -1;
   1396 }
   1397 
   1398 curl_off_t Curl_creader_client_length(struct Curl_easy *data)
   1399 {
   1400   struct Curl_creader *r = data->req.reader_stack;
   1401   while(r && r->phase != CURL_CR_CLIENT)
   1402     r = r->next;
   1403   return r ? r->crt->total_length(data, r) : -1;
   1404 }
   1405 
   1406 CURLcode Curl_creader_resume_from(struct Curl_easy *data, curl_off_t offset)
   1407 {
   1408   struct Curl_creader *r = data->req.reader_stack;
   1409   while(r && r->phase != CURL_CR_CLIENT)
   1410     r = r->next;
   1411   return r ? r->crt->resume_from(data, r, offset) : CURLE_READ_ERROR;
   1412 }
   1413 
   1414 CURLcode Curl_creader_unpause(struct Curl_easy *data)
   1415 {
   1416   struct Curl_creader *reader = data->req.reader_stack;
   1417   CURLcode result = CURLE_OK;
   1418 
   1419   while(reader) {
   1420     result = reader->crt->unpause(data, reader);
   1421     if(result)
   1422       break;
   1423     reader = reader->next;
   1424   }
   1425   return result;
   1426 }
   1427 
   1428 bool Curl_creader_is_paused(struct Curl_easy *data)
   1429 {
   1430   struct Curl_creader *reader = data->req.reader_stack;
   1431 
   1432   while(reader) {
   1433     if(reader->crt->is_paused(data, reader))
   1434       return TRUE;
   1435     reader = reader->next;
   1436   }
   1437   return FALSE;
   1438 }
   1439 
   1440 void Curl_creader_done(struct Curl_easy *data, int premature)
   1441 {
   1442   struct Curl_creader *reader = data->req.reader_stack;
   1443   while(reader) {
   1444     reader->crt->done(data, reader, premature);
   1445     reader = reader->next;
   1446   }
   1447 }
   1448 
   1449 struct Curl_creader *Curl_creader_get_by_type(struct Curl_easy *data,
   1450                                               const struct Curl_crtype *crt)
   1451 {
   1452   struct Curl_creader *r;
   1453   for(r = data->req.reader_stack; r; r = r->next) {
   1454     if(r->crt == crt)
   1455       return r;
   1456   }
   1457   return NULL;
   1458 
   1459 }