LCOV - code coverage report
Current view: top level - source/common/grpc - codec.cc (source / functions) Hit Total Coverage
Test: coverage.dat Lines: 100 109 91.7 %
Date: 2024-01-05 06:35:25 Functions: 8 10 80.0 %

          Line data    Source code
       1             : #include "source/common/grpc/codec.h"
       2             : 
       3             : #include <array>
       4             : #include <cstdint>
       5             : #include <memory>
       6             : #include <vector>
       7             : 
       8             : #include "source/common/buffer/buffer_impl.h"
       9             : 
      10             : #include "absl/container/fixed_array.h"
      11             : 
      12             : namespace Envoy {
      13             : namespace Grpc {
      14             : 
      15         328 : Encoder::Encoder() = default;
      16             : 
      17         328 : void Encoder::newFrame(uint8_t flags, uint64_t length, std::array<uint8_t, 5>& output) {
      18         328 :   output[0] = flags;
      19         328 :   absl::big_endian::Store32(&output[1], length);
      20         328 : }
      21             : 
      22           0 : void Encoder::prependFrameHeader(uint8_t flags, Buffer::Instance& buffer) {
      23           0 :   prependFrameHeader(flags, buffer, buffer.length());
      24           0 : }
      25             : 
      26           0 : void Encoder::prependFrameHeader(uint8_t flags, Buffer::Instance& buffer, uint32_t message_length) {
      27             :   // Compute the size of the payload and construct the length prefix.
      28           0 :   std::array<uint8_t, Grpc::GRPC_FRAME_HEADER_SIZE> frame;
      29           0 :   Grpc::Encoder().newFrame(flags, message_length, frame);
      30           0 :   Buffer::OwnedImpl frame_buffer(frame.data(), frame.size());
      31           0 :   buffer.prepend(frame_buffer);
      32           0 : }
      33             : 
      34        4953 : bool Decoder::decode(Buffer::Instance& input, std::vector<Frame>& output) {
      35        4953 :   decoding_error_ = false;
      36        4953 :   output_ = &output;
      37        4953 :   inspect(input);
      38        4953 :   output_ = nullptr;
      39        4953 :   if (decoding_error_) {
      40          89 :     return false;
      41          89 :   }
      42        4864 :   input.drain(input.length());
      43        4864 :   return true;
      44        4953 : }
      45             : 
      46        1653 : bool Decoder::frameStart(uint8_t flags) {
      47             :   // Unsupported flags.
      48        1653 :   if (flags & ~GRPC_FH_COMPRESSED) {
      49          89 :     decoding_error_ = true;
      50          89 :     return false;
      51          89 :   }
      52        1564 :   frame_.flags_ = flags;
      53        1564 :   return true;
      54        1653 : }
      55             : 
      56        1481 : void Decoder::frameDataStart() {
      57        1481 :   frame_.length_ = length_;
      58        1481 :   frame_.data_ = std::make_unique<Buffer::OwnedImpl>();
      59        1481 : }
      60             : 
      61         952 : void Decoder::frameData(uint8_t* mem, uint64_t length) { frame_.data_->add(mem, length); }
      62             : 
      63        1451 : void Decoder::frameDataEnd() {
      64        1451 :   output_->push_back(std::move(frame_));
      65        1451 :   frame_.flags_ = 0;
      66        1451 :   frame_.length_ = 0;
      67        1451 :   frame_.data_ = nullptr;
      68        1451 : }
      69             : 
      70        4957 : uint64_t FrameInspector::inspect(const Buffer::Instance& data) {
      71        4957 :   uint64_t delta = 0;
      72        4967 :   for (const Buffer::RawSlice& slice : data.getRawSlices()) {
      73        1168 :     uint8_t* mem = reinterpret_cast<uint8_t*>(slice.mem_);
      74        1168 :     uint8_t* end = mem + slice.len_;
      75        9685 :     while (mem < end) {
      76        8606 :       uint8_t c = *mem;
      77        8606 :       switch (state_) {
      78        1654 :       case State::FhFlag:
      79        1654 :         if (!frameStart(c)) {
      80          89 :           return delta;
      81          89 :         }
      82        1565 :         count_ += 1;
      83        1565 :         delta += 1;
      84        1565 :         state_ = State::FhLen0;
      85        1565 :         mem++;
      86        1565 :         break;
      87        1523 :       case State::FhLen0:
      88        1523 :         length_as_bytes_[0] = c;
      89        1523 :         state_ = State::FhLen1;
      90        1523 :         mem++;
      91        1523 :         break;
      92        1502 :       case State::FhLen1:
      93        1502 :         length_as_bytes_[1] = c;
      94        1502 :         state_ = State::FhLen2;
      95        1502 :         mem++;
      96        1502 :         break;
      97        1490 :       case State::FhLen2:
      98        1490 :         length_as_bytes_[2] = c;
      99        1490 :         state_ = State::FhLen3;
     100        1490 :         mem++;
     101        1490 :         break;
     102        1482 :       case State::FhLen3:
     103        1482 :         length_as_bytes_[3] = c;
     104        1482 :         length_ = absl::big_endian::Load32(length_as_bytes_);
     105        1482 :         frameDataStart();
     106        1482 :         if (length_ == 0) {
     107         637 :           frameDataEnd();
     108         637 :           state_ = State::FhFlag;
     109        1243 :         } else {
     110         845 :           state_ = State::Data;
     111         845 :         }
     112        1482 :         mem++;
     113        1482 :         break;
     114         955 :       case State::Data:
     115         955 :         uint64_t remain_in_buffer = end - mem;
     116         955 :         if (remain_in_buffer <= length_) {
     117         697 :           frameData(mem, remain_in_buffer);
     118         697 :           mem += remain_in_buffer;
     119         697 :           length_ -= remain_in_buffer;
     120         697 :         } else {
     121         258 :           frameData(mem, length_);
     122         258 :           mem += length_;
     123         258 :           length_ = 0;
     124         258 :         }
     125         955 :         if (length_ == 0) {
     126         814 :           frameDataEnd();
     127         814 :           state_ = State::FhFlag;
     128         814 :         }
     129         955 :         break;
     130        8606 :       }
     131        8606 :     }
     132        1168 :   }
     133        4868 :   return delta;
     134        4957 : }
     135             : 
     136             : } // namespace Grpc
     137             : } // namespace Envoy

Generated by: LCOV version 1.15