LCOV - code coverage report
Current view: top level - waltz/grpc - fd_grpc_codec.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 38 87 43.7 %
Date: 2025-07-01 05:00:49 Functions: 3 5 60.0 %

          Line data    Source code
       1             : #include "fd_grpc_codec.h"
       2             : #include "../h2/fd_hpack.h"
       3             : #include "../h2/fd_hpack_wr.h"
       4             : 
       5             : static int
       6           6 : fd_hpack_wr_content_type_grpc( fd_h2_rbuf_t * rbuf_tx ) {
       7           6 :   static char const code[] =
       8           6 :     "\x5f" "\x16" "application/grpc+proto";
       9           6 :   if( FD_UNLIKELY( fd_h2_rbuf_free_sz( rbuf_tx)<sizeof(code)-1 ) ) return 0;
      10           6 :   fd_h2_rbuf_push( rbuf_tx, code, sizeof(code)-1 );
      11           6 :   return 1;
      12           6 : }
      13             : 
      14             : int
      15             : fd_grpc_h2_gen_request_hdrs( fd_grpc_req_hdrs_t const * req,
      16             :                              fd_h2_rbuf_t *             rbuf_tx,
      17             :                              char const *               version,
      18           6 :                              ulong                      version_len ) {
      19           6 :   if( FD_UNLIKELY( !fd_hpack_wr_method_post( rbuf_tx ) ) ) return 0;
      20           6 :   if( FD_UNLIKELY( !fd_hpack_wr_scheme( rbuf_tx, 1 ) ) ) return 0;
      21           6 :   if( FD_UNLIKELY( !fd_hpack_wr_path( rbuf_tx, req->path, req->path_len ) ) ) return 0;
      22           6 :   if( FD_UNLIKELY( !fd_hpack_wr_authority( rbuf_tx, req->host, req->host_len, req->port ) ) ) return 0;
      23           6 :   if( FD_UNLIKELY( !fd_hpack_wr_trailers( rbuf_tx ) ) ) return 0;
      24           6 :   if( FD_UNLIKELY( !fd_hpack_wr_content_type_grpc( rbuf_tx ) ) ) return 0;
      25             : 
      26           6 :   static char const user_agent[] = "grpc-firedancer/";
      27           6 :   ulong const user_agent_len = sizeof(user_agent)-1 + version_len;
      28           6 :   if( FD_UNLIKELY( !fd_hpack_wr_user_agent( rbuf_tx, user_agent_len ) ) ) return 0;
      29           6 :   fd_h2_rbuf_push( rbuf_tx, user_agent, sizeof(user_agent)-1 );
      30           6 :   fd_h2_rbuf_push( rbuf_tx, version,    version_len          );
      31             : 
      32           6 :   if( req->bearer_auth_len ) {
      33           3 :     if( FD_UNLIKELY( !fd_hpack_wr_auth_bearer( rbuf_tx, req->bearer_auth, req->bearer_auth_len ) ) ) return 0;
      34           3 :   }
      35           6 :   return 1;
      36           6 : }
      37             : 
      38             : /* fd_grpc_h2_parse_num parses a decimal number in [1,999]. */
      39             : 
      40             : static uint
      41             : fd_grpc_h2_parse_num( char const * num,
      42           0 :                       ulong        num_len ) {
      43           0 :   num_len = fd_ulong_min( num_len, 10 );
      44           0 :   char num_cstr[ 11 ];
      45           0 :   fd_cstr_fini( fd_cstr_append_text( fd_cstr_init( num_cstr ), num, num_len ) );
      46           0 :   return fd_cstr_to_uint( num_cstr );
      47           0 : }
      48             : 
      49             : int
      50             : fd_grpc_h2_read_response_hdrs( fd_grpc_resp_hdrs_t *       resp,
      51             :                                fd_h2_hdr_matcher_t const * matcher,
      52             :                                uchar const *               payload,
      53          18 :                                ulong                       payload_sz ) {
      54          18 :   fd_hpack_rd_t hpack_rd[1];
      55          18 :   fd_hpack_rd_init( hpack_rd, payload, payload_sz );
      56          18 :   while( !fd_hpack_rd_done( hpack_rd ) )  {
      57           3 :     static FD_TL uchar scratch_buf[ 4096 ];
      58           3 :     uchar * scratch = scratch_buf;
      59           3 :     fd_h2_hdr_t hdr[1];
      60           3 :     uint err = fd_hpack_rd_next( hpack_rd, hdr, &scratch, scratch_buf+sizeof(scratch_buf) );
      61           3 :     if( FD_UNLIKELY( err ) ) {
      62           3 :       FD_LOG_WARNING(( "Failed to parse response headers (%u-%s)", err, fd_h2_strerror( err ) ));
      63           3 :       return FD_H2_ERR_PROTOCOL;
      64           3 :     }
      65             : 
      66           0 :     int hdr_idx = fd_h2_hdr_match( matcher, hdr->name, hdr->name_len, hdr->hint );
      67           0 :     switch( hdr_idx ) {
      68           0 :     case FD_H2_HDR_STATUS:
      69           0 :       resp->h2_status = fd_grpc_h2_parse_num( hdr->value, hdr->value_len );
      70           0 :       break;
      71           0 :     case FD_H2_HDR_CONTENT_TYPE:
      72           0 :       resp->is_grpc_proto =
      73           0 :         ( 0==strncmp( hdr->value, "application/grpc",       hdr->value_len ) ||
      74           0 :           0==strncmp( hdr->value, "application/grpc+proto", hdr->value_len ) );
      75           0 :       break;
      76           0 :     case FD_GRPC_HDR_STATUS:
      77           0 :       resp->grpc_status = fd_grpc_h2_parse_num( hdr->value, hdr->value_len );
      78           0 :       break;
      79           0 :     case FD_GRPC_HDR_MESSAGE:
      80           0 :       resp->grpc_msg_len = (uint)fd_ulong_min( hdr->value_len, sizeof(resp->grpc_msg) );
      81           0 :       if( resp->grpc_msg_len ) {
      82           0 :         fd_memcpy( resp->grpc_msg, hdr->value, resp->grpc_msg_len );
      83           0 :       }
      84           0 :       break;
      85           0 :     }
      86           0 :   }
      87          15 :   return FD_H2_SUCCESS;
      88          18 : }
      89             : 
      90             : char const *
      91           0 : fd_grpc_status_cstr( uint status ) {
      92           0 :   switch( status ) {
      93           0 :   case FD_GRPC_STATUS_OK:                   return "ok";
      94           0 :   case FD_GRPC_STATUS_CANCELLED:            return "cancelled";
      95           0 :   case FD_GRPC_STATUS_UNKNOWN:              return "unknown";
      96           0 :   case FD_GRPC_STATUS_INVALID_ARGUMENT:     return "invalid argument";
      97           0 :   case FD_GRPC_STATUS_DEADLINE_EXCEEDED:    return "deadline exceeded";
      98           0 :   case FD_GRPC_STATUS_NOT_FOUND:            return "not found";
      99           0 :   case FD_GRPC_STATUS_ALREADY_EXISTS:       return "already exists";
     100           0 :   case FD_GRPC_STATUS_PERMISSION_DENIED:    return "permission denied";
     101           0 :   case FD_GRPC_STATUS_RESOURCE_EXHAUSTED:   return "resource exhausted";
     102           0 :   case FD_GRPC_STATUS_FAILED_PRECONDITION:  return "failed precondition";
     103           0 :   case FD_GRPC_STATUS_ABORTED:              return "aborted";
     104           0 :   case FD_GRPC_STATUS_OUT_OF_RANGE:         return "out of range";
     105           0 :   case FD_GRPC_STATUS_UNIMPLEMENTED:        return "unimplemented";
     106           0 :   case FD_GRPC_STATUS_INTERNAL:             return "internal";
     107           0 :   case FD_GRPC_STATUS_UNAVAILABLE:          return "unavailable";
     108           0 :   case FD_GRPC_STATUS_DATA_LOSS:            return "data loss";
     109           0 :   case FD_GRPC_STATUS_UNAUTHENTICATED:      return "unauthenticated";
     110           0 :   default:                                  return "unknown";
     111           0 :   }
     112           0 : }

Generated by: LCOV version 1.14