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