LCOV - code coverage report
Current view: top level - waltz/quic - fd_quic_pretty_print.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 428 0.0 %
Date: 2025-07-01 05:00:49 Functions: 0 32 0.0 %

          Line data    Source code
       1             : #pragma GCC diagnostic ignored "-Wtype-limits"
       2             : 
       3             : #include "templ/fd_quic_pretty_print.h"
       4             : #include "templ/fd_quic_templ.h"
       5             : #include "templ/fd_quic_frames_templ.h"
       6             : #include "templ/fd_quic_undefs.h"
       7             : #include "fd_quic_private.h"
       8             : #include "fd_quic_pretty_print.h"
       9             : 
      10             : /* Generate frame pretty-print */
      11             : 
      12             : #define FD_TEMPL_DEF_STRUCT_BEGIN(NAME)                                    \
      13             :   static ulong fd_quic_pretty_print_frame_##NAME(                          \
      14             :       fd_quic_##NAME##_t * frame,                                          \
      15             :       char **              out_buf,                                        \
      16             :       ulong *              out_buf_sz,                                     \
      17             :       uchar const * const  buf,                                            \
      18             :       ulong         const  buf_sz                                          \
      19           0 :   ) {                                                                      \
      20           0 :     uchar const *       p0 = buf;                                          \
      21           0 :     uchar const * const p1 = buf+buf_sz;                                   \
      22           0 :     ulong               rc;                                                \
      23           0 :                                                                            \
      24           0 :     rc = fd_quic_decode_##NAME( frame, p0, (ulong)(p1-p0) );               \
      25           0 :     if( FD_UNLIKELY( rc==FD_QUIC_PARSE_FAIL ) ) return FD_QUIC_PARSE_FAIL; \
      26           0 :     p0 += rc;                                                              \
      27           0 :                                                                            \
      28           0 :     fd_quic_pretty_print_struct_##NAME( out_buf, out_buf_sz, frame );      \
      29           0 :                                                                            \
      30           0 :     return (ulong)(p0-buf);                                                \
      31           0 :   }
      32             : #include "templ/fd_quic_dft.h"
      33             : #include "templ/fd_quic_frames_templ.h"
      34             : #include "templ/fd_quic_undefs.h"
      35             : 
      36             : #include "templ/fd_quic_frame.h"
      37             : 
      38             : 
      39             : #define safe_snprintf( out, sz, ... )               \
      40           0 :   (__extension__({                                  \
      41           0 :     int rtn = snprintf( (out), (sz), __VA_ARGS__ ); \
      42           0 :     if( rtn < 0 ) rtn = 0;                          \
      43           0 :     if( rtn > (int)(sz) ) rtn = (int)(sz);          \
      44           0 :     (ulong)rtn; }))
      45             : 
      46             : ulong
      47             : fd_quic_pretty_print_frame( char **           out_buf,
      48             :                             ulong *           out_buf_sz,
      49             :                             uchar const *     buf,
      50           0 :                             ulong             buf_sz ) {
      51           0 :   if( FD_UNLIKELY( buf_sz<1UL ) ) return FD_QUIC_PARSE_FAIL;
      52             : 
      53           0 :   uchar const * cur_buf = buf;
      54           0 :   uchar const * buf_end = buf + buf_sz;
      55             : 
      56           0 :   if( ( cur_buf[0] & 0xfe ) == 0x00 ) { /* handle padding and pings separately */
      57           0 :     ulong padding_cnt = 0;
      58           0 :     ulong ping_cnt    = 0;
      59           0 :     while( cur_buf < buf_end && ( *cur_buf & 0xfe ) == 0x00 ) {
      60           0 :       uint pad = (uint)( *cur_buf == 0 );
      61           0 :       padding_cnt += pad;
      62           0 :       ping_cnt    += 1u - pad;
      63           0 :       cur_buf++;
      64           0 :     }
      65             : 
      66           0 :     ulong sz = safe_snprintf( *out_buf, *out_buf_sz,
      67           0 :                  "\"frame_type\": \"pad-ping\", \"pad-count\": %lu, "
      68           0 :                  "\"ping-count\": %lu, ",
      69           0 :                  padding_cnt, ping_cnt );
      70           0 :     *out_buf    += sz;
      71           0 :     *out_buf_sz -= sz;
      72             : 
      73           0 :     return (ulong)( cur_buf - buf );
      74           0 :   }
      75             : 
      76             :   /* Frame ID is technically a varint but it's sufficient to look at the
      77             :      first byte. */
      78           0 :   uint id = cur_buf[0];
      79           0 :   if( FD_UNLIKELY( id >= FD_QUIC_FRAME_TYPE_CNT ) ) {
      80           0 :     ulong sz = safe_snprintf( *out_buf, *out_buf_sz, "\"frame_type\": \"%x-unknown\", ", (uint)id );
      81           0 :     *out_buf    += sz;
      82           0 :     *out_buf_sz -= sz;
      83             : 
      84           0 :     return FD_QUIC_PARSE_FAIL;
      85           0 :   }
      86             : 
      87           0 :   ulong consumed = 0UL;
      88             : 
      89           0 :   union {
      90           0 : #define FD_TEMPL_DEF_STRUCT_BEGIN(NAME) fd_quic_##NAME##_t NAME;
      91           0 : #include "templ/fd_quic_dft.h"
      92           0 : #include "templ/fd_quic_frames_templ.h"
      93           0 : #include "templ/fd_quic_undefs.h"
      94           0 :   } data;
      95             : 
      96           0 :   memset( &data, 0, sizeof( data ) );
      97             : 
      98             :   /* tail call to frame handler */
      99           0 :   switch( id ) {
     100             : 
     101           0 : # define F(T,MID,NAME,...) \
     102           0 :     case T: { \
     103           0 :       ulong sz = safe_snprintf( *out_buf, *out_buf_sz, "\"frame_type\": \"%u\", ", (uint)id ); \
     104           0 :       *out_buf    += sz; \
     105           0 :       *out_buf_sz -= sz; \
     106           0 :       consumed = fd_quic_pretty_print_frame_##NAME##_frame( &data.NAME##_frame, out_buf, out_buf_sz, cur_buf, (ulong)( buf_end - cur_buf ) ); \
     107           0 :       break; \
     108           0 :     }
     109           0 :   FD_QUIC_FRAME_TYPES(F)
     110           0 : # undef F
     111             : 
     112           0 :   default:
     113             :     /* we're unable to consume more bytes, since this is invalid */
     114             :     /* TODO put error key in json */
     115           0 :     return FD_QUIC_PARSE_FAIL;
     116           0 :   }
     117             : 
     118           0 :   if( consumed == FD_QUIC_PARSE_FAIL ) return FD_QUIC_PARSE_FAIL;
     119             : 
     120             :   /* handle repeating blocks, etc. */
     121           0 :   cur_buf += consumed;
     122             : 
     123           0 :   switch( id ) {
     124           0 :     case 0x02:
     125           0 :     case 0x03:
     126           0 :     {
     127           0 :       ulong ack_range_count = data.ack_frame.ack_range_count;
     128             : 
     129           0 :       if( ack_range_count ) {
     130           0 :         ulong out_sz = safe_snprintf( *out_buf, *out_buf_sz, "\"ack_ranges\": [ " );
     131           0 :         *out_buf    += out_sz;
     132           0 :         *out_buf_sz -= out_sz;
     133             : 
     134             :         /* skip ack ranges */
     135           0 :         for( ulong j = 0UL; j < ack_range_count; ++j ) {
     136           0 :           fd_quic_ack_range_frag_t ack_range[1];
     137           0 :           ulong rc = fd_quic_decode_ack_range_frag( ack_range, cur_buf, (ulong)( buf_end - cur_buf ) );
     138           0 :           if( FD_UNLIKELY( rc == FD_QUIC_PARSE_FAIL ) ) {
     139           0 :             ulong out_sz = safe_snprintf( *out_buf, *out_buf_sz, "\"err\": \"parse-ack-ranges\", " );
     140           0 :             *out_buf    += out_sz;
     141           0 :             *out_buf_sz -= out_sz;
     142           0 :             return FD_QUIC_PARSE_FAIL;
     143           0 :           }
     144             : 
     145           0 :           cur_buf += rc;
     146             : 
     147           0 :           ulong out_sz = safe_snprintf( *out_buf, *out_buf_sz, "{ " );
     148           0 :           *out_buf    += out_sz;
     149           0 :           *out_buf_sz -= out_sz;
     150             : 
     151           0 :           fd_quic_pretty_print_struct_ack_range_frag( out_buf, out_buf_sz, ack_range );
     152             : 
     153           0 :           out_sz = safe_snprintf( *out_buf, *out_buf_sz, "}, " );
     154           0 :           *out_buf    += out_sz;
     155           0 :           *out_buf_sz -= out_sz;
     156           0 :         }
     157             : 
     158           0 :         out_sz = safe_snprintf( *out_buf, *out_buf_sz, "], " );
     159           0 :         *out_buf    += out_sz;
     160           0 :         *out_buf_sz -= out_sz;
     161           0 :       }
     162             : 
     163           0 :       if( data.ack_frame.type & 1U ) {
     164           0 :         fd_quic_ecn_counts_frag_t ecn_counts[1] = {0};
     165           0 :         ulong rc = fd_quic_decode_ecn_counts_frag( ecn_counts, cur_buf, (ulong)( buf_end - cur_buf ) );
     166           0 :         if( rc == FD_QUIC_PARSE_FAIL ) {
     167           0 :           ulong out_sz = safe_snprintf( *out_buf, *out_buf_sz, "\"err\": \"parse-ecn-counts\", " );
     168           0 :           *out_buf    += out_sz;
     169           0 :           *out_buf_sz -= out_sz;
     170           0 :           return FD_QUIC_PARSE_FAIL;
     171           0 :         }
     172             : 
     173           0 :         fd_quic_pretty_print_struct_ecn_counts_frag( out_buf, out_buf_sz, ecn_counts );
     174             : 
     175           0 :         cur_buf += rc;
     176           0 :       }
     177             : 
     178           0 :       break;
     179           0 :     }
     180             : 
     181           0 :     case 0x06:
     182           0 :     {
     183           0 :       ulong out_sz = 0;
     184           0 :       ulong remain  = (ulong)( buf_end - cur_buf );
     185           0 :       ulong data_sz = data.crypto_frame.length;
     186           0 :       if( data_sz > remain ) {
     187           0 :         out_sz = safe_snprintf( *out_buf, *out_buf_sz, "\"err\": \"overflow\", " );
     188           0 :         *out_buf    += out_sz;
     189           0 :         *out_buf_sz -= out_sz;
     190             : 
     191           0 :         return FD_QUIC_PARSE_FAIL;
     192           0 :       }
     193             : 
     194           0 :       out_sz = safe_snprintf( *out_buf, *out_buf_sz, "\"data\": [ " );
     195           0 :       *out_buf    += out_sz;
     196           0 :       *out_buf_sz -= out_sz;
     197             : 
     198           0 :       for( ulong j = 0; j < data_sz; ++j ) {
     199           0 :         out_sz = safe_snprintf( *out_buf, *out_buf_sz, "0x%02x, ", cur_buf[j] );
     200           0 :         *out_buf    += out_sz;
     201           0 :         *out_buf_sz -= out_sz;
     202           0 :       }
     203             : 
     204           0 :       out_sz = safe_snprintf( *out_buf, *out_buf_sz, "], " );
     205           0 :       *out_buf    += out_sz;
     206           0 :       *out_buf_sz -= out_sz;
     207             : 
     208           0 :       cur_buf  += data_sz;
     209             : 
     210           0 :       break;
     211           0 :     }
     212             : 
     213           0 :     case 0x08:
     214           0 :     case 0x09:
     215           0 :     case 0x0a:
     216           0 :     case 0x0b:
     217           0 :     case 0x0c:
     218           0 :     case 0x0d:
     219           0 :     case 0x0e:
     220           0 :     case 0x0f:
     221           0 :     {
     222           0 :       ulong remain = (ulong)( buf_end - cur_buf );
     223             : 
     224             :       /* stream */
     225             :       /* optional fields decoding */
     226           0 :       ulong offset      = 0;
     227           0 :       ulong stream_id   = 0;
     228           0 :       ulong data_sz     = remain;
     229           0 :       ulong fin         = 0;
     230             : 
     231           0 :       switch( id ) {
     232           0 : #       define _0(ELSE,...) ELSE
     233           0 : #       define _1(ELSE,...) __VA_ARGS__
     234           0 : #       define _CASE(OFF,LEN,FIN,NAME)           \
     235           0 :         case 8 + OFF(0,4) + LEN(0,2) + FIN(0,1): \
     236           0 :           OFF(,offset  = data.NAME.offset;)      \
     237           0 :           LEN(,data_sz = data.NAME.length;)      \
     238           0 :           FIN(,fin     = 1;)                     \
     239           0 :           stream_id   = data.NAME.stream_id;     \
     240           0 :           break;
     241           0 :         _CASE(_0,_0,_0,stream_8_frame)
     242           0 :         _CASE(_0,_0,_1,stream_8_frame)
     243           0 :         _CASE(_0,_1,_0,stream_a_frame)
     244           0 :         _CASE(_0,_1,_1,stream_a_frame)
     245           0 :         _CASE(_1,_0,_0,stream_c_frame)
     246           0 :         _CASE(_1,_0,_1,stream_c_frame)
     247           0 :         _CASE(_1,_1,_0,stream_e_frame)
     248           0 :         _CASE(_1,_1,_1,stream_e_frame)
     249           0 : #       undef _CASE
     250           0 : #       undef _1
     251           0 : #       undef _0
     252           0 :       }
     253             : 
     254           0 :       ulong stream_type = stream_id & 3UL;
     255             : 
     256           0 :       ulong out_sz = safe_snprintf(
     257           0 :                        *out_buf,
     258           0 :                        *out_buf_sz,
     259           0 :                        "\"stream_type\": %u, \"offset\": %lu, \"length\": %lu, \"fin\": %lu, ",
     260           0 :                        (uint)stream_type, offset, data_sz, fin );
     261           0 :       *out_buf    += out_sz;
     262           0 :       *out_buf_sz -= out_sz;
     263             : 
     264           0 :       if( data_sz > remain ) {
     265           0 :         out_sz = safe_snprintf( *out_buf, *out_buf_sz, "\"err\": \"overflow\", " );
     266           0 :         *out_buf    += out_sz;
     267           0 :         *out_buf_sz -= out_sz;
     268             : 
     269           0 :         return FD_QUIC_PARSE_FAIL;
     270           0 :       }
     271             : 
     272           0 :       out_sz = safe_snprintf( *out_buf, *out_buf_sz, "\"data\": [ " );
     273           0 :       *out_buf    += out_sz;
     274           0 :       *out_buf_sz -= out_sz;
     275             : 
     276           0 :       for( ulong j = 0; j < data_sz; ++j ) {
     277           0 :         out_sz = safe_snprintf( *out_buf, *out_buf_sz, "0x%02x, ", cur_buf[j] );
     278           0 :         *out_buf    += out_sz;
     279           0 :         *out_buf_sz -= out_sz;
     280           0 :       }
     281             : 
     282           0 :       out_sz = safe_snprintf( *out_buf, *out_buf_sz, "], " );
     283           0 :       *out_buf    += out_sz;
     284           0 :       *out_buf_sz -= out_sz;
     285             : 
     286           0 :       cur_buf  += data_sz;
     287             : 
     288           0 :       break;
     289           0 :     }
     290             : 
     291           0 :     case 0x1c: /* connection close */
     292           0 :     {
     293             :       /* the conn_close_1_frame structure is different to conn_close_0_frame */
     294           0 :       ulong reason_phrase_length = data.conn_close_0_frame.reason_phrase_length;
     295           0 :       ulong remain               = (ulong)( buf_end - cur_buf );
     296           0 :       if( FD_UNLIKELY( reason_phrase_length > remain ) ) {
     297           0 :         ulong out_sz = safe_snprintf( *out_buf, *out_buf_sz, "\"err\": \"overflow\", " );
     298           0 :         *out_buf    += out_sz;
     299           0 :         *out_buf_sz -= out_sz;
     300             : 
     301           0 :         return FD_QUIC_PARSE_FAIL;
     302           0 :       }
     303             : 
     304             :       /* TODO pretty print the reason phrase */
     305             : 
     306           0 :       cur_buf += reason_phrase_length;
     307             : 
     308           0 :       break;
     309           0 :     }
     310             : 
     311           0 :     case 0x1d: /* connection close */
     312           0 :     {
     313             :       /* the conn_close_1_frame structure is different to conn_close_0_frame */
     314           0 :       ulong reason_phrase_length = data.conn_close_1_frame.reason_phrase_length;
     315           0 :       ulong remain               = (ulong)( buf_end - cur_buf );
     316           0 :       if( FD_UNLIKELY( reason_phrase_length > remain ) ) {
     317           0 :         ulong out_sz = safe_snprintf( *out_buf, *out_buf_sz, "\"err\": \"overflow\", " );
     318           0 :         *out_buf    += out_sz;
     319           0 :         *out_buf_sz -= out_sz;
     320             : 
     321           0 :         return FD_QUIC_PARSE_FAIL;
     322           0 :       }
     323             : 
     324             :       /* TODO pretty print the reason phrase */
     325             : 
     326           0 :       cur_buf += reason_phrase_length;
     327             : 
     328           0 :       break;
     329           0 :     }
     330           0 :   }
     331             : 
     332           0 :   return (ulong)( cur_buf - buf );
     333             : 
     334           0 : }
     335             : 
     336             : ulong
     337             : fd_quic_pretty_print_frames( char **           out_buf,
     338             :                              ulong *           out_buf_sz,
     339             :                              uchar const *     buf,
     340             :                              ulong             buf_sz );
     341             : 
     342             : 
     343             : ulong
     344             : fd_quic_pretty_print_quic_hdr_initial( char **        out_buf,
     345             :                                        ulong *        out_buf_sz,
     346             :                                        uchar const ** frame_ptr,
     347             :                                        ulong *        frame_sz,
     348             :                                        uchar const *  buf,
     349           0 :                                        ulong          buf_sz ) {
     350           0 :   ulong sz = safe_snprintf( *out_buf, *out_buf_sz, "\"hdr_type\": \"initial\", " );
     351           0 :   *out_buf    += sz;
     352           0 :   *out_buf_sz -= sz;
     353             : 
     354           0 :   fd_quic_initial_t initial[1] = {0};
     355           0 :   ulong rc = fd_quic_decode_initial( initial, buf, buf_sz );
     356           0 :   if( FD_UNLIKELY( rc == FD_QUIC_PARSE_FAIL ) ) {
     357           0 :     ulong sz = safe_snprintf( *out_buf, *out_buf_sz, "\"err\": \"hdr_parse_failed\", " );
     358           0 :     *out_buf    += sz;
     359           0 :     *out_buf_sz -= sz;
     360             : 
     361           0 :     FD_LOG_HEXDUMP_ERR(( "hdr_parse_failed", buf, fd_ulong_min( 16, buf_sz ) ));
     362             : 
     363           0 :     return FD_QUIC_PARSE_FAIL;
     364           0 :   }
     365             : 
     366           0 :   ulong body_sz       = initial->len;  /* not a protected field */
     367           0 :   ulong pn_offset     = initial->pkt_num_pnoff;
     368           0 :   ulong pkt_number_sz = fd_quic_h0_pkt_num_len( buf[0] ) + 1u;
     369           0 :   ulong payload_off   = pn_offset + pkt_number_sz;
     370             : 
     371             :   /* now we have decrypted packet number */
     372           0 :   ulong pkt_number = fd_quic_pktnum_decode( buf+pn_offset, pkt_number_sz );
     373             : 
     374             :   /* write pkt_number_sz into initial, for tracing */
     375             :   /* note this is the raw packet number, which may have been truncated */
     376           0 :   initial->pkt_num = pkt_number;
     377             : 
     378           0 :   *frame_ptr   = buf + payload_off;
     379           0 :   *frame_sz    = body_sz - pkt_number_sz - FD_QUIC_CRYPTO_TAG_SZ; /* total size of all frames in packet */
     380             : 
     381           0 :   fd_quic_pretty_print_struct_initial( out_buf, out_buf_sz, initial );
     382             : 
     383           0 :   return payload_off;
     384           0 : }
     385             : 
     386             : 
     387             : ulong
     388             : fd_quic_pretty_print_quic_hdr_handshake( char **        out_buf,
     389             :                                          ulong *        out_buf_sz,
     390             :                                          uchar const ** frame_ptr,
     391             :                                          ulong *        frame_sz,
     392             :                                          uchar const *  buf,
     393           0 :                                          ulong          buf_sz ) {
     394           0 :   ulong sz = safe_snprintf( *out_buf, *out_buf_sz, "\"hdr_type\": \"handshake\", " );
     395           0 :   *out_buf    += sz;
     396           0 :   *out_buf_sz -= sz;
     397             : 
     398           0 :   fd_quic_handshake_t handshake[1] = {0};
     399           0 :   ulong rc = fd_quic_decode_handshake( handshake, buf, buf_sz );
     400           0 :   if( FD_UNLIKELY( rc == FD_QUIC_PARSE_FAIL ) ) {
     401           0 :     ulong sz = safe_snprintf( *out_buf, *out_buf_sz, "\"err\": \"hdr_parse_failed\", " );
     402           0 :     *out_buf    += sz;
     403           0 :     *out_buf_sz -= sz;
     404             : 
     405           0 :     FD_LOG_HEXDUMP_ERR(( "hdr_parse_failed", buf, fd_ulong_min( 16, buf_sz ) ));
     406             : 
     407           0 :     return FD_QUIC_PARSE_FAIL;
     408           0 :   }
     409             : 
     410           0 :   ulong body_sz       = handshake->len;  /* not a protected field */
     411           0 :   ulong pn_offset     = handshake->pkt_num_pnoff;
     412           0 :   ulong pkt_number_sz = fd_quic_h0_pkt_num_len( buf[0] ) + 1u;
     413           0 :   ulong payload_off   = pn_offset + pkt_number_sz;
     414             : 
     415             :   /* now we have decrypted packet number */
     416           0 :   ulong pkt_number = fd_quic_pktnum_decode( buf+pn_offset, pkt_number_sz );
     417             : 
     418             :   /* write pkt_number_sz into handshake, for tracing */
     419             :   /* note this is the raw packet number, which may have been truncated */
     420           0 :   handshake->pkt_num = pkt_number;
     421             : 
     422           0 :   *frame_ptr   = buf + payload_off;
     423           0 :   *frame_sz    = body_sz - pkt_number_sz - FD_QUIC_CRYPTO_TAG_SZ; /* total size of all frames in packet */
     424             : 
     425           0 :   fd_quic_pretty_print_struct_handshake( out_buf, out_buf_sz, handshake );
     426             : 
     427           0 :   return payload_off;
     428           0 : }
     429             : 
     430             : 
     431             : ulong
     432             : fd_quic_pretty_print_quic_hdr_one_rtt( char **        out_buf,
     433             :                                        ulong *        out_buf_sz,
     434             :                                        uchar const ** frame_ptr,
     435             :                                        ulong *        frame_sz,
     436             :                                        uchar const *  buf,
     437           0 :                                        ulong          buf_sz ) {
     438           0 :   ulong sz = safe_snprintf( *out_buf, *out_buf_sz, "\"hdr_type\": \"1-rtt\", " );
     439           0 :   *out_buf    += sz;
     440           0 :   *out_buf_sz -= sz;
     441             : 
     442           0 :   fd_quic_one_rtt_t one_rtt[1] = {0};
     443             : 
     444             :   /* hidden field needed by decode function */
     445           0 :   one_rtt->dst_conn_id_len = 8;
     446             : 
     447           0 :   ulong rc = fd_quic_decode_one_rtt( one_rtt, buf, buf_sz );
     448           0 :   if( FD_UNLIKELY( rc == FD_QUIC_PARSE_FAIL ) ) {
     449           0 :     ulong sz = safe_snprintf( *out_buf, *out_buf_sz, "\"err\": \"hdr_parse_failed\", " );
     450           0 :     *out_buf    += sz;
     451           0 :     *out_buf_sz -= sz;
     452             : 
     453           0 :     FD_LOG_HEXDUMP_ERR(( "hdr_parse_failed", buf, fd_ulong_min( 16, buf_sz ) ));
     454             : 
     455           0 :     return FD_QUIC_PARSE_FAIL;
     456           0 :   }
     457             : 
     458           0 :   ulong pn_offset     = one_rtt->pkt_num_pnoff;
     459           0 :   ulong pkt_number_sz = fd_quic_h0_pkt_num_len( buf[0] ) + 1u;
     460           0 :   ulong payload_off   = pn_offset + pkt_number_sz;
     461           0 :   ulong payload_sz    = buf_sz - pn_offset - pkt_number_sz; /* includes auth tag */
     462             : 
     463             :   /* now we have decrypted packet number */
     464           0 :   ulong pkt_number = fd_quic_pktnum_decode( buf+pn_offset, pkt_number_sz );
     465             : 
     466             :   /* write pkt_number_sz into one_rtt, for tracing */
     467             :   /* note this is the raw packet number, which may have been truncated */
     468           0 :   one_rtt->pkt_num = pkt_number;
     469             : 
     470           0 :   *frame_ptr   = buf + payload_off;
     471           0 :   *frame_sz    = payload_sz - FD_QUIC_CRYPTO_TAG_SZ; /* total size of all frames in packet */
     472             : 
     473           0 :   fd_quic_pretty_print_struct_one_rtt( out_buf, out_buf_sz, one_rtt );
     474             : 
     475           0 :   return payload_off;
     476           0 : }
     477             : 
     478             : 
     479             : ulong
     480             : fd_quic_pretty_print_quic_hdr( char **        out_buf,
     481             :                                ulong *        out_buf_sz,
     482             :                                uchar const ** frame_ptr,
     483             :                                ulong *        frame_sz,
     484             :                                uchar const *  buf,
     485           0 :                                ulong          buf_sz ) {
     486           0 :   ulong sz;
     487             : 
     488           0 :   uint first   = (uint)buf[0];
     489           0 :   uint is_long = first >> 7u;
     490             : 
     491           0 :   if( !is_long ) {
     492           0 :       return fd_quic_pretty_print_quic_hdr_one_rtt( out_buf, out_buf_sz, frame_ptr, frame_sz, buf, buf_sz );
     493           0 :   }
     494             : 
     495           0 :   uint long_type = ( first >> 4u ) & 0x03u;
     496             : 
     497           0 :   switch( long_type ) {
     498           0 :     case 0x00: /* initial */
     499           0 :       return fd_quic_pretty_print_quic_hdr_initial( out_buf, out_buf_sz, frame_ptr, frame_sz, buf, buf_sz );
     500           0 :     case 0x01: /* 0-rtt - unused */
     501           0 :       sz = safe_snprintf( *out_buf, *out_buf_sz, "\"err\": \"0-rtt\", " );
     502           0 :       *out_buf    += sz;
     503           0 :       *out_buf_sz -= sz;
     504           0 :       return FD_QUIC_PARSE_FAIL;
     505           0 :     case 0x02: /* handshake */
     506           0 :       return fd_quic_pretty_print_quic_hdr_handshake( out_buf, out_buf_sz, frame_ptr, frame_sz, buf, buf_sz );
     507           0 :     case 0x03:
     508           0 :       sz = safe_snprintf( *out_buf, *out_buf_sz, "\"err\": \"not-implemented-retry\", " );
     509           0 :       *out_buf    += sz;
     510           0 :       *out_buf_sz -= sz;
     511           0 :       return FD_QUIC_PARSE_FAIL;
     512           0 :   }
     513             : 
     514             :   /* long type is uint & 0x03u - yet gcc thinks this is reachable */
     515           0 :   return FD_QUIC_PARSE_FAIL;
     516           0 : }
     517             : 
     518             : 
     519             : /* 16 bytes allows for: xxx.xxx.xxx.xxx\0 */
     520           0 : #define IP4_TO_STR_BUF_SZ 16
     521             : static
     522             : char const *
     523           0 : ip4_to_str( char buf[IP4_TO_STR_BUF_SZ], uint ip4_addr ) {
     524             :   /* can't use sizeof(buf) here, as technically typeof(buf) is char* */
     525           0 :   ulong sz = safe_snprintf( buf, IP4_TO_STR_BUF_SZ, FD_IP4_ADDR_FMT, FD_IP4_ADDR_FMT_ARGS( ip4_addr ) );
     526             :   /* should not be possible */
     527           0 :   if( FD_UNLIKELY( sz >= IP4_TO_STR_BUF_SZ ) ) buf[IP4_TO_STR_BUF_SZ-1] = '\0';
     528           0 :   return buf;
     529           0 : }
     530             : 
     531             : 
     532             : ulong
     533             : fd_quic_pretty_print_quic_pkt( fd_quic_pretty_print_t * pkt_ctx,
     534             :                                ulong                    now,
     535             :                                uchar const *            buf,
     536           0 :                                ulong                    buf_sz ) {
     537           0 :   (void)now;
     538             : 
     539           0 :   char tmp_buf[16];
     540             : 
     541           0 :   if( buf == NULL ) return FD_QUIC_PARSE_FAIL;
     542             : 
     543           0 :   static FD_TL char pretty_print_buf[16384];
     544             : 
     545           0 :   memset( pretty_print_buf, 0, sizeof( pretty_print_buf ) );
     546             : 
     547           0 :   char * out_buf    = &pretty_print_buf[0];
     548           0 :   ulong  out_buf_sz = sizeof( pretty_print_buf ) - 1UL;
     549             : 
     550           0 :   uchar const * frame_ptr = NULL;
     551           0 :   ulong         frame_sz  = 0;
     552             : 
     553           0 :   ulong sz = safe_snprintf( out_buf, out_buf_sz, "{ \"type\": \"packet\", \"flow\": \"%s\", ",
     554           0 :                             pkt_ctx->flow ? "egress" : "ingress" );
     555           0 :   out_buf    += sz;
     556           0 :   out_buf_sz -= sz;
     557             : 
     558           0 :   /* */ sz = safe_snprintf( out_buf, out_buf_sz, "\"conn_idx\": %u, ",
     559           0 :                             pkt_ctx->conn_idx );
     560           0 :   out_buf    += sz;
     561           0 :   out_buf_sz -= sz;
     562             : 
     563           0 :   char time_str[FD_LOG_WALLCLOCK_CSTR_BUF_SZ];
     564           0 :   /* */ sz = safe_snprintf( out_buf, out_buf_sz, "\"trace_time\": \"%s\", ",
     565           0 :                             fd_log_wallclock_cstr( fd_log_wallclock(), time_str ) );
     566           0 :   out_buf    += sz;
     567           0 :   out_buf_sz -= sz;
     568             : 
     569           0 :   /* */ sz = safe_snprintf( out_buf, out_buf_sz, "\"src_ip_addr\": \"%s\", \"src_udp_port\": \"%u\", ",
     570           0 :                             ip4_to_str( tmp_buf, pkt_ctx->ip4_saddr ), fd_ushort_bswap( (ushort)pkt_ctx->udp_sport ) );
     571           0 :   out_buf    += sz;
     572           0 :   out_buf_sz -= sz;
     573             : 
     574           0 :   /* */ sz = safe_snprintf( out_buf, out_buf_sz, "\"dst_ip_addr\": \"%s\", \"dst_udp_port\": \"%u\", ",
     575           0 :                             ip4_to_str( tmp_buf, pkt_ctx->ip4_daddr ), fd_ushort_bswap( (ushort)pkt_ctx->udp_dport ) );
     576           0 :   out_buf    += sz;
     577           0 :   out_buf_sz -= sz;
     578             : 
     579           0 :   ulong hdr_rc = fd_quic_pretty_print_quic_hdr( &out_buf,
     580           0 :                                                 &out_buf_sz,
     581           0 :                                                 &frame_ptr,
     582           0 :                                                 &frame_sz,
     583           0 :                                                 buf,
     584           0 :                                                 buf_sz );
     585           0 :   if( hdr_rc == FD_QUIC_PARSE_FAIL ) {
     586           0 :     sz = safe_snprintf( out_buf, out_buf_sz, "\"err\": \"parse_fail\" } " );
     587           0 :     out_buf    += sz;
     588           0 :     out_buf_sz -= sz;
     589             : 
     590           0 :     return FD_QUIC_PARSE_FAIL;
     591           0 :   }
     592             : 
     593           0 :   sz = safe_snprintf( out_buf, out_buf_sz, "\"frames\": [ " );
     594           0 :   out_buf    += sz;
     595           0 :   out_buf_sz -= sz;
     596             : 
     597           0 :   ulong rc = fd_quic_pretty_print_frames( &out_buf,
     598           0 :                                           &out_buf_sz,
     599           0 :                                           frame_ptr,
     600           0 :                                           frame_sz );
     601           0 :   if( rc == FD_QUIC_PARSE_FAIL ) {
     602           0 :     sz = safe_snprintf( out_buf, out_buf_sz, "], \"err\": \"parse_fail\" }, " );
     603           0 :     out_buf    += sz;
     604           0 :     out_buf_sz -= sz;
     605           0 :     printf( "\n[ %s ]\n", pretty_print_buf );
     606           0 :     fflush( stdout );
     607           0 :     return FD_QUIC_PARSE_FAIL;
     608           0 :   }
     609             : 
     610           0 :   sz = safe_snprintf( out_buf, out_buf_sz, "] }, " );
     611           0 :   out_buf    += sz;
     612           0 :   out_buf_sz -= sz;
     613             : 
     614           0 :   for( ulong j = 0; j < (ulong)( out_buf - pretty_print_buf); ++j ) {
     615           0 :     if( pretty_print_buf[j] == '\0' ) pretty_print_buf[j] = '*';
     616           0 :   }
     617             : 
     618           0 :   printf( "[ %s ]\n", pretty_print_buf );
     619             : 
     620           0 :   return rc;
     621           0 : }
     622             : 
     623             : ulong
     624             : fd_quic_pretty_print_frames( char **           out_buf,
     625             :                              ulong *           out_buf_sz,
     626             :                              uchar const *     buf,
     627           0 :                              ulong             buf_sz ) {
     628           0 :   uchar const * orig_buf = buf;
     629           0 :   ulong sz;
     630             : 
     631           0 :   while( buf_sz > 0 ) {
     632           0 :     sz          = safe_snprintf( *out_buf, *out_buf_sz, "{ \"type\": \"frame\", " );
     633           0 :     *out_buf    += sz;
     634           0 :     *out_buf_sz -= sz;
     635             : 
     636           0 :     ulong rc = fd_quic_pretty_print_frame( out_buf, out_buf_sz, buf, buf_sz );
     637           0 :     if( rc == FD_QUIC_PARSE_FAIL ) {
     638           0 :       sz          = safe_snprintf( *out_buf, *out_buf_sz, "\"err\": \"parse_fail\" }, " );
     639           0 :       *out_buf    += sz;
     640           0 :       *out_buf_sz -= sz;
     641           0 :       break;
     642           0 :     }
     643             : 
     644           0 :     sz          = safe_snprintf( *out_buf, *out_buf_sz, " }, " );
     645           0 :     *out_buf    += sz;
     646           0 :     *out_buf_sz -= sz;
     647             : 
     648           0 :     if( rc >= buf_sz ) break;
     649             : 
     650           0 :     buf    += rc;
     651           0 :     buf_sz -= rc;
     652           0 :   }
     653             : 
     654           0 :   return (ulong)( buf - orig_buf );
     655           0 : }

Generated by: LCOV version 1.14