1
#include "source/common/quic/envoy_quic_utils.h"
2

            
3
#include <algorithm>
4
#include <cstddef>
5
#include <cstdint>
6
#include <cstring>
7
#include <memory>
8
#include <string>
9

            
10
#include "envoy/api/os_sys_calls_common.h"
11
#include "envoy/http/header_map.h"
12
#include "envoy/http/stream_reset_handler.h"
13
#include "envoy/network/address.h"
14
#include "envoy/network/io_handle.h"
15
#include "envoy/network/listen_socket.h"
16
#include "envoy/network/socket.h"
17
#include "envoy/network/socket_interface.h"
18

            
19
#include "source/common/api/os_sys_calls_impl.h"
20
#include "source/common/common/assert.h"
21
#include "source/common/common/logger.h"
22
#include "source/common/common/utility.h"
23
#include "source/common/http/http_option_limits.h"
24
#include "source/common/network/address_impl.h"
25
#include "source/common/network/connection_socket_impl.h"
26
#include "source/common/network/socket_option_factory.h"
27
#include "source/common/protobuf/utility.h"
28
#include "source/common/quic/quic_io_handle_wrapper.h"
29
#include "source/common/runtime/runtime_features.h"
30
#include "source/common/tls/cert_compression.h"
31

            
32
#include "absl/numeric/int128.h"
33
#include "absl/strings/str_cat.h"
34
#include "absl/strings/string_view.h"
35
#include "openssl/crypto.h"
36
#include "openssl/ec.h"
37
#include "openssl/ec_key.h"
38
#include "openssl/evp.h"
39
#include "openssl/nid.h"
40
#include "openssl/rsa.h"
41
#include "openssl/ssl.h"
42
#include "openssl/x509.h"
43
#include "quiche/common/http/http_header_block.h"
44
#include "quiche/common/quiche_ip_address_family.h"
45
#include "quiche/quic/core/quic_config.h"
46
#include "quiche/quic/core/quic_constants.h"
47
#include "quiche/quic/core/quic_error_codes.h"
48
#include "quiche/quic/core/quic_tag.h"
49
#include "quiche/quic/core/quic_time.h"
50
#include "quiche/quic/core/quic_types.h"
51
#include "quiche/quic/platform/api/quic_socket_address.h"
52

            
53
namespace Envoy {
54
namespace Quic {
55

            
56
namespace {
57

            
58
Network::Address::InstanceConstSharedPtr
59
946
getLoopbackAddress(Network::Address::InstanceConstSharedPtr peer_address) {
60
946
  if (peer_address->ip()->version() == Network::Address::IpVersion::v6) {
61
4
    return std::make_shared<Network::Address::Ipv6Instance>(
62
4
        "::1", 0, &peer_address->socketInterface(), peer_address->ip()->ipv6()->v6only());
63
4
  }
64
942
  return std::make_shared<Network::Address::Ipv4Instance>("127.0.0.1",
65
942
                                                          &peer_address->socketInterface());
66
946
}
67

            
68
} // namespace
69

            
70
// TODO(danzh): this is called on each write. Consider to return an address instance on the stack if
71
// the heap allocation is too expensive.
72
Network::Address::InstanceConstSharedPtr
73
2369518
quicAddressToEnvoyAddressInstance(const quic::QuicSocketAddress& quic_address) {
74
2369518
  return quic_address.IsInitialized()
75
2369518
             ? Network::Address::addressFromSockAddrOrDie(quic_address.generic_address(),
76
2365288
                                                          quic_address.host().address_family() ==
77
2365288
                                                                  quiche::IpAddressFamily::IP_V4
78
2365344
                                                              ? sizeof(sockaddr_in)
79
1101720
                                                              : sizeof(sockaddr_in6),
80
2365288
                                                          -1, false)
81
2369518
             : nullptr;
82
2369518
}
83

            
84
1409615
quic::QuicSocketAddress envoyIpAddressToQuicSocketAddress(const Network::Address::Ip* envoy_ip) {
85
1409615
  if (envoy_ip == nullptr) {
86
    // Return uninitialized socket addr
87
1
    return {};
88
1
  }
89

            
90
1409614
  uint32_t port = envoy_ip->port();
91
1409614
  sockaddr_storage ss;
92

            
93
1409621
  if (envoy_ip->version() == Network::Address::IpVersion::v4) {
94
    // Create and return quic ipv4 address
95
1409554
    auto ipv4_addr = reinterpret_cast<sockaddr_in*>(&ss);
96
1409554
    memset(ipv4_addr, 0, sizeof(sockaddr_in));
97
1409554
    ipv4_addr->sin_family = AF_INET;
98
1409554
    ipv4_addr->sin_port = htons(port);
99
1409554
    ipv4_addr->sin_addr.s_addr = envoy_ip->ipv4()->address();
100
1153883
  } else {
101
    // Create and return quic ipv6 address
102
67
    auto ipv6_addr = reinterpret_cast<sockaddr_in6*>(&ss);
103
67
    memset(ipv6_addr, 0, sizeof(sockaddr_in6));
104
67
    ipv6_addr->sin6_family = AF_INET6;
105
67
    ipv6_addr->sin6_port = htons(port);
106
67
    ASSERT(sizeof(ipv6_addr->sin6_addr.s6_addr) == 16u);
107
67
    *reinterpret_cast<absl::uint128*>(ipv6_addr->sin6_addr.s6_addr) = envoy_ip->ipv6()->address();
108
67
  }
109
1409614
  return quic::QuicSocketAddress(ss);
110
1409615
}
111

            
112
7548
quiche::HttpHeaderBlock envoyHeadersToHttp2HeaderBlock(const Http::HeaderMap& headers) {
113
7548
  quiche::HttpHeaderBlock header_block;
114
157751
  headers.iterate([&header_block](const Http::HeaderEntry& header) -> Http::HeaderMap::Iterate {
115
    // The key-value pairs are copied.
116
157751
    header_block.AppendValueOrAddHeader(header.key().getStringView(),
117
157751
                                        header.value().getStringView());
118
157751
    return Http::HeaderMap::Iterate::Continue;
119
157751
  });
120
7548
  return header_block;
121
7548
}
122

            
123
625
quic::QuicRstStreamErrorCode envoyResetReasonToQuicRstError(Http::StreamResetReason reason) {
124
625
  switch (reason) {
125
12
  case Http::StreamResetReason::LocalRefusedStreamReset:
126
12
    return quic::QUIC_REFUSED_STREAM;
127
4
  case Http::StreamResetReason::LocalConnectionFailure:
128
5
  case Http::StreamResetReason::RemoteConnectionFailure:
129
6
  case Http::StreamResetReason::ConnectionTimeout:
130
15
  case Http::StreamResetReason::ConnectionTermination:
131
15
    return quic::QUIC_STREAM_CONNECTION_ERROR;
132
16
  case Http::StreamResetReason::ConnectError:
133
16
    return quic::QUIC_STREAM_CONNECT_ERROR;
134
576
  case Http::StreamResetReason::LocalReset:
135
576
    return quic::QUIC_STREAM_REQUEST_REJECTED;
136
2
  case Http::StreamResetReason::OverloadManager:
137
2
    return quic::QUIC_STREAM_EXCESSIVE_LOAD;
138
1
  case Http::StreamResetReason::ProtocolError:
139
1
    return quic::QUIC_STREAM_GENERAL_PROTOCOL_ERROR;
140
1
  case Http::StreamResetReason::Overflow:
141
1
    IS_ENVOY_BUG("Resource overflow shouldn't be propagated to QUIC network stack");
142
1
    break;
143
1
  case Http::StreamResetReason::RemoteRefusedStreamReset:
144
1
  case Http::StreamResetReason::RemoteReset:
145
1
    IS_ENVOY_BUG("Remote reset shouldn't be initiated by self.");
146
1
    break;
147
1
  case Http::StreamResetReason::Http1PrematureUpstreamHalfClose:
148
1
    IS_ENVOY_BUG("H/1 premature response reset is not applicable to H/3.");
149
1
    break;
150
625
  }
151

            
152
3
  ENVOY_LOG_MISC(error, absl::StrCat("Unknown reset reason: ", reason));
153
3
  return quic::QUIC_STREAM_UNKNOWN_APPLICATION_ERROR_CODE;
154
625
}
155

            
156
653
Http::StreamResetReason quicRstErrorToEnvoyLocalResetReason(quic::QuicRstStreamErrorCode rst_err) {
157
653
  switch (rst_err) {
158
11
  case quic::QUIC_REFUSED_STREAM:
159
11
    return Http::StreamResetReason::LocalRefusedStreamReset;
160
11
  case quic::QUIC_STREAM_CONNECTION_ERROR:
161
11
    return Http::StreamResetReason::LocalConnectionFailure;
162
1
  case quic::QUIC_STREAM_NO_ERROR:
163
2
  case quic::QUIC_STREAM_CANCELLED:
164
7
  case quic::QUIC_STREAM_EXCESSIVE_LOAD:
165
15
  case quic::QUIC_HEADERS_TOO_LARGE:
166
589
  case quic::QUIC_STREAM_REQUEST_REJECTED:
167
589
    return Http::StreamResetReason::LocalReset;
168
42
  default:
169
42
    return Http::StreamResetReason::ProtocolError;
170
653
  }
171
653
}
172

            
173
827
Http::StreamResetReason quicRstErrorToEnvoyRemoteResetReason(quic::QuicRstStreamErrorCode rst_err) {
174
827
  switch (rst_err) {
175
3
  case quic::QUIC_REFUSED_STREAM:
176
3
    return Http::StreamResetReason::RemoteRefusedStreamReset;
177
1
  case quic::QUIC_STREAM_CONNECTION_ERROR:
178
1
    return Http::StreamResetReason::ConnectionTermination;
179
1
  case quic::QUIC_STREAM_CONNECT_ERROR:
180
1
    return Http::StreamResetReason::ConnectError;
181
108
  case quic::QUIC_STREAM_NO_ERROR:
182
111
  case quic::QUIC_STREAM_CANCELLED:
183
792
  case quic::QUIC_STREAM_REQUEST_REJECTED:
184
792
  case quic::QUIC_STREAM_UNKNOWN_APPLICATION_ERROR_CODE:
185
800
  case quic::QUIC_STREAM_EXCESSIVE_LOAD:
186
800
  case quic::QUIC_HEADERS_TOO_LARGE:
187
800
    return Http::StreamResetReason::RemoteReset;
188
18
  case quic::QUIC_STREAM_GENERAL_PROTOCOL_ERROR:
189
22
  default:
190
22
    return Http::StreamResetReason::ProtocolError;
191
827
  }
192
827
}
193

            
194
Http::StreamResetReason quicErrorCodeToEnvoyLocalResetReason(quic::QuicErrorCode error,
195
971
                                                             bool connected) {
196
971
  switch (error) {
197
4
  case quic::QUIC_HANDSHAKE_FAILED:
198
4
  case quic::QUIC_HANDSHAKE_TIMEOUT:
199
4
    return Http::StreamResetReason::LocalConnectionFailure;
200
3
  case quic::QUIC_PACKET_WRITE_ERROR:
201
6
  case quic::QUIC_NETWORK_IDLE_TIMEOUT:
202
6
    return connected ? Http::StreamResetReason::ConnectionTermination
203
6
                     : Http::StreamResetReason::LocalConnectionFailure;
204
672
  case quic::QUIC_HTTP_FRAME_ERROR:
205
672
    return Http::StreamResetReason::ProtocolError;
206
289
  default:
207
289
    return Http::StreamResetReason::ConnectionTermination;
208
971
  }
209
971
}
210

            
211
876
Http::StreamResetReason quicErrorCodeToEnvoyRemoteResetReason(quic::QuicErrorCode error) {
212
876
  switch (error) {
213
2
  case quic::QUIC_HANDSHAKE_FAILED:
214
3
  case quic::QUIC_HANDSHAKE_TIMEOUT:
215
3
    return Http::StreamResetReason::RemoteConnectionFailure;
216
873
  default:
217
873
    return Http::StreamResetReason::ConnectionTermination;
218
876
  }
219
876
}
220

            
221
Network::ConnectionSocketPtr createConnectionSocket(
222
    const Network::Address::InstanceConstSharedPtr& peer_addr,
223
    Network::Address::InstanceConstSharedPtr& local_addr,
224
    const Network::ConnectionSocket::OptionsSharedPtr& options, quic::QuicNetworkHandle network,
225
3131
    std::function<void(Network::ConnectionSocket&, quic::QuicNetworkHandle)> custom_bind_func) {
226
3131
  ASSERT(peer_addr != nullptr);
227
  // NOTE: If changing the default cache size from 4 entries, make sure to profile it using
228
  // the benchmark test: //test/common/network:io_socket_handle_impl_benchmark
229
  //
230
  // If setting a higher cache size, try profiling std::deque instead of std::vector for the
231
  // `recent_received_addresses_` cache in
232
  // https://github.com/envoyproxy/envoy/blob/main/source/common/network/io_socket_handle_impl.h.
233
3131
  size_t max_addresses_cache_size =
234
3131
      Runtime::runtimeFeatureEnabled(
235
3131
          "envoy.reloadable_features.quic_upstream_socket_use_address_cache_for_read")
236
3131
          ? 4u
237
3131
          : 0u;
238
3131
  auto connection_socket = std::make_unique<Network::ConnectionSocketImpl>(
239
3131
      Network::Socket::Type::Datagram,
240
      // Use the loopback address if `local_addr` is null, to pass in the socket interface used to
241
      // create the IoHandle, without having to make the more expensive `getifaddrs` call.
242
3131
      local_addr ? local_addr : getLoopbackAddress(peer_addr), peer_addr,
243
3131
      Network::SocketCreationOptions{false, max_addresses_cache_size});
244
3131
  connection_socket->setDetectedTransportProtocol("quic");
245
3131
  if (!connection_socket->isOpen()) {
246
3
    ENVOY_LOG_MISC(error, "Failed to create quic socket");
247
3
    return connection_socket;
248
3
  }
249
3128
  if (!Runtime::runtimeFeatureEnabled(
250
3128
          "envoy.reloadable_features.disable_quic_ip_packet_info_socket_options")) {
251
3128
    connection_socket->addOptions(Network::SocketOptionFactory::buildIpPacketInfoOptions());
252
3128
  }
253
3128
  if (!Runtime::runtimeFeatureEnabled(
254
3128
          "envoy.reloadable_features.disable_quic_rx_queue_overflow_socket_options")) {
255
3128
    connection_socket->addOptions(Network::SocketOptionFactory::buildRxQueueOverFlowOptions());
256
3128
  }
257
3128
  connection_socket->addOptions(Network::SocketOptionFactory::buildIpRecvTosOptions());
258
3128
  if (Api::OsSysCallsSingleton::get().supportsUdpGro()) {
259
3123
    connection_socket->addOptions(Network::SocketOptionFactory::buildUdpGroOptions());
260
3123
  }
261
3128
  if (Runtime::runtimeFeatureEnabled("envoy.reloadable_features.udp_set_do_not_fragment")) {
262
3128
    int v6_only = 0;
263
3128
    if (connection_socket->ipVersion().has_value() &&
264
3128
        connection_socket->ipVersion().value() == Network::Address::IpVersion::v6) {
265
35
      socklen_t v6_only_len = sizeof(v6_only);
266
35
      Api::SysCallIntResult result =
267
35
          connection_socket->getSocketOption(IPPROTO_IPV6, IPV6_V6ONLY, &v6_only, &v6_only_len);
268
35
      if (result.return_value_ != 0) {
269
        ENVOY_LOG_MISC(
270
            error, "Failed to get IPV6_V6ONLY socket option, getsockopt() returned {}, errno {}",
271
            result.return_value_, result.errno_);
272
        connection_socket->close();
273
        return connection_socket;
274
      }
275
35
    }
276
3128
    connection_socket->addOptions(Network::SocketOptionFactory::buildDoNotFragmentOptions(
277
3128
        /*mapped_v6*/ connection_socket->ipVersion().value() == Network::Address::IpVersion::v6 &&
278
3128
        v6_only == 0));
279
3128
  }
280
3128
  if (options != nullptr) {
281
970
    connection_socket->addOptions(options);
282
970
  }
283
3128
  if (!Network::Socket::applyOptions(connection_socket->options(), *connection_socket,
284
3128
                                     envoy::config::core::v3::SocketOption::STATE_PREBIND)) {
285
1
    connection_socket->close();
286
1
    ENVOY_LOG_MISC(error, "Fail to apply pre-bind options");
287
1
    return connection_socket;
288
1
  }
289

            
290
3127
  if (local_addr != nullptr) {
291
2184
    connection_socket->bind(local_addr);
292
2184
    ASSERT(local_addr->ip());
293
2493
  } else if (network != quic::kInvalidNetworkHandle && custom_bind_func != nullptr) {
294
1
    custom_bind_func(*connection_socket, network);
295
1
    if (!connection_socket->isOpen()) {
296
1
      ENVOY_LOG_MISC(error, "Custom bind function failed");
297
1
      return connection_socket;
298
1
    }
299
1
  }
300

            
301
3126
  if (auto result = connection_socket->connect(peer_addr); result.return_value_ == -1) {
302
    connection_socket->close();
303
    ENVOY_LOG_MISC(error, "Fail to connect socket: ({}) {}", result.errno_,
304
                   errorDetails(result.errno_));
305
    return connection_socket;
306
  }
307

            
308
3126
  local_addr = connection_socket->connectionInfoProvider().localAddress();
309
3126
  ENVOY_LOG_MISC(trace, "connected to local address: {}",
310
3126
                 local_addr != nullptr ? local_addr->asString() : "<none>");
311
3126
  if (!Network::Socket::applyOptions(connection_socket->options(), *connection_socket,
312
3126
                                     envoy::config::core::v3::SocketOption::STATE_BOUND)) {
313
1
    ENVOY_LOG_MISC(error, "Fail to apply post-bind options");
314
1
    connection_socket->close();
315
1
  }
316
3126
  return connection_socket;
317
3126
}
318

            
319
bssl::UniquePtr<X509> parseDERCertificate(const std::string& der_bytes,
320
2961
                                          std::string* error_details) {
321
2961
  const uint8_t* data;
322
2961
  const uint8_t* orig_data;
323
2961
  orig_data = data = reinterpret_cast<const uint8_t*>(der_bytes.data());
324
2961
  bssl::UniquePtr<X509> cert(d2i_X509(nullptr, &data, der_bytes.size()));
325
2961
  if (!cert.get()) {
326
1
    *error_details = "d2i_X509: fail to parse DER";
327
1
    return nullptr;
328
1
  }
329
2960
  if (data < orig_data || static_cast<size_t>(data - orig_data) != der_bytes.size()) {
330
1
    *error_details = "There is trailing garbage in DER.";
331
1
    return nullptr;
332
1
  }
333
2959
  return cert;
334
2960
}
335

            
336
6908
int deduceSignatureAlgorithmFromPublicKey(const EVP_PKEY* public_key, std::string* error_details) {
337
6908
  int sign_alg = 0;
338
6908
  if (public_key == nullptr) {
339
1
    *error_details = "Invalid leaf cert, bad public key";
340
1
    return sign_alg;
341
1
  }
342
6907
  const int pkey_id = EVP_PKEY_id(public_key);
343
6907
  switch (pkey_id) {
344
27
  case EVP_PKEY_EC: {
345
    // We only support P-256 ECDSA today.
346
27
    const EC_KEY* ecdsa_public_key = EVP_PKEY_get0_EC_KEY(public_key);
347
    // Since we checked the key type above, this should be valid.
348
27
    ASSERT(ecdsa_public_key != nullptr);
349
27
    const EC_GROUP* ecdsa_group = EC_KEY_get0_group(ecdsa_public_key);
350
27
    if (ecdsa_group == nullptr || EC_GROUP_get_curve_name(ecdsa_group) != NID_X9_62_prime256v1) {
351
1
      *error_details = "Invalid leaf cert, only P-256 ECDSA certificates are supported";
352
1
      break;
353
1
    }
354
    // QUICHE uses SHA-256 as hash function in cert signature.
355
26
    sign_alg = SSL_SIGN_ECDSA_SECP256R1_SHA256;
356
26
  } break;
357
6880
  case EVP_PKEY_RSA: {
358
    // We require RSA certificates with 2048-bit or larger keys.
359
6880
    const RSA* rsa_public_key = EVP_PKEY_get0_RSA(public_key);
360
    // Since we checked the key type above, this should be valid.
361
6880
    ASSERT(rsa_public_key != nullptr);
362
6880
    const unsigned rsa_key_length = RSA_size(rsa_public_key);
363
6880
    const bool fips_mode = FIPS_mode();
364
6880
    if (fips_mode) {
365
      if (rsa_key_length != 2048 / 8 && rsa_key_length != 3072 / 8 && rsa_key_length != 4096 / 8) {
366
        *error_details = "Invalid leaf cert, only RSA certificates with 2048-bit, 3072-bit or "
367
                         "4096-bit keys are supported in FIPS mode";
368
        break;
369
      }
370
6880
    } else {
371
6880
      if (rsa_key_length < 2048 / 8) {
372
        *error_details =
373
            "Invalid leaf cert, only RSA certificates with 2048-bit or larger keys are supported";
374
        break;
375
      }
376
6880
    }
377
6880
    sign_alg = SSL_SIGN_RSA_PSS_RSAE_SHA256;
378
6880
  } break;
379
  default:
380
    *error_details = "Invalid leaf cert, only RSA and ECDSA certificates are supported";
381
6907
  }
382
6907
  return sign_alg;
383
6907
}
384

            
385
Network::ConnectionSocketPtr
386
createServerConnectionSocket(Network::IoHandle& io_handle,
387
                             const quic::QuicSocketAddress& self_address,
388
                             const quic::QuicSocketAddress& peer_address,
389
7768
                             const std::string& hostname, absl::string_view alpn) {
390
7768
  auto connection_socket = std::make_unique<Network::ConnectionSocketImpl>(
391
7768
      std::make_unique<QuicIoHandleWrapper>(io_handle),
392
7768
      quicAddressToEnvoyAddressInstance(self_address),
393
7768
      quicAddressToEnvoyAddressInstance(peer_address));
394
7768
  connection_socket->setDetectedTransportProtocol("quic");
395
7768
  connection_socket->setRequestedServerName(hostname);
396
7768
  connection_socket->setRequestedApplicationProtocols({alpn});
397
7768
  return connection_socket;
398
7768
}
399

            
400
void convertQuicConfig(const envoy::config::core::v3::QuicProtocolOptions& config,
401
4155
                       quic::QuicConfig& quic_config) {
402
4155
  int32_t max_streams = PROTOBUF_GET_WRAPPED_OR_DEFAULT(config, max_concurrent_streams, 100);
403
4155
  quic_config.SetMaxBidirectionalStreamsToSend(max_streams);
404
4155
  quic_config.SetMaxUnidirectionalStreamsToSend(max_streams);
405
4155
  configQuicInitialFlowControlWindow(config, quic_config);
406
4155
  quic_config.SetConnectionOptionsToSend(quic::ParseQuicTagVector(config.connection_options()));
407
4155
  quic_config.SetClientConnectionOptions(
408
4155
      quic::ParseQuicTagVector(config.client_connection_options()));
409
4155
  if (config.has_idle_network_timeout()) {
410
1
    quic_config.SetIdleNetworkTimeout(quic::QuicTimeDelta::FromSeconds(
411
1
        DurationUtil::durationToSeconds(config.idle_network_timeout())));
412
1
  }
413
4155
}
414

            
415
void configQuicInitialFlowControlWindow(const envoy::config::core::v3::QuicProtocolOptions& config,
416
4155
                                        quic::QuicConfig& quic_config) {
417
4155
  size_t stream_flow_control_window_to_send = PROTOBUF_GET_WRAPPED_OR_DEFAULT(
418
4155
      config, initial_stream_window_size,
419
4155
      Http3::Utility::OptionsLimits::DEFAULT_INITIAL_STREAM_WINDOW_SIZE);
420
4155
  if (stream_flow_control_window_to_send < quic::kMinimumFlowControlSendWindow) {
421
    // If the configured value is smaller than 16kB, only use it for IETF QUIC, because Google QUIC
422
    // requires minimum 16kB stream flow control window. The QUICHE default 16kB will be used for
423
    // Google QUIC connections.
424
11
    quic_config.SetInitialMaxStreamDataBytesIncomingBidirectionalToSend(
425
11
        stream_flow_control_window_to_send);
426
4150
  } else {
427
    // Both Google QUIC and IETF Quic can be configured from this.
428
4144
    quic_config.SetInitialStreamFlowControlWindowToSend(stream_flow_control_window_to_send);
429
4144
  }
430

            
431
4155
  uint32_t session_flow_control_window_to_send = PROTOBUF_GET_WRAPPED_OR_DEFAULT(
432
4155
      config, initial_connection_window_size,
433
4155
      Http3::Utility::OptionsLimits::DEFAULT_INITIAL_CONNECTION_WINDOW_SIZE);
434
  // Config connection level flow control window shouldn't be smaller than the minimum flow control
435
  // window supported in QUICHE which is 16kB.
436
4155
  quic_config.SetInitialSessionFlowControlWindowToSend(
437
4155
      std::max(quic::kMinimumFlowControlSendWindow,
438
4155
               static_cast<quic::QuicByteCount>(session_flow_control_window_to_send)));
439
4155
}
440

            
441
703182
quic::QuicEcnCodepoint getQuicEcnCodepointFromTosByte(uint8_t tos_byte) {
442
  // Explicit Congestion Notification is encoded in the two least significant
443
  // bits of the TOS byte of the IP header.
444
703182
  constexpr uint8_t kEcnMask = 0b00000011;
445
703182
  return static_cast<quic::QuicEcnCodepoint>(tos_byte & kEcnMask);
446
703182
}
447

            
448
3960
void registerCertCompression(SSL_CTX* ssl_ctx) {
449
3960
  if (Runtime::runtimeFeatureEnabled(
450
3961
          "envoy.reloadable_features.tls_certificate_compression_brotli")) {
451
3961
    Extensions::TransportSockets::Tls::CertCompression::registerBrotli(ssl_ctx);
452
3961
  }
453
3960
  Extensions::TransportSockets::Tls::CertCompression::registerZlib(ssl_ctx);
454
3960
}
455

            
456
} // namespace Quic
457
} // namespace Envoy