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 12716364 : ulong data_sz ) { 11 : /* do we have space to buffer data? */ 12 : /* see fd_quic_stream.h for invariants */ 13 12716364 : uchar * raw = buf->buf; 14 12716364 : ulong cap = buf->cap; 15 12716364 : ulong mask = cap - 1ul; 16 12716364 : ulong head = buf->head; 17 12716364 : ulong tail = buf->tail; 18 12716364 : ulong used = head - tail; 19 12716364 : ulong free = cap - used; 20 12716364 : ulong mtail = tail & mask; 21 12716364 : ulong mhead = head & mask; 22 : 23 : /* not enough room - caller responsible for checking available space */ 24 12716364 : 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 12716364 : if( mhead >= mtail ) { 35 : /* free space split */ 36 12716364 : ulong end_sz = cap - mhead; 37 12716364 : if( data_sz <= end_sz ) { 38 : /* fits entirely into space at end of buffer */ 39 12716364 : fd_memcpy( raw + mhead, data, data_sz ); 40 12716364 : } 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 12716364 : } else { 46 : /* contiguous space */ 47 0 : fd_memcpy( raw + mhead, data, data_sz ); 48 0 : } 49 : 50 12716364 : } 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 12727137 : ulong data_sz ) { 59 12727137 : uchar * raw = buf->buf; 60 12727137 : ulong cap = buf->cap; 61 12727137 : ulong mask = cap - 1ul; 62 12727137 : ulong head = buf->head; 63 12727137 : ulong tail = offs; 64 12727137 : ulong mtail = tail & mask; 65 12727137 : ulong mhead = head & mask; 66 : 67 : /* caller responsible for checking operation valid */ 68 12727137 : 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 12727137 : 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 12727131 : } else { 88 : /* contiguous data */ 89 12727131 : fd_memcpy( data, raw + mtail, data_sz ); 90 12727131 : } 91 12727137 : } 92 : 93 : 94 : extern 95 : ulong 96 : fd_quic_stream_align( void ); 97 : 98 : ulong 99 783600 : fd_quic_stream_footprint( ulong tx_buf_sz ) { 100 783600 : ulong align = fd_quic_stream_align(); 101 783600 : ulong offs = 0ul; 102 : 103 783600 : ulong tx_ack_sz = tx_buf_sz >> 3ul; 104 783600 : ulong align_stream_sz = fd_ulong_align_up( sizeof( fd_quic_stream_t ), align ); 105 783600 : ulong align_tx_ack_sz = fd_ulong_align_up( tx_ack_sz, align ); 106 783600 : ulong align_tx_buf_sz = fd_ulong_align_up( tx_buf_sz, align ); 107 : 108 783600 : offs += align_stream_sz; /* space for stream instance */ 109 783600 : offs += align_tx_buf_sz; /* space for tx_buf */ 110 783600 : offs += align_tx_ack_sz; /* space for tx_ack */ 111 : 112 783600 : return offs; 113 783600 : } 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 779832 : fd_quic_stream_new( void * mem, fd_quic_conn_t * conn, ulong tx_buf_sz ) { 123 779832 : ulong align = fd_quic_stream_align(); 124 : 125 779832 : ulong tx_ack_sz = tx_buf_sz >> 3ul; 126 779832 : ulong align_stream_sz = fd_ulong_align_up( sizeof( fd_quic_stream_t ), align ); 127 779832 : ulong align_tx_buf_sz = fd_ulong_align_up( tx_buf_sz, align ); 128 779832 : ulong align_tx_ack_sz = fd_ulong_align_up( tx_ack_sz, align ); 129 : 130 779832 : ulong offs = 0; 131 779832 : ulong base = (ulong)mem; 132 : 133 : /* allocate memory for the stream */ 134 779832 : fd_quic_stream_t * stream = (fd_quic_stream_t*)mem; 135 : 136 779832 : offs += align_stream_sz; 137 : 138 : /* allocate memory for the tx buffer */ 139 779832 : stream->tx_buf.buf = (uchar*)( base + offs ); 140 779832 : stream->tx_buf.cap = tx_buf_sz; 141 : 142 779832 : offs += align_tx_buf_sz; 143 : 144 : /* allocate memory for the tx ack buffer */ 145 779832 : stream->tx_ack = (uchar*)( base + offs ); 146 : 147 779832 : offs += align_tx_ack_sz; 148 : 149 779832 : 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 779832 : stream->conn = conn; 154 779832 : stream->stream_id = FD_QUIC_STREAM_ID_UNUSED; 155 : 156 : /* stream pointing to itself is not a member of any list */ 157 779832 : stream->next = stream->prev = stream; 158 : 159 779832 : return stream; 160 779832 : } 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 60000 : fd_quic_stream_set_context( fd_quic_stream_t * stream, void * context ) { 181 60000 : stream->context = context; 182 60000 : } 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 : }