lsquic_conn.c revision a74702c6
1/* Copyright (c) 2017 - 2022 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