quickjs-tart

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

sendf.h (16241B)


      1 #ifndef HEADER_CURL_SENDF_H
      2 #define HEADER_CURL_SENDF_H
      3 /***************************************************************************
      4  *                                  _   _ ____  _
      5  *  Project                     ___| | | |  _ \| |
      6  *                             / __| | | | |_) | |
      7  *                            | (__| |_| |  _ <| |___
      8  *                             \___|\___/|_| \_\_____|
      9  *
     10  * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
     11  *
     12  * This software is licensed as described in the file COPYING, which
     13  * you should have received as part of this distribution. The terms
     14  * are also available at https://curl.se/docs/copyright.html.
     15  *
     16  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
     17  * copies of the Software, and permit persons to whom the Software is
     18  * furnished to do so, under the terms of the COPYING file.
     19  *
     20  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
     21  * KIND, either express or implied.
     22  *
     23  * SPDX-License-Identifier: curl
     24  *
     25  ***************************************************************************/
     26 
     27 #include "curl_setup.h"
     28 
     29 #include "curl_trc.h"
     30 
     31 /**
     32  * Type of data that is being written to the client (application)
     33  * - data written can be either BODY or META data
     34  * - META data is either INFO or HEADER
     35  * - INFO is meta information, e.g. not BODY, that cannot be interpreted
     36  *   as headers of a response. Example FTP/IMAP pingpong answers.
     37  * - HEADER can have additional bits set (more than one)
     38  *   - STATUS special "header", e.g. response status line in HTTP
     39  *   - CONNECT header was received during proxying the connection
     40  *   - 1XX header is part of an intermediate response, e.g. HTTP 1xx code
     41  *   - TRAILER header is trailing response data, e.g. HTTP trailers
     42  * BODY, INFO and HEADER should not be mixed, as this would lead to
     43  * confusion on how to interpret/format/convert the data.
     44  */
     45 #define CLIENTWRITE_BODY    (1<<0) /* non-meta information, BODY */
     46 #define CLIENTWRITE_INFO    (1<<1) /* meta information, not a HEADER */
     47 #define CLIENTWRITE_HEADER  (1<<2) /* meta information, HEADER */
     48 #define CLIENTWRITE_STATUS  (1<<3) /* a special status HEADER */
     49 #define CLIENTWRITE_CONNECT (1<<4) /* a CONNECT related HEADER */
     50 #define CLIENTWRITE_1XX     (1<<5) /* a 1xx response related HEADER */
     51 #define CLIENTWRITE_TRAILER (1<<6) /* a trailer HEADER */
     52 #define CLIENTWRITE_EOS     (1<<7) /* End Of transfer download Stream */
     53 
     54 /**
     55  * Write `len` bytes at `prt` to the client. `type` indicates what
     56  * kind of data is being written.
     57  */
     58 CURLcode Curl_client_write(struct Curl_easy *data, int type, const char *ptr,
     59                            size_t len) WARN_UNUSED_RESULT;
     60 
     61 /**
     62  * Free all resources related to client writing.
     63  */
     64 void Curl_client_cleanup(struct Curl_easy *data);
     65 
     66 /**
     67  * Reset readers and writer chains, keep rewind information
     68  * when necessary.
     69  */
     70 void Curl_client_reset(struct Curl_easy *data);
     71 
     72 /**
     73  * A new request is starting, perform any ops like rewinding
     74  * previous readers when needed.
     75  */
     76 CURLcode Curl_client_start(struct Curl_easy *data);
     77 
     78 /**
     79  * Client Writers - a chain passing transfer BODY data to the client.
     80  * Main application: HTTP and related protocols
     81  * Other uses: monitoring of download progress
     82  *
     83  * Writers in the chain are order by their `phase`. First come all
     84  * writers in CURL_CW_RAW, followed by any in CURL_CW_TRANSFER_DECODE,
     85  * followed by any in CURL_CW_PROTOCOL, etc.
     86  *
     87  * When adding a writer, it is inserted as first in its phase. This means
     88  * the order of adding writers of the same phase matters, but writers for
     89  * different phases may be added in any order.
     90  *
     91  * Writers which do modify the BODY data written are expected to be of
     92  * phases TRANSFER_DECODE or CONTENT_DECODE. The other phases are intended
     93  * for monitoring writers. Which do *not* modify the data but gather
     94  * statistics or update progress reporting.
     95  */
     96 
     97 /* Phase a writer operates at. */
     98 typedef enum {
     99   CURL_CW_RAW,  /* raw data written, before any decoding */
    100   CURL_CW_TRANSFER_DECODE, /* remove transfer-encodings */
    101   CURL_CW_PROTOCOL, /* after transfer, but before content decoding */
    102   CURL_CW_CONTENT_DECODE, /* remove content-encodings */
    103   CURL_CW_CLIENT  /* data written to client */
    104 } Curl_cwriter_phase;
    105 
    106 /* Client Writer Type, provides the implementation */
    107 struct Curl_cwtype {
    108   const char *name;        /* writer name. */
    109   const char *alias;       /* writer name alias, maybe NULL. */
    110   CURLcode (*do_init)(struct Curl_easy *data,
    111                       struct Curl_cwriter *writer);
    112   CURLcode (*do_write)(struct Curl_easy *data,
    113                        struct Curl_cwriter *writer, int type,
    114                        const char *buf, size_t nbytes);
    115   void (*do_close)(struct Curl_easy *data,
    116                    struct Curl_cwriter *writer);
    117   size_t cwriter_size;  /* sizeof() allocated struct Curl_cwriter */
    118 };
    119 
    120 /* Client writer instance, allocated on creation.
    121  * `void *ctx` is the pointer from the allocation of
    122  * the `struct Curl_cwriter` itself. This is suitable for "downcasting"
    123  * by the writers implementation. See https://github.com/curl/curl/pull/13054
    124  * for the alignment problems that arise otherwise.
    125  */
    126 struct Curl_cwriter {
    127   const struct Curl_cwtype *cwt;  /* type implementation */
    128   struct Curl_cwriter *next;  /* Downstream writer. */
    129   void *ctx;                  /* allocated instance pointer */
    130   Curl_cwriter_phase phase; /* phase at which it operates */
    131 };
    132 
    133 /**
    134  * Create a new cwriter instance with given type and phase. Is not
    135  * inserted into the writer chain by this call.
    136  * Invokes `writer->do_init()`.
    137  */
    138 CURLcode Curl_cwriter_create(struct Curl_cwriter **pwriter,
    139                              struct Curl_easy *data,
    140                              const struct Curl_cwtype *ce_handler,
    141                              Curl_cwriter_phase phase);
    142 
    143 /**
    144  * Free a cwriter instance.
    145  * Invokes `writer->do_close()`.
    146  */
    147 void Curl_cwriter_free(struct Curl_easy *data,
    148                        struct Curl_cwriter *writer);
    149 
    150 /**
    151  * Count the number of writers installed of the given phase.
    152  */
    153 size_t Curl_cwriter_count(struct Curl_easy *data, Curl_cwriter_phase phase);
    154 
    155 /**
    156  * Adds a writer to the transfer's writer chain.
    157  * The writers `phase` determines where in the chain it is inserted.
    158  */
    159 CURLcode Curl_cwriter_add(struct Curl_easy *data,
    160                           struct Curl_cwriter *writer);
    161 
    162 /**
    163  * Look up an installed client writer on `data` by its type.
    164  * @return first writer with that type or NULL
    165  */
    166 struct Curl_cwriter *Curl_cwriter_get_by_type(struct Curl_easy *data,
    167                                               const struct Curl_cwtype *cwt);
    168 
    169 struct Curl_cwriter *Curl_cwriter_get_by_name(struct Curl_easy *data,
    170                                               const char *name);
    171 
    172 /**
    173  * Convenience method for calling `writer->do_write()` that
    174  * checks for NULL writer.
    175  */
    176 CURLcode Curl_cwriter_write(struct Curl_easy *data,
    177                             struct Curl_cwriter *writer, int type,
    178                             const char *buf, size_t nbytes);
    179 
    180 /**
    181  * Return TRUE iff client writer is paused.
    182  */
    183 bool Curl_cwriter_is_paused(struct Curl_easy *data);
    184 
    185 bool Curl_cwriter_is_content_decoding(struct Curl_easy *data);
    186 
    187 /**
    188  * Unpause client writer and flush any buffered date to the client.
    189  */
    190 CURLcode Curl_cwriter_unpause(struct Curl_easy *data);
    191 
    192 /**
    193  * Default implementations for do_init, do_write, do_close that
    194  * do nothing and pass the data through.
    195  */
    196 CURLcode Curl_cwriter_def_init(struct Curl_easy *data,
    197                                struct Curl_cwriter *writer);
    198 CURLcode Curl_cwriter_def_write(struct Curl_easy *data,
    199                                 struct Curl_cwriter *writer, int type,
    200                                 const char *buf, size_t nbytes);
    201 void Curl_cwriter_def_close(struct Curl_easy *data,
    202                             struct Curl_cwriter *writer);
    203 
    204 
    205 
    206 /* Client Reader Type, provides the implementation */
    207 struct Curl_crtype {
    208   const char *name;        /* writer name. */
    209   CURLcode (*do_init)(struct Curl_easy *data, struct Curl_creader *reader);
    210   CURLcode (*do_read)(struct Curl_easy *data, struct Curl_creader *reader,
    211                       char *buf, size_t blen, size_t *nread, bool *eos);
    212   void (*do_close)(struct Curl_easy *data, struct Curl_creader *reader);
    213   bool (*needs_rewind)(struct Curl_easy *data, struct Curl_creader *reader);
    214   curl_off_t (*total_length)(struct Curl_easy *data,
    215                              struct Curl_creader *reader);
    216   CURLcode (*resume_from)(struct Curl_easy *data,
    217                           struct Curl_creader *reader, curl_off_t offset);
    218   CURLcode (*rewind)(struct Curl_easy *data, struct Curl_creader *reader);
    219   CURLcode (*unpause)(struct Curl_easy *data, struct Curl_creader *reader);
    220   bool (*is_paused)(struct Curl_easy *data, struct Curl_creader *reader);
    221   void (*done)(struct Curl_easy *data,
    222                struct Curl_creader *reader, int premature);
    223   size_t creader_size;  /* sizeof() allocated struct Curl_creader */
    224 };
    225 
    226 /* Phase a reader operates at. */
    227 typedef enum {
    228   CURL_CR_NET,  /* data send to the network (connection filters) */
    229   CURL_CR_TRANSFER_ENCODE, /* add transfer-encodings */
    230   CURL_CR_PROTOCOL, /* before transfer, but after content decoding */
    231   CURL_CR_CONTENT_ENCODE, /* add content-encodings */
    232   CURL_CR_CLIENT  /* data read from client */
    233 } Curl_creader_phase;
    234 
    235 /* Client reader instance, allocated on creation.
    236  * `void *ctx` is the pointer from the allocation of
    237  * the `struct Curl_cwriter` itself. This is suitable for "downcasting"
    238  * by the writers implementation. See https://github.com/curl/curl/pull/13054
    239  * for the alignment problems that arise otherwise.
    240  */
    241 struct Curl_creader {
    242   const struct Curl_crtype *crt;  /* type implementation */
    243   struct Curl_creader *next;  /* Downstream reader. */
    244   void *ctx;
    245   Curl_creader_phase phase; /* phase at which it operates */
    246 };
    247 
    248 /**
    249  * Default implementations for do_init, do_write, do_close that
    250  * do nothing and pass the data through.
    251  */
    252 CURLcode Curl_creader_def_init(struct Curl_easy *data,
    253                                struct Curl_creader *reader);
    254 void Curl_creader_def_close(struct Curl_easy *data,
    255                             struct Curl_creader *reader);
    256 CURLcode Curl_creader_def_read(struct Curl_easy *data,
    257                                struct Curl_creader *reader,
    258                                char *buf, size_t blen,
    259                                size_t *nread, bool *eos);
    260 bool Curl_creader_def_needs_rewind(struct Curl_easy *data,
    261                                    struct Curl_creader *reader);
    262 curl_off_t Curl_creader_def_total_length(struct Curl_easy *data,
    263                                          struct Curl_creader *reader);
    264 CURLcode Curl_creader_def_resume_from(struct Curl_easy *data,
    265                                       struct Curl_creader *reader,
    266                                       curl_off_t offset);
    267 CURLcode Curl_creader_def_rewind(struct Curl_easy *data,
    268                                  struct Curl_creader *reader);
    269 CURLcode Curl_creader_def_unpause(struct Curl_easy *data,
    270                                   struct Curl_creader *reader);
    271 bool Curl_creader_def_is_paused(struct Curl_easy *data,
    272                                 struct Curl_creader *reader);
    273 void Curl_creader_def_done(struct Curl_easy *data,
    274                            struct Curl_creader *reader, int premature);
    275 
    276 /**
    277  * Convenience method for calling `reader->do_read()` that
    278  * checks for NULL reader.
    279  */
    280 CURLcode Curl_creader_read(struct Curl_easy *data,
    281                            struct Curl_creader *reader,
    282                            char *buf, size_t blen, size_t *nread, bool *eos);
    283 
    284 /**
    285  * Create a new creader instance with given type and phase. Is not
    286  * inserted into the writer chain by this call.
    287  * Invokes `reader->do_init()`.
    288  */
    289 CURLcode Curl_creader_create(struct Curl_creader **preader,
    290                              struct Curl_easy *data,
    291                              const struct Curl_crtype *cr_handler,
    292                              Curl_creader_phase phase);
    293 
    294 /**
    295  * Free a creader instance.
    296  * Invokes `reader->do_close()`.
    297  */
    298 void Curl_creader_free(struct Curl_easy *data, struct Curl_creader *reader);
    299 
    300 /**
    301  * Adds a reader to the transfer's reader chain.
    302  * The readers `phase` determines where in the chain it is inserted.
    303  */
    304 CURLcode Curl_creader_add(struct Curl_easy *data,
    305                           struct Curl_creader *reader);
    306 
    307 /**
    308  * Set the given reader, which needs to be of type CURL_CR_CLIENT,
    309  * as the new first reader. Discard any installed readers and init
    310  * the reader chain anew.
    311  * The function takes ownership of `r`.
    312  */
    313 CURLcode Curl_creader_set(struct Curl_easy *data, struct Curl_creader *r);
    314 
    315 /**
    316  * Read at most `blen` bytes at `buf` from the client.
    317  * @param data    the transfer to read client bytes for
    318  * @param buf     the memory location to read to
    319  * @param blen    the amount of memory at `buf`
    320  * @param nread   on return the number of bytes read into `buf`
    321  * @param eos     TRUE iff bytes are the end of data from client
    322  * @return CURLE_OK on successful read (even 0 length) or error
    323  */
    324 CURLcode Curl_client_read(struct Curl_easy *data, char *buf, size_t blen,
    325                           size_t *nread, bool *eos) WARN_UNUSED_RESULT;
    326 
    327 /**
    328  * TRUE iff client reader needs rewing before it can be used for
    329  * a retry request.
    330  */
    331 bool Curl_creader_needs_rewind(struct Curl_easy *data);
    332 
    333 /**
    334  * TRUE iff client reader will rewind at next start
    335  */
    336 bool Curl_creader_will_rewind(struct Curl_easy *data);
    337 
    338 /**
    339  * En-/disable rewind of client reader at next start.
    340  */
    341 void Curl_creader_set_rewind(struct Curl_easy *data, bool enable);
    342 
    343 /**
    344  * Get the total length of bytes provided by the installed readers.
    345  * This is independent of the amount already delivered and is calculated
    346  * by all readers in the stack. If a reader like "chunked" or
    347  * "crlf conversion" is installed, the returned length will be -1.
    348  * @return -1 if length is indeterminate
    349  */
    350 curl_off_t Curl_creader_total_length(struct Curl_easy *data);
    351 
    352 /**
    353  * Get the total length of bytes provided by the reader at phase
    354  * CURL_CR_CLIENT. This may not match the amount of bytes read
    355  * for a request, depending if other, encoding readers are also installed.
    356  * However it allows for rough estimation of the overall length.
    357  * @return -1 if length is indeterminate
    358  */
    359 curl_off_t Curl_creader_client_length(struct Curl_easy *data);
    360 
    361 /**
    362  * Ask the installed reader at phase CURL_CR_CLIENT to start
    363  * reading from the given offset. On success, this will reduce
    364  * the `total_length()` by the amount.
    365  * @param data    the transfer to read client bytes for
    366  * @param offset  the offset where to start reads from, negative
    367  *                values will be ignored.
    368  * @return CURLE_OK if offset could be set
    369  *         CURLE_READ_ERROR if not supported by reader or seek/read failed
    370  *                          of offset larger then total length
    371  *         CURLE_PARTIAL_FILE if offset led to 0 total length
    372  */
    373 CURLcode Curl_creader_resume_from(struct Curl_easy *data, curl_off_t offset);
    374 
    375 /**
    376  * Unpause all installed readers.
    377  */
    378 CURLcode Curl_creader_unpause(struct Curl_easy *data);
    379 
    380 /**
    381  * Return TRUE iff any of the installed readers is paused.
    382  */
    383 bool Curl_creader_is_paused(struct Curl_easy *data);
    384 
    385 /**
    386  * Tell all client readers that they are done.
    387  */
    388 void Curl_creader_done(struct Curl_easy *data, int premature);
    389 
    390 /**
    391  * Look up an installed client reader on `data` by its type.
    392  * @return first reader with that type or NULL
    393  */
    394 struct Curl_creader *Curl_creader_get_by_type(struct Curl_easy *data,
    395                                               const struct Curl_crtype *crt);
    396 
    397 
    398 /**
    399  * Set the client reader to provide 0 bytes, immediate EOS.
    400  */
    401 CURLcode Curl_creader_set_null(struct Curl_easy *data);
    402 
    403 /**
    404  * Set the client reader the reads from fread callback.
    405  */
    406 CURLcode Curl_creader_set_fread(struct Curl_easy *data, curl_off_t len);
    407 
    408 /**
    409  * Set the client reader the reads from the supplied buf (NOT COPIED).
    410  */
    411 CURLcode Curl_creader_set_buf(struct Curl_easy *data,
    412                               const char *buf, size_t blen);
    413 
    414 #endif /* HEADER_CURL_SENDF_H */