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 15435055 : ulong data_sz ) { 11 : /* do we have space to buffer data? */ 12 : /* see fd_quic_stream.h for invariants */ 13 15435055 : uchar * raw = buf->buf; 14 15435055 : ulong cap = buf->cap; 15 15435055 : ulong mask = cap - 1ul; 16 15435055 : ulong head = buf->head; 17 15435055 : ulong tail = buf->tail; 18 15435055 : ulong used = head - tail; 19 15435055 : ulong free = cap - used; 20 15435055 : ulong mtail = tail & mask; 21 15435055 : ulong mhead = head & mask; 22 : 23 : /* not enough room - caller responsible for checking available space */ 24 15435055 : 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 15435055 : if( mhead >= mtail ) { 35 : /* free space split */ 36 15435055 : ulong end_sz = cap - mhead; 37 15435055 : if( data_sz <= end_sz ) { 38 : /* fits entirely into space at end of buffer */ 39 15435055 : fd_memcpy( raw + mhead, data, data_sz ); 40 15435055 : } 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 15435055 : } else { 46 : /* contiguous space */ 47 0 : fd_memcpy( raw + mhead, data, data_sz ); 48 0 : } 49 : 50 15435055 : } 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 15445858 : ulong data_sz ) { 59 15445858 : uchar * raw = buf->buf; 60 15445858 : ulong cap = buf->cap; 61 15445858 : ulong mask = cap - 1ul; 62 15445858 : ulong head = buf->head; 63 15445858 : ulong tail = offs; 64 15445858 : ulong mtail = tail & mask; 65 15445858 : ulong mhead = head & mask; 66 : 67 : /* caller responsible for checking operation valid */ 68 15445858 : 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 15445858 : if( mtail >= mhead ) { 77 : /* free space split */ 78 15361693 : ulong end_sz = cap - mtail; 79 15361693 : if( data_sz <= end_sz ) { 80 : /* consists entirely of space at end of buffer */ 81 15361693 : fd_memcpy( data, raw + mtail, data_sz ); 82 15361693 : } 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 15361693 : } else { 88 : /* contiguous data */ 89 84165 : fd_memcpy( data, raw + mtail, data_sz ); 90 84165 : } 91 15445858 : } 92 : 93 : 94 : extern 95 : ulong 96 : fd_quic_stream_align( void ); 97 : 98 : ulong 99 821925 : fd_quic_stream_footprint( ulong tx_buf_sz ) { 100 821925 : if( FD_UNLIKELY( !fd_ulong_is_pow2( tx_buf_sz ) ) ) return 0UL; 101 : 102 821922 : ulong align = fd_quic_stream_align(); 103 821922 : ulong offs = 0ul; 104 : 105 821922 : ulong tx_ack_sz = tx_buf_sz >> 3ul; 106 821922 : ulong align_stream_sz = fd_ulong_align_up( sizeof( fd_quic_stream_t ), align ); 107 821922 : ulong align_tx_ack_sz = fd_ulong_align_up( tx_ack_sz, align ); 108 821922 : ulong align_tx_buf_sz = fd_ulong_align_up( tx_buf_sz, align ); 109 : 110 821922 : offs += align_stream_sz; /* space for stream instance */ 111 821922 : offs += align_tx_buf_sz; /* space for tx_buf */ 112 821922 : offs += align_tx_ack_sz; /* space for tx_ack */ 113 : 114 821922 : return offs; 115 821925 : } 116 : 117 : /* returns a newly initialized stream 118 : 119 : args 120 : mem the memory aligned to fd_quic_stream_align, and at least fd_quic_stream_footprint 121 : bytes 122 : tx_buf_sz the size of the tx buffer */ 123 : fd_quic_stream_t * 124 807555 : fd_quic_stream_new( void * mem, fd_quic_conn_t * conn, ulong tx_buf_sz ) { 125 807555 : ulong align = fd_quic_stream_align(); 126 : 127 807555 : ulong tx_ack_sz = tx_buf_sz >> 3ul; 128 807555 : ulong align_stream_sz = fd_ulong_align_up( sizeof( fd_quic_stream_t ), align ); 129 807555 : ulong align_tx_buf_sz = fd_ulong_align_up( tx_buf_sz, align ); 130 807555 : ulong align_tx_ack_sz = fd_ulong_align_up( tx_ack_sz, align ); 131 : 132 807555 : ulong offs = 0; 133 807555 : ulong base = (ulong)mem; 134 : 135 : /* allocate memory for the stream */ 136 807555 : fd_quic_stream_t * stream = (fd_quic_stream_t*)mem; 137 : 138 807555 : offs += align_stream_sz; 139 : 140 : /* allocate memory for the tx buffer */ 141 807555 : stream->tx_buf.buf = (uchar*)( base + offs ); 142 807555 : stream->tx_buf.cap = tx_buf_sz; 143 : 144 807555 : offs += align_tx_buf_sz; 145 : 146 : /* allocate memory for the tx ack buffer */ 147 807555 : stream->tx_ack = (uchar*)( base + offs ); 148 : 149 807555 : offs += align_tx_ack_sz; 150 : 151 807555 : if( offs != fd_quic_stream_footprint( tx_buf_sz ) ) { 152 0 : FD_LOG_ERR(( "fd_quic_stream_new : allocated size of stream does not match footprint" )); 153 0 : } 154 : 155 807555 : stream->conn = conn; 156 807555 : stream->stream_id = FD_QUIC_STREAM_ID_UNUSED; 157 : 158 : /* stream pointing to itself is not a member of any list */ 159 807555 : stream->next = stream->prev = stream; 160 : 161 807555 : return stream; 162 807555 : } 163 : 164 : /* delete a stream 165 : 166 : args 167 : stream the stream to free */ 168 : void 169 0 : fd_quic_stream_delete( fd_quic_stream_t * stream ) { 170 : /* stream pointing to itself is not a member of any list */ 171 0 : stream->next = stream->prev = stream; 172 0 : stream->list_memb = FD_QUIC_STREAM_LIST_MEMB_NONE; 173 0 : } 174 : 175 : 176 : /* set stream context 177 : 178 : args 179 : stream the stream with which to associate the context 180 : context the user-defined context associated with the stream */ 181 : void 182 0 : fd_quic_stream_set_context( fd_quic_stream_t * stream, void * context ) { 183 0 : stream->context = context; 184 0 : } 185 : 186 : 187 : /* get stream context 188 : 189 : args 190 : stream the stream from which to obtain the context 191 : 192 : returns 193 : context the user defined context associated with the stream */ 194 : void * 195 0 : fd_quic_stream_get_context( fd_quic_stream_t * stream ) { 196 0 : return stream->context; 197 0 : }