Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

quiche: implement ActiveQuicListener #7896

Merged
merged 107 commits into from
Sep 16, 2019
Merged
Show file tree
Hide file tree
Changes from 93 commits
Commits
Show all changes
107 commits
Select commit Hold shift + click to select a range
3253b11
add fake proof source/verifier
danzh1989 May 8, 2019
9914fb4
move to test
danzh1989 May 9, 2019
2ea58dd
Revert "move to test"
danzh1989 Jun 14, 2019
a8aa262
Merge branch 'master' into fakeproof
danzh1989 Jun 14, 2019
6b5315b
add tests
danzh1989 Jun 17, 2019
02e4fd9
actually add test file
danzh1989 Jun 17, 2019
6f8c2e4
Merge branch 'master' into fakeproof
danzh1989 Jun 19, 2019
58f3842
revert flag change
danzh1989 Jun 19, 2019
8fec99d
more comment
danzh1989 Jun 19, 2019
15e5e33
add words to dict
danzh1989 Jun 19, 2019
72c2f84
fix clang_tidy
danzh1989 Jun 19, 2019
25998ab
s/dummy/fake
danzh1989 Jun 20, 2019
2fd6df0
Merge branch 'master' into fakeproof
danzh1989 Jun 21, 2019
aacc588
update spell_dict
danzh1989 Jun 21, 2019
f68e5dd
add nofips
danzh1989 Jun 25, 2019
12ef3c7
fix build exlucsion
danzh1989 Jun 26, 2019
6029aeb
add more nofips
danzh1989 Jun 27, 2019
14f1e79
add build_tests_only
danzh1989 Jun 27, 2019
2fccff1
remove build_tag_filter for test
danzh1989 Jun 27, 2019
ef7cf28
update tarball
danzh1989 Jun 27, 2019
5419162
add all targets
danzh1989 Jun 28, 2019
117244f
fix http2 file path
danzh1989 Jul 1, 2019
1719fd0
build spdy
danzh1989 Jul 3, 2019
732b3c8
build quic http lib
danzh1989 Jul 3, 2019
f94f424
add server_push_utils
danzh1989 Jul 3, 2019
0d56de4
Merge branch 'master' into quichttp
danzh1989 Jul 3, 2019
bacb5c5
fix quic_platofrm_test
danzh1989 Jul 3, 2019
f04a469
fix typo
danzh1989 Jul 3, 2019
9ba2754
update spell dict
danzh1989 Jul 3, 2019
05daf8d
switch to NOT_IMPLEMENTED_GCOVR_EXCL_LINE
danzh1989 Jul 8, 2019
6eca9c6
envoy quic stream and session
danzh1989 Jul 10, 2019
b8fc520
Merge branch 'master' into quichttp
danzh1989 Jul 17, 2019
f5e0c11
add listener and test
danzh1989 Jul 24, 2019
b881ae8
more comment
danzh1989 Jul 25, 2019
3db6847
fix connection dealloc
danzh1989 Jul 25, 2019
1e55f68
fix format
danzh1989 Jul 25, 2019
ab474d5
fix stream test
danzh1989 Jul 26, 2019
5f7dd41
Merge branch 'master' into quichttp
danzh1989 Jul 26, 2019
fcfe160
remove debug log
danzh1989 Jul 26, 2019
9dc44be
decouple listener and quic dispatcher
danzh1989 Aug 5, 2019
7a2395f
delete listener impl
danzh1989 Aug 5, 2019
e9d66fa
Revert "delete listener impl"
danzh1989 Aug 5, 2019
3e4388b
test quic dispatcher
danzh1989 Aug 5, 2019
2397898
replace NOT_REACHED
danzh1989 Aug 6, 2019
0641fba
add tests
danzh1989 Aug 7, 2019
a5f8ba3
merge quichttp
danzh1989 Aug 7, 2019
30d976b
fix stream test
danzh1989 Aug 7, 2019
a50fc1e
fix asan
danzh1989 Aug 7, 2019
dbda7ef
Merge branch 'quichttp' into quiclistener2
danzh1989 Aug 7, 2019
ed15996
remove listener_lib
danzh1989 Aug 9, 2019
8b297e4
fix release failure
danzh1989 Aug 9, 2019
adbdee0
format
danzh1989 Aug 12, 2019
3dc7365
Merge branch 'quichttp' into quiclistener2
danzh1989 Aug 12, 2019
57144ed
remove unused .cc file
danzh1989 Aug 12, 2019
c9abaa5
Revert "remove listener_lib"
danzh1989 Aug 12, 2019
d278167
address comments
danzh1989 Aug 13, 2019
1b8117b
fix compile error
danzh1989 Aug 13, 2019
8375028
Merge branch 'master' into quichttp
danzh1989 Aug 13, 2019
6361860
Merge branch 'master' into quichttp
danzh1989 Aug 14, 2019
4e51861
error flush write
danzh1989 Aug 14, 2019
44e262f
ownership of connection
danzh1989 Aug 15, 2019
f2fc291
fix include
danzh1989 Aug 15, 2019
97b7d90
TODO for self_address
danzh1989 Aug 16, 2019
7361ca0
split utils to cc
danzh1989 Aug 19, 2019
10e85f6
add .cc file
danzh1989 Aug 19, 2019
5f55a97
spell
danzh1989 Aug 19, 2019
a4050dc
Merge branch 'master' into quichttp
danzh1989 Aug 23, 2019
81e5f9a
adjust comment
danzh1989 Aug 28, 2019
109e9a9
Merge branch 'master' into quichttp
danzh1989 Aug 28, 2019
9d545c5
fix typo
danzh1989 Aug 28, 2019
4e91aae
Merge branch 'master' into quichttp
danzh1989 Aug 29, 2019
7c863ef
fix stream test
danzh1989 Aug 29, 2019
c6f0763
fix pcc sender
danzh1989 Aug 29, 2019
bca0450
more test
danzh1989 Sep 3, 2019
42b5df3
add more tests
danzh1989 Sep 4, 2019
8891a14
fix coverage test failure
danzh1989 Sep 4, 2019
9a5468e
fix recvmsg test
danzh1989 Sep 4, 2019
1d23053
format
danzh1989 Sep 4, 2019
817c08d
revert Http3
danzh1989 Sep 5, 2019
5987586
Merge branch 'quichttp' into quiclistener2
danzh1989 Sep 5, 2019
3405bfc
more unit tests, remove isQuic
danzh1989 Sep 6, 2019
548f8f5
comments
danzh1989 Sep 6, 2019
b218f5a
fix session test
danzh1989 Sep 6, 2019
3deb19e
active listener factory creation
danzh1989 Sep 9, 2019
be37cb1
skip coverage for quiche
danzh1989 Sep 9, 2019
d7c551f
Merge branch 'master' into quichttp
danzh1989 Sep 9, 2019
bb1e435
update interface change
danzh1989 Sep 9, 2019
799c5fa
Merge branch 'quichttp' into quiclistener2
danzh1989 Sep 9, 2019
c617a40
test for quic config
danzh1989 Sep 9, 2019
7618f8b
Merge branch 'master' into quiclistener2
danzh1989 Sep 9, 2019
6a58153
comments
danzh1989 Sep 9, 2019
c8428df
remove go_package
danzh1989 Sep 9, 2019
8e4d2a6
add test for config factory
danzh1989 Sep 10, 2019
4b3d7be
more logging details
danzh1989 Sep 10, 2019
11b653f
rewording
danzh1989 Sep 10, 2019
dcbb7d0
rename protobuf
danzh1989 Sep 11, 2019
6ecaff1
fix doc ci
danzh1989 Sep 11, 2019
fe5a5fa
add nofips
danzh1989 Sep 11, 2019
dfc26fd
split quic test for listener manager
danzh1989 Sep 11, 2019
c7e416d
remove downcast
danzh1989 Sep 12, 2019
5b317be
fix build error
danzh1989 Sep 12, 2019
32d0e78
format
danzh1989 Sep 12, 2019
2b0273f
fix EXPECT_CALL
danzh1989 Sep 12, 2019
2a6efb5
clang
danzh1989 Sep 12, 2019
94dc9a3
rename quic listener
danzh1989 Sep 13, 2019
ce75217
fix udp_listener_name in test
danzh1989 Sep 16, 2019
e31e933
move quic listener name definition
danzh1989 Sep 16, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions api/envoy/api/v2/listener/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,9 @@ api_proto_library_internal(
"//envoy/api/v2/core:base",
],
)

api_proto_library_internal(
name = "quic_config",
srcs = ["quic_config.proto"],
visibility = ["//envoy/api/v2:friends"],
)
25 changes: 25 additions & 0 deletions api/envoy/api/v2/listener/quic_config.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
syntax = "proto3";

package envoy.api.v2.listener;

option java_outer_classname = "ListenerProto";
option java_multiple_files = true;
option java_package = "io.envoyproxy.envoy.api.v2.listener";
option csharp_namespace = "Envoy.Api.V2.ListenerNS";
option ruby_package = "Envoy::Api::V2::ListenerNS";

// Configuration specific to the QUIC protocol.
// Next id: 4
message QuicConfigProto {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

QuicProtocolOptions to mirror Http2ProtocolOptions and TcpProtocolOptions

Though do we want to say QUIC or H3? Itooks to me like this is all QUIC specific, but if we have configuration options which are H2 specific (say HPACK related) what do we want the structure to be? I'd think we'd want Http3ProtocolOptions containing QuicProtocolOptions so we can reuse QuicProtocolOptions for non-HTTP3 things like QuicWebRTC

@ianswett @envoyproxy/api-shepherds for thoughts

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that QUIC is a transport and H3 is an application, separate configs make sense, though it's not how the code is currently structured.

If we create separate configs, I'm not sure whether nesting makes more sense or putting them side-by-side? If TcpProtocolOptions is inside Http2ProtocolOptions, then following that pattern is the most obvious approach.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Http2ProtocolOptions seems to already have all the config we want. But it's a network filter (HCM) proto, which is not accessed before connection is created.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Http2ProtocolOptions is in protocol.proto so we can easily reuse it, but don't we have issues with HPACK settings? Should we make QuicProtocolOptions and Http3ProtocolOptions as needed and clean this up in v3 if there are shared message possibilities?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point that Http2ProtocolOptions has unwanted HPACK setting config except for the stream multiplexing config which we wanted in QuicProtocolOptions. And Http3ProtocolOptions will have its own config for things like QPACK table size. I think it's better not to reuse Http2ProtocolOptions, instead, adding all the fields needed in our own protobuf messages, basically, as it is currently defined now. WDYT?

Since I didn't know protocol.proto before, would it make more sense to define QuicProtocolOptions and Http3ProtocolOptions there instead?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd be cool with adding them there, but given we want QUIC to be optional, I don't know if we want to be purists about having the protos compiled out.

I'm inclined to say it's useful to have all transport things in the same place, even the optional ones, given that the protos will only add negligable overhead to non-QUIC builds.

@htuch would be the person to ask but he's out this week. I'm good with landing it in either place and checking in with him when he gets back, since they'll be hidden and "Ok" to move without the deprecation dance.

// Maximum number of streams that the client can negotiate per connection. 100
// if not specified.
int32 max_streams_per_connection = 1;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also let's model naming off of existing config where we can
api/envoy/api/v2/core/protocol.proto -> max_concurrent_streams

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should I include envoy::api::v2::core::Http2ProtocolOptions here instead of duplicating the same fields?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 please reuse messages where we can, though per the comment above if there are HPACK options in Http2ProtocolOptions I'm not sure if we will be able to do it?

Copy link
Contributor Author

@danzh2010 danzh2010 Sep 11, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about defining stand alone fields here for now and consolidate with H2/TCP Proto options later?


// Maximum number of milliseconds that connection will be alive when there is
// no network activity. 300000ms if not specified.
int32 idle_network_timeout_ms = 2;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is comparable to
google.protobuf.Duration idle_timeout
in tcp_proxy.proto, WDYT?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reuse TcpProxy message or define our own here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TcpProxy message is for raw tcp proxying, (including things like upstream (backend) configuration) so I don't think we want to reuse the proto, just have similar names.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


// Connection timeout before the crypto handshake is finished. 20s if not
// specified.
int32 max_time_before_crypto_handshake_ms = 3;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was assuming there was an equivalent for TLS but I'm not seeing it. @PiotrSikora am I missing this or do we not configure handshake specific timeouts?

Either way should probably be a Duration

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't believe we have one today, it's just covered under the general idle timeout.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, if this is the first of its kind we can't totally copy naming, but I'd lean towards having timeout in there somewhere. handshake_timeout? crypto_handshake_timeout? I think we've gone for "idle timeout" for keepalive style timeouts, and just "timeout" for overall timeouts, like http connection manager's request_timeout for overall request duration

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

renamed it to crypto_handshake_timeout

}
10 changes: 10 additions & 0 deletions include/envoy/network/connection_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,16 @@ class ConnectionHandler {
*/
virtual uint64_t numConnections() PURE;

/**
* Increment the return value of numConnections() by one.
*/
virtual void incNumConnections() PURE;
mattklein123 marked this conversation as resolved.
Show resolved Hide resolved

/**
* Decrement the return value of numConnections() by one.
*/
virtual void decNumConnections() PURE;

/**
* Adds a listener to the handler.
* @param config listener configuration options.
Expand Down
4 changes: 4 additions & 0 deletions include/envoy/server/active_udp_listener_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

#include "envoy/network/connection_handler.h"

#include "common/protobuf/protobuf.h"

namespace Envoy {
namespace Server {

Expand All @@ -13,6 +15,8 @@ class ActiveUdpListenerConfigFactory {
public:
virtual ~ActiveUdpListenerConfigFactory() = default;

virtual ProtobufTypes::MessagePtr createEmptyConfigProto() PURE;

/**
* Create an ActiveUdpListenerFactory object according to given message.
*/
Expand Down
30 changes: 30 additions & 0 deletions source/extensions/quic_listeners/quiche/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,36 @@ envoy_cc_library(
],
)

envoy_cc_library(
name = "active_quic_listener_lib",
srcs = ["active_quic_listener.cc"],
hdrs = ["active_quic_listener.h"],
tags = ["nofips"],
deps = [
":envoy_quic_alarm_factory_lib",
":envoy_quic_connection_helper_lib",
":envoy_quic_dispatcher_lib",
":envoy_quic_packet_writer_lib",
":envoy_quic_proof_source_lib",
":envoy_quic_utils_lib",
"//include/envoy/network:listener_interface",
"//source/common/network:listener_lib",
"//source/server:connection_handler_lib",
"@envoy_api//envoy/api/v2/listener:quic_config_cc",
],
)

envoy_cc_library(
name = "active_quic_listener_config_lib",
mattklein123 marked this conversation as resolved.
Show resolved Hide resolved
srcs = ["active_quic_listener_config.cc"],
hdrs = ["active_quic_listener_config.h"],
deps = [
":active_quic_listener_lib",
"//include/envoy/registry",
"//source/server:well_known_names_lib",
],
)

envoy_cc_library(
name = "envoy_quic_utils_lib",
srcs = ["envoy_quic_utils.cc"],
Expand Down
76 changes: 76 additions & 0 deletions source/extensions/quic_listeners/quiche/active_quic_listener.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#include "extensions/quic_listeners/quiche/active_quic_listener.h"

#include "extensions/quic_listeners/quiche/envoy_quic_alarm_factory.h"
#include "extensions/quic_listeners/quiche/envoy_quic_connection_helper.h"
#include "extensions/quic_listeners/quiche/envoy_quic_dispatcher.h"
#include "extensions/quic_listeners/quiche/envoy_quic_fake_proof_source.h"
#include "extensions/quic_listeners/quiche/envoy_quic_packet_writer.h"
#include "extensions/quic_listeners/quiche/envoy_quic_utils.h"

namespace Envoy {
namespace Quic {

ActiveQuicListener::ActiveQuicListener(Event::Dispatcher& dispatcher,
Network::ConnectionHandler& parent, spdlog::logger& logger,
Network::ListenerConfig& listener_config,
const quic::QuicConfig& quic_config)
: ActiveQuicListener(dispatcher, parent,
dispatcher.createUdpListener(listener_config.socket(), *this), logger,
listener_config, quic_config) {}

ActiveQuicListener::ActiveQuicListener(Event::Dispatcher& dispatcher,
Network::ConnectionHandler& parent,
Network::ListenerPtr&& listener, spdlog::logger& logger,
Network::ListenerConfig& listener_config,
const quic::QuicConfig& quic_config)
: Server::ConnectionHandlerImpl::ActiveListenerImplBase(std::move(listener), listener_config),
logger_(logger), dispatcher_(dispatcher), version_manager_(quic::CurrentSupportedVersions()) {
quic::QuicRandom* const random = quic::QuicRandom::GetInstance();
random->RandBytes(random_seed_, sizeof(random_seed_));
crypto_config_ = std::make_unique<quic::QuicCryptoServerConfig>(
quic::QuicStringPiece(reinterpret_cast<char*>(random_seed_), sizeof(random_seed_)),
quic::QuicRandom::GetInstance(), std::make_unique<EnvoyQuicFakeProofSource>(),
quic::KeyExchangeSource::Default());
auto connection_helper = std::make_unique<EnvoyQuicConnectionHelper>(dispatcher_);
auto alarm_factory =
std::make_unique<EnvoyQuicAlarmFactory>(dispatcher_, *connection_helper->GetClock());
quic_dispatcher_ = std::make_unique<EnvoyQuicDispatcher>(
crypto_config_.get(), quic_config, &version_manager_, std::move(connection_helper),
std::move(alarm_factory), quic::kQuicDefaultConnectionIdLength, parent, config_, stats_,
dispatcher);
quic_dispatcher_->InitializeWithWriter(
new EnvoyQuicPacketWriter(*dynamic_cast<Network::UdpListener*>(listener_.get())));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a TODO here to try to get rid of the dynamic cast? I will try to look at this myself and provide some guidance instead of just complaining. :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one is easy to remove actually. I modified Dispatcher interface and ActiveQuicListener constructor a bit. Done

}

void ActiveQuicListener::onListenerShutdown() {
ENVOY_LOG_TO_LOGGER(logger_, info, "Listener shutdown.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: can we make this log message more useful? Especially if it stays info level?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a once per lifetime message, so I think it worth to be at info level. I added the listener tag in the log. Would it be more useful then?

quic_dispatcher_->Shutdown();
}

void ActiveQuicListener::onData(Network::UdpRecvData& data) {
quic::QuicSocketAddress peer_address(envoyAddressInstanceToQuicSocketAddress(data.peer_address_));
quic::QuicSocketAddress self_address(
envoyAddressInstanceToQuicSocketAddress(data.local_address_));
quic::QuicTime timestamp =
quic::QuicTime::Zero() +
quic::QuicTime::Delta::FromMilliseconds(std::chrono::duration_cast<std::chrono::milliseconds>(
data.receive_time_.time_since_epoch())
.count());
uint64_t num_slice = data.buffer_->getRawSlices(nullptr, 0);
ASSERT(num_slice == 1);
Buffer::RawSlice slice;
data.buffer_->getRawSlices(&slice, 1);
// TODO(danzh): pass in TTL and UDP header.
quic::QuicReceivedPacket packet(reinterpret_cast<char*>(slice.mem_), slice.len_, timestamp,
/*owns_buffer=*/false, /*ttl=*/0, /*ttl_valid=*/true,
/*packet_headers=*/nullptr, /*headers_length=*/0,
/*owns_header_buffer*/ false);
quic_dispatcher_->ProcessPacket(self_address, peer_address, packet);
}

void ActiveQuicListener::onWriteReady(const Network::Socket& /*socket*/) {
quic_dispatcher_->OnCanWrite();
}

} // namespace Quic
} // namespace Envoy
98 changes: 98 additions & 0 deletions source/extensions/quic_listeners/quiche/active_quic_listener.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
#pragma once

#include "envoy/api/v2/listener/quic_config.pb.h"
#include "envoy/network/connection_handler.h"
#include "envoy/network/listener.h"

#include "server/connection_handler_impl.h"

#include "extensions/quic_listeners/quiche/envoy_quic_dispatcher.h"

namespace Envoy {
namespace Quic {

// QUIC specific UdpListenerCallbacks implemention which delegates incoming
// packets, write signals and listener errors to QuicDispatcher.
class ActiveQuicListener : public Network::UdpListenerCallbacks,
public Server::ConnectionHandlerImpl::ActiveListenerImplBase,
// Inherits below two interfaces just to have common
mattklein123 marked this conversation as resolved.
Show resolved Hide resolved
// interfaces. Not expected to support listener
// filter.
public Network::UdpListenerFilterManager,
public Network::UdpReadFilterCallbacks {
public:
ActiveQuicListener(Event::Dispatcher& dispatcher, Network::ConnectionHandler& parent,
spdlog::logger& logger, Network::ListenerConfig& listener_config,
const quic::QuicConfig& quic_config);

ActiveQuicListener(Event::Dispatcher& dispatcher, Network::ConnectionHandler& parent,
Network::ListenerPtr&& listener, spdlog::logger& logger,
Network::ListenerConfig& listener_config, const quic::QuicConfig& quic_config);
// TODO(#7465): Make this a callback.
void onListenerShutdown();

// Network::UdpListenerCallbacks
void onData(Network::UdpRecvData& data) override;
void onWriteReady(const Network::Socket& socket) override;
void onReceiveError(const Network::UdpListenerCallbacks::ErrorCode& /*error_code*/,
Api::IoError::IoErrorCode /*err*/) override {
// No-op. Quic can't do anything upon listener error.
}

// Network::UdpListenerFilterManager
void addReadFilter(Network::UdpListenerReadFilterPtr&& /*filter*/) override {
// QUIC doesn't support listener filter.
NOT_REACHED_GCOVR_EXCL_LINE;
}

// Network::UdpReadFilterCallbacks
Network::UdpListener& udpListener() override { NOT_REACHED_GCOVR_EXCL_LINE; }

private:
friend class ActiveQuicListenerPeer;

uint8_t random_seed_[16];
std::unique_ptr<quic::QuicCryptoServerConfig> crypto_config_;
spdlog::logger& logger_;
Event::Dispatcher& dispatcher_;
quic::QuicVersionManager version_manager_;
std::unique_ptr<EnvoyQuicDispatcher> quic_dispatcher_;
};

using ActiveQuicListenerPtr = std::unique_ptr<ActiveQuicListener>;

// A factory to create ActiveQuicListener based on given config.
class ActiveQuicListenerFactory : public Network::ActiveUdpListenerFactory {
public:
ActiveQuicListenerFactory(const envoy::api::v2::listener::QuicConfigProto& config) {
int32_t idle_network_timeout_ms =
config.idle_network_timeout_ms() == 0 ? 300000 : config.idle_network_timeout_ms();
quic_config_.SetIdleNetworkTimeout(
quic::QuicTime::Delta::FromMilliseconds(idle_network_timeout_ms),
quic::QuicTime::Delta::FromMilliseconds(idle_network_timeout_ms));
int32_t max_time_before_crypto_handshake_ms =
config.max_time_before_crypto_handshake_ms() == 0
? 20000
: config.max_time_before_crypto_handshake_ms();
quic_config_.set_max_time_before_crypto_handshake(
quic::QuicTime::Delta::FromMilliseconds(max_time_before_crypto_handshake_ms));
int32_t max_streams =
config.max_streams_per_connection() == 0 ? 100 : config.max_streams_per_connection();
quic_config_.SetMaxIncomingBidirectionalStreamsToSend(max_streams);
quic_config_.SetMaxIncomingUnidirectionalStreamsToSend(max_streams);
}

Network::ConnectionHandler::ActiveListenerPtr
createActiveUdpListener(Network::ConnectionHandler& parent, Event::Dispatcher& disptacher,
spdlog::logger& logger, Network::ListenerConfig& config) const override {
return std::make_unique<ActiveQuicListener>(disptacher, parent, logger, config, quic_config_);
}

private:
friend class ActiveQuicListenerFactoryPeer;

quic::QuicConfig quic_config_;
};

} // namespace Quic
} // namespace Envoy
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include "extensions/quic_listeners/quiche/active_quic_listener_config.h"

#include "envoy/api/v2/listener/quic_config.pb.h"

#include "server/well_known_names.h"

#include "extensions/quic_listeners/quiche/active_quic_listener.h"

namespace Envoy {
namespace Quic {

ProtobufTypes::MessagePtr ActiveQuicListenerConfigFactory::createEmptyConfigProto() {
return std::make_unique<envoy::api::v2::listener::QuicConfigProto>();
}

Network::ActiveUdpListenerFactoryPtr
ActiveQuicListenerConfigFactory::createActiveUdpListenerFactory(const Protobuf::Message& message) {
auto& config = dynamic_cast<const envoy::api::v2::listener::QuicConfigProto&>(message);
return std::make_unique<ActiveQuicListenerFactory>(config);
}

std::string ActiveQuicListenerConfigFactory::name() { return Server::UdpListenerNames::get().Quic; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The name can now be moved out of Server::UdpListenerNames and just inlined here? I don't think it needs to live outside the extension? (If it does please move it into an extension well known names file)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what inline means here. The string is also used in tests. So I added a statistic const in the .h file.


REGISTER_FACTORY(ActiveQuicListenerConfigFactory, Server::ActiveUdpListenerConfigFactory);

} // namespace Quic
} // namespace Envoy
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#pragma once

#include "envoy/registry/registry.h"
#include "envoy/server/active_udp_listener_config.h"

namespace Envoy {
namespace Quic {

// A factory to create ActiveQuicListenerFactory based on given protobuf.
class ActiveQuicListenerConfigFactory : public Server::ActiveUdpListenerConfigFactory {
public:
ProtobufTypes::MessagePtr createEmptyConfigProto() override;

Network::ActiveUdpListenerFactoryPtr
createActiveUdpListenerFactory(const Protobuf::Message&) override;

std::string name() override;
};

DECLARE_FACTORY(ActiveQuicListenerConfigFactory);

} // namespace Quic
} // namespace Envoy
20 changes: 11 additions & 9 deletions source/extensions/quic_listeners/quiche/envoy_quic_dispatcher.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,18 @@ namespace Envoy {
namespace Quic {

EnvoyQuicDispatcher::EnvoyQuicDispatcher(
const quic::QuicCryptoServerConfig* crypto_config, quic::QuicVersionManager* version_manager,
const quic::QuicCryptoServerConfig* crypto_config, const quic::QuicConfig& quic_config,
quic::QuicVersionManager* version_manager,
std::unique_ptr<quic::QuicConnectionHelperInterface> helper,
std::unique_ptr<quic::QuicAlarmFactory> alarm_factory,
uint8_t expected_server_connection_id_length, Server::ConnectionHandlerImpl& connection_handler,
Network::ListenerConfig& listener_config, Server::ListenerStats& listener_stats)
: quic::QuicDispatcher(&quic_config_, crypto_config, version_manager, std::move(helper),
uint8_t expected_server_connection_id_length, Network::ConnectionHandler& connection_handler,
Network::ListenerConfig& listener_config, Server::ListenerStats& listener_stats,
Event::Dispatcher& dispatcher)
: quic::QuicDispatcher(&quic_config, crypto_config, version_manager, std::move(helper),
std::make_unique<EnvoyQuicCryptoServerStreamHelper>(),
std::move(alarm_factory), expected_server_connection_id_length),
connection_handler_(connection_handler), listener_config_(listener_config),
listener_stats_(listener_stats) {
listener_stats_(listener_stats), dispatcher_(dispatcher) {
// Turn off chlo buffering in QuicDispatcher because per event loop clean
// up is not implemented.
// TODO(danzh): Add a per event loop callback to
Expand All @@ -29,8 +31,8 @@ void EnvoyQuicDispatcher::OnConnectionClosed(quic::QuicConnectionId connection_i
const std::string& error_details,
quic::ConnectionCloseSource source) {
quic::QuicDispatcher::OnConnectionClosed(connection_id, error, error_details, source);
ASSERT(connection_handler_.num_connections_ > 0);
--connection_handler_.num_connections_;
ASSERT(connection_handler_.numConnections() > 0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you move this assert into the dec call itself?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

connection_handler_.decNumConnections();
}

quic::QuicSession* EnvoyQuicDispatcher::CreateQuicSession(
Expand All @@ -42,15 +44,15 @@ quic::QuicSession* EnvoyQuicDispatcher::CreateQuicSession(
listener_config_, listener_stats_);
auto quic_session = new EnvoyQuicServerSession(
config(), quic::ParsedQuicVersionVector{version}, std::move(quic_connection), this,
session_helper(), crypto_config(), compressed_certs_cache(), connection_handler_.dispatcher_);
session_helper(), crypto_config(), compressed_certs_cache(), dispatcher_);
quic_session->Initialize();
// Filter chain can't be retrieved here as self address is unknown at this
// point.
// TODO(danzh): change QUIC interface to pass in self address as it is already
// known. In this way, filter chain can be retrieved at this point. But one
// thing to pay attention is that if the retrival fails, connection needs to
// be closed, and it should be added to time wait list instead of session map.
++connection_handler_.num_connections_;
connection_handler_.incNumConnections();
return quic_session;
}

Expand Down
Loading