lsquic_conn.h revision 5392f7a3
1/* Copyright (c) 2017 - 2019 LiteSpeed Technologies Inc.  See LICENSE. */
2/*
3 * lsquic_conn.h -- Connection interface
4 *
5 * There are two types of connections: full (lsquic_full_conn.h) and mini
6 * (lsquic_mini_conn.h).  The function pointers and struct in this header
7 * file provide a unified interface engine.c can use to interact with
8 * either of the connection types.  For this to work, struct lsquic_conn
9 * must be the first element of struct full_conn and struct mini_conn.
10 */
11#ifndef LSQUIC_CONN_H
12#define LSQUIC_CONN_H
13
14#include <sys/queue.h>
15#ifndef WIN32
16#include <sys/socket.h>
17#include <netinet/in.h>
18#else
19#include <ws2ipdef.h>
20#endif
21
22struct lsquic_conn;
23struct lsquic_engine_public;
24struct lsquic_packet_out;
25struct lsquic_packet_in;
26struct sockaddr;
27struct parse_funcs;
28struct attq_elem;
29#if LSQUIC_CONN_STATS
30struct conn_stats;
31#endif
32
33enum lsquic_conn_flags {
34    LSCONN_TICKED         = (1 << 0),
35    LSCONN_HAS_OUTGOING   = (1 << 1),
36    LSCONN_HASHED         = (1 << 2),
37    LSCONN_MINI           = (1 << 3),   /* This is a mini connection */
38    LSCONN_UNUSED_4       = (1 << 4),
39    LSCONN_UNUSED_5       = (1 << 5),
40    LSCONN_HANDSHAKE_DONE = (1 << 6),
41    LSCONN_CLOSING        = (1 << 7),
42    LSCONN_PEER_GOING_AWAY= (1 << 8),
43    LSCONN_TCID0          = (1 << 9),
44    LSCONN_VER_SET        = (1 <<10),   /* cn_version is set */
45    LSCONN_EVANESCENT     = (1 <<11),   /* evanescent connection */
46    LSCONN_TICKABLE       = (1 <<12),   /* Connection is in the Tickable Queue */
47    LSCONN_COI_ACTIVE     = (1 <<13),
48    LSCONN_COI_INACTIVE   = (1 <<14),
49    LSCONN_SEND_BLOCKED   = (1 <<15),   /* Send connection blocked frame */
50    LSCONN_PROMOTED       = (1 <<16),   /* Promoted.  Only set if LSCONN_MINI is set */
51    LSCONN_NEVER_TICKABLE = (1 <<17),   /* Do not put onto the Tickable Queue */
52    LSCONN_UNUSED_18      = (1 <<18),
53    LSCONN_ATTQ           = (1 <<19),
54    LSCONN_SKIP_ON_PROC   = (1 <<20),
55#if LSQUIC_ENABLE_HANDSHAKE_DISABLE
56    LSCONN_NO_CRYPTO      = (1 <<21),
57#endif
58    LSCONN_SERVER         = (1 <<22),
59    LSCONN_IETF           = (1 <<23),
60    LSCONN_RETRY_CONN     = (1 <<24),   /* This is a retry connection */
61};
62
63/* A connection may have things to send and be closed at the same time.
64 */
65enum tick_st {
66    TICK_SEND    = (1 << 0),
67    TICK_CLOSE   = (1 << 1),
68    TICK_PROMOTE = (1 << 2), /* Promote mini connection to full connection */
69};
70
71#define TICK_QUIET 0
72
73struct network_path
74{
75    union {
76        unsigned char           buf[sizeof(struct sockaddr_in6)];
77        struct sockaddr         sockaddr;
78    }               np_local_addr_u;
79#define np_local_addr np_local_addr_u.buf
80    unsigned char   np_peer_addr[sizeof(struct sockaddr_in6)];
81    void           *np_peer_ctx;
82    lsquic_cid_t    np_dcid;
83    unsigned short  np_pack_size;
84    unsigned char   np_path_id;     /* Used for logging */
85};
86
87#define NP_LOCAL_SA(path_) (&(path_)->np_local_addr_u.sockaddr)
88#define NP_PEER_SA(path_) ((struct sockaddr *) (path_)->np_peer_addr)
89#define NP_IS_IPv6(path_) (AF_INET6 == NP_LOCAL_SA(path_)->sa_family)
90
91struct conn_iface
92{
93    enum tick_st
94    (*ci_tick) (struct lsquic_conn *, lsquic_time_t now);
95
96    void
97    (*ci_packet_in) (struct lsquic_conn *, struct lsquic_packet_in *);
98
99    /* Note: all packets "checked out" by calling this method should be
100     * returned back to the connection via ci_packet_sent() or
101     * ci_packet_not_sent() calls before the connection is ticked next.
102     * The connection, in turn, should not perform any extra processing
103     * (especially schedule more packets) during any of these method
104     * calls.  This is because the checked out packets are not accounted
105     * for by the congestion controller.
106     */
107    struct lsquic_packet_out *
108    (*ci_next_packet_to_send) (struct lsquic_conn *, size_t);
109
110    void
111    (*ci_packet_sent) (struct lsquic_conn *, struct lsquic_packet_out *);
112
113    void
114    (*ci_packet_not_sent) (struct lsquic_conn *, struct lsquic_packet_out *);
115
116    void
117    (*ci_hsk_done) (struct lsquic_conn *, enum lsquic_hsk_status);
118
119    void
120    (*ci_destroy) (struct lsquic_conn *);
121
122    int
123    (*ci_is_tickable) (struct lsquic_conn *);
124
125    lsquic_time_t
126    (*ci_next_tick_time) (struct lsquic_conn *);
127
128    int
129    (*ci_can_write_ack) (struct lsquic_conn *);
130
131    /* No return status: best effort */
132    void
133    (*ci_write_ack) (struct lsquic_conn *, struct lsquic_packet_out *);
134
135#if LSQUIC_CONN_STATS
136    const struct conn_stats *
137    (*ci_get_stats) (struct lsquic_conn *);
138#endif
139
140    void
141    (*ci_client_call_on_new) (struct lsquic_conn *);
142
143    enum LSQUIC_CONN_STATUS
144    (*ci_status) (struct lsquic_conn *, char *errbuf, size_t bufsz);
145
146    unsigned
147    (*ci_n_avail_streams) (const struct lsquic_conn *);
148
149    unsigned
150    (*ci_n_pending_streams) (const struct lsquic_conn *);
151
152    unsigned
153    (*ci_cancel_pending_streams) (struct lsquic_conn *, unsigned n);
154
155    void
156    (*ci_going_away) (struct lsquic_conn *);
157
158    int
159    (*ci_is_push_enabled) (struct lsquic_conn *);
160
161    struct lsquic_stream *
162    (*ci_get_stream_by_id) (struct lsquic_conn *, lsquic_stream_id_t stream_id);
163
164    struct lsquic_engine *
165    (*ci_get_engine) (struct lsquic_conn *);
166
167    struct lsquic_conn_ctx *
168    (*ci_get_ctx) (const struct lsquic_conn *);
169
170    void
171    (*ci_set_ctx) (struct lsquic_conn *, struct lsquic_conn_ctx *);
172
173    void
174    (*ci_make_stream) (struct lsquic_conn *);
175
176    void
177    (*ci_abort) (struct lsquic_conn *);
178
179    void
180    (*ci_retire_cid) (struct lsquic_conn *);
181
182    void
183    (*ci_close) (struct lsquic_conn *);
184
185    void
186    (*ci_stateless_reset) (struct lsquic_conn *);
187
188    int
189    (*ci_crypto_keysize) (const struct lsquic_conn *);
190
191    int
192    (*ci_crypto_alg_keysize) (const struct lsquic_conn *);
193
194    enum lsquic_crypto_ver
195    (*ci_crypto_ver) (const struct lsquic_conn *);
196
197    const char *
198    (*ci_crypto_cipher) (const struct lsquic_conn *);
199
200    int
201    (*ci_push_stream) (struct lsquic_conn *, void *hset, struct lsquic_stream *,
202        const struct iovec* url, const struct iovec* authority,
203        const struct lsquic_http_headers *headers);
204
205    /* Use this to abort the connection when unlikely errors occur */
206    void
207    (*ci_internal_error) (struct lsquic_conn *, const char *format, ...)
208#if __GNUC__
209            __attribute__((format(printf, 2, 3)))
210#endif
211    ;
212
213    /* Abort connection with error */
214    void
215    (*ci_abort_error) (struct lsquic_conn *, int is_app, unsigned error_code,
216                                                        const char *format, ...)
217#if __GNUC__
218            __attribute__((format(printf, 4, 5)))
219#endif
220    ;
221
222    void
223    (*ci_tls_alert) (struct lsquic_conn *, uint8_t);
224
225    /* Returns 0 if connection is to be deleted immediately */
226    lsquic_time_t
227    (*ci_drain_time) (const struct lsquic_conn *);
228
229    /* Returns true if it's time to report the connection's CIDs' liveness */
230    int
231    (*ci_report_live) (struct lsquic_conn *, lsquic_time_t now);
232
233    /* If `local_sa' is NULL, return default path */
234    struct network_path *
235    (*ci_get_path) (struct lsquic_conn *, const struct sockaddr *local_sa);
236
237    unsigned char
238    (*ci_record_addrs) (struct lsquic_conn *, void *peer_ctx,
239        const struct sockaddr *local_sa, const struct sockaddr *peer_sa);
240
241    const lsquic_cid_t *
242    (*ci_get_log_cid) (const struct lsquic_conn *);
243};
244
245struct cert_susp_head;
246
247#define LSCONN_CCE_BITS 3
248#define LSCONN_MAX_CCES (1 << LSCONN_CCE_BITS)
249
250struct conn_cid_elem
251{
252    struct lsquic_hash_elem     cce_hash_el;    /* Must be first element */
253    lsquic_cid_t                cce_cid;
254    union {
255        unsigned            seqno;
256        unsigned short      port;
257    }                           cce_u;
258#define cce_seqno cce_u.seqno
259#define cce_port cce_u.port
260    enum conn_cce_flags {
261        CCE_USED        = 1 << 0,       /* Connection ID has been used */
262        CCE_SEQNO       = 1 << 1,       /* cce_seqno is set (CIDs in Initial
263                                         * packets have no sequence number).
264                                         */
265        CCE_REG         = 1 << 2,       /* CID has been registered */
266        CCE_PORT        = 1 << 3,       /* It's not a CID element at all:
267                                         * cce_port is the hash value.
268                                         */
269    }                           cce_flags;
270};
271
272struct lsquic_conn
273{
274    void                        *cn_enc_session;
275    const struct enc_session_funcs_common
276                                *cn_esf_c;
277    union {
278        const struct enc_session_funcs_gquic   *g;
279        const struct enc_session_funcs_iquic   *i;
280    }                            cn_esf;
281#define cn_cid cn_cces[0].cce_cid
282    STAILQ_ENTRY(lsquic_conn)    cn_next_closed_conn;
283    /* This and cn_next_closed_conn could be made into a union, as new full
284     * connections are never closed.
285     */
286    STAILQ_ENTRY(lsquic_conn)    cn_next_new_full;
287    TAILQ_ENTRY(lsquic_conn)     cn_next_ticked;
288    TAILQ_ENTRY(lsquic_conn)     cn_next_out;
289    TAILQ_ENTRY(lsquic_conn)     cn_next_susp_cert;
290    /* Reuse this entry, as evanecsent connections are never suspended: */
291#define cn_next_pr cn_next_susp_cert
292    const struct conn_iface     *cn_if;
293    const struct parse_funcs    *cn_pf;
294    struct attq_elem            *cn_attq_elem;
295    struct cert_susp_head        *cn_cert_susp_head;
296    lsquic_time_t                cn_last_sent;
297    lsquic_time_t                cn_last_ticked;
298    struct conn_cid_elem        *cn_cces;   /* At least one is available */
299    enum lsquic_conn_flags       cn_flags;
300    enum lsquic_version          cn_version:8;
301    unsigned char                cn_cces_mask;  /* Those that are set */
302    unsigned char                cn_n_cces; /* Number of CCEs in cn_cces */
303    unsigned char                cn_cur_cce_idx;
304#if LSQUIC_TEST
305    struct conn_cid_elem         cn_cces_buf[8];
306#define LSCONN_INITIALIZER_CID(lsconn_, cid_) { \
307                .cn_cces = (lsconn_).cn_cces_buf, \
308                .cn_cces_buf[0].cce_seqno = 0, \
309                .cn_cces_buf[0].cce_flags = CCE_SEQNO, \
310                .cn_cces_buf[0].cce_cid = (cid_), \
311                .cn_n_cces = 8, .cn_cces_mask = 1, }
312#define LSCONN_INITIALIZER_CIDLEN(lsconn_, len_) { \
313                .cn_cces = (lsconn_).cn_cces_buf, \
314                .cn_cces_buf[0].cce_seqno = 0, \
315                .cn_cces_buf[0].cce_flags = CCE_SEQNO, \
316                .cn_cces_buf[0].cce_cid = { .len = len_ }, \
317                .cn_n_cces = 8, .cn_cces_mask = 1, }
318#define LSCONN_INITIALIZE(lsconn_) do { \
319            (lsconn_)->cn_cces = (lsconn_)->cn_cces_buf; \
320            (lsconn_)->cn_n_cces = 8; (lsconn_)->cn_cces_mask = 1; } while (0)
321#endif
322};
323
324#define END_OF_CCES(conn) ((conn)->cn_cces + (conn)->cn_n_cces)
325
326#define CN_SCID(conn) (&(conn)->cn_cces[(conn)->cn_cur_cce_idx].cce_cid)
327
328unsigned char
329lsquic_conn_record_sockaddr (lsquic_conn_t *lconn, void *peer_ctx,
330            const struct sockaddr *local_sa, const struct sockaddr *peer_sa);
331
332int
333lsquic_conn_decrypt_packet (lsquic_conn_t *lconn,
334                    struct lsquic_engine_public *, struct lsquic_packet_in *);
335
336int
337lsquic_conn_copy_and_release_pi_data (const lsquic_conn_t *conn,
338                    struct lsquic_engine_public *, struct lsquic_packet_in *);
339
340void
341lsquic_generate_cid (lsquic_cid_t *cid, size_t len);
342
343void
344lsquic_generate_cid_gquic (lsquic_cid_t *cid);
345
346void
347lsquic_conn_retire_cid (lsquic_conn_t *lconn);
348
349#define lsquic_conn_adv_time(c) ((c)->cn_attq_elem->ae_adv_time)
350
351#if LSQUIC_CONN_STATS
352struct conn_stats {
353    /* All counters are of the same type, unsigned long, because we cast the
354     * struct to an array to update the aggregate.
355     */
356    unsigned long           n_ticks;            /* How many time connection was ticked */
357    struct {
358        unsigned long       stream_data_sz;     /* Sum of all STREAM frames payload */
359        unsigned long       stream_frames;      /* Number of STREAM frames */
360        unsigned long       packets,            /* Incoming packets */
361                            undec_packets,      /* Undecryptable packets */
362                            dup_packets,        /* Duplicate packets */
363                            err_packets;        /* Error packets(?) */
364        unsigned long       n_acks,
365                            n_acks_proc,
366                            n_acks_merged[2];
367        unsigned long       bytes;              /* Overall bytes in */
368        unsigned long       headers_uncomp;     /* Sum of uncompressed header bytes */
369        unsigned long       headers_comp;       /* Sum of compressed header bytes */
370    }                   in;
371    struct {
372        unsigned long       stream_data_sz;
373        unsigned long       stream_frames;
374        unsigned long       acks;
375        unsigned long       packets;            /* Number of sent packets */
376        unsigned long       acked_via_loss;     /* Number of packets acked via loss record */
377        unsigned long       retx_packets;       /* Number of retransmitted packets */
378        unsigned long       bytes;              /* Overall bytes out */
379        unsigned long       headers_uncomp;     /* Sum of uncompressed header bytes */
380        unsigned long       headers_comp;       /* Sum of compressed header bytes */
381    }                   out;
382};
383#endif
384
385#endif
386