Coverage Report

Created: 2023-11-12 09:30

/proc/self/cwd/source/common/grpc/codec.cc
Line
Count
Source (jump to first uncovered line)
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
1.14k
Encoder::Encoder() = default;
16
17
1.12k
void Encoder::newFrame(uint8_t flags, uint64_t length, std::array<uint8_t, 5>& output) {
18
1.12k
  output[0] = flags;
19
1.12k
  absl::big_endian::Store32(&output[1], length);
20
1.12k
}
21
22
0
void Encoder::prependFrameHeader(uint8_t flags, Buffer::Instance& buffer) {
23
0
  prependFrameHeader(flags, buffer, buffer.length());
24
0
}
25
26
14
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
14
  std::array<uint8_t, Grpc::GRPC_FRAME_HEADER_SIZE> frame;
29
14
  Grpc::Encoder().newFrame(flags, message_length, frame);
30
14
  Buffer::OwnedImpl frame_buffer(frame.data(), frame.size());
31
14
  buffer.prepend(frame_buffer);
32
14
}
33
34
17.5k
bool Decoder::decode(Buffer::Instance& input, std::vector<Frame>& output) {
35
17.5k
  decoding_error_ = false;
36
17.5k
  output_ = &output;
37
17.5k
  inspect(input);
38
17.5k
  output_ = nullptr;
39
17.5k
  if (decoding_error_) {
40
725
    return false;
41
725
  }
42
16.7k
  input.drain(input.length());
43
16.7k
  return true;
44
17.5k
}
45
46
47.0k
bool Decoder::frameStart(uint8_t flags) {
47
  // Unsupported flags.
48
47.0k
  if (flags & ~GRPC_FH_COMPRESSED) {
49
725
    decoding_error_ = true;
50
725
    return false;
51
725
  }
52
46.3k
  frame_.flags_ = flags;
53
46.3k
  return true;
54
47.0k
}
55
56
46.0k
void Decoder::frameDataStart() {
57
46.0k
  frame_.length_ = length_;
58
46.0k
  frame_.data_ = std::make_unique<Buffer::OwnedImpl>();
59
46.0k
}
60
61
10.8k
void Decoder::frameData(uint8_t* mem, uint64_t length) { frame_.data_->add(mem, length); }
62
63
45.3k
void Decoder::frameDataEnd() {
64
45.3k
  output_->push_back(std::move(frame_));
65
45.3k
  frame_.flags_ = 0;
66
45.3k
  frame_.length_ = 0;
67
45.3k
  frame_.data_ = nullptr;
68
45.3k
}
69
70
29.1k
uint64_t FrameInspector::inspect(const Buffer::Instance& data) {
71
29.1k
  uint64_t delta = 0;
72
29.1k
  for (const Buffer::RawSlice& slice : data.getRawSlices()) {
73
25.9k
    uint8_t* mem = reinterpret_cast<uint8_t*>(slice.mem_);
74
25.9k
    uint8_t* end = mem + slice.len_;
75
280k
    while (mem < end) {
76
255k
      uint8_t c = *mem;
77
255k
      switch (state_) {
78
47.9k
      case State::FhFlag:
79
47.9k
        if (!frameStart(c)) {
80
822
          return delta;
81
822
        }
82
47.1k
        count_ += 1;
83
47.1k
        delta += 1;
84
47.1k
        state_ = State::FhLen0;
85
47.1k
        mem++;
86
47.1k
        break;
87
46.9k
      case State::FhLen0:
88
46.9k
        length_as_bytes_[0] = c;
89
46.9k
        state_ = State::FhLen1;
90
46.9k
        mem++;
91
46.9k
        break;
92
46.9k
      case State::FhLen1:
93
46.9k
        length_as_bytes_[1] = c;
94
46.9k
        state_ = State::FhLen2;
95
46.9k
        mem++;
96
46.9k
        break;
97
46.8k
      case State::FhLen2:
98
46.8k
        length_as_bytes_[2] = c;
99
46.8k
        state_ = State::FhLen3;
100
46.8k
        mem++;
101
46.8k
        break;
102
46.7k
      case State::FhLen3:
103
46.7k
        length_as_bytes_[3] = c;
104
46.7k
        length_ = absl::big_endian::Load32(length_as_bytes_);
105
46.7k
        frameDataStart();
106
46.7k
        if (length_ == 0) {
107
41.3k
          frameDataEnd();
108
41.3k
          state_ = State::FhFlag;
109
41.3k
        } else {
110
5.41k
          state_ = State::Data;
111
5.41k
        }
112
46.7k
        mem++;
113
46.7k
        break;
114
20.0k
      case State::Data:
115
20.0k
        uint64_t remain_in_buffer = end - mem;
116
20.0k
        if (remain_in_buffer <= length_) {
117
18.3k
          frameData(mem, remain_in_buffer);
118
18.3k
          mem += remain_in_buffer;
119
18.3k
          length_ -= remain_in_buffer;
120
18.3k
        } else {
121
1.70k
          frameData(mem, length_);
122
1.70k
          mem += length_;
123
1.70k
          length_ = 0;
124
1.70k
        }
125
20.0k
        if (length_ == 0) {
126
4.69k
          frameDataEnd();
127
4.69k
          state_ = State::FhFlag;
128
4.69k
        }
129
20.0k
        break;
130
255k
      }
131
255k
    }
132
25.9k
  }
133
28.3k
  return delta;
134
29.1k
}
135
136
} // namespace Grpc
137
} // namespace Envoy