quickjs-tart

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

cfilters.h (30204B)


      1 #ifndef HEADER_CURL_CFILTERS_H
      2 #define HEADER_CURL_CFILTERS_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 "curlx/timediff.h"
     28 
     29 struct bufq;
     30 struct Curl_cfilter;
     31 struct Curl_easy;
     32 struct Curl_dns_entry;
     33 struct connectdata;
     34 struct ip_quadruple;
     35 struct curl_tlssessioninfo;
     36 
     37 /* Callback to destroy resources held by this filter instance.
     38  * Implementations MUST NOT chain calls to cf->next.
     39  */
     40 typedef void     Curl_cft_destroy_this(struct Curl_cfilter *cf,
     41                                        struct Curl_easy *data);
     42 
     43 /* Callback to close the connection immediately. */
     44 typedef void     Curl_cft_close(struct Curl_cfilter *cf,
     45                                 struct Curl_easy *data);
     46 
     47 /* Callback to close the connection filter gracefully, non-blocking.
     48  * Implementations MUST NOT chain calls to cf->next.
     49  */
     50 typedef CURLcode Curl_cft_shutdown(struct Curl_cfilter *cf,
     51                                    struct Curl_easy *data,
     52                                    bool *done);
     53 
     54 typedef CURLcode Curl_cft_connect(struct Curl_cfilter *cf,
     55                                   struct Curl_easy *data,
     56                                   bool *done);
     57 
     58 struct easy_pollset;
     59 
     60 /* Passing in an easy_pollset for monitoring of sockets, let
     61  * filters add or remove sockets actions (CURL_POLL_OUT, CURL_POLL_IN).
     62  * This may add a socket or, in case no actions remain, remove
     63  * a socket from the set.
     64  *
     65  * Filter implementations need to call filters "below" *after* they have
     66  * made their adjustments. This allows lower filters to override "upper"
     67  * actions. If a "lower" filter is unable to write, it needs to be able
     68  * to disallow POLL_OUT.
     69  *
     70  * A filter without own restrictions/preferences should not modify
     71  * the pollset. Filters, whose filter "below" is not connected, should
     72  * also do no adjustments.
     73  *
     74  * Examples: a TLS handshake, while ongoing, might remove POLL_IN when it
     75  * needs to write, or vice versa. An HTTP/2 filter might remove POLL_OUT when
     76  * a stream window is exhausted and a WINDOW_UPDATE needs to be received first
     77  * and add instead POLL_IN.
     78  *
     79  * @param cf     the filter to ask
     80  * @param data   the easy handle the pollset is about
     81  * @param ps     the pollset (inout) for the easy handle
     82  */
     83 typedef void     Curl_cft_adjust_pollset(struct Curl_cfilter *cf,
     84                                          struct Curl_easy *data,
     85                                          struct easy_pollset *ps);
     86 
     87 typedef bool     Curl_cft_data_pending(struct Curl_cfilter *cf,
     88                                        const struct Curl_easy *data);
     89 
     90 typedef CURLcode Curl_cft_send(struct Curl_cfilter *cf,
     91                                struct Curl_easy *data, /* transfer */
     92                                const void *buf,        /* data to write */
     93                                size_t len,             /* amount to write */
     94                                bool eos,               /* last chunk */
     95                                size_t *pnwritten);     /* how much sent */
     96 
     97 typedef CURLcode Curl_cft_recv(struct Curl_cfilter *cf,
     98                                struct Curl_easy *data, /* transfer */
     99                                char *buf,              /* store data here */
    100                                size_t len,             /* amount to read */
    101                                size_t *pnread);        /* how much received */
    102 
    103 typedef bool     Curl_cft_conn_is_alive(struct Curl_cfilter *cf,
    104                                         struct Curl_easy *data,
    105                                         bool *input_pending);
    106 
    107 typedef CURLcode Curl_cft_conn_keep_alive(struct Curl_cfilter *cf,
    108                                           struct Curl_easy *data);
    109 
    110 /**
    111  * Events/controls for connection filters, their arguments and
    112  * return code handling. Filter callbacks are invoked "top down".
    113  * Return code handling:
    114  * "first fail" meaning that the first filter returning != CURLE_OK, will
    115  *              abort further event distribution and determine the result.
    116  * "ignored" meaning return values are ignored and the event is distributed
    117  *           to all filters in the chain. Overall result is always CURLE_OK.
    118  */
    119 /*      data event                          arg1       arg2     return */
    120 #define CF_CTRL_DATA_SETUP            4  /* 0          NULL     first fail */
    121 #define CF_CTRL_DATA_IDLE             5  /* 0          NULL     first fail */
    122 #define CF_CTRL_DATA_PAUSE            6  /* on/off     NULL     first fail */
    123 #define CF_CTRL_DATA_DONE             7  /* premature  NULL     ignored */
    124 #define CF_CTRL_DATA_DONE_SEND        8  /* 0          NULL     ignored */
    125 /* update conn info at connection and data */
    126 #define CF_CTRL_CONN_INFO_UPDATE (256+0) /* 0          NULL     ignored */
    127 #define CF_CTRL_FORGET_SOCKET    (256+1) /* 0          NULL     ignored */
    128 #define CF_CTRL_FLUSH            (256+2) /* 0          NULL     first fail */
    129 
    130 /**
    131  * Handle event/control for the filter.
    132  * Implementations MUST NOT chain calls to cf->next.
    133  */
    134 typedef CURLcode Curl_cft_cntrl(struct Curl_cfilter *cf,
    135                                 struct Curl_easy *data,
    136                                 int event, int arg1, void *arg2);
    137 
    138 
    139 /**
    140  * Queries to ask via a `Curl_cft_query *query` method on a cfilter chain.
    141  * - MAX_CONCURRENT: the maximum number of parallel transfers the filter
    142  *                   chain expects to handle at the same time.
    143  *                   default: 1 if no filter overrides.
    144  * - CONNECT_REPLY_MS: milliseconds until the first indication of a server
    145  *                   response was received on a connect. For TCP, this
    146  *                   reflects the time until the socket connected. On UDP
    147  *                   this gives the time the first bytes from the server
    148  *                   were received.
    149  *                   -1 if not determined yet.
    150  * - CF_QUERY_SOCKET: the socket used by the filter chain
    151  * - CF_QUERY_NEED_FLUSH: TRUE iff any of the filters have unsent data
    152  * - CF_QUERY_IP_INFO: res1 says if connection used IPv6, res2 is the
    153  *                   ip quadruple
    154  * - CF_QUERY_HOST_PORT: the remote hostname and port a filter talks to
    155  * - CF_QUERY_SSL_INFO: fill out the passed curl_tlssessioninfo with the
    156  *                      internal from the SSL secured connection when
    157  *                      available.
    158  * - CF_QUERY_SSL_CTX_INFO: same as CF_QUERY_SSL_INFO, but give the SSL_CTX
    159  *                      when available, or the same internal pointer
    160  *                      when the TLS stack does not differentiate.
    161  */
    162 /*      query                             res1       res2     */
    163 #define CF_QUERY_MAX_CONCURRENT     1  /* number     -        */
    164 #define CF_QUERY_CONNECT_REPLY_MS   2  /* number     -        */
    165 #define CF_QUERY_SOCKET             3  /* -          curl_socket_t */
    166 #define CF_QUERY_TIMER_CONNECT      4  /* -          struct curltime */
    167 #define CF_QUERY_TIMER_APPCONNECT   5  /* -          struct curltime */
    168 #define CF_QUERY_STREAM_ERROR       6  /* error code - */
    169 #define CF_QUERY_NEED_FLUSH         7  /* TRUE/FALSE - */
    170 #define CF_QUERY_IP_INFO            8  /* TRUE/FALSE struct ip_quadruple */
    171 #define CF_QUERY_HTTP_VERSION       9  /* number (10/11/20/30)   -  */
    172 /* pass in a `const struct Curl_sockaddr_ex **` as `pres2`. Gets set
    173  * to NULL when not connected. */
    174 #define CF_QUERY_REMOTE_ADDR       10  /* -          `Curl_sockaddr_ex *` */
    175 #define CF_QUERY_HOST_PORT         11  /* port       const char * */
    176 #define CF_QUERY_SSL_INFO          12  /* -    struct curl_tlssessioninfo * */
    177 #define CF_QUERY_SSL_CTX_INFO      13  /* -    struct curl_tlssessioninfo * */
    178 #define CF_QUERY_TRANSPORT         14  /* TRNSPRT_*  - * */
    179 
    180 /**
    181  * Query the cfilter for properties. Filters ignorant of a query will
    182  * pass it "down" the filter chain.
    183  */
    184 typedef CURLcode Curl_cft_query(struct Curl_cfilter *cf,
    185                                 struct Curl_easy *data,
    186                                 int query, int *pres1, void *pres2);
    187 
    188 /**
    189  * Type flags for connection filters. A filter can have none, one or
    190  * many of those. Use to evaluate state/capabilities of a filter chain.
    191  *
    192  * CF_TYPE_IP_CONNECT: provides an IP connection or sth equivalent, like
    193  *                     a CONNECT tunnel, a UNIX domain socket, a QUIC
    194  *                     connection, etc.
    195  * CF_TYPE_SSL:        provide SSL/TLS
    196  * CF_TYPE_MULTIPLEX:  provides multiplexing of easy handles
    197  * CF_TYPE_PROXY       provides proxying
    198  * CF_TYPE_HTTP        implement a version of the HTTP protocol
    199  */
    200 #define CF_TYPE_IP_CONNECT  (1 << 0)
    201 #define CF_TYPE_SSL         (1 << 1)
    202 #define CF_TYPE_MULTIPLEX   (1 << 2)
    203 #define CF_TYPE_PROXY       (1 << 3)
    204 #define CF_TYPE_HTTP        (1 << 4)
    205 
    206 /* A connection filter type, e.g. specific implementation. */
    207 struct Curl_cftype {
    208   const char *name;                       /* name of the filter type */
    209   int flags;                              /* flags of filter type */
    210   int log_level;                          /* log level for such filters */
    211   Curl_cft_destroy_this *destroy;         /* destroy resources of this cf */
    212   Curl_cft_connect *do_connect;           /* establish connection */
    213   Curl_cft_close *do_close;               /* close conn */
    214   Curl_cft_shutdown *do_shutdown;         /* shutdown conn */
    215   Curl_cft_adjust_pollset *adjust_pollset; /* adjust transfer poll set */
    216   Curl_cft_data_pending *has_data_pending;/* conn has data pending */
    217   Curl_cft_send *do_send;                 /* send data */
    218   Curl_cft_recv *do_recv;                 /* receive data */
    219   Curl_cft_cntrl *cntrl;                  /* events/control */
    220   Curl_cft_conn_is_alive *is_alive;       /* FALSE if conn is dead, Jim! */
    221   Curl_cft_conn_keep_alive *keep_alive;   /* try to keep it alive */
    222   Curl_cft_query *query;                  /* query filter chain */
    223 };
    224 
    225 /* A connection filter instance, e.g. registered at a connection */
    226 struct Curl_cfilter {
    227   const struct Curl_cftype *cft; /* the type providing implementation */
    228   struct Curl_cfilter *next;     /* next filter in chain */
    229   void *ctx;                     /* filter type specific settings */
    230   struct connectdata *conn;      /* the connection this filter belongs to */
    231   int sockindex;                 /* the index the filter is installed at */
    232   BIT(connected);                /* != 0 iff this filter is connected */
    233   BIT(shutdown);                 /* != 0 iff this filter has shut down */
    234 };
    235 
    236 /* Default implementations for the type functions, implementing nop. */
    237 void Curl_cf_def_destroy_this(struct Curl_cfilter *cf,
    238                               struct Curl_easy *data);
    239 
    240 /* Default implementations for the type functions, implementing pass-through
    241  * the filter chain. */
    242 void     Curl_cf_def_adjust_pollset(struct Curl_cfilter *cf,
    243                                     struct Curl_easy *data,
    244                                     struct easy_pollset *ps);
    245 bool     Curl_cf_def_data_pending(struct Curl_cfilter *cf,
    246                                   const struct Curl_easy *data);
    247 CURLcode Curl_cf_def_send(struct Curl_cfilter *cf, struct Curl_easy *data,
    248                           const void *buf, size_t len, bool eos,
    249                           size_t *pnwritten);
    250 CURLcode Curl_cf_def_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
    251                           char *buf, size_t len, size_t *pnread);
    252 CURLcode Curl_cf_def_cntrl(struct Curl_cfilter *cf,
    253                            struct Curl_easy *data,
    254                            int event, int arg1, void *arg2);
    255 bool     Curl_cf_def_conn_is_alive(struct Curl_cfilter *cf,
    256                                    struct Curl_easy *data,
    257                                    bool *input_pending);
    258 CURLcode Curl_cf_def_conn_keep_alive(struct Curl_cfilter *cf,
    259                                      struct Curl_easy *data);
    260 CURLcode Curl_cf_def_query(struct Curl_cfilter *cf,
    261                            struct Curl_easy *data,
    262                            int query, int *pres1, void *pres2);
    263 CURLcode Curl_cf_def_shutdown(struct Curl_cfilter *cf,
    264                               struct Curl_easy *data, bool *done);
    265 
    266 /**
    267  * Create a new filter instance, unattached to the filter chain.
    268  * Use Curl_conn_cf_add() to add it to the chain.
    269  * @param pcf  on success holds the created instance
    270  * @param cft   the filter type
    271  * @param ctx  the type specific context to use
    272  */
    273 CURLcode Curl_cf_create(struct Curl_cfilter **pcf,
    274                         const struct Curl_cftype *cft,
    275                         void *ctx);
    276 
    277 /**
    278  * Add a filter instance to the `sockindex` filter chain at connection
    279  * `conn`. The filter must not already be attached. It is inserted at
    280  * the start of the chain (top).
    281  */
    282 void Curl_conn_cf_add(struct Curl_easy *data,
    283                       struct connectdata *conn,
    284                       int sockindex,
    285                       struct Curl_cfilter *cf);
    286 
    287 /**
    288  * Insert a filter (chain) after `cf_at`.
    289  * `cf_new` must not already be attached.
    290  */
    291 void Curl_conn_cf_insert_after(struct Curl_cfilter *cf_at,
    292                                struct Curl_cfilter *cf_new);
    293 
    294 /**
    295  * Discard, e.g. remove and destroy `discard` iff
    296  * it still is in the filter chain below `cf`. If `discard`
    297  * is no longer found beneath `cf` return FALSE.
    298  * if `destroy_always` is TRUE, will call `discard`s destroy
    299  * function and free it even if not found in the subchain.
    300  */
    301 bool Curl_conn_cf_discard_sub(struct Curl_cfilter *cf,
    302                               struct Curl_cfilter *discard,
    303                               struct Curl_easy *data,
    304                               bool destroy_always);
    305 
    306 /**
    307  * Discard all cfilters starting with `*pcf` and clearing it afterwards.
    308  */
    309 void Curl_conn_cf_discard_chain(struct Curl_cfilter **pcf,
    310                                 struct Curl_easy *data);
    311 
    312 /**
    313  * Remove and destroy all filters at chain `sockindex` on connection `conn`.
    314  */
    315 void Curl_conn_cf_discard_all(struct Curl_easy *data,
    316                               struct connectdata *conn,
    317                               int sockindex);
    318 
    319 
    320 CURLcode Curl_conn_cf_connect(struct Curl_cfilter *cf,
    321                               struct Curl_easy *data,
    322                               bool *done);
    323 void Curl_conn_cf_close(struct Curl_cfilter *cf, struct Curl_easy *data);
    324 CURLcode Curl_conn_cf_send(struct Curl_cfilter *cf, struct Curl_easy *data,
    325                            const void *buf, size_t len, bool eos,
    326                            size_t *pnwritten);
    327 CURLcode Curl_conn_cf_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
    328                            char *buf, size_t len, size_t *pnread);
    329 CURLcode Curl_conn_cf_cntrl(struct Curl_cfilter *cf,
    330                             struct Curl_easy *data,
    331                             bool ignore_result,
    332                             int event, int arg1, void *arg2);
    333 
    334 /**
    335  * Determine if the connection filter chain is using SSL to the remote host
    336  * (or will be once connected).
    337  */
    338 bool Curl_conn_cf_is_ssl(struct Curl_cfilter *cf);
    339 
    340 /**
    341  * Get the socket used by the filter chain starting at `cf`.
    342  * Returns CURL_SOCKET_BAD if not available.
    343  */
    344 curl_socket_t Curl_conn_cf_get_socket(struct Curl_cfilter *cf,
    345                                       struct Curl_easy *data);
    346 
    347 CURLcode Curl_conn_cf_get_ip_info(struct Curl_cfilter *cf,
    348                                   struct Curl_easy *data,
    349                                   int *is_ipv6, struct ip_quadruple *ipquad);
    350 
    351 bool Curl_conn_cf_needs_flush(struct Curl_cfilter *cf,
    352                               struct Curl_easy *data);
    353 
    354 unsigned char Curl_conn_cf_get_transport(struct Curl_cfilter *cf,
    355                                          struct Curl_easy *data);
    356 
    357 #define CURL_CF_SSL_DEFAULT  -1
    358 #define CURL_CF_SSL_DISABLE  0
    359 #define CURL_CF_SSL_ENABLE   1
    360 
    361 /**
    362  * Bring the filter chain at `sockindex` for connection `data->conn` into
    363  * connected state. Which will set `*done` to TRUE.
    364  * This can be called on an already connected chain with no side effects.
    365  * When not `blocking`, calls may return without error and `*done != TRUE`,
    366  * while the individual filters negotiated the connection.
    367  */
    368 CURLcode Curl_conn_connect(struct Curl_easy *data, int sockindex,
    369                            bool blocking, bool *done);
    370 
    371 /**
    372  * Check if a filter chain at `sockindex` for connection `conn` exists.
    373  */
    374 bool Curl_conn_is_setup(struct connectdata *conn, int sockindex);
    375 
    376 /**
    377  * Check if the filter chain at `sockindex` for connection `conn` is
    378  * completely connected.
    379  */
    380 bool Curl_conn_is_connected(struct connectdata *conn, int sockindex);
    381 
    382 /**
    383  * Determine if we have reached the remote host on IP level, e.g.
    384  * have a TCP connection. This turns TRUE before a possible SSL
    385  * handshake has been started/done.
    386  */
    387 bool Curl_conn_is_ip_connected(struct Curl_easy *data, int sockindex);
    388 
    389 /**
    390  * Determine if the connection is using SSL to the remote host
    391  * (or will be once connected). This will return FALSE, if SSL
    392  * is only used in proxying and not for the tunnel itself.
    393  */
    394 bool Curl_conn_is_ssl(struct connectdata *conn, int sockindex);
    395 
    396 /*
    397  * Fill `info` with information about the TLS instance securing
    398  * the connection when available, otherwise e.g. when
    399  * Curl_conn_is_ssl() is FALSE, return FALSE.
    400  */
    401 bool Curl_conn_get_ssl_info(struct Curl_easy *data,
    402                             struct connectdata *conn, int sockindex,
    403                             struct curl_tlssessioninfo *info);
    404 
    405 /**
    406  * Connection provides multiplexing of easy handles at `socketindex`.
    407  */
    408 bool Curl_conn_is_multiplex(struct connectdata *conn, int sockindex);
    409 
    410 /**
    411  * Return the HTTP version used on the FIRSTSOCKET connection filters
    412  * or 0 if unknown. Value otherwise is 09, 10, 11, etc.
    413  */
    414 unsigned char Curl_conn_http_version(struct Curl_easy *data,
    415                                      struct connectdata *conn);
    416 
    417 /* Get the TRNSPRT_* the connection is using */
    418 unsigned char Curl_conn_get_transport(struct Curl_easy *data,
    419                                       struct connectdata *conn);
    420 
    421 /**
    422  * Close the filter chain at `sockindex` for connection `data->conn`.
    423   * Filters remain in place and may be connected again afterwards.
    424  */
    425 void Curl_conn_close(struct Curl_easy *data, int sockindex);
    426 
    427 /**
    428  * Shutdown the connection at `sockindex` non-blocking, using timeout
    429  * from `data->set.shutdowntimeout`, default DEFAULT_SHUTDOWN_TIMEOUT_MS.
    430  * Will return CURLE_OK and *done == FALSE if not finished.
    431  */
    432 CURLcode Curl_conn_shutdown(struct Curl_easy *data, int sockindex, bool *done);
    433 
    434 /**
    435  * Return if data is pending in some connection filter at chain
    436  * `sockindex` for connection `data->conn`.
    437  */
    438 bool Curl_conn_data_pending(struct Curl_easy *data,
    439                             int sockindex);
    440 
    441 /**
    442  * Return TRUE if any of the connection filters at chain `sockindex`
    443  * have data still to send.
    444  */
    445 bool Curl_conn_needs_flush(struct Curl_easy *data, int sockindex);
    446 
    447 /**
    448  * Flush any pending data on the connection filters at chain `sockindex`.
    449  */
    450 CURLcode Curl_conn_flush(struct Curl_easy *data, int sockindex);
    451 
    452 /**
    453  * Return the socket used on data's connection for the index.
    454  * Returns CURL_SOCKET_BAD if not available.
    455  */
    456 curl_socket_t Curl_conn_get_socket(struct Curl_easy *data, int sockindex);
    457 
    458 /* Return a pointer to the connected socket address or NULL. */
    459 const struct Curl_sockaddr_ex *
    460 Curl_conn_get_remote_addr(struct Curl_easy *data, int sockindex);
    461 
    462 /**
    463  * Tell filters to forget about the socket at sockindex.
    464  */
    465 void Curl_conn_forget_socket(struct Curl_easy *data, int sockindex);
    466 
    467 /**
    468  * Adjust the pollset for the filter chain starting at `cf`.
    469  */
    470 void Curl_conn_cf_adjust_pollset(struct Curl_cfilter *cf,
    471                                  struct Curl_easy *data,
    472                                  struct easy_pollset *ps);
    473 
    474 /**
    475  * Adjust pollset from filters installed at transfer's connection.
    476  */
    477 void Curl_conn_adjust_pollset(struct Curl_easy *data,
    478                               struct connectdata *conn,
    479                               struct easy_pollset *ps);
    480 
    481 /**
    482  * Curl_poll() the filter chain at `cf` with timeout `timeout_ms`.
    483  * Returns 0 on timeout, negative on error or number of sockets
    484  * with requested poll events.
    485  */
    486 int Curl_conn_cf_poll(struct Curl_cfilter *cf,
    487                       struct Curl_easy *data,
    488                       timediff_t timeout_ms);
    489 
    490 /**
    491  * Receive data through the filter chain at `sockindex` for connection
    492  * `data->conn`. Copy at most `len` bytes into `buf`. Return the
    493  * actual number of bytes copied in `*pnread`or an error.
    494  */
    495 CURLcode Curl_cf_recv(struct Curl_easy *data, int sockindex, char *buf,
    496                       size_t len, size_t *pnread);
    497 
    498 /**
    499  * Send `len` bytes of data from `buf` through the filter chain `sockindex`
    500  * at connection `data->conn`. Return the actual number of bytes written
    501  * in `*pnwritten` or on error.
    502  */
    503 CURLcode Curl_cf_send(struct Curl_easy *data, int sockindex,
    504                       const void *buf, size_t len, bool eos,
    505                       size_t *pnwritten);
    506 
    507 /**
    508  * Receive bytes from connection filter `cf` into `bufq`.
    509  * Convenience wrappter around `Curl_bufq_sipn()`,
    510  * so users do not have to implement a callback.
    511  */
    512 CURLcode Curl_cf_recv_bufq(struct Curl_cfilter *cf,
    513                            struct Curl_easy *data,
    514                            struct bufq *bufq,
    515                            size_t maxlen,
    516                            size_t *pnread);
    517 
    518 /**
    519  * Send bytes in `bufq` using connection filter `cf`.
    520  * A convenience wrapper around `Curl_bufq_write_pass()`,
    521  * so users do not have to implement a callback.
    522  */
    523 CURLcode Curl_cf_send_bufq(struct Curl_cfilter *cf,
    524                            struct Curl_easy *data,
    525                            struct bufq *bufq,
    526                            const unsigned char *buf, size_t blen,
    527                            size_t *pnwritten);
    528 
    529 /**
    530  * Notify connection filters that they need to setup data for
    531  * a transfer.
    532  */
    533 CURLcode Curl_conn_ev_data_setup(struct Curl_easy *data);
    534 
    535 /**
    536  * Notify connection filters that now would be a good time to
    537  * perform any idle, e.g. time related, actions.
    538  */
    539 CURLcode Curl_conn_ev_data_idle(struct Curl_easy *data);
    540 
    541 /**
    542  * Notify connection filters that the transfer represented by `data`
    543  * is done with sending data (e.g. has uploaded everything).
    544  */
    545 void Curl_conn_ev_data_done_send(struct Curl_easy *data);
    546 
    547 /**
    548  * Notify connection filters that the transfer represented by `data`
    549  * is finished - eventually premature, e.g. before being complete.
    550  */
    551 void Curl_conn_ev_data_done(struct Curl_easy *data, bool premature);
    552 
    553 /**
    554  * Notify connection filters that the transfer of data is paused/unpaused.
    555  */
    556 CURLcode Curl_conn_ev_data_pause(struct Curl_easy *data, bool do_pause);
    557 
    558 /**
    559  * Check if FIRSTSOCKET's cfilter chain deems connection alive.
    560  */
    561 bool Curl_conn_is_alive(struct Curl_easy *data, struct connectdata *conn,
    562                         bool *input_pending);
    563 
    564 /**
    565  * Try to upkeep the connection filters at sockindex.
    566  */
    567 CURLcode Curl_conn_keep_alive(struct Curl_easy *data,
    568                               struct connectdata *conn,
    569                               int sockindex);
    570 
    571 #ifdef UNITTESTS
    572 void Curl_cf_def_close(struct Curl_cfilter *cf, struct Curl_easy *data);
    573 #endif
    574 
    575 /**
    576  * Get the remote hostname and port that the connection is currently
    577  * talking to (or will talk to).
    578  * Once connected or before connect starts,
    579  * it is `conn->host.name` and `conn->remote_port`.
    580  * During connect, when tunneling proxies are involved (http or socks),
    581  * it will be the name and port the proxy currently negotiates with.
    582  */
    583 void Curl_conn_get_current_host(struct Curl_easy *data, int sockindex,
    584                                 const char **phost, int *pport);
    585 
    586 /**
    587  * Get the maximum number of parallel transfers the connection
    588  * expects to be able to handle at `sockindex`.
    589  */
    590 size_t Curl_conn_get_max_concurrent(struct Curl_easy *data,
    591                                     struct connectdata *conn,
    592                                     int sockindex);
    593 
    594 /**
    595  * Get the underlying error code for a transfer stream or 0 if not known.
    596  */
    597 int Curl_conn_get_stream_error(struct Curl_easy *data,
    598                                struct connectdata *conn,
    599                                int sockindex);
    600 
    601 /**
    602  * Get the index of the given socket in the connection's sockets.
    603  * Useful in calling `Curl_conn_send()/Curl_conn_recv()` with the
    604  * correct socket index.
    605  */
    606 int Curl_conn_sockindex(struct Curl_easy *data, curl_socket_t sockfd);
    607 
    608 /*
    609  * Receive data on the connection, using FIRSTSOCKET/SECONDARYSOCKET.
    610  * Will return CURLE_AGAIN iff blocked on receiving.
    611  */
    612 CURLcode Curl_conn_recv(struct Curl_easy *data, int sockindex,
    613                         char *buf, size_t buffersize,
    614                         size_t *pnread);
    615 
    616 /*
    617  * Send data on the connection, using FIRSTSOCKET/SECONDARYSOCKET.
    618  * Will return CURLE_AGAIN iff blocked on sending.
    619  */
    620 CURLcode Curl_conn_send(struct Curl_easy *data, int sockindex,
    621                         const void *buf, size_t blen, bool eos,
    622                         size_t *pnwritten);
    623 
    624 
    625 void Curl_pollset_reset(struct Curl_easy *data,
    626                         struct easy_pollset *ps);
    627 
    628 /* Change the poll flags (CURL_POLL_IN/CURL_POLL_OUT) to the poll set for
    629  * socket `sock`. If the socket is not already part of the poll set, it
    630  * will be added.
    631  * If the socket is present and all poll flags are cleared, it will be removed.
    632  */
    633 void Curl_pollset_change(struct Curl_easy *data,
    634                          struct easy_pollset *ps, curl_socket_t sock,
    635                          int add_flags, int remove_flags);
    636 
    637 void Curl_pollset_set(struct Curl_easy *data,
    638                       struct easy_pollset *ps, curl_socket_t sock,
    639                       bool do_in, bool do_out);
    640 
    641 #define Curl_pollset_add_in(data, ps, sock) \
    642           Curl_pollset_change((data), (ps), (sock), CURL_POLL_IN, 0)
    643 #define Curl_pollset_add_out(data, ps, sock) \
    644           Curl_pollset_change((data), (ps), (sock), CURL_POLL_OUT, 0)
    645 #define Curl_pollset_add_inout(data, ps, sock) \
    646           Curl_pollset_change((data), (ps), (sock), \
    647                                CURL_POLL_IN|CURL_POLL_OUT, 0)
    648 #define Curl_pollset_set_in_only(data, ps, sock) \
    649           Curl_pollset_change((data), (ps), (sock), \
    650                                CURL_POLL_IN, CURL_POLL_OUT)
    651 #define Curl_pollset_set_out_only(data, ps, sock) \
    652           Curl_pollset_change((data), (ps), (sock), \
    653                                CURL_POLL_OUT, CURL_POLL_IN)
    654 
    655 void Curl_pollset_add_socks(struct Curl_easy *data,
    656                             struct easy_pollset *ps,
    657                             int (*get_socks_cb)(struct Curl_easy *data,
    658                                                 curl_socket_t *socks));
    659 
    660 /**
    661  * Check if the pollset, as is, wants to read and/or write regarding
    662  * the given socket.
    663  */
    664 void Curl_pollset_check(struct Curl_easy *data,
    665                         struct easy_pollset *ps, curl_socket_t sock,
    666                         bool *pwant_read, bool *pwant_write);
    667 
    668 /**
    669  * Return TRUE if the pollset contains socket with CURL_POLL_IN.
    670  */
    671 bool Curl_pollset_want_read(struct Curl_easy *data,
    672                             struct easy_pollset *ps,
    673                             curl_socket_t sock);
    674 
    675 /**
    676  * Types and macros used to keep the current easy handle in filter calls,
    677  * allowing for nested invocations. See #10336.
    678  *
    679  * `cf_call_data` is intended to be a member of the cfilter's `ctx` type.
    680  * A filter defines the macro `CF_CTX_CALL_DATA` to give access to that.
    681  *
    682  * With all values 0, the default, this indicates that there is no cfilter
    683  * call with `data` ongoing.
    684  * Macro `CF_DATA_SAVE` preserves the current `cf_call_data` in a local
    685  * variable and sets the `data` given, incrementing the `depth` counter.
    686  *
    687  * Macro `CF_DATA_RESTORE` restores the old values from the local variable,
    688  * while checking that `depth` values are as expected (debug build), catching
    689  * cases where a "lower" RESTORE was not called.
    690  *
    691  * Finally, macro `CF_DATA_CURRENT` gives the easy handle of the current
    692  * invocation.
    693  */
    694 struct cf_call_data {
    695   struct Curl_easy *data;
    696 #ifdef DEBUGBUILD
    697   int depth;
    698 #endif
    699 };
    700 
    701 /**
    702  * define to access the `struct cf_call_data for a cfilter. Normally
    703  * a member in the cfilter's `ctx`.
    704  *
    705  * #define CF_CTX_CALL_DATA(cf)   -> struct cf_call_data instance
    706 */
    707 
    708 #ifdef DEBUGBUILD
    709 
    710 #define CF_DATA_SAVE(save, cf, data) \
    711   do { \
    712     (save) = CF_CTX_CALL_DATA(cf); \
    713     DEBUGASSERT((save).data == NULL || (save).depth > 0); \
    714     CF_CTX_CALL_DATA(cf).depth++;  \
    715     CF_CTX_CALL_DATA(cf).data = (struct Curl_easy *)CURL_UNCONST(data); \
    716   } while(0)
    717 
    718 #define CF_DATA_RESTORE(cf, save) \
    719   do { \
    720     DEBUGASSERT(CF_CTX_CALL_DATA(cf).depth == (save).depth + 1); \
    721     DEBUGASSERT((save).data == NULL || (save).depth > 0); \
    722     CF_CTX_CALL_DATA(cf) = (save); \
    723   } while(0)
    724 
    725 #else /* DEBUGBUILD */
    726 
    727 #define CF_DATA_SAVE(save, cf, data) \
    728   do { \
    729     (save) = CF_CTX_CALL_DATA(cf); \
    730     CF_CTX_CALL_DATA(cf).data = (struct Curl_easy *)CURL_UNCONST(data); \
    731   } while(0)
    732 
    733 #define CF_DATA_RESTORE(cf, save) \
    734   do { \
    735     CF_CTX_CALL_DATA(cf) = (save); \
    736   } while(0)
    737 
    738 #endif /* !DEBUGBUILD */
    739 
    740 #define CF_DATA_CURRENT(cf) \
    741   ((cf)? (CF_CTX_CALL_DATA(cf).data) : NULL)
    742 
    743 #endif /* HEADER_CURL_CFILTERS_H */