From cd7bc3834d5207553534a574404b402a60e7486d Mon Sep 17 00:00:00 2001 From: Dmitri Tikhonov Date: Wed, 13 Jun 2018 11:10:28 -0400 Subject: [PATCH] [BUGFIX] allow multiple parallel connections by default Use the original method of tracking connections by CIDs by default. If zero-sized CID support is turned on, connections are tracked by the address. A new connection is not created if another connection is using the same network address. --- CHANGELOG | 9 +++++++++ include/lsquic.h | 9 +++++++-- src/liblsquic/lsquic_conn_hash.c | 13 +++++++------ src/liblsquic/lsquic_conn_hash.h | 11 ++++++++++- src/liblsquic/lsquic_engine.c | 23 +++++++++++++++++++++-- test/unittests/test_conn_hash.c | 2 +- 6 files changed, 55 insertions(+), 12 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 324cd433e..5390bd46b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,12 @@ +2018-06-13 + + - [BUGFIX] allow multiple parallel connections by default + + Use the original method of tracking connections by CIDs by default. + If zero-sized CID support is turned on, connections are tracked by + the address. A new connection is not created if another connection + is using the same network address + 2018-05-30 - [FEATURE, API CHANGE] Support zero-sized CIDs in received packets diff --git a/include/lsquic.h b/include/lsquic.h index 48170522d..f09558a98 100644 --- a/include/lsquic.h +++ b/include/lsquic.h @@ -201,7 +201,7 @@ struct lsquic_stream_if { /** Do not use NSTP by default */ #define LSQUIC_DF_SUPPORT_NSTP 0 #define LSQUIC_DF_SUPPORT_PUSH 1 -#define LSQUIC_DF_SUPPORT_TCID0 1 +#define LSQUIC_DF_SUPPORT_TCID0 0 /** By default, LSQUIC ignores Public Reset packets. */ #define LSQUIC_DF_HONOR_PRST 0 @@ -319,7 +319,12 @@ struct lsquic_engine_settings { * If set to true value, the server will not include connection ID in * outgoing packets if client's CHLO specifies TCID=0. * - * For client, this means including TCID=0 into CHLO message. + * For client, this means including TCID=0 into CHLO message. Note that + * in this case, the engine tracks connections by the + * (source-addr, dest-addr) tuple, thereby making it necessary to create + * a socket for each connection. + * + * The default is @ref LSQUIC_DF_SUPPORT_TCID0. */ int es_support_tcid0; diff --git a/src/liblsquic/lsquic_conn_hash.c b/src/liblsquic/lsquic_conn_hash.c index 7024092d5..6b2bb7c6b 100644 --- a/src/liblsquic/lsquic_conn_hash.c +++ b/src/liblsquic/lsquic_conn_hash.c @@ -26,7 +26,7 @@ static const unsigned char * -conn2hash_server (const struct lsquic_conn *lconn, unsigned char *buf, +conn2hash_by_cid (const struct lsquic_conn *lconn, unsigned char *buf, size_t *sz) { *sz = sizeof(lconn->cn_cid); @@ -63,7 +63,7 @@ sockaddr2hash (const struct sockaddr *sa, unsigned char *buf, size_t *sz) static const unsigned char * -conn2hash_client (const struct lsquic_conn *lconn, unsigned char *buf, +conn2hash_by_addr (const struct lsquic_conn *lconn, unsigned char *buf, size_t *sz) { sockaddr2hash((struct sockaddr *) &lconn->cn_local_addr, buf, sz); @@ -72,7 +72,7 @@ conn2hash_client (const struct lsquic_conn *lconn, unsigned char *buf, int -conn_hash_init (struct conn_hash *conn_hash, int server) +conn_hash_init (struct conn_hash *conn_hash, enum conn_hash_flags flags) { unsigned n; @@ -84,10 +84,11 @@ conn_hash_init (struct conn_hash *conn_hash, int server) return -1; for (n = 0; n < n_buckets(conn_hash->ch_nbits); ++n) TAILQ_INIT(&conn_hash->ch_buckets[n]); - if (server) - conn_hash->ch_conn2hash = conn2hash_server; + conn_hash->ch_flags = flags; + if (flags & CHF_USE_ADDR) + conn_hash->ch_conn2hash = conn2hash_by_addr; else - conn_hash->ch_conn2hash = conn2hash_client; + conn_hash->ch_conn2hash = conn2hash_by_cid; LSQ_INFO("initialized"); return 0; } diff --git a/src/liblsquic/lsquic_conn_hash.h b/src/liblsquic/lsquic_conn_hash.h index ce2a88874..4c8fd8ea4 100644 --- a/src/liblsquic/lsquic_conn_hash.h +++ b/src/liblsquic/lsquic_conn_hash.h @@ -20,6 +20,12 @@ struct sockaddr; TAILQ_HEAD(lsquic_conn_head, lsquic_conn); +enum conn_hash_flags +{ + CHF_USE_ADDR = 1 << 0, +}; + + struct conn_hash { struct lsquic_conn_head *ch_buckets; @@ -29,6 +35,7 @@ struct conn_hash } ch_iter; unsigned ch_count; unsigned ch_nbits; + enum conn_hash_flags ch_flags; const unsigned char * (*ch_conn2hash)(const struct lsquic_conn *, unsigned char *, size_t *); }; @@ -37,7 +44,7 @@ struct conn_hash /* Returns -1 if malloc fails */ int -conn_hash_init (struct conn_hash *, int server); +conn_hash_init (struct conn_hash *, enum conn_hash_flags); void conn_hash_cleanup (struct conn_hash *); @@ -76,4 +83,6 @@ conn_hash_first (struct conn_hash *); struct lsquic_conn * conn_hash_next (struct conn_hash *); +#define conn_hash_using_addr(h) ((h)->ch_flags & CHF_USE_ADDR) + #endif diff --git a/src/liblsquic/lsquic_engine.c b/src/liblsquic/lsquic_engine.c index 5ef598843..16a96f995 100644 --- a/src/liblsquic/lsquic_engine.c +++ b/src/liblsquic/lsquic_engine.c @@ -323,7 +323,9 @@ lsquic_engine_new (unsigned flags, engine->pub.enp_pmi_ctx = NULL; } engine->pub.enp_engine = engine; - conn_hash_init(&engine->conns_hash, flags & ENG_SERVER); + conn_hash_init(&engine->conns_hash, + !(flags & ENG_SERVER) && engine->pub.enp_settings.es_support_tcid0 ? + CHF_USE_ADDR : 0); engine->attq = attq_create(); eng_hist_init(&engine->history); engine->batch_size = INITIAL_OUT_BATCH_SIZE; @@ -419,7 +421,17 @@ find_conn (lsquic_engine_t *engine, lsquic_packet_in_t *packet_in, { lsquic_conn_t *conn; - conn = conn_hash_find_by_addr(&engine->conns_hash, sa_local); + if (conn_hash_using_addr(&engine->conns_hash)) + conn = conn_hash_find_by_addr(&engine->conns_hash, sa_local); + else if (packet_in->pi_flags & PI_CONN_ID) + conn = conn_hash_find_by_cid(&engine->conns_hash, + packet_in->pi_conn_id); + else + { + LSQ_DEBUG("packet header does not have connection ID: discarding"); + return NULL; + } + if (!conn) return NULL; @@ -568,6 +580,13 @@ lsquic_engine_connect (lsquic_engine_t *engine, const struct sockaddr *local_sa, goto err; } + if (conn_hash_using_addr(&engine->conns_hash) + && conn_hash_find_by_addr(&engine->conns_hash, local_sa)) + { + LSQ_ERROR("cannot have more than one connection on the same port"); + goto err; + } + if (0 == max_packet_size) { switch (peer_sa->sa_family) diff --git a/test/unittests/test_conn_hash.c b/test/unittests/test_conn_hash.c index 8ff0bc5ab..a4ae61b25 100644 --- a/test/unittests/test_conn_hash.c +++ b/test/unittests/test_conn_hash.c @@ -48,7 +48,7 @@ main (int argc, char **argv) lsquic_set_log_level("info"); malo = lsquic_malo_create(sizeof(*lconn)); - s = conn_hash_init(&conn_hash, 1); + s = conn_hash_init(&conn_hash, 0); assert(0 == s); for (n = 0; n < nelems; ++n)