Line data Source code
1 : #include "fd_quic_conn.h" 2 : #include "fd_quic_common.h" 3 : #include "../../util/fd_util.h" 4 : #include "fd_quic_enum.h" 5 : #include "fd_quic_pkt_meta.h" 6 : #include "fd_quic_private.h" 7 : 8 : /* define a map for stream_id -> stream* */ 9 : #define MAP_NAME fd_quic_stream_map 10 2798982 : #define MAP_KEY stream_id 11 632748 : #define MAP_T fd_quic_stream_map_t 12 2798982 : #define MAP_KEY_NULL FD_QUIC_STREAM_ID_UNUSED 13 : #define MAP_KEY_INVAL(key) ((key)==MAP_KEY_NULL) 14 : #define MAP_QUERY_OPT 1 15 : 16 : #include "../../util/tmpl/fd_map_dynamic.c" 17 : 18 : struct fd_quic_conn_layout { 19 : ulong stream_cnt; 20 : ulong stream_ptr_off; 21 : ulong stream_footprint; 22 : int stream_map_lg; 23 : ulong stream_map_off; 24 : ulong pkt_meta_off; 25 : ulong token_len_off; 26 : ulong token_off; 27 : }; 28 : typedef struct fd_quic_conn_layout fd_quic_conn_layout_t; 29 : 30 : /* TODO maybe introduce a separate parameter for size of pkt_meta 31 : pool? */ 32 : ulong 33 10917 : fd_quic_conn_align( void ) { 34 10917 : ulong align = fd_ulong_max( alignof( fd_quic_conn_t ), alignof( fd_quic_stream_t ) ); 35 10917 : align = fd_ulong_max( align, alignof( fd_quic_pkt_meta_t ) ); 36 10917 : align = fd_ulong_max( align, fd_quic_stream_map_align() ); 37 10917 : return align; 38 10917 : } 39 : 40 : static ulong 41 : fd_quic_conn_footprint_ext( fd_quic_limits_t const * limits, 42 327291 : fd_quic_conn_layout_t * layout ) { 43 : 44 327291 : ulong inflight_pkt_cnt = limits->inflight_pkt_cnt; 45 327291 : if( FD_UNLIKELY( inflight_pkt_cnt==0UL ) ) return 0UL; 46 : 47 327291 : layout->stream_cnt = limits->rx_stream_cnt; 48 327291 : ulong stream_id_cnt = limits->stream_id_cnt; 49 327291 : if( !stream_id_cnt ) stream_id_cnt = limits->rx_stream_cnt; 50 : 51 327291 : ulong off = 0; 52 : 53 327291 : off += sizeof( fd_quic_conn_t ); 54 : 55 : /* allocate space for stream hash map */ 56 : /* about a million seems like a decent bound, with expected values up to 20,000 */ 57 327291 : ulong lg = 0; 58 1313565 : while( lg < 20 && (1ul<<lg) < (ulong)((double)stream_id_cnt*FD_QUIC_DEFAULT_SPARSITY) ) { 59 986274 : lg++; 60 986274 : } 61 327291 : layout->stream_map_lg = (int)lg; 62 : 63 327291 : off = fd_ulong_align_up( off, fd_quic_stream_align() ); 64 327291 : layout->stream_map_off = off; 65 327291 : off += fd_quic_stream_map_footprint( (int)lg ); 66 : 67 : /* allocate space for packet metadata */ 68 327291 : off = fd_ulong_align_up( off, alignof(fd_quic_pkt_meta_t) ); 69 327291 : layout->pkt_meta_off = off; 70 327291 : off += inflight_pkt_cnt * sizeof(fd_quic_pkt_meta_t); 71 : 72 : /* align total footprint */ 73 : 74 327291 : return off; 75 327291 : } 76 : 77 : FD_FN_PURE ulong 78 10917 : fd_quic_conn_footprint( fd_quic_limits_t const * limits ) { 79 10917 : fd_quic_conn_layout_t layout; 80 10917 : return fd_quic_conn_footprint_ext( limits, &layout ); 81 10917 : } 82 : 83 : fd_quic_conn_t * 84 : fd_quic_conn_new( void * mem, 85 : fd_quic_t * quic, 86 316374 : fd_quic_limits_t const * limits ) { 87 : 88 : /* Argument checks */ 89 : 90 316374 : if( FD_UNLIKELY( !mem ) ) { 91 0 : FD_LOG_WARNING(( "NULL mem" )); 92 0 : return NULL; 93 0 : } 94 : 95 316374 : ulong align = fd_quic_conn_align(); 96 316374 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)mem, align ) ) ) { 97 0 : FD_LOG_WARNING(( "misaligned mem" )); 98 0 : return NULL; 99 0 : } 100 : 101 316374 : if( FD_UNLIKELY( !quic ) ) { 102 0 : FD_LOG_WARNING(( "NULL quic" )); 103 0 : return NULL; 104 0 : } 105 : 106 316374 : if( FD_UNLIKELY( !limits ) ) { 107 0 : FD_LOG_WARNING(( "NULL limits" )); 108 0 : return NULL; 109 0 : } 110 : 111 316374 : fd_quic_conn_layout_t layout = {0}; 112 316374 : ulong footprint = fd_quic_conn_footprint_ext( limits, &layout ); 113 316374 : if( FD_UNLIKELY( !footprint ) ) { 114 0 : FD_LOG_WARNING(( "invalid footprint for limits" )); 115 0 : return NULL; 116 0 : } 117 : 118 : /* Initialize conn */ 119 : 120 316374 : fd_quic_conn_t * conn = (fd_quic_conn_t *)mem; 121 316374 : fd_memset( conn, 0, sizeof(fd_quic_conn_t) ); 122 : 123 316374 : conn->quic = quic; 124 316374 : conn->state = FD_QUIC_CONN_STATE_INVALID; 125 : 126 : /* Initialize streams */ 127 : 128 316374 : FD_QUIC_STREAM_LIST_SENTINEL( conn->send_streams ); 129 316374 : FD_QUIC_STREAM_LIST_SENTINEL( conn->used_streams ); 130 : 131 : /* Initialize stream hash map */ 132 : 133 316374 : ulong stream_map_laddr = (ulong)mem + layout.stream_map_off; 134 316374 : conn->stream_map = fd_quic_stream_map_join( fd_quic_stream_map_new( (void *)stream_map_laddr, layout.stream_map_lg ) ); 135 316374 : if( FD_UNLIKELY( !conn->stream_map ) ) return NULL; 136 : 137 : /* Initialize packet meta pool */ 138 : 139 316374 : ulong pkt_meta_cnt = limits->inflight_pkt_cnt; 140 316374 : fd_quic_pkt_meta_t * pkt_meta = (fd_quic_pkt_meta_t *)( (ulong)mem + layout.pkt_meta_off ); 141 316374 : fd_memset( pkt_meta, 0, pkt_meta_cnt*sizeof(fd_quic_pkt_meta_t) ); 142 : 143 : /* store pointer to storage and size */ 144 316374 : conn->pkt_meta_mem = pkt_meta; 145 : 146 316374 : return conn; 147 316374 : } 148 : 149 : /* set the user-defined context value on the connection */ 150 : void 151 18000 : fd_quic_conn_set_context( fd_quic_conn_t * conn, void * context ) { 152 18000 : conn->context = context; 153 18000 : } 154 : 155 : 156 : /* get the user-defined context value from a connection */ 157 : void * 158 11997 : fd_quic_conn_get_context( fd_quic_conn_t * conn ) { 159 11997 : return conn->context; 160 11997 : }