/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 |