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