lsquic_conn.c revision eea99896
1/* Copyright (c) 2017 - 2021 LiteSpeed Technologies Inc.  See LICENSE. */
2#include <assert.h>
3#include <inttypes.h>
4#include <string.h>
5#include <sys/queue.h>
6
7#include <openssl/rand.h>
8
9#include "lsquic.h"
10#include "lsquic_int_types.h"
11#include "lsquic_hash.h"
12#include "lsquic_conn.h"
13#include "lsquic_packet_common.h"
14#include "lsquic_packet_gquic.h"
15#include "lsquic_packet_in.h"
16#include "lsquic_str.h"
17#include "lsquic_enc_sess.h"
18#include "lsquic_mm.h"
19#include "lsquic_engine_public.h"
20#include "lsquic_ev_log.h"
21
22#include "lsquic_logger.h"
23
24const lsquic_cid_t *
25lsquic_conn_id (const lsquic_conn_t *lconn)
26{
27    /* TODO */
28    return lsquic_conn_log_cid(lconn);
29}
30
31
32void *
33lsquic_conn_get_peer_ctx (struct lsquic_conn *lconn,
34                                            const struct sockaddr *local_sa)
35{
36    const struct network_path *path;
37
38    path = lconn->cn_if->ci_get_path(lconn, local_sa);
39    return path->np_peer_ctx;
40}
41
42
43unsigned char
44lsquic_conn_record_sockaddr (lsquic_conn_t *lconn, void *peer_ctx,
45            const struct sockaddr *local_sa, const struct sockaddr *peer_sa)
46{
47    return lconn->cn_if->ci_record_addrs(lconn, peer_ctx, local_sa, peer_sa);
48}
49
50
51int
52lsquic_conn_get_sockaddr (struct lsquic_conn *lconn,
53                const struct sockaddr **local, const struct sockaddr **peer)
54{
55    const struct network_path *path;
56
57    path = lconn->cn_if->ci_get_path(lconn, NULL);
58    *local = NP_LOCAL_SA(path);
59    *peer = NP_PEER_SA(path);
60    return 0;
61}
62
63
64int
65lsquic_conn_copy_and_release_pi_data (const lsquic_conn_t *conn,
66          struct lsquic_engine_public *enpub, lsquic_packet_in_t *packet_in)
67{
68    unsigned char *copy;
69
70    assert(!(packet_in->pi_flags & PI_OWN_DATA));
71    copy = lsquic_mm_get_packet_in_buf(&enpub->enp_mm, packet_in->pi_data_sz);
72    if (!copy)
73    {
74        LSQ_WARN("cannot allocate memory to copy incoming packet data");
75        return -1;
76    }
77    memcpy(copy, packet_in->pi_data, packet_in->pi_data_sz);
78    packet_in->pi_data = copy;
79    packet_in->pi_flags |= PI_OWN_DATA;
80    return 0;
81}
82
83
84enum lsquic_version
85lsquic_conn_quic_version (const lsquic_conn_t *lconn)
86{
87    if (lconn->cn_flags & LSCONN_VER_SET)
88        return lconn->cn_version;
89    else
90        return -1;
91}
92
93
94enum lsquic_crypto_ver
95lsquic_conn_crypto_ver (const lsquic_conn_t *lconn)
96{
97    return LSQ_CRY_QUIC;
98}
99
100
101const char *
102lsquic_conn_crypto_cipher (const lsquic_conn_t *lconn)
103{
104    if (lconn->cn_enc_session)
105        return lconn->cn_esf_c->esf_cipher(lconn->cn_enc_session);
106    else
107        return NULL;
108}
109
110
111int
112lsquic_conn_crypto_keysize (const lsquic_conn_t *lconn)
113{
114    if (lconn->cn_enc_session)
115        return lconn->cn_esf_c->esf_keysize(lconn->cn_enc_session);
116    else
117        return -1;
118}
119
120
121int
122lsquic_conn_crypto_alg_keysize (const lsquic_conn_t *lconn)
123{
124    if (lconn->cn_enc_session)
125        return lconn->cn_esf_c->esf_alg_keysize(lconn->cn_enc_session);
126    else
127        return -1;
128}
129
130
131struct stack_st_X509 *
132lsquic_conn_get_server_cert_chain (struct lsquic_conn *lconn)
133{
134    if (lconn->cn_enc_session)
135        return lconn->cn_esf_c->esf_get_server_cert_chain(lconn->cn_enc_session);
136    else
137        return NULL;
138}
139
140
141void
142lsquic_conn_make_stream (struct lsquic_conn *lconn)
143{
144    lconn->cn_if->ci_make_stream(lconn);
145}
146
147
148unsigned
149lsquic_conn_n_pending_streams (const struct lsquic_conn *lconn)
150{
151    return lconn->cn_if->ci_n_pending_streams(lconn);
152}
153
154
155unsigned
156lsquic_conn_n_avail_streams (const struct lsquic_conn *lconn)
157{
158    return lconn->cn_if->ci_n_avail_streams(lconn);
159}
160
161
162unsigned
163lsquic_conn_cancel_pending_streams (struct lsquic_conn *lconn, unsigned count)
164{
165    return lconn->cn_if->ci_cancel_pending_streams(lconn, count);
166}
167
168
169void
170lsquic_conn_going_away (struct lsquic_conn *lconn)
171{
172    lconn->cn_if->ci_going_away(lconn);
173}
174
175
176void
177lsquic_conn_close (struct lsquic_conn *lconn)
178{
179    lconn->cn_if->ci_close(lconn);
180}
181
182
183int
184lsquic_conn_is_push_enabled (lsquic_conn_t *lconn)
185{
186    return lconn->cn_if->ci_is_push_enabled(lconn);
187}
188
189
190struct lsquic_engine *
191lsquic_conn_get_engine (struct lsquic_conn *lconn)
192{
193    return lconn->cn_if->ci_get_engine(lconn);
194}
195
196
197int
198lsquic_conn_push_stream (struct lsquic_conn *lconn, void *hset,
199    struct lsquic_stream *stream, const struct lsquic_http_headers *headers)
200{
201    return lconn->cn_if->ci_push_stream(lconn, hset, stream, headers);
202}
203
204
205lsquic_conn_ctx_t *
206lsquic_conn_get_ctx (const struct lsquic_conn *lconn)
207{
208    return lconn->cn_conn_ctx;
209}
210
211
212void
213lsquic_conn_set_ctx (struct lsquic_conn *lconn, lsquic_conn_ctx_t *ctx)
214{
215    lconn->cn_conn_ctx = ctx;
216}
217
218
219void
220lsquic_conn_abort (struct lsquic_conn *lconn)
221{
222    lconn->cn_if->ci_abort(lconn);
223}
224
225
226void
227lsquic_generate_cid (lsquic_cid_t *cid, size_t len)
228{
229    if (!len)
230    {
231        /* If not set, generate ID between 8 and MAX_CID_LEN bytes in length */
232        RAND_bytes((uint8_t *) &len, sizeof(len));
233        len %= MAX_CID_LEN - 7;
234        len += 8;
235    }
236    RAND_bytes(cid->idbuf, len);
237    cid->len = len;
238}
239
240
241void
242lsquic_generate_scid (void *ctx, struct lsquic_conn *lconn, lsquic_cid_t *scid,
243                                                                unsigned len)
244{
245    if (len)
246        lsquic_generate_cid(scid, len);
247    else
248        scid->len = len;
249}
250
251
252void
253lsquic_generate_cid_gquic (lsquic_cid_t *cid)
254{
255    lsquic_generate_cid(cid, GQUIC_CID_LEN);
256}
257
258
259void
260lsquic_conn_retire_cid (struct lsquic_conn *lconn)
261{
262    if (lconn->cn_if->ci_retire_cid)
263        lconn->cn_if->ci_retire_cid(lconn);
264}
265
266
267enum LSQUIC_CONN_STATUS
268lsquic_conn_status (struct lsquic_conn *lconn, char *errbuf, size_t bufsz)
269{
270    return lconn->cn_if->ci_status(lconn, errbuf, bufsz);
271}
272
273
274const lsquic_cid_t *
275lsquic_conn_log_cid (const struct lsquic_conn *lconn)
276{
277    if (lconn->cn_if && lconn->cn_if->ci_get_log_cid)
278        return lconn->cn_if->ci_get_log_cid(lconn);
279    return CN_SCID(lconn);
280}
281
282
283int
284lsquic_conn_want_datagram_write (struct lsquic_conn *lconn, int is_want)
285{
286    if (lconn->cn_if && lconn->cn_if->ci_want_datagram_write)
287        return lconn->cn_if->ci_want_datagram_write(lconn, is_want);
288    else
289        return -1;
290}
291
292
293int
294lsquic_conn_set_min_datagram_size (struct lsquic_conn *lconn, size_t sz)
295{
296    if (lconn->cn_if && lconn->cn_if->ci_set_min_datagram_size)
297        return lconn->cn_if->ci_set_min_datagram_size(lconn, sz);
298    else
299        return -1;
300}
301
302
303size_t
304lsquic_conn_get_min_datagram_size (struct lsquic_conn *lconn)
305{
306    if (lconn->cn_if && lconn->cn_if->ci_get_min_datagram_size)
307        return lconn->cn_if->ci_get_min_datagram_size(lconn);
308    else
309        return 0;
310}
311
312
313#if LSQUIC_CONN_STATS
314void
315lsquic_conn_stats_diff (const struct conn_stats *cumulative_stats,
316                        const struct conn_stats *previous_stats,
317                        struct conn_stats *new_stats)
318{
319    const unsigned long *const cum = (void *) cumulative_stats,
320                        *const prev = (void *) previous_stats;
321    unsigned long *const new = (void *) new_stats;
322    unsigned i;
323
324    for (i = 0; i < sizeof(*new_stats) / sizeof(new[0]); ++i)
325        new[i] = cum[i] - prev[i];
326}
327
328
329#endif
330
331
332const char *
333lsquic_conn_get_sni (struct lsquic_conn *lconn)
334{
335    if (lconn->cn_esf_c && lconn->cn_esf_c->esf_get_sni)
336        return lconn->cn_esf_c->esf_get_sni(lconn->cn_enc_session);
337    else
338        return NULL;
339}
340