forked from envoyproxy/envoy
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
quiche: implement ActiveQuicListener (envoyproxy#7896)
Signed-off-by: Dan Zhang <danzh@google.com>
- Loading branch information
Showing
32 changed files
with
852 additions
and
146 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
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"; | ||
|
||
import "google/protobuf/duration.proto"; | ||
import "google/protobuf/wrappers.proto"; | ||
|
||
// Configuration specific to the QUIC protocol. | ||
// Next id: 4 | ||
message QuicProtocolOptions { | ||
// Maximum number of streams that the client can negotiate per connection. 100 | ||
// if not specified. | ||
google.protobuf.UInt32Value max_concurrent_streams = 1; | ||
|
||
// Maximum number of milliseconds that connection will be alive when there is | ||
// no network activity. 300000ms if not specified. | ||
google.protobuf.Duration idle_timeout = 2; | ||
|
||
// Connection timeout in milliseconds before the crypto handshake is finished. | ||
// 20000ms if not specified. | ||
google.protobuf.Duration crypto_handshake_timeout = 3; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
84 changes: 84 additions & 0 deletions
84
source/extensions/quic_listeners/quiche/active_quic_listener.cc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
#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::UdpListenerPtr&& listener, spdlog::logger& logger, | ||
Network::ListenerConfig& listener_config, | ||
const quic::QuicConfig& quic_config) | ||
: ActiveQuicListener(dispatcher, parent, std::make_unique<EnvoyQuicPacketWriter>(*listener), | ||
std::move(listener), logger, listener_config, quic_config) {} | ||
|
||
ActiveQuicListener::ActiveQuicListener(Event::Dispatcher& dispatcher, | ||
Network::ConnectionHandler& parent, | ||
std::unique_ptr<quic::QuicPacketWriter> writer, | ||
Network::UdpListenerPtr&& 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(writer.release()); | ||
} | ||
|
||
void ActiveQuicListener::onListenerShutdown() { | ||
ENVOY_LOG_TO_LOGGER(logger_, info, "Quic listener {} shutdown.", config_.name()); | ||
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 |
107 changes: 107 additions & 0 deletions
107
source/extensions/quic_listeners/quiche/active_quic_listener.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
#pragma once | ||
|
||
#include "envoy/api/v2/listener/quic_config.pb.h" | ||
#include "envoy/network/connection_handler.h" | ||
#include "envoy/network/listener.h" | ||
|
||
#include "common/protobuf/utility.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 | ||
// interfaces. Not expected to support listener | ||
// filter. | ||
// TODO(danzh): clean up meaningless inheritance. | ||
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::UdpListenerPtr&& 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; | ||
|
||
ActiveQuicListener(Event::Dispatcher& dispatcher, Network::ConnectionHandler& parent, | ||
std::unique_ptr<quic::QuicPacketWriter> writer, | ||
Network::UdpListenerPtr&& listener, spdlog::logger& logger, | ||
Network::ListenerConfig& listener_config, const quic::QuicConfig& quic_config); | ||
|
||
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::QuicProtocolOptions& config) { | ||
uint64_t idle_network_timeout_ms = | ||
config.has_idle_timeout() ? DurationUtil::durationToMilliseconds(config.idle_timeout()) | ||
: 300000; | ||
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.has_crypto_handshake_timeout() | ||
? DurationUtil::durationToMilliseconds(config.crypto_handshake_timeout()) | ||
: 20000; | ||
quic_config_.set_max_time_before_crypto_handshake( | ||
quic::QuicTime::Delta::FromMilliseconds(max_time_before_crypto_handshake_ms)); | ||
int32_t max_streams = PROTOBUF_GET_WRAPPED_OR_DEFAULT(config, max_concurrent_streams, 100); | ||
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 |
25 changes: 25 additions & 0 deletions
25
source/extensions/quic_listeners/quiche/active_quic_listener_config.cc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
#include "extensions/quic_listeners/quiche/active_quic_listener_config.h" | ||
|
||
#include "envoy/api/v2/listener/quic_config.pb.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::QuicProtocolOptions>(); | ||
} | ||
|
||
Network::ActiveUdpListenerFactoryPtr | ||
ActiveQuicListenerConfigFactory::createActiveUdpListenerFactory(const Protobuf::Message& message) { | ||
auto& config = dynamic_cast<const envoy::api::v2::listener::QuicProtocolOptions&>(message); | ||
return std::make_unique<ActiveQuicListenerFactory>(config); | ||
} | ||
|
||
std::string ActiveQuicListenerConfigFactory::name() { return QuicListenerName; } | ||
|
||
REGISTER_FACTORY(ActiveQuicListenerConfigFactory, Server::ActiveUdpListenerConfigFactory); | ||
|
||
} // namespace Quic | ||
} // namespace Envoy |
Oops, something went wrong.