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 454 0.0 %
Date: 2026-09-17 04:28:31 Functions: 0 34 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 0x30:
     292           0 :     case 0x31:
     293           0 :     {
     294           0 :       ulong remain  = (ulong)( buf_end - cur_buf );
     295           0 :       ulong data_sz = id==0x30U ? remain : data.datagram_1_frame.length;
     296           0 :       ulong out_sz;
     297             : 
     298           0 :       if( FD_UNLIKELY( data_sz > remain ) ) {
     299           0 :         out_sz = safe_snprintf( *out_buf, *out_buf_sz, "\"err\": \"overflow\", " );
     300           0 :         *out_buf    += out_sz;
     301           0 :         *out_buf_sz -= out_sz;
     302             : 
     303           0 :         return FD_QUIC_PARSE_FAIL;
     304           0 :       }
     305             : 
     306           0 :       out_sz = safe_snprintf( *out_buf, *out_buf_sz, "\"data\": [ " );
     307           0 :       *out_buf    += out_sz;
     308           0 :       *out_buf_sz -= out_sz;
     309             : 
     310           0 :       for( ulong j = 0UL; j < data_sz; ++j ) {
     311           0 :         out_sz = safe_snprintf( *out_buf, *out_buf_sz, "0x%02x, ", cur_buf[j] );
     312           0 :         *out_buf    += out_sz;
     313           0 :         *out_buf_sz -= out_sz;
     314           0 :       }
     315             : 
     316           0 :       out_sz = safe_snprintf( *out_buf, *out_buf_sz, "], " );
     317           0 :       *out_buf    += out_sz;
     318           0 :       *out_buf_sz -= out_sz;
     319             : 
     320           0 :       cur_buf += data_sz;
     321             : 
     322           0 :       break;
     323           0 :     }
     324             : 
     325           0 :     case 0x1c: /* connection close */
     326           0 :     {
     327             :       /* the conn_close_1_frame structure is different to conn_close_0_frame */
     328           0 :       ulong reason_phrase_length = data.conn_close_0_frame.reason_phrase_length;
     329           0 :       ulong remain               = (ulong)( buf_end - cur_buf );
     330           0 :       if( FD_UNLIKELY( reason_phrase_length > remain ) ) {
     331           0 :         ulong out_sz = safe_snprintf( *out_buf, *out_buf_sz, "\"err\": \"overflow\", " );
     332           0 :         *out_buf    += out_sz;
     333           0 :         *out_buf_sz -= out_sz;
     334             : 
     335           0 :         return FD_QUIC_PARSE_FAIL;
     336           0 :       }
     337             : 
     338             :       /* TODO pretty print the reason phrase */
     339             : 
     340           0 :       cur_buf += reason_phrase_length;
     341             : 
     342           0 :       break;
     343           0 :     }
     344             : 
     345           0 :     case 0x1d: /* connection close */
     346           0 :     {
     347             :       /* the conn_close_1_frame structure is different to conn_close_0_frame */
     348           0 :       ulong reason_phrase_length = data.conn_close_1_frame.reason_phrase_length;
     349           0 :       ulong remain               = (ulong)( buf_end - cur_buf );
     350           0 :       if( FD_UNLIKELY( reason_phrase_length > remain ) ) {
     351           0 :         ulong out_sz = safe_snprintf( *out_buf, *out_buf_sz, "\"err\": \"overflow\", " );
     352           0 :         *out_buf    += out_sz;
     353           0 :         *out_buf_sz -= out_sz;
     354             : 
     355           0 :         return FD_QUIC_PARSE_FAIL;
     356           0 :       }
     357             : 
     358             :       /* TODO pretty print the reason phrase */
     359             : 
     360           0 :       cur_buf += reason_phrase_length;
     361             : 
     362           0 :       break;
     363           0 :     }
     364           0 :   }
     365             : 
     366           0 :   return (ulong)( cur_buf - buf );
     367             : 
     368           0 : }
     369             : 
     370             : ulong
     371             : fd_quic_pretty_print_frames( char **           out_buf,
     372             :                              ulong *           out_buf_sz,
     373             :                              uchar const *     buf,
     374             :                              ulong             buf_sz );
     375             : 
     376             : 
     377             : ulong
     378             : fd_quic_pretty_print_quic_hdr_initial( char **        out_buf,
     379             :                                        ulong *        out_buf_sz,
     380             :                                        uchar const ** frame_ptr,
     381             :                                        ulong *        frame_sz,
     382             :                                        uchar const *  buf,
     383           0 :                                        ulong          buf_sz ) {
     384           0 :   ulong sz = safe_snprintf( *out_buf, *out_buf_sz, "\"hdr_type\": \"initial\", " );
     385           0 :   *out_buf    += sz;
     386           0 :   *out_buf_sz -= sz;
     387             : 
     388           0 :   fd_quic_initial_t initial[1] = {0};
     389           0 :   ulong rc = fd_quic_decode_initial( initial, buf, buf_sz );
     390           0 :   if( FD_UNLIKELY( rc == FD_QUIC_PARSE_FAIL ) ) {
     391           0 :     ulong sz = safe_snprintf( *out_buf, *out_buf_sz, "\"err\": \"hdr_parse_failed\", " );
     392           0 :     *out_buf    += sz;
     393           0 :     *out_buf_sz -= sz;
     394             : 
     395           0 :     FD_LOG_HEXDUMP_ERR(( "hdr_parse_failed", buf, fd_ulong_min( 16, buf_sz ) ));
     396             : 
     397           0 :     return FD_QUIC_PARSE_FAIL;
     398           0 :   }
     399             : 
     400           0 :   ulong body_sz       = initial->len;  /* not a protected field */
     401           0 :   ulong pn_offset     = initial->pkt_num_pnoff;
     402           0 :   ulong pkt_number_sz = fd_quic_h0_pkt_num_len( buf[0] ) + 1u;
     403           0 :   ulong payload_off   = pn_offset + pkt_number_sz;
     404             : 
     405             :   /* now we have decrypted packet number */
     406           0 :   ulong pkt_number = fd_quic_pktnum_decode( buf+pn_offset, pkt_number_sz );
     407             : 
     408             :   /* write pkt_number_sz into initial, for tracing */
     409             :   /* note this is the raw packet number, which may have been truncated */
     410           0 :   initial->pkt_num = pkt_number;
     411             : 
     412           0 :   *frame_ptr   = buf + payload_off;
     413           0 :   *frame_sz    = body_sz - pkt_number_sz - FD_QUIC_CRYPTO_TAG_SZ; /* total size of all frames in packet */
     414             : 
     415           0 :   fd_quic_pretty_print_struct_initial( out_buf, out_buf_sz, initial );
     416             : 
     417           0 :   return payload_off;
     418           0 : }
     419             : 
     420             : 
     421             : ulong
     422             : fd_quic_pretty_print_quic_hdr_handshake( char **        out_buf,
     423             :                                          ulong *        out_buf_sz,
     424             :                                          uchar const ** frame_ptr,
     425             :                                          ulong *        frame_sz,
     426             :                                          uchar const *  buf,
     427           0 :                                          ulong          buf_sz ) {
     428           0 :   ulong sz = safe_snprintf( *out_buf, *out_buf_sz, "\"hdr_type\": \"handshake\", " );
     429           0 :   *out_buf    += sz;
     430           0 :   *out_buf_sz -= sz;
     431             : 
     432           0 :   fd_quic_handshake_t handshake[1] = {0};
     433           0 :   ulong rc = fd_quic_decode_handshake( handshake, buf, buf_sz );
     434           0 :   if( FD_UNLIKELY( rc == FD_QUIC_PARSE_FAIL ) ) {
     435           0 :     ulong sz = safe_snprintf( *out_buf, *out_buf_sz, "\"err\": \"hdr_parse_failed\", " );
     436           0 :     *out_buf    += sz;
     437           0 :     *out_buf_sz -= sz;
     438             : 
     439           0 :     FD_LOG_HEXDUMP_ERR(( "hdr_parse_failed", buf, fd_ulong_min( 16, buf_sz ) ));
     440             : 
     441           0 :     return FD_QUIC_PARSE_FAIL;
     442           0 :   }
     443             : 
     444           0 :   ulong body_sz       = handshake->len;  /* not a protected field */
     445           0 :   ulong pn_offset     = handshake->pkt_num_pnoff;
     446           0 :   ulong pkt_number_sz = fd_quic_h0_pkt_num_len( buf[0] ) + 1u;
     447           0 :   ulong payload_off   = pn_offset + pkt_number_sz;
     448             : 
     449             :   /* now we have decrypted packet number */
     450           0 :   ulong pkt_number = fd_quic_pktnum_decode( buf+pn_offset, pkt_number_sz );
     451             : 
     452             :   /* write pkt_number_sz into handshake, for tracing */
     453             :   /* note this is the raw packet number, which may have been truncated */
     454           0 :   handshake->pkt_num = pkt_number;
     455             : 
     456           0 :   *frame_ptr   = buf + payload_off;
     457           0 :   *frame_sz    = body_sz - pkt_number_sz - FD_QUIC_CRYPTO_TAG_SZ; /* total size of all frames in packet */
     458             : 
     459           0 :   fd_quic_pretty_print_struct_handshake( out_buf, out_buf_sz, handshake );
     460             : 
     461           0 :   return payload_off;
     462           0 : }
     463             : 
     464             : 
     465             : ulong
     466             : fd_quic_pretty_print_quic_hdr_one_rtt( char **        out_buf,
     467             :                                        ulong *        out_buf_sz,
     468             :                                        uchar const ** frame_ptr,
     469             :                                        ulong *        frame_sz,
     470             :                                        uchar const *  buf,
     471           0 :                                        ulong          buf_sz ) {
     472           0 :   ulong sz = safe_snprintf( *out_buf, *out_buf_sz, "\"hdr_type\": \"1-rtt\", " );
     473           0 :   *out_buf    += sz;
     474           0 :   *out_buf_sz -= sz;
     475             : 
     476           0 :   fd_quic_one_rtt_t one_rtt[1] = {0};
     477             : 
     478             :   /* hidden field needed by decode function */
     479           0 :   one_rtt->dst_conn_id_len = 8;
     480             : 
     481           0 :   ulong rc = fd_quic_decode_one_rtt( one_rtt, buf, buf_sz );
     482           0 :   if( FD_UNLIKELY( rc == FD_QUIC_PARSE_FAIL ) ) {
     483           0 :     ulong sz = safe_snprintf( *out_buf, *out_buf_sz, "\"err\": \"hdr_parse_failed\", " );
     484           0 :     *out_buf    += sz;
     485           0 :     *out_buf_sz -= sz;
     486             : 
     487           0 :     FD_LOG_HEXDUMP_ERR(( "hdr_parse_failed", buf, fd_ulong_min( 16, buf_sz ) ));
     488             : 
     489           0 :     return FD_QUIC_PARSE_FAIL;
     490           0 :   }
     491             : 
     492           0 :   ulong pn_offset     = one_rtt->pkt_num_pnoff;
     493           0 :   ulong pkt_number_sz = fd_quic_h0_pkt_num_len( buf[0] ) + 1u;
     494           0 :   ulong payload_off   = pn_offset + pkt_number_sz;
     495           0 :   ulong payload_sz    = buf_sz - pn_offset - pkt_number_sz; /* includes auth tag */
     496             : 
     497             :   /* now we have decrypted packet number */
     498           0 :   ulong pkt_number = fd_quic_pktnum_decode( buf+pn_offset, pkt_number_sz );
     499             : 
     500             :   /* write pkt_number_sz into one_rtt, for tracing */
     501             :   /* note this is the raw packet number, which may have been truncated */
     502           0 :   one_rtt->pkt_num = pkt_number;
     503             : 
     504           0 :   *frame_ptr   = buf + payload_off;
     505           0 :   *frame_sz    = payload_sz - FD_QUIC_CRYPTO_TAG_SZ; /* total size of all frames in packet */
     506             : 
     507           0 :   fd_quic_pretty_print_struct_one_rtt( out_buf, out_buf_sz, one_rtt );
     508             : 
     509           0 :   return payload_off;
     510           0 : }
     511             : 
     512             : 
     513             : ulong
     514             : fd_quic_pretty_print_quic_hdr( char **        out_buf,
     515             :                                ulong *        out_buf_sz,
     516             :                                uchar const ** frame_ptr,
     517             :                                ulong *        frame_sz,
     518             :                                uchar const *  buf,
     519           0 :                                ulong          buf_sz ) {
     520           0 :   ulong sz;
     521             : 
     522           0 :   uint first   = (uint)buf[0];
     523           0 :   uint is_long = first >> 7u;
     524             : 
     525           0 :   if( !is_long ) {
     526           0 :       return fd_quic_pretty_print_quic_hdr_one_rtt( out_buf, out_buf_sz, frame_ptr, frame_sz, buf, buf_sz );
     527           0 :   }
     528             : 
     529           0 :   uint long_type = ( first >> 4u ) & 0x03u;
     530             : 
     531           0 :   switch( long_type ) {
     532           0 :     case 0x00: /* initial */
     533           0 :       return fd_quic_pretty_print_quic_hdr_initial( out_buf, out_buf_sz, frame_ptr, frame_sz, buf, buf_sz );
     534           0 :     case 0x01: /* 0-rtt - unused */
     535           0 :       sz = safe_snprintf( *out_buf, *out_buf_sz, "\"err\": \"0-rtt\", " );
     536           0 :       *out_buf    += sz;
     537           0 :       *out_buf_sz -= sz;
     538           0 :       return FD_QUIC_PARSE_FAIL;
     539           0 :     case 0x02: /* handshake */
     540           0 :       return fd_quic_pretty_print_quic_hdr_handshake( out_buf, out_buf_sz, frame_ptr, frame_sz, buf, buf_sz );
     541           0 :     case 0x03:
     542           0 :       sz = safe_snprintf( *out_buf, *out_buf_sz, "\"err\": \"not-implemented-retry\", " );
     543           0 :       *out_buf    += sz;
     544           0 :       *out_buf_sz -= sz;
     545           0 :       return FD_QUIC_PARSE_FAIL;
     546           0 :   }
     547             : 
     548             :   /* long type is uint & 0x03u - yet gcc thinks this is reachable */
     549           0 :   return FD_QUIC_PARSE_FAIL;
     550           0 : }
     551             : 
     552             : 
     553             : /* 16 bytes allows for: xxx.xxx.xxx.xxx\0 */
     554           0 : #define IP4_TO_STR_BUF_SZ 16
     555             : static
     556             : char const *
     557           0 : ip4_to_str( char buf[IP4_TO_STR_BUF_SZ], uint ip4_addr ) {
     558             :   /* can't use sizeof(buf) here, as technically typeof(buf) is char* */
     559           0 :   ulong sz = safe_snprintf( buf, IP4_TO_STR_BUF_SZ, FD_IP4_ADDR_FMT, FD_IP4_ADDR_FMT_ARGS( ip4_addr ) );
     560             :   /* should not be possible */
     561           0 :   if( FD_UNLIKELY( sz >= IP4_TO_STR_BUF_SZ ) ) buf[IP4_TO_STR_BUF_SZ-1] = '\0';
     562           0 :   return buf;
     563           0 : }
     564             : 
     565             : 
     566             : ulong
     567             : fd_quic_pretty_print_quic_pkt( fd_quic_pretty_print_t * pkt_ctx,
     568             :                                long                     now,
     569             :                                uchar const *            buf,
     570           0 :                                ulong                    buf_sz ) {
     571           0 :   (void)now;
     572             : 
     573           0 :   char tmp_buf[16];
     574             : 
     575           0 :   if( buf == NULL ) return FD_QUIC_PARSE_FAIL;
     576             : 
     577           0 :   static FD_TL char pretty_print_buf[16384];
     578             : 
     579           0 :   memset( pretty_print_buf, 0, sizeof( pretty_print_buf ) );
     580             : 
     581           0 :   char * out_buf    = &pretty_print_buf[0];
     582           0 :   ulong  out_buf_sz = sizeof( pretty_print_buf ) - 1UL;
     583             : 
     584           0 :   uchar const * frame_ptr = NULL;
     585           0 :   ulong         frame_sz  = 0;
     586             : 
     587           0 :   ulong sz = safe_snprintf( out_buf, out_buf_sz, "{ \"type\": \"packet\", \"flow\": \"%s\", ",
     588           0 :                             pkt_ctx->flow ? "egress" : "ingress" );
     589           0 :   out_buf    += sz;
     590           0 :   out_buf_sz -= sz;
     591             : 
     592           0 :   /* */ sz = safe_snprintf( out_buf, out_buf_sz, "\"conn_idx\": %u, ",
     593           0 :                             pkt_ctx->conn_idx );
     594           0 :   out_buf    += sz;
     595           0 :   out_buf_sz -= sz;
     596             : 
     597           0 :   char time_str[FD_LOG_WALLCLOCK_CSTR_BUF_SZ];
     598           0 :   /* */ sz = safe_snprintf( out_buf, out_buf_sz, "\"trace_time\": \"%s\", ",
     599           0 :                             fd_log_wallclock_cstr( fd_log_wallclock(), time_str ) );
     600           0 :   out_buf    += sz;
     601           0 :   out_buf_sz -= sz;
     602             : 
     603           0 :   /* */ sz = safe_snprintf( out_buf, out_buf_sz, "\"src_ip_addr\": \"%s\", \"src_udp_port\": \"%u\", ",
     604           0 :                             ip4_to_str( tmp_buf, pkt_ctx->ip4_saddr ), pkt_ctx->udp_sport );
     605           0 :   out_buf    += sz;
     606           0 :   out_buf_sz -= sz;
     607             : 
     608           0 :   /* */ sz = safe_snprintf( out_buf, out_buf_sz, "\"dst_ip_addr\": \"%s\", \"dst_udp_port\": \"%u\", ",
     609           0 :                             ip4_to_str( tmp_buf, pkt_ctx->ip4_daddr ), pkt_ctx->udp_dport );
     610           0 :   out_buf    += sz;
     611           0 :   out_buf_sz -= sz;
     612             : 
     613           0 :   ulong hdr_rc = fd_quic_pretty_print_quic_hdr( &out_buf,
     614           0 :                                                 &out_buf_sz,
     615           0 :                                                 &frame_ptr,
     616           0 :                                                 &frame_sz,
     617           0 :                                                 buf,
     618           0 :                                                 buf_sz );
     619           0 :   if( hdr_rc == FD_QUIC_PARSE_FAIL ) {
     620           0 :     sz = safe_snprintf( out_buf, out_buf_sz, "\"err\": \"parse_fail\" } " );
     621           0 :     out_buf    += sz;
     622           0 :     out_buf_sz -= sz;
     623             : 
     624           0 :     return FD_QUIC_PARSE_FAIL;
     625           0 :   }
     626             : 
     627           0 :   sz = safe_snprintf( out_buf, out_buf_sz, "\"frames\": [ " );
     628           0 :   out_buf    += sz;
     629           0 :   out_buf_sz -= sz;
     630             : 
     631           0 :   ulong rc = fd_quic_pretty_print_frames( &out_buf,
     632           0 :                                           &out_buf_sz,
     633           0 :                                           frame_ptr,
     634           0 :                                           frame_sz );
     635           0 :   if( rc == FD_QUIC_PARSE_FAIL ) {
     636           0 :     sz = safe_snprintf( out_buf, out_buf_sz, "], \"err\": \"parse_fail\" }, " );
     637           0 :     out_buf    += sz;
     638           0 :     out_buf_sz -= sz;
     639           0 :     printf( "\n[ %s ]\n", pretty_print_buf );
     640           0 :     fflush( stdout );
     641           0 :     return FD_QUIC_PARSE_FAIL;
     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 :   for( ulong j = 0; j < (ulong)( out_buf - pretty_print_buf); ++j ) {
     649           0 :     if( pretty_print_buf[j] == '\0' ) pretty_print_buf[j] = '*';
     650           0 :   }
     651             : 
     652           0 :   printf( "[ %s ]\n", pretty_print_buf );
     653             : 
     654           0 :   return rc;
     655           0 : }
     656             : 
     657             : ulong
     658             : fd_quic_pretty_print_frames( char **           out_buf,
     659             :                              ulong *           out_buf_sz,
     660             :                              uchar const *     buf,
     661           0 :                              ulong             buf_sz ) {
     662           0 :   uchar const * orig_buf = buf;
     663           0 :   ulong sz;
     664             : 
     665           0 :   while( buf_sz > 0 ) {
     666           0 :     sz          = safe_snprintf( *out_buf, *out_buf_sz, "{ \"type\": \"frame\", " );
     667           0 :     *out_buf    += sz;
     668           0 :     *out_buf_sz -= sz;
     669             : 
     670           0 :     ulong rc = fd_quic_pretty_print_frame( out_buf, out_buf_sz, buf, buf_sz );
     671           0 :     if( rc == FD_QUIC_PARSE_FAIL ) {
     672           0 :       sz          = safe_snprintf( *out_buf, *out_buf_sz, "\"err\": \"parse_fail\" }, " );
     673           0 :       *out_buf    += sz;
     674           0 :       *out_buf_sz -= sz;
     675           0 :       break;
     676           0 :     }
     677             : 
     678           0 :     sz          = safe_snprintf( *out_buf, *out_buf_sz, " }, " );
     679           0 :     *out_buf    += sz;
     680           0 :     *out_buf_sz -= sz;
     681             : 
     682           0 :     if( rc >= buf_sz ) break;
     683             : 
     684           0 :     buf    += rc;
     685           0 :     buf_sz -= rc;
     686           0 :   }
     687             : 
     688           0 :   return (ulong)( buf - orig_buf );
     689           0 : }

Generated by: LCOV version 1.14