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 19200 : #define MAP_KEY stream_id 9 390 : #define MAP_T fd_quic_stream_map_t 10 19200 : #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 10938 : fd_quic_conn_align( void ) { 27 10938 : ulong align = fd_ulong_max( alignof( fd_quic_conn_t ), alignof( fd_quic_stream_t ) ); 28 10938 : align = fd_ulong_max( align, alignof( fd_quic_pkt_meta_t ) ); 29 10938 : align = fd_ulong_max( align, fd_quic_stream_map_align() ); 30 10938 : return align; 31 10938 : } 32 : 33 : static ulong 34 : fd_quic_conn_footprint_ext( fd_quic_limits_t const * limits, 35 327324 : fd_quic_conn_layout_t * layout ) { 36 : 37 327324 : ulong inflight_pkt_cnt = limits->inflight_pkt_cnt; 38 327324 : if( FD_UNLIKELY( inflight_pkt_cnt==0UL ) ) return 0UL; 39 : 40 327324 : ulong stream_id_cnt = limits->stream_id_cnt; 41 : 42 327324 : ulong off = 0; 43 : 44 327324 : off += sizeof( fd_quic_conn_t ); 45 : 46 327324 : 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 2034 : while( lg < 20 && (1ul<<lg) < (ulong)((double)stream_id_cnt*FD_QUIC_DEFAULT_SPARSITY) ) { 51 1722 : lg++; 52 1722 : } 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 327012 : } else { 59 327012 : layout->stream_map_lg = 0; 60 327012 : layout->stream_map_off = 0UL; 61 327012 : } 62 : 63 : /* allocate space for packet metadata */ 64 327324 : off = fd_ulong_align_up( off, alignof(fd_quic_pkt_meta_t) ); 65 327324 : layout->pkt_meta_off = off; 66 327324 : off += inflight_pkt_cnt * sizeof(fd_quic_pkt_meta_t); 67 : 68 327324 : return off; 69 327324 : } 70 : 71 : ulong 72 10938 : fd_quic_conn_footprint( fd_quic_limits_t const * limits ) { 73 10938 : fd_quic_conn_layout_t layout; 74 10938 : return fd_quic_conn_footprint_ext( limits, &layout ); 75 10938 : } 76 : 77 : fd_quic_conn_t * 78 : fd_quic_conn_new( void * mem, 79 : fd_quic_t * quic, 80 316386 : fd_quic_limits_t const * limits ) { 81 : 82 : /* Argument checks */ 83 : 84 316386 : if( FD_UNLIKELY( !mem ) ) { 85 0 : FD_LOG_WARNING(( "NULL mem" )); 86 0 : return NULL; 87 0 : } 88 : 89 316386 : ulong align = fd_quic_conn_align(); 90 316386 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)mem, align ) ) ) { 91 0 : FD_LOG_WARNING(( "misaligned mem" )); 92 0 : return NULL; 93 0 : } 94 : 95 316386 : if( FD_UNLIKELY( !quic ) ) { 96 0 : FD_LOG_WARNING(( "NULL quic" )); 97 0 : return NULL; 98 0 : } 99 : 100 316386 : if( FD_UNLIKELY( !limits ) ) { 101 0 : FD_LOG_WARNING(( "NULL limits" )); 102 0 : return NULL; 103 0 : } 104 : 105 316386 : fd_quic_conn_layout_t layout = {0}; 106 316386 : ulong footprint = fd_quic_conn_footprint_ext( limits, &layout ); 107 316386 : if( FD_UNLIKELY( !footprint ) ) { 108 0 : FD_LOG_WARNING(( "invalid footprint for limits" )); 109 0 : return NULL; 110 0 : } 111 : 112 : /* Initialize conn */ 113 : 114 316386 : fd_quic_conn_t * conn = (fd_quic_conn_t *)mem; 115 316386 : fd_memset( conn, 0, sizeof(fd_quic_conn_t) ); 116 : 117 316386 : conn->quic = quic; 118 316386 : conn->state = FD_QUIC_CONN_STATE_INVALID; 119 : 120 : /* Initialize streams */ 121 : 122 316386 : FD_QUIC_STREAM_LIST_SENTINEL( conn->send_streams ); 123 316386 : FD_QUIC_STREAM_LIST_SENTINEL( conn->used_streams ); 124 : 125 : /* Initialize stream hash map */ 126 : 127 316386 : if( layout.stream_map_off ) { 128 195 : ulong stream_map_laddr = (ulong)mem + layout.stream_map_off; 129 195 : conn->stream_map = fd_quic_stream_map_join( fd_quic_stream_map_new( (void *)stream_map_laddr, layout.stream_map_lg ) ); 130 195 : if( FD_UNLIKELY( !conn->stream_map ) ) return NULL; 131 195 : } 132 : 133 : /* Initialize packet meta pool */ 134 : 135 316386 : ulong pkt_meta_cnt = limits->inflight_pkt_cnt; 136 316386 : fd_quic_pkt_meta_t * pkt_meta = (fd_quic_pkt_meta_t *)( (ulong)mem + layout.pkt_meta_off ); 137 316386 : fd_memset( pkt_meta, 0, pkt_meta_cnt*sizeof(fd_quic_pkt_meta_t) ); 138 : 139 : /* store pointer to storage and size */ 140 316386 : conn->pkt_meta_mem = pkt_meta; 141 : 142 316386 : return conn; 143 316386 : } 144 : 145 : /* set the user-defined context value on the connection */ 146 : void 147 18003 : fd_quic_conn_set_context( fd_quic_conn_t * conn, void * context ) { 148 18003 : conn->context = context; 149 18003 : } 150 : 151 : 152 : /* get the user-defined context value from a connection */ 153 : void * 154 3 : fd_quic_conn_get_context( fd_quic_conn_t * conn ) { 155 3 : return conn->context; 156 3 : } 157 : 158 : char const * 159 0 : fd_quic_conn_reason_name( uint reason ) { 160 : /* define mapping from reason code to name as a c-string */ 161 0 : static char const * fd_quic_conn_reason_names[] = { 162 0 : # define COMMA , 163 0 : # define _(NAME,CODE,DESC) \ 164 0 : [CODE] = #NAME 165 0 : FD_QUIC_REASON_CODES(_,COMMA) 166 0 : # undef _ 167 0 : # undef COMMA 168 0 : }; 169 : 170 0 : # define ELEMENTS ( sizeof(fd_quic_conn_reason_names) / sizeof(fd_quic_conn_reason_names[0]) ) 171 : 172 0 : if( FD_UNLIKELY( reason >= ELEMENTS ) ) return "N/A"; 173 : 174 0 : char const * name = fd_quic_conn_reason_names[reason]; 175 : 176 0 : return name ? name : "N/A"; 177 0 : }