grpc 1.55.0 → 1.55.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Makefile +4 -2
- data/src/core/ext/filters/client_channel/client_channel.cc +4 -6
- data/src/core/ext/filters/client_channel/client_channel.h +2 -0
- data/src/core/ext/transport/chttp2/transport/hpack_parse_result.cc +176 -0
- data/src/core/ext/transport/chttp2/transport/hpack_parse_result.h +325 -0
- data/src/core/ext/transport/chttp2/transport/hpack_parser.cc +567 -543
- data/src/core/ext/transport/chttp2/transport/hpack_parser.h +150 -9
- data/src/core/ext/transport/chttp2/transport/hpack_parser_table.cc +46 -32
- data/src/core/ext/transport/chttp2/transport/hpack_parser_table.h +18 -5
- data/src/core/ext/transport/chttp2/transport/parsing.cc +12 -12
- data/src/core/lib/backoff/random_early_detection.h +5 -0
- data/src/core/lib/event_engine/posix_engine/posix_engine.cc +30 -17
- data/src/core/lib/event_engine/posix_engine/posix_engine.h +1 -0
- data/src/core/lib/event_engine/posix_engine/posix_engine_listener.cc +29 -0
- data/src/core/lib/event_engine/posix_engine/posix_engine_listener.h +3 -0
- data/src/core/lib/iomgr/tcp_server_posix.cc +39 -14
- data/src/core/lib/iomgr/tcp_server_utils_posix.h +12 -0
- data/src/core/lib/iomgr/tcp_server_utils_posix_common.cc +21 -0
- data/src/core/lib/surface/validate_metadata.cc +37 -22
- data/src/core/lib/surface/validate_metadata.h +13 -3
- data/src/ruby/lib/grpc/version.rb +1 -1
- metadata +5 -3
@@ -21,16 +21,28 @@
|
|
21
21
|
|
22
22
|
#include <grpc/support/port_platform.h>
|
23
23
|
|
24
|
+
#include <stddef.h>
|
24
25
|
#include <stdint.h>
|
25
26
|
|
27
|
+
#include <string>
|
28
|
+
#include <utility>
|
26
29
|
#include <vector>
|
27
30
|
|
31
|
+
#include "absl/strings/str_cat.h"
|
32
|
+
#include "absl/strings/string_view.h"
|
33
|
+
#include "absl/types/optional.h"
|
34
|
+
#include "absl/types/span.h"
|
35
|
+
#include "absl/types/variant.h"
|
36
|
+
|
28
37
|
#include <grpc/slice.h>
|
29
38
|
|
30
39
|
#include "src/core/ext/transport/chttp2/transport/frame.h"
|
40
|
+
#include "src/core/ext/transport/chttp2/transport/hpack_parse_result.h"
|
31
41
|
#include "src/core/ext/transport/chttp2/transport/hpack_parser_table.h"
|
32
42
|
#include "src/core/lib/backoff/random_early_detection.h"
|
33
43
|
#include "src/core/lib/iomgr/error.h"
|
44
|
+
#include "src/core/lib/slice/slice.h"
|
45
|
+
#include "src/core/lib/slice/slice_refcount.h"
|
34
46
|
#include "src/core/lib/transport/metadata_batch.h"
|
35
47
|
|
36
48
|
// IWYU pragma: no_include <type_traits>
|
@@ -92,17 +104,150 @@ class HPackParser {
|
|
92
104
|
void FinishFrame();
|
93
105
|
|
94
106
|
// Retrieve the associated hpack table (for tests, debugging)
|
95
|
-
HPackTable* hpack_table() { return &
|
107
|
+
HPackTable* hpack_table() { return &state_.hpack_table; }
|
96
108
|
// Is the current frame a boundary of some sort
|
97
109
|
bool is_boundary() const { return boundary_ != Boundary::None; }
|
98
110
|
// Is the current frame the end of a stream
|
99
111
|
bool is_eof() const { return boundary_ == Boundary::EndOfStream; }
|
100
112
|
|
113
|
+
// How many bytes are buffered (for tests to assert on)
|
114
|
+
size_t buffered_bytes() const { return unparsed_bytes_.size(); }
|
115
|
+
|
101
116
|
private:
|
102
117
|
// Helper classes: see implementation
|
103
118
|
class Parser;
|
104
119
|
class Input;
|
105
|
-
|
120
|
+
|
121
|
+
// Helper to parse a string and turn it into a slice with appropriate memory
|
122
|
+
// management characteristics
|
123
|
+
class String {
|
124
|
+
public:
|
125
|
+
// StringResult carries both a HpackParseStatus and the parsed string
|
126
|
+
struct StringResult;
|
127
|
+
|
128
|
+
String() : value_(absl::Span<const uint8_t>()) {}
|
129
|
+
String(const String&) = delete;
|
130
|
+
String& operator=(const String&) = delete;
|
131
|
+
String(String&& other) noexcept : value_(std::move(other.value_)) {
|
132
|
+
other.value_ = absl::Span<const uint8_t>();
|
133
|
+
}
|
134
|
+
String& operator=(String&& other) noexcept {
|
135
|
+
value_ = std::move(other.value_);
|
136
|
+
other.value_ = absl::Span<const uint8_t>();
|
137
|
+
return *this;
|
138
|
+
}
|
139
|
+
|
140
|
+
// Take the value and leave this empty
|
141
|
+
Slice Take();
|
142
|
+
|
143
|
+
// Return a reference to the value as a string view
|
144
|
+
absl::string_view string_view() const;
|
145
|
+
|
146
|
+
// Parse a non-binary string
|
147
|
+
static StringResult Parse(Input* input, bool is_huff, size_t length);
|
148
|
+
|
149
|
+
// Parse a binary string
|
150
|
+
static StringResult ParseBinary(Input* input, bool is_huff, size_t length);
|
151
|
+
|
152
|
+
private:
|
153
|
+
void AppendBytes(const uint8_t* data, size_t length);
|
154
|
+
explicit String(std::vector<uint8_t> v) : value_(std::move(v)) {}
|
155
|
+
explicit String(absl::Span<const uint8_t> v) : value_(v) {}
|
156
|
+
String(grpc_slice_refcount* r, const uint8_t* begin, const uint8_t* end)
|
157
|
+
: value_(Slice::FromRefcountAndBytes(r, begin, end)) {}
|
158
|
+
|
159
|
+
// Parse some huffman encoded bytes, using output(uint8_t b) to emit each
|
160
|
+
// decoded byte.
|
161
|
+
template <typename Out>
|
162
|
+
static HpackParseStatus ParseHuff(Input* input, uint32_t length,
|
163
|
+
Out output);
|
164
|
+
|
165
|
+
// Parse some uncompressed string bytes.
|
166
|
+
static StringResult ParseUncompressed(Input* input, uint32_t length,
|
167
|
+
uint32_t wire_size);
|
168
|
+
|
169
|
+
// Turn base64 encoded bytes into not base64 encoded bytes.
|
170
|
+
static StringResult Unbase64(String s);
|
171
|
+
|
172
|
+
// Main loop for Unbase64
|
173
|
+
static absl::optional<std::vector<uint8_t>> Unbase64Loop(
|
174
|
+
const uint8_t* cur, const uint8_t* end);
|
175
|
+
|
176
|
+
absl::variant<Slice, absl::Span<const uint8_t>, std::vector<uint8_t>>
|
177
|
+
value_;
|
178
|
+
};
|
179
|
+
|
180
|
+
// Prefix for a string
|
181
|
+
struct StringPrefix {
|
182
|
+
// Number of bytes in input for string
|
183
|
+
uint32_t length;
|
184
|
+
// Is it huffman compressed
|
185
|
+
bool huff;
|
186
|
+
|
187
|
+
std::string ToString() const {
|
188
|
+
return absl::StrCat(length, " bytes ",
|
189
|
+
huff ? "huffman compressed" : "uncompressed");
|
190
|
+
}
|
191
|
+
};
|
192
|
+
|
193
|
+
// Current parse state
|
194
|
+
// ┌───┐
|
195
|
+
// │Top│
|
196
|
+
// └┬─┬┘
|
197
|
+
// │┌▽────────────────┐
|
198
|
+
// ││ParsingKeyLength │
|
199
|
+
// │└┬───────────────┬┘
|
200
|
+
// │┌▽─────────────┐┌▽──────────────┐
|
201
|
+
// ││ParsingKeyBody││SkippingKeyBody│
|
202
|
+
// │└┬─────────────┘└───┬───────────┘
|
203
|
+
// ┌▽─▽────────────────┐┌▽──────────────────┐
|
204
|
+
// │ParsingValueLength ││SkippingValueLength│
|
205
|
+
// └┬─────────────────┬┘└┬──────────────────┘
|
206
|
+
// ┌▽───────────────┐┌▽──▽─────────────┐
|
207
|
+
// │ParsingValueBody││SkippingValueBody│
|
208
|
+
// └────────────────┘└─────────────────┘
|
209
|
+
enum class ParseState : uint8_t {
|
210
|
+
// Start of one opcode
|
211
|
+
kTop,
|
212
|
+
// Parsing a literal keys length
|
213
|
+
kParsingKeyLength,
|
214
|
+
// Parsing a literal key
|
215
|
+
kParsingKeyBody,
|
216
|
+
// Skipping a literal key
|
217
|
+
kSkippingKeyBody,
|
218
|
+
// Parsing a literal value length
|
219
|
+
kParsingValueLength,
|
220
|
+
// Parsing a literal value
|
221
|
+
kParsingValueBody,
|
222
|
+
// Reading a literal value length (so we can skip it)
|
223
|
+
kSkippingValueLength,
|
224
|
+
// Skipping a literal value
|
225
|
+
kSkippingValueBody,
|
226
|
+
};
|
227
|
+
|
228
|
+
// Shared state for Parser instances between slices.
|
229
|
+
struct InterSliceState {
|
230
|
+
HPackTable hpack_table;
|
231
|
+
// Error so far for this frame (set by class Input)
|
232
|
+
HpackParseResult frame_error;
|
233
|
+
// Length of frame so far.
|
234
|
+
uint32_t frame_length = 0;
|
235
|
+
// Length of the string being parsed
|
236
|
+
uint32_t string_length;
|
237
|
+
// How many more dynamic table updates are allowed
|
238
|
+
uint8_t dynamic_table_updates_allowed;
|
239
|
+
// Current parse state
|
240
|
+
ParseState parse_state = ParseState::kTop;
|
241
|
+
// RED for overly large metadata sets
|
242
|
+
RandomEarlyDetection metadata_early_detection;
|
243
|
+
// Should the current header be added to the hpack table?
|
244
|
+
bool add_to_table;
|
245
|
+
// Is the string being parsed huffman compressed?
|
246
|
+
bool is_string_huff_compressed;
|
247
|
+
// Is the value being parsed binary?
|
248
|
+
bool is_binary_header;
|
249
|
+
absl::variant<const HPackTable::Memento*, Slice> key;
|
250
|
+
};
|
106
251
|
|
107
252
|
grpc_error_handle ParseInput(Input input, bool is_last);
|
108
253
|
void ParseInputInner(Input* input);
|
@@ -114,6 +259,8 @@ class HPackParser {
|
|
114
259
|
|
115
260
|
// Bytes that could not be parsed last parsing round
|
116
261
|
std::vector<uint8_t> unparsed_bytes_;
|
262
|
+
// How many bytes would be needed before progress could be made?
|
263
|
+
size_t min_progress_size_ = 0;
|
117
264
|
// Buffer kind of boundary
|
118
265
|
// TODO(ctiller): see if we can move this argument to Parse, and avoid
|
119
266
|
// buffering.
|
@@ -122,15 +269,9 @@ class HPackParser {
|
|
122
269
|
// TODO(ctiller): see if we can move this argument to Parse, and avoid
|
123
270
|
// buffering.
|
124
271
|
Priority priority_;
|
125
|
-
uint8_t dynamic_table_updates_allowed_;
|
126
|
-
// Length of frame so far.
|
127
|
-
uint32_t frame_length_;
|
128
|
-
RandomEarlyDetection metadata_early_detection_;
|
129
272
|
// Information for logging
|
130
273
|
LogInfo log_info_;
|
131
|
-
|
132
|
-
// hpack table
|
133
|
-
HPackTable table_;
|
274
|
+
InterSliceState state_;
|
134
275
|
};
|
135
276
|
|
136
277
|
} // namespace grpc_core
|
@@ -25,16 +25,16 @@
|
|
25
25
|
#include <algorithm>
|
26
26
|
#include <cstddef>
|
27
27
|
#include <cstring>
|
28
|
-
#include <initializer_list>
|
29
28
|
#include <utility>
|
30
29
|
|
31
30
|
#include "absl/status/status.h"
|
32
|
-
#include "absl/strings/
|
31
|
+
#include "absl/strings/str_cat.h"
|
33
32
|
#include "absl/strings/string_view.h"
|
34
33
|
|
35
34
|
#include <grpc/support/log.h>
|
36
35
|
|
37
36
|
#include "src/core/ext/transport/chttp2/transport/hpack_constants.h"
|
37
|
+
#include "src/core/ext/transport/chttp2/transport/hpack_parse_result.h"
|
38
38
|
#include "src/core/ext/transport/chttp2/transport/http_trace.h"
|
39
39
|
#include "src/core/lib/debug/trace.h"
|
40
40
|
#include "src/core/lib/slice/slice.h"
|
@@ -80,6 +80,14 @@ void HPackTable::MementoRingBuffer::Rebuild(uint32_t max_entries) {
|
|
80
80
|
entries_.swap(entries);
|
81
81
|
}
|
82
82
|
|
83
|
+
void HPackTable::MementoRingBuffer::ForEach(
|
84
|
+
absl::FunctionRef<void(uint32_t, const Memento&)> f) const {
|
85
|
+
uint32_t index = 0;
|
86
|
+
while (auto* m = Lookup(index++)) {
|
87
|
+
f(index, *m);
|
88
|
+
}
|
89
|
+
}
|
90
|
+
|
83
91
|
// Evict one element from the table
|
84
92
|
void HPackTable::EvictOne() {
|
85
93
|
auto first_entry = entries_.PopOne();
|
@@ -100,15 +108,9 @@ void HPackTable::SetMaxBytes(uint32_t max_bytes) {
|
|
100
108
|
max_bytes_ = max_bytes;
|
101
109
|
}
|
102
110
|
|
103
|
-
|
104
|
-
if (current_table_bytes_ == bytes)
|
105
|
-
|
106
|
-
}
|
107
|
-
if (bytes > max_bytes_) {
|
108
|
-
return absl::InternalError(absl::StrFormat(
|
109
|
-
"Attempt to make hpack table %d bytes when max is %d bytes", bytes,
|
110
|
-
max_bytes_));
|
111
|
-
}
|
111
|
+
bool HPackTable::SetCurrentTableSize(uint32_t bytes) {
|
112
|
+
if (current_table_bytes_ == bytes) return true;
|
113
|
+
if (bytes > max_bytes_) return false;
|
112
114
|
if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace)) {
|
113
115
|
gpr_log(GPR_INFO, "Update hpack parser table size to %d", bytes);
|
114
116
|
}
|
@@ -119,30 +121,16 @@ grpc_error_handle HPackTable::SetCurrentTableSize(uint32_t bytes) {
|
|
119
121
|
uint32_t new_cap = std::max(hpack_constants::EntriesForBytes(bytes),
|
120
122
|
hpack_constants::kInitialTableEntries);
|
121
123
|
entries_.Rebuild(new_cap);
|
122
|
-
return
|
124
|
+
return true;
|
123
125
|
}
|
124
126
|
|
125
|
-
|
126
|
-
if (current_table_bytes_ > max_bytes_)
|
127
|
-
return GRPC_ERROR_CREATE(absl::StrFormat(
|
128
|
-
"HPACK max table size reduced to %d but not reflected by hpack "
|
129
|
-
"stream (still at %d)",
|
130
|
-
max_bytes_, current_table_bytes_));
|
131
|
-
}
|
127
|
+
bool HPackTable::Add(Memento md) {
|
128
|
+
if (current_table_bytes_ > max_bytes_) return false;
|
132
129
|
|
133
130
|
// we can't add elements bigger than the max table size
|
134
131
|
if (md.md.transport_size() > current_table_bytes_) {
|
135
|
-
|
136
|
-
|
137
|
-
// size, that entry is added to the table. It is not an error to
|
138
|
-
// attempt to add an entry that is larger than the maximum size; an
|
139
|
-
// attempt to add an entry larger than the entire table causes
|
140
|
-
// the table to be emptied of all existing entries, and results in an
|
141
|
-
// empty table.
|
142
|
-
while (entries_.num_entries()) {
|
143
|
-
EvictOne();
|
144
|
-
}
|
145
|
-
return absl::OkStatus();
|
132
|
+
AddLargerThanCurrentTableSize();
|
133
|
+
return true;
|
146
134
|
}
|
147
135
|
|
148
136
|
// evict entries to ensure no overflow
|
@@ -154,7 +142,33 @@ grpc_error_handle HPackTable::Add(Memento md) {
|
|
154
142
|
// copy the finalized entry in
|
155
143
|
mem_used_ += md.md.transport_size();
|
156
144
|
entries_.Put(std::move(md));
|
157
|
-
return
|
145
|
+
return true;
|
146
|
+
}
|
147
|
+
|
148
|
+
void HPackTable::AddLargerThanCurrentTableSize() {
|
149
|
+
// HPACK draft 10 section 4.4 states:
|
150
|
+
// If the size of the new entry is less than or equal to the maximum
|
151
|
+
// size, that entry is added to the table. It is not an error to
|
152
|
+
// attempt to add an entry that is larger than the maximum size; an
|
153
|
+
// attempt to add an entry larger than the entire table causes
|
154
|
+
// the table to be emptied of all existing entries, and results in an
|
155
|
+
// empty table.
|
156
|
+
while (entries_.num_entries()) {
|
157
|
+
EvictOne();
|
158
|
+
}
|
159
|
+
}
|
160
|
+
|
161
|
+
std::string HPackTable::TestOnlyDynamicTableAsString() const {
|
162
|
+
std::string out;
|
163
|
+
entries_.ForEach([&out](uint32_t i, const Memento& m) {
|
164
|
+
if (m.parse_status.ok()) {
|
165
|
+
absl::StrAppend(&out, i, ": ", m.md.DebugString(), "\n");
|
166
|
+
} else {
|
167
|
+
absl::StrAppend(&out, i, ": ", m.parse_status.Materialize().ToString(),
|
168
|
+
"\n");
|
169
|
+
}
|
170
|
+
});
|
171
|
+
return out;
|
158
172
|
}
|
159
173
|
|
160
174
|
namespace {
|
@@ -236,7 +250,7 @@ HPackTable::Memento MakeMemento(size_t i) {
|
|
236
250
|
[](absl::string_view, const Slice&) {
|
237
251
|
abort(); // not expecting to see this
|
238
252
|
}),
|
239
|
-
|
253
|
+
HpackParseResult()};
|
240
254
|
}
|
241
255
|
|
242
256
|
} // namespace
|
@@ -23,13 +23,14 @@
|
|
23
23
|
|
24
24
|
#include <stdint.h>
|
25
25
|
|
26
|
+
#include <string>
|
26
27
|
#include <vector>
|
27
28
|
|
28
|
-
#include "absl/
|
29
|
+
#include "absl/functional/function_ref.h"
|
29
30
|
|
30
31
|
#include "src/core/ext/transport/chttp2/transport/hpack_constants.h"
|
32
|
+
#include "src/core/ext/transport/chttp2/transport/hpack_parse_result.h"
|
31
33
|
#include "src/core/lib/gprpp/no_destruct.h"
|
32
|
-
#include "src/core/lib/iomgr/error.h"
|
33
34
|
#include "src/core/lib/transport/metadata_batch.h"
|
34
35
|
#include "src/core/lib/transport/parsed_metadata.h"
|
35
36
|
|
@@ -45,11 +46,12 @@ class HPackTable {
|
|
45
46
|
HPackTable& operator=(const HPackTable&) = delete;
|
46
47
|
|
47
48
|
void SetMaxBytes(uint32_t max_bytes);
|
48
|
-
|
49
|
+
bool SetCurrentTableSize(uint32_t bytes);
|
50
|
+
uint32_t current_table_size() { return current_table_bytes_; }
|
49
51
|
|
50
52
|
struct Memento {
|
51
53
|
ParsedMetadata<grpc_metadata_batch> md;
|
52
|
-
|
54
|
+
HpackParseResult parse_status;
|
53
55
|
};
|
54
56
|
|
55
57
|
// Lookup, but don't ref.
|
@@ -68,7 +70,8 @@ class HPackTable {
|
|
68
70
|
}
|
69
71
|
|
70
72
|
// add a table entry to the index
|
71
|
-
|
73
|
+
bool Add(Memento md) GRPC_MUST_USE_RESULT;
|
74
|
+
void AddLargerThanCurrentTableSize();
|
72
75
|
|
73
76
|
// Current entry count in the table.
|
74
77
|
uint32_t num_entries() const { return entries_.num_entries(); }
|
@@ -76,6 +79,13 @@ class HPackTable {
|
|
76
79
|
// Current size of the table.
|
77
80
|
uint32_t test_only_table_size() const { return mem_used_; }
|
78
81
|
|
82
|
+
// Maximum allowed size of the table currently
|
83
|
+
uint32_t max_bytes() const { return max_bytes_; }
|
84
|
+
uint32_t current_table_bytes() const { return current_table_bytes_; }
|
85
|
+
|
86
|
+
// Dynamic table entries, stringified
|
87
|
+
std::string TestOnlyDynamicTableAsString() const;
|
88
|
+
|
79
89
|
private:
|
80
90
|
struct StaticMementos {
|
81
91
|
StaticMementos();
|
@@ -98,6 +108,9 @@ class HPackTable {
|
|
98
108
|
// Lookup the entry at index, or return nullptr if none exists.
|
99
109
|
const Memento* Lookup(uint32_t index) const;
|
100
110
|
|
111
|
+
void ForEach(absl::FunctionRef<void(uint32_t dynamic_index, const Memento&)>
|
112
|
+
f) const;
|
113
|
+
|
101
114
|
uint32_t max_entries() const { return max_entries_; }
|
102
115
|
uint32_t num_entries() const { return num_entries_; }
|
103
116
|
|
@@ -23,7 +23,6 @@
|
|
23
23
|
|
24
24
|
#include <initializer_list>
|
25
25
|
#include <string>
|
26
|
-
#include <utility>
|
27
26
|
|
28
27
|
#include "absl/base/attributes.h"
|
29
28
|
#include "absl/status/status.h"
|
@@ -470,8 +469,8 @@ static HPackParser::LogInfo hpack_parser_log_info(
|
|
470
469
|
}
|
471
470
|
|
472
471
|
static grpc_error_handle init_header_skip_frame_parser(
|
473
|
-
grpc_chttp2_transport* t, HPackParser::Priority priority_type
|
474
|
-
|
472
|
+
grpc_chttp2_transport* t, HPackParser::Priority priority_type,
|
473
|
+
bool is_eoh) {
|
475
474
|
t->parser = grpc_chttp2_transport::Parser{
|
476
475
|
"header", grpc_chttp2_header_parser_parse, &t->hpack_parser};
|
477
476
|
t->hpack_parser.BeginFrame(
|
@@ -595,7 +594,7 @@ static grpc_error_handle init_header_frame_parser(grpc_chttp2_transport* t,
|
|
595
594
|
GRPC_CHTTP2_IF_TRACING(
|
596
595
|
gpr_log(GPR_ERROR,
|
597
596
|
"grpc_chttp2_stream disbanded before CONTINUATION received"));
|
598
|
-
return init_header_skip_frame_parser(t, priority_type);
|
597
|
+
return init_header_skip_frame_parser(t, priority_type, is_eoh);
|
599
598
|
}
|
600
599
|
if (t->is_client) {
|
601
600
|
if (GPR_LIKELY((t->incoming_stream_id & 1) &&
|
@@ -605,7 +604,7 @@ static grpc_error_handle init_header_frame_parser(grpc_chttp2_transport* t,
|
|
605
604
|
GRPC_CHTTP2_IF_TRACING(gpr_log(
|
606
605
|
GPR_ERROR, "ignoring new grpc_chttp2_stream creation on client"));
|
607
606
|
}
|
608
|
-
return init_header_skip_frame_parser(t, priority_type);
|
607
|
+
return init_header_skip_frame_parser(t, priority_type, is_eoh);
|
609
608
|
} else if (GPR_UNLIKELY(t->last_new_stream_id >= t->incoming_stream_id)) {
|
610
609
|
GRPC_CHTTP2_IF_TRACING(gpr_log(
|
611
610
|
GPR_ERROR,
|
@@ -613,13 +612,13 @@ static grpc_error_handle init_header_frame_parser(grpc_chttp2_transport* t,
|
|
613
612
|
"last grpc_chttp2_stream "
|
614
613
|
"id=%d, new grpc_chttp2_stream id=%d",
|
615
614
|
t->last_new_stream_id, t->incoming_stream_id));
|
616
|
-
return init_header_skip_frame_parser(t, priority_type);
|
615
|
+
return init_header_skip_frame_parser(t, priority_type, is_eoh);
|
617
616
|
} else if (GPR_UNLIKELY((t->incoming_stream_id & 1) == 0)) {
|
618
617
|
GRPC_CHTTP2_IF_TRACING(gpr_log(
|
619
618
|
GPR_ERROR,
|
620
619
|
"ignoring grpc_chttp2_stream with non-client generated index %d",
|
621
620
|
t->incoming_stream_id));
|
622
|
-
return init_header_skip_frame_parser(t, priority_type);
|
621
|
+
return init_header_skip_frame_parser(t, priority_type, is_eoh);
|
623
622
|
} else if (GPR_UNLIKELY(
|
624
623
|
grpc_chttp2_stream_map_size(&t->stream_map) >=
|
625
624
|
t->settings[GRPC_ACKED_SETTINGS]
|
@@ -632,7 +631,7 @@ static grpc_error_handle init_header_frame_parser(grpc_chttp2_transport* t,
|
|
632
631
|
"grpc_chttp2_stream request id=%d, last grpc_chttp2_stream id=%d",
|
633
632
|
t, std::string(t->peer_string.as_string_view()).c_str(),
|
634
633
|
t->incoming_stream_id, t->last_new_stream_id));
|
635
|
-
return init_header_skip_frame_parser(t, priority_type);
|
634
|
+
return init_header_skip_frame_parser(t, priority_type, is_eoh);
|
636
635
|
}
|
637
636
|
t->last_new_stream_id = t->incoming_stream_id;
|
638
637
|
s = t->incoming_stream =
|
@@ -640,7 +639,7 @@ static grpc_error_handle init_header_frame_parser(grpc_chttp2_transport* t,
|
|
640
639
|
if (GPR_UNLIKELY(s == nullptr)) {
|
641
640
|
GRPC_CHTTP2_IF_TRACING(
|
642
641
|
gpr_log(GPR_ERROR, "grpc_chttp2_stream not accepted"));
|
643
|
-
return init_header_skip_frame_parser(t, priority_type);
|
642
|
+
return init_header_skip_frame_parser(t, priority_type, is_eoh);
|
644
643
|
}
|
645
644
|
if (t->channelz_socket != nullptr) {
|
646
645
|
t->channelz_socket->RecordStreamStartedFromRemote();
|
@@ -654,7 +653,7 @@ static grpc_error_handle init_header_frame_parser(grpc_chttp2_transport* t,
|
|
654
653
|
GRPC_CHTTP2_IF_TRACING(gpr_log(
|
655
654
|
GPR_ERROR, "skipping already closed grpc_chttp2_stream header"));
|
656
655
|
t->incoming_stream = nullptr;
|
657
|
-
return init_header_skip_frame_parser(t, priority_type);
|
656
|
+
return init_header_skip_frame_parser(t, priority_type, is_eoh);
|
658
657
|
}
|
659
658
|
t->parser = grpc_chttp2_transport::Parser{
|
660
659
|
"header", grpc_chttp2_header_parser_parse, &t->hpack_parser};
|
@@ -687,7 +686,7 @@ static grpc_error_handle init_header_frame_parser(grpc_chttp2_transport* t,
|
|
687
686
|
break;
|
688
687
|
case 2:
|
689
688
|
gpr_log(GPR_ERROR, "too many header frames received");
|
690
|
-
return init_header_skip_frame_parser(t, priority_type);
|
689
|
+
return init_header_skip_frame_parser(t, priority_type, is_eoh);
|
691
690
|
}
|
692
691
|
if (frame_type == HPackParser::LogInfo::kTrailers && !t->header_eof) {
|
693
692
|
return GRPC_ERROR_CREATE(
|
@@ -815,8 +814,9 @@ static grpc_error_handle parse_frame_slice(grpc_chttp2_transport* t,
|
|
815
814
|
&unused)) {
|
816
815
|
grpc_chttp2_parsing_become_skip_parser(t);
|
817
816
|
if (s) {
|
818
|
-
grpc_chttp2_cancel_stream(t, s,
|
817
|
+
grpc_chttp2_cancel_stream(t, s, err);
|
819
818
|
}
|
819
|
+
return absl::OkStatus();
|
820
820
|
}
|
821
821
|
return err;
|
822
822
|
}
|
@@ -43,6 +43,11 @@ class RandomEarlyDetection {
|
|
43
43
|
uint64_t soft_limit() const { return soft_limit_; }
|
44
44
|
uint64_t hard_limit() const { return hard_limit_; }
|
45
45
|
|
46
|
+
void SetLimits(uint64_t soft_limit, uint64_t hard_limit) {
|
47
|
+
soft_limit_ = soft_limit;
|
48
|
+
hard_limit_ = hard_limit;
|
49
|
+
}
|
50
|
+
|
46
51
|
private:
|
47
52
|
// The soft limit is the size at which we start rejecting items with a
|
48
53
|
// probability that increases linearly to 1 as the size approaches the hard
|
@@ -60,6 +60,15 @@
|
|
60
60
|
|
61
61
|
// IWYU pragma: no_include <ratio>
|
62
62
|
|
63
|
+
// TODO(eryu): remove this GRPC_CFSTREAM condition when the CFEngine is ready.
|
64
|
+
// The posix poller currently crashes iOS.
|
65
|
+
#if defined(GRPC_POSIX_SOCKET_TCP) && !defined(GRPC_CFSTREAM) && \
|
66
|
+
!defined(GRPC_DO_NOT_INSTANTIATE_POSIX_POLLER)
|
67
|
+
#define GRPC_PLATFORM_SUPPORTS_POSIX_POLLING true
|
68
|
+
#else
|
69
|
+
#define GRPC_PLATFORM_SUPPORTS_POSIX_POLLING false
|
70
|
+
#endif
|
71
|
+
|
63
72
|
using namespace std::chrono_literals;
|
64
73
|
|
65
74
|
namespace grpc_event_engine {
|
@@ -335,13 +344,16 @@ PosixEventEngine::PosixEventEngine(PosixEventPoller* poller)
|
|
335
344
|
: connection_shards_(std::max(2 * gpr_cpu_num_cores(), 1u)),
|
336
345
|
executor_(std::make_shared<ThreadPool>()),
|
337
346
|
timer_manager_(executor_) {
|
347
|
+
#if GRPC_PLATFORM_SUPPORTS_POSIX_POLLING
|
338
348
|
poller_manager_ = std::make_shared<PosixEnginePollerManager>(poller);
|
349
|
+
#endif
|
339
350
|
}
|
340
351
|
|
341
352
|
PosixEventEngine::PosixEventEngine()
|
342
353
|
: connection_shards_(std::max(2 * gpr_cpu_num_cores(), 1u)),
|
343
354
|
executor_(std::make_shared<ThreadPool>()),
|
344
355
|
timer_manager_(executor_) {
|
356
|
+
#if GRPC_PLATFORM_SUPPORTS_POSIX_POLLING
|
345
357
|
poller_manager_ = std::make_shared<PosixEnginePollerManager>(executor_);
|
346
358
|
// The threadpool must be instantiated after the poller otherwise, the
|
347
359
|
// process will deadlock when forking.
|
@@ -350,6 +362,7 @@ PosixEventEngine::PosixEventEngine()
|
|
350
362
|
PollerWorkInternal(poller_manager);
|
351
363
|
});
|
352
364
|
}
|
365
|
+
#endif // GRPC_PLATFORM_SUPPORTS_POSIX_POLLING
|
353
366
|
}
|
354
367
|
|
355
368
|
void PosixEventEngine::PollerWorkInternal(
|
@@ -420,11 +433,11 @@ PosixEventEngine::~PosixEventEngine() {
|
|
420
433
|
GPR_ASSERT(GPR_LIKELY(known_handles_.empty()));
|
421
434
|
}
|
422
435
|
timer_manager_.Shutdown();
|
423
|
-
#
|
436
|
+
#if GRPC_PLATFORM_SUPPORTS_POSIX_POLLING
|
424
437
|
if (poller_manager_ != nullptr) {
|
425
438
|
poller_manager_->TriggerShutdown();
|
426
439
|
}
|
427
|
-
#endif //
|
440
|
+
#endif // GRPC_PLATFORM_SUPPORTS_POSIX_POLLING
|
428
441
|
executor_->Quiesce();
|
429
442
|
}
|
430
443
|
|
@@ -481,7 +494,7 @@ std::unique_ptr<EventEngine::DNSResolver> PosixEventEngine::GetDNSResolver(
|
|
481
494
|
bool PosixEventEngine::IsWorkerThread() { grpc_core::Crash("unimplemented"); }
|
482
495
|
|
483
496
|
bool PosixEventEngine::CancelConnect(EventEngine::ConnectionHandle handle) {
|
484
|
-
#
|
497
|
+
#if GRPC_PLATFORM_SUPPORTS_POSIX_POLLING
|
485
498
|
int connection_handle = handle.keys[0];
|
486
499
|
if (connection_handle <= 0) {
|
487
500
|
return false;
|
@@ -530,17 +543,17 @@ bool PosixEventEngine::CancelConnect(EventEngine::ConnectionHandle handle) {
|
|
530
543
|
delete ac;
|
531
544
|
}
|
532
545
|
return connection_cancel_success;
|
533
|
-
#else //
|
546
|
+
#else // GRPC_PLATFORM_SUPPORTS_POSIX_POLLING
|
534
547
|
grpc_core::Crash(
|
535
548
|
"EventEngine::CancelConnect is not supported on this platform");
|
536
|
-
#endif //
|
549
|
+
#endif // GRPC_PLATFORM_SUPPORTS_POSIX_POLLING
|
537
550
|
}
|
538
551
|
|
539
552
|
EventEngine::ConnectionHandle PosixEventEngine::Connect(
|
540
553
|
OnConnectCallback on_connect, const ResolvedAddress& addr,
|
541
554
|
const EndpointConfig& args, MemoryAllocator memory_allocator,
|
542
555
|
Duration timeout) {
|
543
|
-
#
|
556
|
+
#if GRPC_PLATFORM_SUPPORTS_POSIX_POLLING
|
544
557
|
GPR_ASSERT(poller_manager_ != nullptr);
|
545
558
|
PosixTcpOptions options = TcpOptionsFromEndpointConfig(args);
|
546
559
|
absl::StatusOr<PosixSocketWrapper::PosixSocketCreateResult> socket =
|
@@ -553,16 +566,16 @@ EventEngine::ConnectionHandle PosixEventEngine::Connect(
|
|
553
566
|
return ConnectInternal((*socket).sock, std::move(on_connect),
|
554
567
|
(*socket).mapped_target_addr,
|
555
568
|
std::move(memory_allocator), options, timeout);
|
556
|
-
#else //
|
569
|
+
#else // GRPC_PLATFORM_SUPPORTS_POSIX_POLLING
|
557
570
|
grpc_core::Crash("EventEngine::Connect is not supported on this platform");
|
558
|
-
#endif //
|
571
|
+
#endif // GRPC_PLATFORM_SUPPORTS_POSIX_POLLING
|
559
572
|
}
|
560
573
|
|
561
574
|
std::unique_ptr<PosixEndpointWithFdSupport>
|
562
575
|
PosixEventEngine::CreatePosixEndpointFromFd(int fd,
|
563
576
|
const EndpointConfig& config,
|
564
577
|
MemoryAllocator memory_allocator) {
|
565
|
-
#
|
578
|
+
#if GRPC_PLATFORM_SUPPORTS_POSIX_POLLING
|
566
579
|
GPR_DEBUG_ASSERT(fd > 0);
|
567
580
|
PosixEventPoller* poller = poller_manager_->Poller();
|
568
581
|
GPR_DEBUG_ASSERT(poller != nullptr);
|
@@ -571,11 +584,11 @@ PosixEventEngine::CreatePosixEndpointFromFd(int fd,
|
|
571
584
|
return CreatePosixEndpoint(handle, nullptr, shared_from_this(),
|
572
585
|
std::move(memory_allocator),
|
573
586
|
TcpOptionsFromEndpointConfig(config));
|
574
|
-
#else //
|
587
|
+
#else // GRPC_PLATFORM_SUPPORTS_POSIX_POLLING
|
575
588
|
grpc_core::Crash(
|
576
589
|
"PosixEventEngine::CreatePosixEndpointFromFd is not supported on "
|
577
590
|
"this platform");
|
578
|
-
#endif //
|
591
|
+
#endif // GRPC_PLATFORM_SUPPORTS_POSIX_POLLING
|
579
592
|
}
|
580
593
|
|
581
594
|
absl::StatusOr<std::unique_ptr<EventEngine::Listener>>
|
@@ -584,7 +597,7 @@ PosixEventEngine::CreateListener(
|
|
584
597
|
absl::AnyInvocable<void(absl::Status)> on_shutdown,
|
585
598
|
const EndpointConfig& config,
|
586
599
|
std::unique_ptr<MemoryAllocatorFactory> memory_allocator_factory) {
|
587
|
-
#
|
600
|
+
#if GRPC_PLATFORM_SUPPORTS_POSIX_POLLING
|
588
601
|
PosixEventEngineWithFdSupport::PosixAcceptCallback posix_on_accept =
|
589
602
|
[on_accept_cb = std::move(on_accept)](
|
590
603
|
int /*listener_fd*/, std::unique_ptr<EventEngine::Endpoint> ep,
|
@@ -596,10 +609,10 @@ PosixEventEngine::CreateListener(
|
|
596
609
|
std::move(posix_on_accept), std::move(on_shutdown), config,
|
597
610
|
std::move(memory_allocator_factory), poller_manager_->Poller(),
|
598
611
|
shared_from_this());
|
599
|
-
#else //
|
612
|
+
#else // GRPC_PLATFORM_SUPPORTS_POSIX_POLLING
|
600
613
|
grpc_core::Crash(
|
601
614
|
"EventEngine::CreateListener is not supported on this platform");
|
602
|
-
#endif //
|
615
|
+
#endif // GRPC_PLATFORM_SUPPORTS_POSIX_POLLING
|
603
616
|
}
|
604
617
|
|
605
618
|
absl::StatusOr<std::unique_ptr<PosixListenerWithFdSupport>>
|
@@ -608,15 +621,15 @@ PosixEventEngine::CreatePosixListener(
|
|
608
621
|
absl::AnyInvocable<void(absl::Status)> on_shutdown,
|
609
622
|
const EndpointConfig& config,
|
610
623
|
std::unique_ptr<MemoryAllocatorFactory> memory_allocator_factory) {
|
611
|
-
#
|
624
|
+
#if GRPC_PLATFORM_SUPPORTS_POSIX_POLLING
|
612
625
|
return std::make_unique<PosixEngineListener>(
|
613
626
|
std::move(on_accept), std::move(on_shutdown), config,
|
614
627
|
std::move(memory_allocator_factory), poller_manager_->Poller(),
|
615
628
|
shared_from_this());
|
616
|
-
#else //
|
629
|
+
#else // GRPC_PLATFORM_SUPPORTS_POSIX_POLLING
|
617
630
|
grpc_core::Crash(
|
618
631
|
"EventEngine::CreateListener is not supported on this platform");
|
619
|
-
#endif //
|
632
|
+
#endif // GRPC_PLATFORM_SUPPORTS_POSIX_POLLING
|
620
633
|
}
|
621
634
|
|
622
635
|
} // namespace experimental
|
@@ -196,6 +196,7 @@ class PosixEventEngine final : public PosixEventEngineWithFdSupport,
|
|
196
196
|
const DNSResolver::ResolverOptions& options) override;
|
197
197
|
void Run(Closure* closure) override;
|
198
198
|
void Run(absl::AnyInvocable<void()> closure) override;
|
199
|
+
// Caution!! The timer implementation cannot create any fds. See #20418.
|
199
200
|
TaskHandle RunAfter(Duration when, Closure* closure) override;
|
200
201
|
TaskHandle RunAfter(Duration when,
|
201
202
|
absl::AnyInvocable<void()> closure) override;
|