LCOV - code coverage report
Current view: top level - waltz/quic/templ - fd_quic_encoders.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 48 68 70.6 %
Date: 2024-11-13 11:58:15 Functions: 0 0 -

          Line data    Source code
       1             : // QUIC encoders
       2             : 
       3             : /* TODO replace FD_QUIC_PARSE_FAIL with FD_QUIC_ENCODE_FAIL */
       4             : 
       5             : /* TODO add platform optimized versions of these
       6             :    e.g. 32 bit unaligned fetch w/ byte swap on intel */
       7    28469495 : #define FD_TEMPL_ENCODE_IMPL_uchar(p,val) (                            \
       8    28469495 :     ( (p)[0] = (uchar)( (val) ) ) )
       9          12 : #define FD_TEMPL_ENCODE_IMPL_ushort(p,val) (                           \
      10          12 :     ( (p)[0] = (uchar)( (ushort)(val) >> (ushort)0x08 ) ),             \
      11          12 :     ( (p)[1] = (uchar)( (ushort)(val) >> (ushort)0x00 ) ) )
      12     3025134 : #define FD_TEMPL_ENCODE_IMPL_uint(p,val) (                             \
      13     3025134 :     ( (p)[0] = (uchar)(   (uint)(val) >>   (uint)0x18 ) ),             \
      14     3025134 :     ( (p)[1] = (uchar)(   (uint)(val) >>   (uint)0x10 ) ),             \
      15     3025134 :     ( (p)[2] = (uchar)(   (uint)(val) >>   (uint)0x08 ) ),             \
      16     3025134 :     ( (p)[3] = (uchar)(   (uint)(val) >>   (uint)0x00 ) ) )
      17             : #define FD_TEMPL_ENCODE_IMPL_ulong(p,val) (                            \
      18             :     ( (p)[0] = (uchar)(  (ulong)(val) >>  (ulong)0x38 ) ),             \
      19             :     ( (p)[1] = (uchar)(  (ulong)(val) >>  (ulong)0x30 ) ),             \
      20             :     ( (p)[2] = (uchar)(  (ulong)(val) >>  (ulong)0x28 ) ),             \
      21             :     ( (p)[3] = (uchar)(  (ulong)(val) >>  (ulong)0x20 ) ),             \
      22             :     ( (p)[4] = (uchar)(  (ulong)(val) >>  (ulong)0x18 ) ),             \
      23             :     ( (p)[5] = (uchar)(  (ulong)(val) >>  (ulong)0x10 ) ),             \
      24             :     ( (p)[6] = (uchar)(  (ulong)(val) >>  (ulong)0x08 ) ),             \
      25             :     ( (p)[7] = (uchar)(  (ulong)(val) >>  (ulong)0x00 ) ) )
      26             : 
      27             : /* encodes the given type, "returns" the number of bytes encoded */
      28    31494641 : #define FD_TEMPL_ENCODE(TYPE,VAR,p) ( ( FD_TEMPL_ENCODE_IMPL_##TYPE((p),(VAR)) ), sizeof(fd_quic_##TYPE) )
      29             : 
      30             : /* returns bytes encoded
      31             : 
      32             :    frame is not const, as it may be mutated, for example to store offsets
      33             :    to particular bytes in the encoded data */
      34             : #define FD_TEMPL_DEF_STRUCT_BEGIN(NAME)                                \
      35             :   static inline                                                        \
      36             :   ulong                                                                \
      37             :   fd_quic_encode_##NAME( uchar *              buf,                     \
      38             :                          ulong                sz,                      \
      39    70290437 :                          fd_quic_##NAME##_t * frame ) {                \
      40    70290437 :     (void)frame;                                                       \
      41    70290437 :     uchar *  orig_buf = buf;                                           \
      42    70290437 :     uchar *  buf_end  = buf + sz;                                      \
      43    70290437 :     ulong    tmp_len  = 0;          (void)tmp_len;                     \
      44    70290437 :     uchar *  type_ptr = NULL;       (void)type_ptr;
      45             : 
      46             : /* encodes TYPE into output */
      47             : #define FD_TEMPL_MBR_FRAME_TYPE(NAME,ID_LO,ID_HI)                      \
      48    47871357 :     if( buf >= buf_end ) return FD_QUIC_PARSE_FAIL;                    \
      49    47871357 :     buf[0] = ID_LO;                                                    \
      50    47871354 :     type_ptr = buf++;
      51             : 
      52             : /* encodes frame->NAME into the type field */
      53             : #define FD_TEMPL_MBR_FRAME_TYPE_FLAG(NAME,MASK)                        \
      54           0 :     if( type_ptr ) {                                                   \
      55           0 :       type_ptr[0] = (uchar)( ( type_ptr[0] & ~(uint)(MASK) )           \
      56           0 :                            | ( frame->NAME &  (uint)(MASK) ) );        \
      57           0 :     }
      58             : 
      59             : 
      60             : /* encodes aligned bytes into output */
      61             : #define FD_TEMPL_MBR_ELEM(NAME,TYPE)                                   \
      62    31494425 :     if( FD_UNLIKELY( buf+sizeof(fd_quic_##TYPE) > buf_end ) )          \
      63    31494425 :       return FD_QUIC_PARSE_FAIL;                                       \
      64    31494425 :     buf += FD_TEMPL_ENCODE(TYPE,frame->NAME,buf);
      65             : 
      66             : 
      67             : /* encodes a packet number.  Assumes pkt_number_len == 3 (4 bytes)
      68             :    keeps the pointer to the start of the packet number field */
      69             : #define FD_TEMPL_MBR_ELEM_PKTNUM(NAME,TYPE)                            \
      70    19418909 :     if( FD_UNLIKELY( buf+4 > buf_end ) ) return FD_QUIC_ENCODE_FAIL;   \
      71    19418909 :     frame->NAME##_pnoff = (unsigned)( buf - orig_buf );                \
      72    19418909 :     FD_STORE( uint, buf, fd_uint_bswap( (uint)frame->NAME ) );         \
      73    19418909 :     buf += 4;
      74             : 
      75             : 
      76             : /* encodes a VARINT
      77             :    always aligned
      78             :    most significant two bits represent the width of the int
      79             :    remaining bits are all data bits
      80             :    checks for capacity before writing */
      81             : #define FD_TEMPL_MBR_ELEM_VARINT(NAME,TYPE)                            \
      82    57928098 :     if( FD_UNLIKELY( buf+8 > buf_end ) ) return FD_QUIC_ENCODE_FAIL;   \
      83    57928098 :     buf += fd_quic_varint_encode( buf, frame->NAME );
      84             : 
      85             : 
      86             : // VAR currently assumed to be aligned bytes
      87             : #define FD_TEMPL_MBR_ELEM_VAR(NAME,BITS_MIN,BITS_MAX,LEN_NAME)         \
      88    25456997 :     tmp_len = frame->LEN_NAME;                                         \
      89    25456997 :     if( FD_UNLIKELY( tmp_len*8 < BITS_MIN || tmp_len*8 > BITS_MAX ) ) {\
      90           0 :       FD_LOG_DEBUG(( "buffer overflow encoding variable length field." \
      91           0 :             "  field: " #NAME                                          \
      92           0 :             "  BITS_MIN: %lu"                                          \
      93           0 :             "  BITS_MAX: %lu"                                          \
      94           0 :             "  " #LEN_NAME ": %lu"                                     \
      95           0 :             "  tmp_len*8: %lu\n",                                      \
      96           0 :             (ulong)BITS_MIN,                                           \
      97           0 :             (ulong)BITS_MAX,                                           \
      98           0 :             (ulong)frame->LEN_NAME,                                    \
      99           0 :             (ulong)( tmp_len * 8 ) ));                                 \
     100           0 :       return FD_QUIC_PARSE_FAIL;                                       \
     101           0 :     }                                                                  \
     102    25456997 :     if( FD_UNLIKELY( (ulong)buf + tmp_len > (ulong)buf_end ) ) {       \
     103           0 :       return FD_QUIC_PARSE_FAIL;                                       \
     104           0 :     }                                                                  \
     105    25456997 :     fd_memcpy( buf, frame->NAME, tmp_len );                            \
     106    25456997 :     buf += tmp_len;
     107             : 
     108             : 
     109             : // VAR currently assumed to be aligned bytes
     110             : #define FD_TEMPL_MBR_ELEM_VAR_RAW(NAME,BITS_MIN,BITS_MAX,LEN_NAME)     \
     111             :     tmp_len = frame->LEN_NAME;                                         \
     112             :     if( FD_UNLIKELY( tmp_len*8 < BITS_MIN || tmp_len*8 > BITS_MAX ) ) {\
     113             :       FD_LOG_DEBUG(( "buffer overflow encoding variable length field." \
     114             :             "  field: " #NAME                                          \
     115             :             "  BITS_MIN: %lu"                                          \
     116             :             "  BITS_MAX: %lu"                                          \
     117             :             "  " #LEN_NAME ": %lu"                                     \
     118             :             "  tmp_len*8: %lu\n",                                      \
     119             :             (ulong)BITS_MIN,                                           \
     120             :             (ulong)BITS_MAX,                                           \
     121             :             (ulong)frame->LEN_NAME,                                    \
     122             :             (ulong)( tmp_len * 8 ) ));                                 \
     123             :       return FD_QUIC_PARSE_FAIL;                                       \
     124             :     }                                                                  \
     125             :     if( FD_UNLIKELY( (ulong)buf + tmp_len > (ulong)buf_end ) ) {       \
     126             :       return FD_QUIC_PARSE_FAIL;                                       \
     127             :     }                                                                  \
     128             :     fd_memcpy( buf, frame->NAME, tmp_len );                            \
     129             :     buf += tmp_len;
     130             : 
     131             : /* ARRAY is an array of elements, each of the same size,
     132             :    with length implied by the packet size
     133             :    caller has responsibility of ensuring the size of the array is not
     134             :    too large for the space in a packet */
     135             : #define FD_TEMPL_MBR_ELEM_ARRAY(NAME,TYPE,BYTES_MIN,BYTES_MAX)         \
     136             :     tmp_len = frame->NAME##_len;                                       \
     137             :     if( tmp_len * sizeof( fd_quic_##TYPE ) > BYTES_MAX ) {             \
     138             :       return FD_QUIC_ENCODE_FAIL;                                      \
     139             :     }                                                                  \
     140             :     for( ulong j=0; j<tmp_len; ++j ) {                                 \
     141             :       buf += FD_TEMPL_ENCODE(TYPE,frame->NAME[j],buf);                 \
     142             :     }
     143             : 
     144             : /* FIXED is an array of elements, each of the same size,
     145             :    with length constant */
     146             : #define FD_TEMPL_MBR_ELEM_FIXED(NAME,TYPE,BYTES)                       \
     147          18 :     if( FD_UNLIKELY( BYTES > buf_end-buf ||                            \
     148          18 :                      BYTES % sizeof(fd_quic_##TYPE) ) )                \
     149          18 :       return FD_QUIC_PARSE_FAIL;                                       \
     150          18 :     tmp_len = BYTES / sizeof(fd_quic_##TYPE);                          \
     151         234 :     for( ulong j=0; j<tmp_len; ++j ) {                                 \
     152         216 :       buf += FD_TEMPL_ENCODE(TYPE,frame->NAME[j],buf);                 \
     153         216 :     }
     154             : 
     155             : /* TODO remove abort() once tested */
     156             : #define FD_TEMPL_MBR_OPT(TYPE,NAME,MASK,...)                           \
     157   126757248 :     if( !type_ptr ) {                                                  \
     158           0 :       abort();                                                         \
     159           0 :     }                                                                  \
     160   126757248 :     if( frame->NAME##_opt ) {                                          \
     161    59343097 :       type_ptr[0] |= (uchar)(MASK);                                    \
     162    59343097 :       __VA_ARGS__                                                      \
     163    25634946 :     }
     164             : 
     165             :     /* TODO probably easier to split up relevant frames rather than
     166             :        code a generic optional in macros */
     167             : 
     168             : 
     169             : /* at end, return the number of bytes consumed */
     170             : #define FD_TEMPL_DEF_STRUCT_END(NAME)                                  \
     171    70290395 :     return (ulong)( buf-orig_buf );                                    \
     172    70290422 :   }
     173             : 
     174             : #include "fd_quic_dft.h"
     175             : 

Generated by: LCOV version 1.14