quickjs-tart

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

ares_conn.h (8345B)


      1 /* MIT License
      2  *
      3  * Copyright (c) 2024 Brad House
      4  *
      5  * Permission is hereby granted, free of charge, to any person obtaining a copy
      6  * of this software and associated documentation files (the "Software"), to deal
      7  * in the Software without restriction, including without limitation the rights
      8  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      9  * copies of the Software, and to permit persons to whom the Software is
     10  * furnished to do so, subject to the following conditions:
     11  *
     12  * The above copyright notice and this permission notice (including the next
     13  * paragraph) shall be included in all copies or substantial portions of the
     14  * Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     22  * SOFTWARE.
     23  *
     24  * SPDX-License-Identifier: MIT
     25  */
     26 #ifndef __ARES_CONN_H
     27 #define __ARES_CONN_H
     28 
     29 #include "ares_socket.h"
     30 
     31 struct ares_conn;
     32 typedef struct ares_conn ares_conn_t;
     33 
     34 struct ares_server;
     35 typedef struct ares_server ares_server_t;
     36 
     37 typedef enum {
     38   /*! No flags */
     39   ARES_CONN_FLAG_NONE = 0,
     40   /*! TCP connection, not UDP */
     41   ARES_CONN_FLAG_TCP = 1 << 0,
     42   /*! TCP Fast Open is enabled and being used if supported by the OS */
     43   ARES_CONN_FLAG_TFO = 1 << 1,
     44   /*! TCP Fast Open has not yet sent its first packet. Gets unset on first
     45    *  write to a connection */
     46   ARES_CONN_FLAG_TFO_INITIAL = 1 << 2
     47 } ares_conn_flags_t;
     48 
     49 typedef enum {
     50   ARES_CONN_STATE_NONE      = 0,
     51   ARES_CONN_STATE_READ      = 1 << 0,
     52   ARES_CONN_STATE_WRITE     = 1 << 1,
     53   ARES_CONN_STATE_CONNECTED = 1 << 2, /* This doesn't get a callback */
     54   ARES_CONN_STATE_CBFLAGS   = ARES_CONN_STATE_READ | ARES_CONN_STATE_WRITE
     55 } ares_conn_state_flags_t;
     56 
     57 struct ares_conn {
     58   ares_server_t          *server;
     59   ares_socket_t           fd;
     60   struct ares_addr        self_ip;
     61   ares_conn_flags_t       flags;
     62   ares_conn_state_flags_t state_flags;
     63 
     64   /*! Outbound buffered data that is not yet sent.  Exists as one contiguous
     65    *  stream in TCP format (big endian 16bit length prefix followed by DNS
     66    *  wire-format message).  For TCP this can be sent as-is, UDP this must
     67    *  be sent per-packet (stripping the length prefix) */
     68   ares_buf_t             *out_buf;
     69 
     70   /*! Inbound buffered data that is not yet parsed.  Exists as one contiguous
     71    *  stream in TCP format (big endian 16bit length prefix followed by DNS
     72    *  wire-format message).  TCP may have partial data and this needs to be
     73    *  handled gracefully, but UDP will always have a full message */
     74   ares_buf_t             *in_buf;
     75 
     76   /* total number of queries run on this connection since it was established */
     77   size_t                  total_queries;
     78 
     79   /* list of outstanding queries to this connection */
     80   ares_llist_t           *queries_to_conn;
     81 };
     82 
     83 /*! Various buckets for grouping history */
     84 typedef enum {
     85   ARES_METRIC_1MINUTE = 0, /*!< Bucket for tracking over the last minute */
     86   ARES_METRIC_15MINUTES,   /*!< Bucket for tracking over the last 15 minutes */
     87   ARES_METRIC_1HOUR,       /*!< Bucket for tracking over the last hour */
     88   ARES_METRIC_1DAY,        /*!< Bucket for tracking over the last day */
     89   ARES_METRIC_INCEPTION,   /*!< Bucket for tracking since inception */
     90   ARES_METRIC_COUNT        /*!< Count of buckets, not a real bucket */
     91 } ares_server_bucket_t;
     92 
     93 /*! Data metrics collected for each bucket */
     94 typedef struct {
     95   time_t        ts;             /*!< Timestamp divided by bucket divisor */
     96   unsigned int  latency_min_ms; /*!< Minimum latency for queries */
     97   unsigned int  latency_max_ms; /*!< Maximum latency for queries */
     98   ares_uint64_t total_ms;       /*!< Cumulative query time for bucket */
     99   ares_uint64_t total_count;    /*!< Number of queries for bucket */
    100 
    101   time_t        prev_ts;        /*!< Previous period bucket timestamp */
    102   ares_uint64_t
    103     prev_total_ms; /*!< Previous period bucket cumulative query time */
    104   ares_uint64_t prev_total_count; /*!< Previous period bucket query count */
    105 } ares_server_metrics_t;
    106 
    107 typedef enum {
    108   ARES_COOKIE_INITIAL     = 0,
    109   ARES_COOKIE_GENERATED   = 1,
    110   ARES_COOKIE_SUPPORTED   = 2,
    111   ARES_COOKIE_UNSUPPORTED = 3
    112 } ares_cookie_state_t;
    113 
    114 /*! Structure holding tracking data for RFC 7873/9018 DNS cookies.
    115  *  Implementation plan for this feature is here:
    116  *  https://github.com/c-ares/c-ares/issues/620
    117  */
    118 typedef struct {
    119   /*! starts at INITIAL, transitions as needed. */
    120   ares_cookie_state_t state;
    121   /*! randomly-generate client cookie */
    122   unsigned char       client[8];
    123   /*! timestamp client cookie was generated, used for rotation purposes */
    124   ares_timeval_t      client_ts;
    125   /*! IP address last used for client to connect to server.  If this changes
    126    *  The client cookie gets invalidated */
    127   struct ares_addr    client_ip;
    128   /*! Server Cookie last received, 8-32 bytes in length */
    129   unsigned char       server[32];
    130   /*! Length of server cookie on file. */
    131   size_t              server_len;
    132   /*! Timestamp of last attempt to use cookies, but it was determined that the
    133    *  server didn't support them */
    134   ares_timeval_t      unsupported_ts;
    135 } ares_cookie_t;
    136 
    137 struct ares_server {
    138   /* Configuration */
    139   size_t                idx;      /* index for server in system configuration */
    140   struct ares_addr      addr;
    141   unsigned short        udp_port; /* host byte order */
    142   unsigned short        tcp_port; /* host byte order */
    143   char                  ll_iface[64];    /* IPv6 Link Local Interface */
    144   unsigned int          ll_scope;        /* IPv6 Link Local Scope */
    145 
    146   size_t                consec_failures; /* Consecutive query failure count
    147                                           * can be hard errors or timeouts
    148                                           */
    149   ares_bool_t           probe_pending;   /* Whether a probe is pending for this
    150                                           * server due to prior failures */
    151   ares_llist_t         *connections;
    152   ares_conn_t          *tcp_conn;
    153 
    154   /* The next time when we will retry this server if it has hit failures */
    155   ares_timeval_t        next_retry_time;
    156 
    157   /*! Buckets for collecting metrics about the server */
    158   ares_server_metrics_t metrics[ARES_METRIC_COUNT];
    159 
    160   /*! RFC 7873/9018 DNS Cookies */
    161   ares_cookie_t         cookie;
    162 
    163   /* Link back to owning channel */
    164   ares_channel_t       *channel;
    165 };
    166 
    167 void ares_close_connection(ares_conn_t *conn, ares_status_t requeue_status);
    168 void ares_close_sockets(ares_server_t *server);
    169 void ares_check_cleanup_conns(const ares_channel_t *channel);
    170 
    171 void ares_destroy_servers_state(ares_channel_t *channel);
    172 ares_status_t   ares_open_connection(ares_conn_t   **conn_out,
    173                                      ares_channel_t *channel,
    174                                      ares_server_t *server, ares_bool_t is_tcp);
    175 
    176 ares_conn_err_t ares_conn_write(ares_conn_t *conn, const void *data, size_t len,
    177                                 size_t *written);
    178 ares_status_t   ares_conn_flush(ares_conn_t *conn);
    179 ares_conn_err_t ares_conn_read(ares_conn_t *conn, void *data, size_t len,
    180                                size_t *read_bytes);
    181 ares_conn_t *ares_conn_from_fd(const ares_channel_t *channel, ares_socket_t fd);
    182 void         ares_conn_sock_state_cb_update(ares_conn_t            *conn,
    183                                             ares_conn_state_flags_t flags);
    184 ares_conn_err_t ares_socket_recv(ares_channel_t *channel, ares_socket_t s,
    185                                  ares_bool_t is_tcp, void *data,
    186                                  size_t data_len, size_t *read_bytes);
    187 ares_conn_err_t ares_socket_recvfrom(ares_channel_t *channel, ares_socket_t s,
    188                                      ares_bool_t is_tcp, void *data,
    189                                      size_t data_len, int flags,
    190                                      struct sockaddr *from,
    191                                      ares_socklen_t  *from_len,
    192                                      size_t          *read_bytes);
    193 
    194 void            ares_destroy_server(ares_server_t *server);
    195 
    196 #endif