Coverage Report

Created: 2023-11-12 09:30

/proc/self/cwd/source/extensions/filters/network/thrift_proxy/compact_protocol_impl.cc
Line
Count
Source (jump to first uncovered line)
1
#include "source/extensions/filters/network/thrift_proxy/compact_protocol_impl.h"
2
3
#include <limits>
4
5
#include "envoy/common/exception.h"
6
7
#include "source/common/common/assert.h"
8
#include "source/common/common/fmt.h"
9
#include "source/common/common/macros.h"
10
#include "source/common/runtime/runtime_features.h"
11
#include "source/extensions/filters/network/thrift_proxy/buffer_helper.h"
12
13
namespace Envoy {
14
namespace Extensions {
15
namespace NetworkFilters {
16
namespace ThriftProxy {
17
18
const uint16_t CompactProtocolImpl::Magic = 0x8201;
19
const uint16_t CompactProtocolImpl::MagicMask = 0xFF1F;
20
21
0
bool CompactProtocolImpl::readMessageBegin(Buffer::Instance& buffer, MessageMetadata& metadata) {
22
  // Minimum message length:
23
  //   protocol, message type, and version: 2 bytes +
24
  //   seq id (var int): 1 byte +
25
  //   name length (var int): 1 byte +
26
  //   name: 0 bytes
27
0
  if (buffer.length() < 4) {
28
0
    return false;
29
0
  }
30
31
0
  uint16_t version = buffer.peekBEInt<uint16_t>();
32
0
  if ((version & MagicMask) != Magic) {
33
0
    throw EnvoyException(fmt::format("invalid compact protocol version 0x{:04x} != 0x{:04x}",
34
0
                                     version & MagicMask, Magic));
35
0
  }
36
37
0
  MessageType type = static_cast<MessageType>((version & ~MagicMask) >> 5);
38
0
  if (type < MessageType::Call || type > MessageType::LastMessageType) {
39
0
    throw EnvoyException(
40
0
        fmt::format("invalid compact protocol message type {}", static_cast<int8_t>(type)));
41
0
  }
42
43
0
  int id_size;
44
0
  int32_t id = BufferHelper::peekVarIntI32(buffer, 2, id_size);
45
0
  if (id_size < 0) {
46
0
    return false;
47
0
  }
48
49
0
  int name_len_size;
50
0
  int32_t name_len = BufferHelper::peekVarIntI32(buffer, id_size + 2, name_len_size);
51
0
  if (name_len_size < 0) {
52
0
    return false;
53
0
  }
54
55
0
  if (name_len < 0) {
56
0
    throw EnvoyException(absl::StrCat("negative compact protocol message name length ", name_len));
57
0
  }
58
59
0
  if (buffer.length() < static_cast<uint64_t>(id_size + name_len_size + name_len + 2)) {
60
0
    return false;
61
0
  }
62
63
0
  buffer.drain(id_size + name_len_size + 2);
64
65
0
  if (name_len > 0) {
66
0
    metadata.setMethodName(
67
0
        std::string(static_cast<const char*>(buffer.linearize(name_len)), name_len));
68
0
    buffer.drain(name_len);
69
0
  } else {
70
0
    metadata.setMethodName("");
71
0
  }
72
0
  metadata.setMessageType(type);
73
0
  metadata.setSequenceId(id);
74
75
0
  return true;
76
0
}
77
78
0
bool CompactProtocolImpl::readMessageEnd(Buffer::Instance& buffer) {
79
0
  UNREFERENCED_PARAMETER(buffer);
80
0
  return true;
81
0
}
82
83
0
bool CompactProtocolImpl::peekReplyPayload(Buffer::Instance& buffer, ReplyType& reply_type) {
84
  // compact protocol does not transmit struct names so go straight to peek for field begin
85
  // Minimum size: FieldType::Stop is encoded as 1 byte.
86
0
  if (buffer.length() < 1) {
87
0
    return false;
88
0
  }
89
90
0
  uint8_t delta_and_type = buffer.peekInt<int8_t>();
91
0
  if ((delta_and_type & 0x0f) == 0) {
92
    // Type is stop, no need to do further decoding
93
    // If the first field is stop then response is void success
94
0
    reply_type = ReplyType::Success;
95
0
    return true;
96
0
  }
97
98
0
  if ((delta_and_type >> 4) != 0) {
99
    // field id delta is non zero and so is an IDL exception (success field id is 0)
100
0
    reply_type = ReplyType::Error;
101
0
    return true;
102
0
  }
103
104
0
  int id_size = 0;
105
  // Field ID delta is zero: this is a long-form field header, followed by zig-zag field id.
106
0
  if (buffer.length() < 2) {
107
0
    return false;
108
0
  }
109
110
0
  int32_t id = BufferHelper::peekZigZagI32(buffer, 1, id_size);
111
0
  if (id_size < 0) {
112
0
    return false;
113
0
  }
114
115
0
  validateFieldId(id);
116
  // successful response struct in field id 0, error (IDL exception) in field id greater than 0
117
0
  reply_type = id == 0 ? ReplyType::Success : ReplyType::Error;
118
0
  return true;
119
0
}
120
121
0
void CompactProtocolImpl::validateFieldId(int32_t id) {
122
0
  if (id >= 0 && id <= std::numeric_limits<int16_t>::max()) {
123
0
    return;
124
0
  }
125
126
0
  if (Runtime::runtimeFeatureEnabled("envoy.reloadable_features.thrift_allow_negative_field_ids") &&
127
0
      id < 0 && id >= std::numeric_limits<int16_t>::min()) {
128
0
    return;
129
0
  }
130
131
0
  throw EnvoyException(absl::StrCat("invalid compact protocol field id ", id));
132
0
}
133
134
0
bool CompactProtocolImpl::readStructBegin(Buffer::Instance& buffer, std::string& name) {
135
0
  UNREFERENCED_PARAMETER(buffer);
136
0
  name.clear(); // compact protocol does not transmit struct names
137
138
  // Field ids are encoded as deltas specific to the field's containing struct. Field ids are
139
  // tracked in a stack to handle nested structs.
140
0
  last_field_id_stack_.push(last_field_id_);
141
0
  last_field_id_ = 0;
142
143
0
  return true;
144
0
}
145
146
0
bool CompactProtocolImpl::readStructEnd(Buffer::Instance& buffer) {
147
0
  UNREFERENCED_PARAMETER(buffer);
148
149
0
  if (last_field_id_stack_.empty()) {
150
0
    throw EnvoyException("invalid check for compact protocol struct end");
151
0
  }
152
153
0
  last_field_id_ = last_field_id_stack_.top();
154
0
  last_field_id_stack_.pop();
155
156
0
  return true;
157
0
}
158
159
bool CompactProtocolImpl::readFieldBegin(Buffer::Instance& buffer, std::string& name,
160
0
                                         FieldType& field_type, int16_t& field_id) {
161
  // Minimum size: FieldType::Stop is encoded as 1 byte.
162
0
  if (buffer.length() < 1) {
163
0
    return false;
164
0
  }
165
166
0
  uint8_t delta_and_type = buffer.peekInt<int8_t>();
167
0
  if ((delta_and_type & 0x0f) == 0) {
168
    // Type is stop, no need to do further decoding.
169
0
    name.clear();
170
0
    field_id = 0;
171
0
    field_type = FieldType::Stop;
172
0
    buffer.drain(1);
173
174
0
    return true;
175
0
  }
176
177
0
  int16_t compact_field_id;
178
0
  CompactFieldType compact_field_type;
179
0
  int id_size = 0;
180
0
  if ((delta_and_type >> 4) == 0) {
181
    // Field ID delta is zero: this is a long-form field header, followed by zig-zag field id.
182
0
    if (buffer.length() < 2) {
183
0
      return false;
184
0
    }
185
186
0
    int32_t id = BufferHelper::peekZigZagI32(buffer, 1, id_size);
187
0
    if (id_size < 0) {
188
0
      return false;
189
0
    }
190
191
0
    validateFieldId(id);
192
0
    compact_field_type = static_cast<CompactFieldType>(delta_and_type);
193
0
    compact_field_id = static_cast<int16_t>(id);
194
0
  } else {
195
    // Short form field header: 4 bits of field id delta, 4 bits of field type.
196
0
    compact_field_type = static_cast<CompactFieldType>(delta_and_type & 0x0F);
197
0
    compact_field_id = last_field_id_ + static_cast<int16_t>(delta_and_type >> 4);
198
0
  }
199
200
0
  field_type = convertCompactFieldType(compact_field_type);
201
  // For simple fields, boolean values are transmitted as a type with no further data.
202
0
  if (field_type == FieldType::Bool) {
203
0
    bool_value_ = compact_field_type == CompactFieldType::BoolTrue;
204
0
  }
205
206
0
  name.clear(); // compact protocol does not transmit field names
207
0
  field_id = compact_field_id;
208
0
  last_field_id_ = compact_field_id;
209
210
0
  buffer.drain(id_size + 1);
211
212
0
  return true;
213
0
}
214
215
0
bool CompactProtocolImpl::readFieldEnd(Buffer::Instance& buffer) {
216
0
  UNREFERENCED_PARAMETER(buffer);
217
0
  bool_value_.reset();
218
0
  return true;
219
0
}
220
221
bool CompactProtocolImpl::readMapBegin(Buffer::Instance& buffer, FieldType& key_type,
222
0
                                       FieldType& value_type, uint32_t& size) {
223
0
  int s_size;
224
0
  int32_t s = BufferHelper::peekVarIntI32(buffer, 0, s_size);
225
0
  if (s_size < 0) {
226
0
    return false;
227
0
  }
228
229
0
  if (s < 0) {
230
0
    throw EnvoyException(absl::StrCat("negative compact protocol map size ", s));
231
0
  }
232
233
0
  if (s == 0) {
234
    // Empty map. Compact protocol provides no type information in this case.
235
0
    key_type = value_type = FieldType::Stop;
236
0
    size = 0;
237
0
    buffer.drain(s_size);
238
0
    return true;
239
0
  }
240
241
0
  if (buffer.length() < static_cast<uint64_t>(s_size + 1)) {
242
0
    return false;
243
0
  }
244
245
0
  uint8_t types = buffer.peekInt<int8_t>(s_size);
246
0
  FieldType ktype = convertCompactFieldType(static_cast<CompactFieldType>(types >> 4));
247
0
  FieldType vtype = convertCompactFieldType(static_cast<CompactFieldType>(types & 0xF));
248
249
  // Drain the size and the types byte.
250
0
  buffer.drain(s_size + 1);
251
252
0
  key_type = ktype;
253
0
  value_type = vtype;
254
0
  size = static_cast<uint32_t>(s);
255
256
0
  return true;
257
0
}
258
259
0
bool CompactProtocolImpl::readMapEnd(Buffer::Instance& buffer) {
260
0
  UNREFERENCED_PARAMETER(buffer);
261
0
  return true;
262
0
}
263
264
bool CompactProtocolImpl::readListBegin(Buffer::Instance& buffer, FieldType& elem_type,
265
0
                                        uint32_t& size) {
266
  // Minimum length:
267
  //   size and type: 1 byte
268
0
  if (buffer.length() < 1) {
269
0
    return false;
270
0
  }
271
272
0
  uint32_t sz = 0;
273
0
  int s_size = 0;
274
0
  uint8_t size_and_type = buffer.peekInt<int8_t>();
275
0
  if ((size_and_type & 0xF0) != 0xF0) {
276
    // Short form list header: size and type byte.
277
0
    sz = static_cast<uint32_t>(size_and_type >> 4);
278
0
  } else {
279
    // Long form list header: type byte followed by var int size.
280
0
    int32_t s = BufferHelper::peekVarIntI32(buffer, 1, s_size);
281
0
    if (s_size < 0) {
282
0
      return false;
283
0
    }
284
285
0
    if (s < 0) {
286
0
      throw EnvoyException(fmt::format("negative compact protocol list/set size {}", s));
287
0
    }
288
289
0
    sz = static_cast<uint32_t>(s);
290
0
  }
291
292
0
  elem_type = convertCompactFieldType(static_cast<CompactFieldType>(size_and_type & 0x0F));
293
0
  size = sz;
294
295
0
  buffer.drain(s_size + 1);
296
0
  return true;
297
0
}
298
299
0
bool CompactProtocolImpl::readListEnd(Buffer::Instance& buffer) {
300
0
  UNREFERENCED_PARAMETER(buffer);
301
0
  return true;
302
0
}
303
304
bool CompactProtocolImpl::readSetBegin(Buffer::Instance& buffer, FieldType& elem_type,
305
0
                                       uint32_t& size) {
306
0
  return readListBegin(buffer, elem_type, size);
307
0
}
308
309
0
bool CompactProtocolImpl::readSetEnd(Buffer::Instance& buffer) { return readListEnd(buffer); }
310
311
0
bool CompactProtocolImpl::readBool(Buffer::Instance& buffer, bool& value) {
312
  // Boolean struct fields have their value encoded in the field type.
313
0
  if (bool_value_.has_value()) {
314
0
    value = bool_value_.value();
315
0
    return true;
316
0
  }
317
318
  // All other boolean values (list, set, or map elements) are encoded as single bytes.
319
0
  if (buffer.length() < 1) {
320
0
    return false;
321
0
  }
322
323
0
  value = buffer.drainInt<int8_t>() != 0;
324
0
  return true;
325
0
}
326
327
0
bool CompactProtocolImpl::readByte(Buffer::Instance& buffer, uint8_t& value) {
328
0
  if (buffer.length() < 1) {
329
0
    return false;
330
0
  }
331
0
  value = buffer.drainInt<int8_t>();
332
0
  return true;
333
0
}
334
335
0
bool CompactProtocolImpl::readInt16(Buffer::Instance& buffer, int16_t& value) {
336
0
  if (buffer.length() < 1) {
337
0
    return false;
338
0
  }
339
340
0
  int size;
341
0
  int32_t i = BufferHelper::peekZigZagI32(buffer, 0, size);
342
0
  if (size < 0) {
343
0
    return false;
344
0
  }
345
346
0
  if (i < std::numeric_limits<int16_t>::min() || i > std::numeric_limits<int16_t>::max()) {
347
0
    throw EnvoyException(fmt::format("compact protocol i16 exceeds allowable range {}", i));
348
0
  }
349
350
0
  buffer.drain(size);
351
0
  value = static_cast<int16_t>(i);
352
0
  return true;
353
0
}
354
355
0
bool CompactProtocolImpl::readInt32(Buffer::Instance& buffer, int32_t& value) {
356
0
  if (buffer.length() < 1) {
357
0
    return false;
358
0
  }
359
360
0
  int size;
361
0
  int32_t i = BufferHelper::peekZigZagI32(buffer, 0, size);
362
0
  if (size < 0) {
363
0
    return false;
364
0
  }
365
366
0
  buffer.drain(size);
367
0
  value = i;
368
0
  return true;
369
0
}
370
371
0
bool CompactProtocolImpl::readInt64(Buffer::Instance& buffer, int64_t& value) {
372
0
  if (buffer.length() < 1) {
373
0
    return false;
374
0
  }
375
376
0
  int size;
377
0
  int64_t i = BufferHelper::peekZigZagI64(buffer, 0, size);
378
0
  if (size < 0) {
379
0
    return false;
380
0
  }
381
382
0
  buffer.drain(size);
383
0
  value = i;
384
0
  return true;
385
0
}
386
387
0
bool CompactProtocolImpl::readDouble(Buffer::Instance& buffer, double& value) {
388
0
  static_assert(sizeof(double) == sizeof(uint64_t), "sizeof(double) != size(uint64_t)");
389
390
0
  if (buffer.length() < 8) {
391
0
    return false;
392
0
  }
393
394
0
  value = BufferHelper::drainBEDouble(buffer);
395
0
  return true;
396
0
}
397
398
0
bool CompactProtocolImpl::readString(Buffer::Instance& buffer, std::string& value) {
399
0
  if (buffer.length() < 1) {
400
0
    return false;
401
0
  }
402
403
0
  int len_size;
404
0
  int32_t str_len = BufferHelper::peekVarIntI32(buffer, 0, len_size);
405
0
  if (len_size < 0) {
406
0
    return false;
407
0
  }
408
409
0
  if (str_len < 0) {
410
0
    throw EnvoyException(fmt::format("negative compact protocol string/binary length {}", str_len));
411
0
  }
412
413
0
  if (str_len == 0) {
414
0
    buffer.drain(len_size);
415
0
    value.clear();
416
0
    return true;
417
0
  }
418
419
0
  if (buffer.length() < static_cast<uint64_t>(str_len + len_size)) {
420
0
    return false;
421
0
  }
422
423
0
  buffer.drain(len_size);
424
0
  value.assign(static_cast<const char*>(buffer.linearize(str_len)), str_len);
425
0
  buffer.drain(str_len);
426
0
  return true;
427
0
}
428
429
0
bool CompactProtocolImpl::readBinary(Buffer::Instance& buffer, std::string& value) {
430
0
  return readString(buffer, value);
431
0
}
432
433
void CompactProtocolImpl::writeMessageBegin(Buffer::Instance& buffer,
434
0
                                            const MessageMetadata& metadata) {
435
0
  MessageType msg_type = metadata.messageType();
436
437
0
  uint16_t ptv = (Magic & MagicMask) | (static_cast<uint16_t>(msg_type) << 5);
438
0
  ASSERT((ptv & MagicMask) == Magic);
439
0
  ASSERT((ptv & ~MagicMask) >> 5 == static_cast<uint16_t>(msg_type));
440
441
0
  buffer.writeBEInt<uint16_t>(ptv);
442
0
  BufferHelper::writeVarIntI32(buffer, metadata.sequenceId());
443
0
  writeString(buffer, metadata.methodName());
444
0
}
445
446
0
void CompactProtocolImpl::writeMessageEnd(Buffer::Instance& buffer) {
447
0
  UNREFERENCED_PARAMETER(buffer);
448
0
}
449
450
0
void CompactProtocolImpl::writeStructBegin(Buffer::Instance& buffer, const std::string& name) {
451
0
  UNREFERENCED_PARAMETER(buffer);
452
0
  UNREFERENCED_PARAMETER(name);
453
454
  // Field ids are encoded as deltas specific to the field's containing struct. Field ids are
455
  // tracked in a stack to handle nested structs.
456
0
  last_field_id_stack_.push(last_field_id_);
457
0
  last_field_id_ = 0;
458
0
}
459
460
0
void CompactProtocolImpl::writeStructEnd(Buffer::Instance& buffer) {
461
0
  UNREFERENCED_PARAMETER(buffer);
462
463
0
  if (last_field_id_stack_.empty()) {
464
0
    throw EnvoyException("invalid write of compact protocol struct end");
465
0
  }
466
467
0
  last_field_id_ = last_field_id_stack_.top();
468
0
  last_field_id_stack_.pop();
469
0
}
470
471
void CompactProtocolImpl::writeFieldBegin(Buffer::Instance& buffer, const std::string& name,
472
0
                                          FieldType field_type, int16_t field_id) {
473
0
  UNREFERENCED_PARAMETER(name);
474
475
0
  if (field_type == FieldType::Stop) {
476
0
    buffer.writeByte(0);
477
0
    return;
478
0
  }
479
480
0
  if (field_type == FieldType::Bool) {
481
0
    bool_field_id_ = field_id;
482
0
    return;
483
0
  }
484
485
0
  writeFieldBeginInternal(buffer, field_type, field_id, {});
486
0
}
487
488
void CompactProtocolImpl::writeFieldBeginInternal(
489
    Buffer::Instance& buffer, FieldType field_type, int16_t field_id,
490
0
    absl::optional<CompactFieldType> field_type_override) {
491
0
  CompactFieldType compact_field_type;
492
0
  if (field_type_override.has_value()) {
493
0
    compact_field_type = field_type_override.value();
494
0
  } else {
495
0
    compact_field_type = convertFieldType(field_type);
496
0
  }
497
498
0
  if (field_id > last_field_id_ && field_id - last_field_id_ <= 15) {
499
    // Encode short-form field header.
500
0
    buffer.writeByte((static_cast<int8_t>(field_id - last_field_id_) << 4) |
501
0
                     static_cast<int8_t>(compact_field_type));
502
0
  } else {
503
0
    buffer.writeByte(static_cast<int8_t>(compact_field_type));
504
0
    BufferHelper::writeZigZagI32(buffer, static_cast<int32_t>(field_id));
505
0
  }
506
507
0
  last_field_id_ = field_id;
508
0
}
509
510
0
void CompactProtocolImpl::writeFieldEnd(Buffer::Instance& buffer) {
511
0
  UNREFERENCED_PARAMETER(buffer);
512
513
0
  bool_field_id_.reset();
514
0
}
515
516
void CompactProtocolImpl::writeMapBegin(Buffer::Instance& buffer, FieldType key_type,
517
0
                                        FieldType value_type, uint32_t size) {
518
0
  if (size > static_cast<uint32_t>(std::numeric_limits<int32_t>::max())) {
519
0
    throw EnvoyException(absl::StrCat("illegal compact protocol map size ", size));
520
0
  }
521
522
0
  BufferHelper::writeVarIntI32(buffer, static_cast<int32_t>(size));
523
0
  if (size == 0) {
524
0
    return;
525
0
  }
526
527
0
  CompactFieldType compact_key_type = convertFieldType(key_type);
528
0
  CompactFieldType compact_value_type = convertFieldType(value_type);
529
0
  buffer.writeByte((static_cast<int8_t>(compact_key_type) << 4) |
530
0
                   static_cast<int8_t>(compact_value_type));
531
0
}
532
533
0
void CompactProtocolImpl::writeMapEnd(Buffer::Instance& buffer) { UNREFERENCED_PARAMETER(buffer); }
534
535
void CompactProtocolImpl::writeListBegin(Buffer::Instance& buffer, FieldType elem_type,
536
0
                                         uint32_t size) {
537
0
  if (size > static_cast<uint32_t>(std::numeric_limits<int32_t>::max())) {
538
0
    throw EnvoyException(fmt::format("illegal compact protocol list/set size {}", size));
539
0
  }
540
541
0
  CompactFieldType compact_elem_type = convertFieldType(elem_type);
542
543
0
  if (size < 0xF) {
544
    // Short form list/set header
545
0
    int8_t short_size = static_cast<int8_t>(size & 0xF);
546
0
    buffer.writeByte((short_size << 4) | static_cast<int8_t>(compact_elem_type));
547
0
  } else {
548
0
    buffer.writeByte(0xF0 | static_cast<int8_t>(compact_elem_type));
549
0
    BufferHelper::writeVarIntI32(buffer, static_cast<int32_t>(size));
550
0
  }
551
0
}
552
553
0
void CompactProtocolImpl::writeListEnd(Buffer::Instance& buffer) { UNREFERENCED_PARAMETER(buffer); }
554
555
void CompactProtocolImpl::writeSetBegin(Buffer::Instance& buffer, FieldType elem_type,
556
0
                                        uint32_t size) {
557
0
  writeListBegin(buffer, elem_type, size);
558
0
}
559
560
0
void CompactProtocolImpl::writeSetEnd(Buffer::Instance& buffer) { UNREFERENCED_PARAMETER(buffer); }
561
562
0
void CompactProtocolImpl::writeBool(Buffer::Instance& buffer, bool value) {
563
0
  if (bool_field_id_.has_value()) {
564
    // Boolean fields have their value encoded by type.
565
0
    CompactFieldType bool_field_type =
566
0
        value ? CompactFieldType::BoolTrue : CompactFieldType::BoolFalse;
567
0
    writeFieldBeginInternal(buffer, FieldType::Bool, bool_field_id_.value(), {bool_field_type});
568
0
    return;
569
0
  }
570
571
  // Map/Set/List booleans are encoded as bytes.
572
0
  buffer.writeByte(value ? 1 : 0);
573
0
}
574
575
0
void CompactProtocolImpl::writeByte(Buffer::Instance& buffer, uint8_t value) {
576
0
  buffer.writeByte(value);
577
0
}
578
579
0
void CompactProtocolImpl::writeInt16(Buffer::Instance& buffer, int16_t value) {
580
0
  int32_t extended = static_cast<int32_t>(value);
581
0
  BufferHelper::writeZigZagI32(buffer, extended);
582
0
}
583
584
0
void CompactProtocolImpl::writeInt32(Buffer::Instance& buffer, int32_t value) {
585
0
  BufferHelper::writeZigZagI32(buffer, value);
586
0
}
587
588
0
void CompactProtocolImpl::writeInt64(Buffer::Instance& buffer, int64_t value) {
589
0
  BufferHelper::writeZigZagI64(buffer, value);
590
0
}
591
592
0
void CompactProtocolImpl::writeDouble(Buffer::Instance& buffer, double value) {
593
0
  BufferHelper::writeBEDouble(buffer, value);
594
0
}
595
596
0
void CompactProtocolImpl::writeString(Buffer::Instance& buffer, const std::string& value) {
597
0
  BufferHelper::writeVarIntI32(buffer, value.length());
598
0
  buffer.add(value);
599
0
}
600
601
0
void CompactProtocolImpl::writeBinary(Buffer::Instance& buffer, const std::string& value) {
602
0
  writeString(buffer, value);
603
0
}
604
605
0
FieldType CompactProtocolImpl::convertCompactFieldType(CompactFieldType compact_field_type) {
606
0
  switch (compact_field_type) {
607
0
  case CompactFieldType::BoolTrue:
608
0
    return FieldType::Bool;
609
0
  case CompactFieldType::BoolFalse:
610
0
    return FieldType::Bool;
611
0
  case CompactFieldType::Byte:
612
0
    return FieldType::Byte;
613
0
  case CompactFieldType::I16:
614
0
    return FieldType::I16;
615
0
  case CompactFieldType::I32:
616
0
    return FieldType::I32;
617
0
  case CompactFieldType::I64:
618
0
    return FieldType::I64;
619
0
  case CompactFieldType::Double:
620
0
    return FieldType::Double;
621
0
  case CompactFieldType::String:
622
0
    return FieldType::String;
623
0
  case CompactFieldType::List:
624
0
    return FieldType::List;
625
0
  case CompactFieldType::Set:
626
0
    return FieldType::Set;
627
0
  case CompactFieldType::Map:
628
0
    return FieldType::Map;
629
0
  case CompactFieldType::Struct:
630
0
    return FieldType::Struct;
631
0
  default:
632
0
    throw EnvoyException(fmt::format("unknown compact protocol field type {}",
633
0
                                     static_cast<int8_t>(compact_field_type)));
634
0
  }
635
0
}
636
637
0
CompactProtocolImpl::CompactFieldType CompactProtocolImpl::convertFieldType(FieldType field_type) {
638
0
  switch (field_type) {
639
0
  case FieldType::Bool:
640
    // c.f. special handling in writeFieldBegin
641
0
    return CompactFieldType::BoolTrue;
642
0
  case FieldType::Byte:
643
0
    return CompactFieldType::Byte;
644
0
  case FieldType::I16:
645
0
    return CompactFieldType::I16;
646
0
  case FieldType::I32:
647
0
    return CompactFieldType::I32;
648
0
  case FieldType::I64:
649
0
    return CompactFieldType::I64;
650
0
  case FieldType::Double:
651
0
    return CompactFieldType::Double;
652
0
  case FieldType::String:
653
0
    return CompactFieldType::String;
654
0
  case FieldType::Struct:
655
0
    return CompactFieldType::Struct;
656
0
  case FieldType::Map:
657
0
    return CompactFieldType::Map;
658
0
  case FieldType::Set:
659
0
    return CompactFieldType::Set;
660
0
  case FieldType::List:
661
0
    return CompactFieldType::List;
662
0
  default:
663
0
    throw EnvoyException(
664
0
        fmt::format("unknown protocol field type {}", static_cast<int8_t>(field_type)));
665
0
  }
666
0
}
667
668
class CompactProtocolConfigFactory : public ProtocolFactoryBase<CompactProtocolImpl> {
669
public:
670
4
  CompactProtocolConfigFactory() : ProtocolFactoryBase(ProtocolNames::get().COMPACT) {}
671
};
672
673
/**
674
 * Static registration for the binary protocol. @see RegisterFactory.
675
 */
676
REGISTER_FACTORY(CompactProtocolConfigFactory, NamedProtocolConfigFactory);
677
678
} // namespace ThriftProxy
679
} // namespace NetworkFilters
680
} // namespace Extensions
681
} // namespace Envoy