Line data Source code
1 : #include "fd_quic_stream.h" 2 : #include "fd_quic_enum.h" 3 : 4 : /* buffer helper functions */ 5 : /* fd_quic_buffer_store 6 : store data into circular buffer */ 7 : void 8 : fd_quic_buffer_store( fd_quic_buffer_t * buf, 9 : uchar const * data, 10 13549232 : ulong data_sz ) { 11 : /* do we have space to buffer data? */ 12 : /* see fd_quic_stream.h for invariants */ 13 13549232 : uchar * raw = buf->buf; 14 13549232 : ulong cap = buf->cap; 15 13549232 : ulong mask = cap - 1ul; 16 13549232 : ulong head = buf->head; 17 13549232 : ulong tail = buf->tail; 18 13549232 : ulong used = head - tail; 19 13549232 : ulong free = cap - used; 20 13549232 : ulong mtail = tail & mask; 21 13549232 : ulong mhead = head & mask; 22 : 23 : /* not enough room - caller responsible for checking available space */ 24 13549232 : if( data_sz > free ) { 25 0 : return; 26 0 : } 27 : 28 : /* two cases: 29 : 1. data fits within free contiguous space at m_head 30 : 2. data must be split 31 : 32 : used is in [tail,head) */ 33 : 34 13549232 : if( mhead >= mtail ) { 35 : /* free space split */ 36 13549232 : ulong end_sz = cap - mhead; 37 13549232 : if( data_sz <= end_sz ) { 38 : /* fits entirely into space at end of buffer */ 39 13549232 : fd_memcpy( raw + mhead, data, data_sz ); 40 13549232 : } else { 41 : /* must split between front and end of buffer */ 42 0 : fd_memcpy( raw + mhead, data, end_sz ); 43 0 : fd_memcpy( raw, data + end_sz, data_sz - end_sz ); 44 0 : } 45 13549232 : } else { 46 : /* contiguous space */ 47 0 : fd_memcpy( raw + mhead, data, data_sz ); 48 0 : } 49 : 50 13549232 : } 51 : 52 : /* fd_quic_buffer_load 53 : load data from circular buffer */ 54 : void 55 : fd_quic_buffer_load( fd_quic_buffer_t * buf, 56 : ulong offs, 57 : uchar * data, 58 13560005 : ulong data_sz ) { 59 13560005 : uchar * raw = buf->buf; 60 13560005 : ulong cap = buf->cap; 61 13560005 : ulong mask = cap - 1ul; 62 13560005 : ulong head = buf->head; 63 13560005 : ulong tail = offs; 64 13560005 : ulong mtail = tail & mask; 65 13560005 : ulong mhead = head & mask; 66 : 67 : /* caller responsible for checking operation valid */ 68 13560005 : if( FD_UNLIKELY( tail > head || offs < buf->tail ) ) return; 69 : 70 : /* two cases: 71 : 1. data fits within free contiguous space at m_tail 72 : 2. data is split 73 : 74 : used is in [tail,head) */ 75 : 76 13560005 : if( mtail >= mhead ) { 77 : /* free space split */ 78 6 : ulong end_sz = cap - mhead; 79 6 : if( data_sz <= end_sz ) { 80 : /* consists entirely of space at end of buffer */ 81 6 : fd_memcpy( data, raw + mtail, data_sz ); 82 6 : } else { 83 : /* split between front and end of buffer */ 84 0 : fd_memcpy( data, raw + mtail, end_sz ); 85 0 : fd_memcpy( data + end_sz, raw, data_sz - end_sz ); 86 0 : } 87 13559999 : } else { 88 : /* contiguous data */ 89 13559999 : fd_memcpy( data, raw + mtail, data_sz ); 90 13559999 : } 91 13560005 : } 92 : 93 : 94 : extern 95 : ulong 96 : fd_quic_stream_align( void ); 97 : 98 : ulong 99 783747 : fd_quic_stream_footprint( ulong tx_buf_sz ) { 100 783747 : ulong align = fd_quic_stream_align(); 101 783747 : ulong offs = 0ul; 102 : 103 783747 : ulong tx_ack_sz = tx_buf_sz >> 3ul; 104 783747 : ulong align_stream_sz = fd_ulong_align_up( sizeof( fd_quic_stream_t ), align ); 105 783747 : ulong align_tx_ack_sz = fd_ulong_align_up( tx_ack_sz, align ); 106 783747 : ulong align_tx_buf_sz = fd_ulong_align_up( tx_buf_sz, align ); 107 : 108 783747 : offs += align_stream_sz; /* space for stream instance */ 109 783747 : offs += align_tx_buf_sz; /* space for tx_buf */ 110 783747 : offs += align_tx_ack_sz; /* space for tx_ack */ 111 : 112 783747 : return offs; 113 783747 : } 114 : 115 : /* returns a newly initialized stream 116 : 117 : args 118 : mem the memory aligned to fd_quic_stream_align, and at least fd_quic_stream_footprint 119 : bytes 120 : tx_buf_sz the size of the tx buffer */ 121 : fd_quic_stream_t * 122 779979 : fd_quic_stream_new( void * mem, fd_quic_conn_t * conn, ulong tx_buf_sz ) { 123 779979 : ulong align = fd_quic_stream_align(); 124 : 125 779979 : ulong tx_ack_sz = tx_buf_sz >> 3ul; 126 779979 : ulong align_stream_sz = fd_ulong_align_up( sizeof( fd_quic_stream_t ), align ); 127 779979 : ulong align_tx_buf_sz = fd_ulong_align_up( tx_buf_sz, align ); 128 779979 : ulong align_tx_ack_sz = fd_ulong_align_up( tx_ack_sz, align ); 129 : 130 779979 : ulong offs = 0; 131 779979 : ulong base = (ulong)mem; 132 : 133 : /* allocate memory for the stream */ 134 779979 : fd_quic_stream_t * stream = (fd_quic_stream_t*)mem; 135 : 136 779979 : offs += align_stream_sz; 137 : 138 : /* allocate memory for the tx buffer */ 139 779979 : stream->tx_buf.buf = (uchar*)( base + offs ); 140 779979 : stream->tx_buf.cap = tx_buf_sz; 141 : 142 779979 : offs += align_tx_buf_sz; 143 : 144 : /* allocate memory for the tx ack buffer */ 145 779979 : stream->tx_ack = (uchar*)( base + offs ); 146 : 147 779979 : offs += align_tx_ack_sz; 148 : 149 779979 : if( offs != fd_quic_stream_footprint( tx_buf_sz ) ) { 150 0 : FD_LOG_ERR(( "fd_quic_stream_new : allocated size of stream does not match footprint" )); 151 0 : } 152 : 153 779979 : stream->conn = conn; 154 779979 : stream->stream_id = FD_QUIC_STREAM_ID_UNUSED; 155 : 156 : /* stream pointing to itself is not a member of any list */ 157 779979 : stream->next = stream->prev = stream; 158 : 159 779979 : return stream; 160 779979 : } 161 : 162 : /* delete a stream 163 : 164 : args 165 : stream the stream to free */ 166 : void 167 0 : fd_quic_stream_delete( fd_quic_stream_t * stream ) { 168 : /* stream pointing to itself is not a member of any list */ 169 0 : stream->next = stream->prev = stream; 170 0 : stream->list_memb = FD_QUIC_STREAM_LIST_MEMB_NONE; 171 0 : } 172 : 173 : 174 : /* set stream context 175 : 176 : args 177 : stream the stream with which to associate the context 178 : context the user-defined context associated with the stream */ 179 : void 180 0 : fd_quic_stream_set_context( fd_quic_stream_t * stream, void * context ) { 181 0 : stream->context = context; 182 0 : } 183 : 184 : 185 : /* get stream context 186 : 187 : args 188 : stream the stream from which to obtain the context 189 : 190 : returns 191 : context the user defined context associated with the stream */ 192 : void * 193 0 : fd_quic_stream_get_context( fd_quic_stream_t * stream ) { 194 0 : return stream->context; 195 0 : }