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