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
127
Encoder::Encoder() = default;
16

            
17
73
void Encoder::newFrame(uint8_t flags, uint64_t length, std::array<uint8_t, 5>& output) {
18
73
  output[0] = flags;
19
73
  absl::big_endian::Store32(&output[1], length);
20
73
}
21

            
22
47
void Encoder::prependFrameHeader(uint8_t flags, Buffer::Instance& buffer) {
23
47
  prependFrameHeader(flags, buffer, buffer.length());
24
47
}
25

            
26
59
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
59
  std::array<uint8_t, Grpc::GRPC_FRAME_HEADER_SIZE> frame;
29
59
  Grpc::Encoder().newFrame(flags, message_length, frame);
30
59
  Buffer::OwnedImpl frame_buffer(frame.data(), frame.size());
31
59
  buffer.prepend(frame_buffer);
32
59
}
33

            
34
287898
absl::Status Decoder::decode(Buffer::Instance& input, std::vector<Frame>& output) {
35
  // Make sure those flags are set to initial state.
36
287898
  decoding_error_ = false;
37
287898
  is_frame_oversized_ = false;
38
287898
  output_ = &output;
39
287898
  inspect(input);
40
287898
  output_ = nullptr;
41

            
42
287898
  if (decoding_error_) {
43
8
    return absl::InternalError("Grpc decoding error");
44
8
  }
45

            
46
287890
  if (is_frame_oversized_) {
47
6
    return absl::ResourceExhaustedError("Grpc frame length exceeds limit");
48
6
  }
49

            
50
287884
  input.drain(input.length());
51
287884
  return absl::OkStatus();
52
287890
}
53

            
54
228112
bool Decoder::frameStart(uint8_t flags) {
55
  // Unsupported flags.
56
228112
  if (flags & ~GRPC_FH_COMPRESSED) {
57
8
    decoding_error_ = true;
58
8
    return false;
59
8
  }
60
228104
  frame_.flags_ = flags;
61
228104
  return true;
62
228112
}
63

            
64
228099
void Decoder::frameDataStart() {
65
228099
  frame_.length_ = length_;
66
228099
  frame_.data_ = std::make_unique<Buffer::OwnedImpl>();
67
228099
}
68

            
69
387561
void Decoder::frameData(uint8_t* mem, uint64_t length) { frame_.data_->add(mem, length); }
70

            
71
228098
void Decoder::frameDataEnd() {
72
228098
  output_->push_back(std::move(frame_));
73
228098
  frame_.flags_ = 0;
74
228098
  frame_.length_ = 0;
75
228098
  frame_.data_ = nullptr;
76
228098
}
77

            
78
287920
uint64_t FrameInspector::inspect(const Buffer::Instance& data) {
79
287920
  uint64_t delta = 0;
80
466823
  for (const Buffer::RawSlice& slice : data.getRawSlices()) {
81
466823
    uint8_t* mem = reinterpret_cast<uint8_t*>(slice.mem_);
82
466823
    uint8_t* end = mem + slice.len_;
83
1995026
    while (mem < end) {
84
1528218
      uint8_t c = *mem;
85
1528218
      switch (state_) {
86
228136
      case State::FhFlag:
87
228136
        if (!frameStart(c)) {
88
9
          return delta;
89
9
        }
90
228127
        count_ += 1;
91
228127
        delta += 1;
92
228127
        state_ = State::FhLen0;
93
228127
        mem++;
94
228127
        break;
95
228125
      case State::FhLen0:
96
228125
        length_as_bytes_[0] = c;
97
228125
        state_ = State::FhLen1;
98
228125
        mem++;
99
228125
        break;
100
228125
      case State::FhLen1:
101
228125
        length_as_bytes_[1] = c;
102
228125
        state_ = State::FhLen2;
103
228125
        mem++;
104
228125
        break;
105
228125
      case State::FhLen2:
106
228125
        length_as_bytes_[2] = c;
107
228125
        state_ = State::FhLen3;
108
228125
        mem++;
109
228125
        break;
110
228126
      case State::FhLen3:
111
228126
        length_as_bytes_[3] = c;
112
228126
        length_ = absl::big_endian::Load32(length_as_bytes_);
113
        // Compares the frame length against maximum length when `max_frame_length_` is configured,
114
228126
        if (max_frame_length_ != 0 && length_ > max_frame_length_) {
115
          // Set the flag to indicate the over-limit error and return.
116
6
          is_frame_oversized_ = true;
117
6
          return delta;
118
6
        }
119
228120
        frameDataStart();
120
228120
        if (length_ == 0) {
121
48
          frameDataEnd();
122
48
          state_ = State::FhFlag;
123
228072
        } else {
124
228072
          state_ = State::Data;
125
228072
        }
126
228120
        mem++;
127
228120
        break;
128
387581
      case State::Data:
129
387581
        uint64_t remain_in_buffer = end - mem;
130
387581
        if (remain_in_buffer <= length_) {
131
376572
          frameData(mem, remain_in_buffer);
132
376572
          mem += remain_in_buffer;
133
376572
          length_ -= remain_in_buffer;
134
377581
        } else {
135
11009
          frameData(mem, length_);
136
11009
          mem += length_;
137
11009
          length_ = 0;
138
11009
        }
139
387581
        if (length_ == 0) {
140
228071
          frameDataEnd();
141
228071
          state_ = State::FhFlag;
142
228071
        }
143
387581
        break;
144
1528218
      }
145
1528218
    }
146
466823
  }
147
287905
  return delta;
148
287920
}
149

            
150
} // namespace Grpc
151
} // namespace Envoy