Switch QuicServer to use QuicEventLoop instead of QuicEpollServer This allows QuicServer to work on all platforms supported by QuicEventLoop, instead of being Linux-only. PiperOrigin-RevId: 460286930
diff --git a/quiche/quic/bindings/quic_libevent.cc b/quiche/quic/bindings/quic_libevent.cc index 668f441..996d70b 100644 --- a/quiche/quic/bindings/quic_libevent.cc +++ b/quiche/quic/bindings/quic_libevent.cc
@@ -35,30 +35,33 @@ LibeventAlarm(LibeventQuicEventLoop* loop, QuicArenaScopedPtr<QuicAlarm::Delegate> delegate) : QuicAlarm(std::move(delegate)), clock_(loop->clock()) { - evtimer_assign( - &event_, loop->base(), + event_.reset(evtimer_new( + loop->base(), [](evutil_socket_t, LibeventEventMask, void* arg) { LibeventAlarm* self = reinterpret_cast<LibeventAlarm*>(arg); self->Fire(); }, - this); + this)); } - ~LibeventAlarm() { event_del(&event_); } protected: void SetImpl() override { absl::Duration timeout = absl::Microseconds((deadline() - clock_->Now()).ToMicroseconds()); timeval unix_time = absl::ToTimeval(timeout); - event_add(&event_, &unix_time); + event_add(event_.get(), &unix_time); } - void CancelImpl() override { event_del(&event_); } + void CancelImpl() override { event_del(event_.get()); } private: - // While this decreases ABI portability, we use event inline, rather than - // allocating it with event_new(), since this improves cache locality. - event event_; + // While we inline `struct event` elsewhere, it is actually quite large, so + // doing that for the libevent-based QuicAlarm would cause it to not fit into + // the QuicConnectionArena. + struct EventDeleter { + void operator()(event* ev) { event_free(ev); } + }; + std::unique_ptr<event, EventDeleter> event_; QuicClock* clock_; }; @@ -205,8 +208,9 @@ void operator()(event_config* config) { event_config_free(config); } }; -std::unique_ptr<QuicEventLoop> QuicLibeventEventLoopFactory::Create( - QuicClock* clock) { +std::unique_ptr<LibeventQuicEventLoopWithOwnership> +LibeventQuicEventLoopWithOwnership::Create(QuicClock* clock, + bool force_level_triggered) { // Required for event_base_loopbreak() to actually work. static int threads_initialized = []() { #ifdef _WIN32 @@ -219,7 +223,7 @@ std::unique_ptr<event_config, LibeventConfigDeleter> config( event_config_new()); - if (force_level_triggered_) { + if (force_level_triggered) { // epoll and kqueue are the two only current libevent backends that support // edge-triggered I/O. event_config_avoid_method(config.get(), "epoll");
diff --git a/quiche/quic/bindings/quic_libevent.h b/quiche/quic/bindings/quic_libevent.h index 5eabb45..d8aa493 100644 --- a/quiche/quic/bindings/quic_libevent.h +++ b/quiche/quic/bindings/quic_libevent.h
@@ -109,6 +109,9 @@ : public LibeventLoop, public LibeventQuicEventLoop { public: + static std::unique_ptr<LibeventQuicEventLoopWithOwnership> Create( + QuicClock* clock, bool force_level_triggered = false); + // Takes ownership of |base|. explicit LibeventQuicEventLoopWithOwnership(struct event_base* base, QuicClock* clock) @@ -134,7 +137,10 @@ return factory; } - std::unique_ptr<QuicEventLoop> Create(QuicClock* clock) override; + std::unique_ptr<QuicEventLoop> Create(QuicClock* clock) override { + return LibeventQuicEventLoopWithOwnership::Create(clock, + force_level_triggered_); + } std::string GetName() const override { return name_; } private:
diff --git a/quiche/quic/core/http/end_to_end_test.cc b/quiche/quic/core/http/end_to_end_test.cc index c1c46f0..8b7add5 100644 --- a/quiche/quic/core/http/end_to_end_test.cc +++ b/quiche/quic/core/http/end_to_end_test.cc
@@ -21,6 +21,8 @@ #include "quiche/quic/core/http/http_constants.h" #include "quiche/quic/core/http/quic_spdy_client_stream.h" #include "quiche/quic/core/http/web_transport_http3.h" +#include "quiche/quic/core/io/quic_default_event_loop.h" +#include "quiche/quic/core/io/quic_event_loop.h" #include "quiche/quic/core/quic_connection.h" #include "quiche/quic/core/quic_constants.h" #include "quiche/quic/core/quic_data_writer.h" @@ -98,9 +100,11 @@ // Run all tests with the cross products of all versions. struct TestParams { TestParams(const ParsedQuicVersion& version, QuicTag congestion_control_tag, + QuicEventLoopFactory* event_loop, int override_server_connection_id_length) : version(version), congestion_control_tag(congestion_control_tag), + event_loop(event_loop), override_server_connection_id_length( override_server_connection_id_length) {} @@ -108,6 +112,7 @@ os << "{ version: " << ParsedQuicVersionToString(p.version); os << " congestion_control_tag: " << QuicTagToString(p.congestion_control_tag) + << " event loop: " << p.event_loop->GetName() << " connection ID length: " << p.override_server_connection_id_length << " }"; return os; @@ -115,6 +120,7 @@ ParsedQuicVersion version; QuicTag congestion_control_tag; + QuicEventLoopFactory* event_loop; int override_server_connection_id_length; }; @@ -122,7 +128,8 @@ std::string PrintToString(const TestParams& p) { std::string rv = absl::StrCat( ParsedQuicVersionToString(p.version), "_", - QuicTagToString(p.congestion_control_tag), "_", + QuicTagToString(p.congestion_control_tag), "_", p.event_loop->GetName(), + "_", std::to_string((p.override_server_connection_id_length == -1) ? static_cast<int>(kQuicDefaultConnectionIdLength) : p.override_server_connection_id_length)); @@ -148,12 +155,22 @@ // qQUIC as well. if (connection_id_length == -1 || version.UsesTls()) { params.push_back(TestParams(version, congestion_control_tag, + GetDefaultEventLoop(), connection_id_length)); } } // End of outer version loop. } // End of congestion_control_tag loop. } // End of connection_id_length loop. + // Only run every event loop implementation for one fixed configuration. + for (QuicEventLoopFactory* event_loop : GetAllSupportedEventLoops()) { + if (event_loop == GetDefaultEventLoop()) { + continue; + } + params.push_back( + TestParams(ParsedQuicVersion::RFCv1(), kTBBR, event_loop, -1)); + } + return params; }
diff --git a/quiche/quic/core/io/quic_default_event_loop.h b/quiche/quic/core/io/quic_default_event_loop.h index 6315b76..6073a6e 100644 --- a/quiche/quic/core/io/quic_default_event_loop.h +++ b/quiche/quic/core/io/quic_default_event_loop.h
@@ -8,14 +8,13 @@ #include <memory> #include "quiche/quic/core/io/quic_event_loop.h" -#include "quiche/quic/core/quic_clock.h" namespace quic { // Returns the default implementation of QuicheEventLoop. The embedders can // override this using the platform API. The factory pointer returned is an // unowned static variable. -QUICHE_NO_EXPORT QuicEventLoopFactory* GetDefaultEventLoop(QuicClock* clock); +QUICHE_NO_EXPORT QuicEventLoopFactory* GetDefaultEventLoop(); // Returns the factory objects for all event loops. This is particularly useful // for the unit tests. The factory pointers returned are unowned static
diff --git a/quiche/quic/masque/masque_dispatcher.cc b/quiche/quic/masque/masque_dispatcher.cc index d0440a6..32776ee 100644 --- a/quiche/quic/masque/masque_dispatcher.cc +++ b/quiche/quic/masque/masque_dispatcher.cc
@@ -11,7 +11,7 @@ MasqueDispatcher::MasqueDispatcher( MasqueMode masque_mode, const QuicConfig* config, const QuicCryptoServerConfig* crypto_config, - QuicVersionManager* version_manager, QuicEpollServer* epoll_server, + QuicVersionManager* version_manager, QuicEventLoop* event_loop, std::unique_ptr<QuicConnectionHelperInterface> helper, std::unique_ptr<QuicCryptoServerStreamBase::Helper> session_helper, std::unique_ptr<QuicAlarmFactory> alarm_factory, @@ -22,7 +22,7 @@ std::move(alarm_factory), masque_server_backend, expected_server_connection_id_length), masque_mode_(masque_mode), - epoll_server_(epoll_server), + event_loop_(event_loop), masque_server_backend_(masque_server_backend) {} std::unique_ptr<QuicSession> MasqueDispatcher::CreateQuicSession( @@ -39,8 +39,8 @@ auto session = std::make_unique<MasqueServerSession>( masque_mode_, config(), GetSupportedVersions(), connection, this, - epoll_server_, session_helper(), crypto_config(), - compressed_certs_cache(), masque_server_backend_); + event_loop_, session_helper(), crypto_config(), compressed_certs_cache(), + masque_server_backend_); session->Initialize(); return session; }
diff --git a/quiche/quic/masque/masque_dispatcher.h b/quiche/quic/masque/masque_dispatcher.h index b5ef5bb..804d2e9 100644 --- a/quiche/quic/masque/masque_dispatcher.h +++ b/quiche/quic/masque/masque_dispatcher.h
@@ -6,10 +6,10 @@ #define QUICHE_QUIC_MASQUE_MASQUE_DISPATCHER_H_ #include "absl/container/flat_hash_map.h" +#include "quiche/quic/core/io/quic_event_loop.h" #include "quiche/quic/masque/masque_server_backend.h" #include "quiche/quic/masque/masque_server_session.h" #include "quiche/quic/masque/masque_utils.h" -#include "quiche/quic/platform/api/quic_epoll.h" #include "quiche/quic/platform/api/quic_export.h" #include "quiche/quic/tools/quic_simple_dispatcher.h" @@ -22,7 +22,7 @@ explicit MasqueDispatcher( MasqueMode masque_mode, const QuicConfig* config, const QuicCryptoServerConfig* crypto_config, - QuicVersionManager* version_manager, QuicEpollServer* epoll_server, + QuicVersionManager* version_manager, QuicEventLoop* event_loop, std::unique_ptr<QuicConnectionHelperInterface> helper, std::unique_ptr<QuicCryptoServerStreamBase::Helper> session_helper, std::unique_ptr<QuicAlarmFactory> alarm_factory, @@ -42,7 +42,7 @@ private: MasqueMode masque_mode_; - QuicEpollServer* epoll_server_; // Unowned. + QuicEventLoop* event_loop_; // Unowned. MasqueServerBackend* masque_server_backend_; // Unowned. };
diff --git a/quiche/quic/masque/masque_epoll_server.cc b/quiche/quic/masque/masque_epoll_server.cc index 1efc5e1..a67c507 100644 --- a/quiche/quic/masque/masque_epoll_server.cc +++ b/quiche/quic/masque/masque_epoll_server.cc
@@ -4,7 +4,7 @@ #include "quiche/quic/masque/masque_epoll_server.h" -#include "quiche/quic/core/quic_epoll_alarm_factory.h" +#include "quiche/quic/core/quic_default_connection_helper.h" #include "quiche/quic/masque/masque_dispatcher.h" #include "quiche/quic/masque/masque_utils.h" #include "quiche/quic/platform/api/quic_default_proof_providers.h" @@ -22,12 +22,10 @@ QuicDispatcher* MasqueEpollServer::CreateQuicDispatcher() { return new MasqueDispatcher( masque_mode_, &config(), &crypto_config(), version_manager(), - epoll_server(), - std::make_unique<QuicEpollConnectionHelper>(epoll_server(), - QuicAllocator::BUFFER_POOL), + event_loop(), std::make_unique<QuicDefaultConnectionHelper>(), std::make_unique<QuicSimpleCryptoServerStreamHelper>(), - std::make_unique<QuicEpollAlarmFactory>(epoll_server()), - masque_server_backend_, expected_server_connection_id_length()); + event_loop()->CreateAlarmFactory(), masque_server_backend_, + expected_server_connection_id_length()); } } // namespace quic
diff --git a/quiche/quic/masque/masque_server_session.cc b/quiche/quic/masque/masque_server_session.cc index 742b0c6..03fc326 100644 --- a/quiche/quic/masque/masque_server_session.cc +++ b/quiche/quic/masque/masque_server_session.cc
@@ -9,11 +9,13 @@ #include <cstddef> #include <limits> +#include "absl/cleanup/cleanup.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_split.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "quiche/quic/core/http/spdy_utils.h" +#include "quiche/quic/core/io/quic_event_loop.h" #include "quiche/quic/core/quic_data_reader.h" #include "quiche/quic/core/quic_udp_socket.h" #include "quiche/quic/tools/quic_url.h" @@ -79,7 +81,7 @@ MasqueMode masque_mode, const QuicConfig& config, const ParsedQuicVersionVector& supported_versions, QuicConnection* connection, QuicSession::Visitor* visitor, - QuicEpollServer* epoll_server, QuicCryptoServerStreamBase::Helper* helper, + QuicEventLoop* event_loop, QuicCryptoServerStreamBase::Helper* helper, const QuicCryptoServerConfig* crypto_config, QuicCompressedCertsCache* compressed_certs_cache, MasqueServerBackend* masque_server_backend) @@ -87,7 +89,7 @@ helper, crypto_config, compressed_certs_cache, masque_server_backend), masque_server_backend_(masque_server_backend), - epoll_server_(epoll_server), + event_loop_(event_loop), masque_mode_(masque_mode) { // Artificially increase the max packet length to 1350 to ensure we can fit // QUIC packets inside DATAGRAM frames. @@ -95,7 +97,7 @@ connection->SetMaxPacketLength(kDefaultMaxPacketSize); masque_server_backend_->RegisterBackendClient(connection_id(), this); - QUICHE_DCHECK_NE(epoll_server_, nullptr); + QUICHE_DCHECK_NE(event_loop_, nullptr); } void MasqueServerSession::OnMessageAcked(QuicMessageId message_id, @@ -229,7 +231,11 @@ QUIC_DLOG(ERROR) << "Socket bind failed"; return CreateBackendErrorResponse("500", "Socket bind failed"); } - epoll_server_->RegisterFDForRead(fd_wrapper.fd(), this); + if (!event_loop_->RegisterSocket(fd_wrapper.fd(), kSocketEventReadable, + this)) { + QUIC_DLOG(ERROR) << "Failed to register socket with the event loop"; + return CreateBackendErrorResponse("500", "Registering socket failed"); + } QuicSpdyStream* stream = static_cast<QuicSpdyStream*>(GetActiveStream(request_handler->stream_id())); @@ -252,19 +258,11 @@ return response; } -void MasqueServerSession::OnRegistration(QuicEpollServer* /*eps*/, - QuicUdpSocketFd fd, int event_mask) { - QUIC_DVLOG(1) << "OnRegistration " << fd << " event_mask " << event_mask; -} - -void MasqueServerSession::OnModification(QuicUdpSocketFd fd, int event_mask) { - QUIC_DVLOG(1) << "OnModification " << fd << " event_mask " << event_mask; -} - -void MasqueServerSession::OnEvent(QuicUdpSocketFd fd, QuicEpollEvent* event) { - if ((event->in_events & EPOLLIN) == 0) { - QUIC_DVLOG(1) << "Ignoring OnEvent fd " << fd << " event mask " - << event->in_events; +void MasqueServerSession::OnSocketEvent(QuicEventLoop* /*event_loop*/, + QuicUdpSocketFd fd, + QuicSocketEventMask events) { + if ((events & kSocketEventReadable) == 0) { + QUIC_DVLOG(1) << "Ignoring OnEvent fd " << fd << " event mask " << events; return; } auto it = absl::c_find_if(connect_udp_server_states_, @@ -272,16 +270,26 @@ return connect_udp.fd() == fd; }); if (it == connect_udp_server_states_.end()) { - QUIC_BUG(quic_bug_10974_1) << "Got unexpected event mask " - << event->in_events << " on unknown fd " << fd; + QUIC_BUG(quic_bug_10974_1) + << "Got unexpected event mask " << events << " on unknown fd " << fd; return; } + + auto rearm = absl::MakeCleanup([&]() { + if (!event_loop_->SupportsEdgeTriggered()) { + if (!event_loop_->RearmSocket(fd, kSocketEventReadable)) { + QUIC_BUG(MasqueServerSession_OnSocketEvent_Rearm) + << "Failed to re-arm socket " << fd << " for reading"; + } + } + }); + QuicSocketAddress expected_target_server_address = it->target_server_address(); QUICHE_DCHECK(expected_target_server_address.IsInitialized()); - QUIC_DVLOG(1) << "Received readable event on fd " << fd << " (mask " - << event->in_events << ") stream ID " << it->stream()->id() - << " server " << expected_target_server_address; + QUIC_DVLOG(1) << "Received readable event on fd " << fd << " (mask " << events + << ") stream ID " << it->stream()->id() << " server " + << expected_target_server_address; QuicUdpSocketApi socket_api; BitMask64 packet_info_interested(QuicUdpPacketInfoBit::PEER_ADDRESS); char packet_buffer[1 + kMaxIncomingPacketSize]; @@ -329,20 +337,6 @@ } } -void MasqueServerSession::OnUnregistration(QuicUdpSocketFd fd, bool replaced) { - QUIC_DVLOG(1) << "OnUnregistration " << fd << " " << (replaced ? "" : "!") - << " replaced"; -} - -void MasqueServerSession::OnShutdown(QuicEpollServer* /*eps*/, - QuicUdpSocketFd fd) { - QUIC_DVLOG(1) << "OnShutdown " << fd; -} - -std::string MasqueServerSession::Name() const { - return std::string("MasqueServerSession-") + connection_id().ToString(); -} - bool MasqueServerSession::OnSettingsFrame(const SettingsFrame& frame) { QUIC_DLOG(INFO) << "Received SETTINGS: " << frame; if (!QuicSimpleServerSession::OnSettingsFrame(frame)) { @@ -377,7 +371,9 @@ } QuicUdpSocketApi socket_api; QUIC_DLOG(INFO) << "Closing fd " << fd_; - masque_session_->epoll_server()->UnregisterFD(fd_); + if (!masque_session_->event_loop()->UnregisterSocket(fd_)) { + QUIC_DLOG(ERROR) << "Failed to unregister FD " << fd_; + } socket_api.Destroy(fd_); } @@ -393,7 +389,9 @@ if (fd_ != kQuicInvalidSocketFd) { QuicUdpSocketApi socket_api; QUIC_DLOG(INFO) << "Closing fd " << fd_; - masque_session_->epoll_server()->UnregisterFD(fd_); + if (!masque_session_->event_loop()->UnregisterSocket(fd_)) { + QUIC_DLOG(ERROR) << "Failed to unregister FD " << fd_; + } socket_api.Destroy(fd_); } stream_ = other.stream_;
diff --git a/quiche/quic/masque/masque_server_session.h b/quiche/quic/masque/masque_server_session.h index 59b33c2..d820137 100644 --- a/quiche/quic/masque/masque_server_session.h +++ b/quiche/quic/masque/masque_server_session.h
@@ -5,11 +5,11 @@ #ifndef QUICHE_QUIC_MASQUE_MASQUE_SERVER_SESSION_H_ #define QUICHE_QUIC_MASQUE_MASQUE_SERVER_SESSION_H_ +#include "quiche/quic/core/io/quic_event_loop.h" #include "quiche/quic/core/quic_types.h" #include "quiche/quic/core/quic_udp_socket.h" #include "quiche/quic/masque/masque_server_backend.h" #include "quiche/quic/masque/masque_utils.h" -#include "quiche/quic/platform/api/quic_epoll.h" #include "quiche/quic/platform/api/quic_export.h" #include "quiche/quic/tools/quic_simple_server_session.h" @@ -19,13 +19,13 @@ class QUIC_NO_EXPORT MasqueServerSession : public QuicSimpleServerSession, public MasqueServerBackend::BackendClient, - public QuicEpollCallbackInterface { + public QuicSocketEventListener { public: explicit MasqueServerSession( MasqueMode masque_mode, const QuicConfig& config, const ParsedQuicVersionVector& supported_versions, QuicConnection* connection, QuicSession::Visitor* visitor, - QuicEpollServer* epoll_server, QuicCryptoServerStreamBase::Helper* helper, + QuicEventLoop* event_loop, QuicCryptoServerStreamBase::Helper* helper, const QuicCryptoServerConfig* crypto_config, QuicCompressedCertsCache* compressed_certs_cache, MasqueServerBackend* masque_server_backend); @@ -47,16 +47,11 @@ const spdy::Http2HeaderBlock& request_headers, QuicSimpleServerBackend::RequestHandler* request_handler) override; - // From QuicEpollCallbackInterface. - void OnRegistration(QuicEpollServer* eps, QuicUdpSocketFd fd, - int event_mask) override; - void OnModification(QuicUdpSocketFd fd, int event_mask) override; - void OnEvent(QuicUdpSocketFd fd, QuicEpollEvent* event) override; - void OnUnregistration(QuicUdpSocketFd fd, bool replaced) override; - void OnShutdown(QuicEpollServer* eps, QuicUdpSocketFd fd) override; - std::string Name() const override; + // From QuicSocketEventListener. + void OnSocketEvent(QuicEventLoop* event_loop, QuicUdpSocketFd fd, + QuicSocketEventMask events) override; - QuicEpollServer* epoll_server() const { return epoll_server_; } + QuicEventLoop* event_loop() const { return event_loop_; } private: // State that the MasqueServerSession keeps for each CONNECT-UDP request. @@ -64,7 +59,7 @@ : public QuicSpdyStream::Http3DatagramVisitor { public: // ConnectUdpServerState takes ownership of |fd|. It will unregister it - // from |epoll_server| and close the file descriptor when destructed. + // from |event_loop| and close the file descriptor when destructed. explicit ConnectUdpServerState( QuicSpdyStream* stream, const QuicSocketAddress& target_server_address, QuicUdpSocketFd fd, MasqueServerSession* masque_session); @@ -101,7 +96,7 @@ } MasqueServerBackend* masque_server_backend_; // Unowned. - QuicEpollServer* epoll_server_; // Unowned. + QuicEventLoop* event_loop_; // Unowned. MasqueMode masque_mode_; std::list<ConnectUdpServerState> connect_udp_server_states_; bool masque_initialized_ = false;
diff --git a/quiche/quic/qbone/qbone_client_test.cc b/quiche/quic/qbone/qbone_client_test.cc index 5fd7229..0e6d5eb 100644 --- a/quiche/quic/qbone/qbone_client_test.cc +++ b/quiche/quic/qbone/qbone_client_test.cc
@@ -8,6 +8,7 @@ #include "absl/strings/string_view.h" #include "quiche/quic/core/quic_alarm_factory.h" +#include "quiche/quic/core/quic_default_connection_helper.h" #include "quiche/quic/core/quic_default_packet_writer.h" #include "quiche/quic/core/quic_dispatcher.h" #include "quiche/quic/core/quic_epoll_alarm_factory.h" @@ -137,17 +138,11 @@ explicit QboneTestServer(std::unique_ptr<ProofSource> proof_source) : QuicServer(std::move(proof_source), &response_cache_) {} QuicDispatcher* CreateQuicDispatcher() override { - QuicEpollAlarmFactory alarm_factory(epoll_server()); return new QuicQboneDispatcher( &config(), &crypto_config(), version_manager(), - std::unique_ptr<QuicEpollConnectionHelper>( - new QuicEpollConnectionHelper(epoll_server(), - QuicAllocator::BUFFER_POOL)), - std::unique_ptr<QuicCryptoServerStreamBase::Helper>( - new QboneCryptoServerStreamHelper()), - std::unique_ptr<QuicEpollAlarmFactory>( - new QuicEpollAlarmFactory(epoll_server())), - &writer_); + std::make_unique<QuicDefaultConnectionHelper>(), + std::make_unique<QboneCryptoServerStreamHelper>(), + event_loop()->CreateAlarmFactory(), &writer_); } std::vector<std::string> data() { return writer_.data(); }
diff --git a/quiche/quic/test_tools/quic_test_server.cc b/quiche/quic/test_tools/quic_test_server.cc index 53068df..83a060d 100644 --- a/quiche/quic/test_tools/quic_test_server.cc +++ b/quiche/quic/test_tools/quic_test_server.cc
@@ -8,8 +8,7 @@ #include "absl/memory/memory.h" #include "absl/strings/string_view.h" -#include "quiche/quic/core/quic_epoll_alarm_factory.h" -#include "quiche/quic/core/quic_epoll_connection_helper.h" +#include "quiche/quic/core/quic_default_connection_helper.h" #include "quiche/quic/tools/quic_simple_crypto_server_stream_helper.h" #include "quiche/quic/tools/quic_simple_dispatcher.h" #include "quiche/quic/tools/quic_simple_server_session.h" @@ -178,11 +177,10 @@ QuicDispatcher* QuicTestServer::CreateQuicDispatcher() { return new QuicTestDispatcher( &config(), &crypto_config(), version_manager(), - std::make_unique<QuicEpollConnectionHelper>(epoll_server(), - QuicAllocator::BUFFER_POOL), + std::make_unique<QuicDefaultConnectionHelper>(), std::unique_ptr<QuicCryptoServerStreamBase::Helper>( new QuicSimpleCryptoServerStreamHelper()), - std::make_unique<QuicEpollAlarmFactory>(epoll_server()), server_backend(), + event_loop()->CreateAlarmFactory(), server_backend(), expected_server_connection_id_length()); }
diff --git a/quiche/quic/test_tools/server_thread.cc b/quiche/quic/test_tools/server_thread.cc index 1594612..c0d32ea 100644 --- a/quiche/quic/test_tools/server_thread.cc +++ b/quiche/quic/test_tools/server_thread.cc
@@ -4,6 +4,7 @@ #include "quiche/quic/test_tools/server_thread.h" +#include "quiche/quic/core/quic_default_clock.h" #include "quiche/quic/core/quic_dispatcher.h" #include "quiche/quic/test_tools/crypto_test_utils.h" #include "quiche/quic/test_tools/quic_dispatcher_peer.h" @@ -16,7 +17,7 @@ const QuicSocketAddress& address) : QuicThread("server_thread"), server_(std::move(server)), - clock_(server_->epoll_server()), + clock_(QuicDefaultClock::Get()), address_(address), port_(0), initialized_(false) {} @@ -73,8 +74,8 @@ bool ServerThread::WaitUntil(std::function<bool()> termination_predicate, QuicTime::Delta timeout) { - const QuicTime deadline = clock_.Now() + timeout; - while (clock_.Now() < deadline) { + const QuicTime deadline = clock_->Now() + timeout; + while (clock_->Now() < deadline) { QuicNotification done_checking; bool should_terminate = false; Schedule([&] {
diff --git a/quiche/quic/test_tools/server_thread.h b/quiche/quic/test_tools/server_thread.h index fc53467..c29d633 100644 --- a/quiche/quic/test_tools/server_thread.h +++ b/quiche/quic/test_tools/server_thread.h
@@ -8,7 +8,6 @@ #include <memory> #include "quiche/quic/core/quic_config.h" -#include "quiche/quic/core/quic_epoll_clock.h" #include "quiche/quic/platform/api/quic_mutex.h" #include "quiche/quic/platform/api/quic_socket_address.h" #include "quiche/quic/platform/api/quic_thread.h" @@ -79,7 +78,7 @@ QuicNotification quit_; // Notified when the server should quit. std::unique_ptr<QuicServer> server_; - QuicEpollClock clock_; + QuicClock* clock_; QuicSocketAddress address_; mutable QuicMutex port_lock_; int port_ QUIC_GUARDED_BY(port_lock_);
diff --git a/quiche/quic/tools/quic_server.cc b/quiche/quic/tools/quic_server.cc index c5ab6ea..53985e7 100644 --- a/quiche/quic/tools/quic_server.cc +++ b/quiche/quic/tools/quic_server.cc
@@ -16,14 +16,15 @@ #include "quiche/quic/core/crypto/crypto_handshake.h" #include "quiche/quic/core/crypto/quic_random.h" +#include "quiche/quic/core/io/quic_default_event_loop.h" +#include "quiche/quic/core/io/quic_event_loop.h" #include "quiche/quic/core/quic_clock.h" #include "quiche/quic/core/quic_crypto_stream.h" #include "quiche/quic/core/quic_data_reader.h" +#include "quiche/quic/core/quic_default_clock.h" +#include "quiche/quic/core/quic_default_connection_helper.h" #include "quiche/quic/core/quic_default_packet_writer.h" #include "quiche/quic/core/quic_dispatcher.h" -#include "quiche/quic/core/quic_epoll_alarm_factory.h" -#include "quiche/quic/core/quic_epoll_clock.h" -#include "quiche/quic/core/quic_epoll_connection_helper.h" #include "quiche/quic/core/quic_packet_reader.h" #include "quiche/quic/core/quic_packets.h" #include "quiche/quic/platform/api/quic_flags.h" @@ -36,7 +37,6 @@ namespace { -const int kEpollFlags = EPOLLIN | EPOLLOUT | EPOLLET; const char kSourceAddressTokenSecret[] = "secret"; } // namespace @@ -95,17 +95,19 @@ kInitialSessionFlowControlWindow); } - epoll_server_.set_timeout_in_us(50 * 1000); - - QuicEpollClock clock(&epoll_server_); - std::unique_ptr<CryptoHandshakeMessage> scfg(crypto_config_.AddDefaultConfig( - QuicRandom::GetInstance(), &clock, crypto_config_options_)); + QuicRandom::GetInstance(), QuicDefaultClock::Get(), + crypto_config_options_)); } -QuicServer::~QuicServer() = default; +QuicServer::~QuicServer() { + close(fd_); + fd_ = -1; +} bool QuicServer::CreateUDPSocketAndListen(const QuicSocketAddress& address) { + event_loop_ = CreateEventLoop(); + QuicUdpSocketApi socket_api; fd_ = socket_api.Create(address.host().AddressFamilyToInt(), /*receive_buffer_size =*/kDefaultSocketReceiveBuffer, @@ -135,7 +137,11 @@ port_ = address.port(); } - epoll_server_.RegisterFD(fd_, this, kEpollFlags); + bool register_result = event_loop_->RegisterSocket( + fd_, kSocketEventReadable | kSocketEventWritable, this); + if (!register_result) { + return false; + } dispatcher_.reset(CreateQuicDispatcher()); dispatcher_->InitializeWithWriter(CreateWriter(fd_)); @@ -147,16 +153,17 @@ } QuicDispatcher* QuicServer::CreateQuicDispatcher() { - QuicEpollAlarmFactory alarm_factory(&epoll_server_); return new QuicSimpleDispatcher( &config_, &crypto_config_, &version_manager_, - std::unique_ptr<QuicEpollConnectionHelper>(new QuicEpollConnectionHelper( - &epoll_server_, QuicAllocator::BUFFER_POOL)), + std::make_unique<QuicDefaultConnectionHelper>(), std::unique_ptr<QuicCryptoServerStreamBase::Helper>( new QuicSimpleCryptoServerStreamHelper()), - std::unique_ptr<QuicEpollAlarmFactory>( - new QuicEpollAlarmFactory(&epoll_server_)), - quic_simple_server_backend_, expected_server_connection_id_length_); + event_loop_->CreateAlarmFactory(), quic_simple_server_backend_, + expected_server_connection_id_length_); +} + +std::unique_ptr<QuicEventLoop> QuicServer::CreateEventLoop() { + return GetDefaultEventLoop()->Create(QuicDefaultClock::Get()); } void QuicServer::HandleEventsForever() { @@ -166,7 +173,7 @@ } void QuicServer::WaitForEvents() { - epoll_server_.WaitForEventsAndExecuteCallbacks(); + event_loop_->RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(50)); } void QuicServer::Shutdown() { @@ -176,17 +183,15 @@ dispatcher_->Shutdown(); } - epoll_server_.Shutdown(); - - close(fd_); - fd_ = -1; + dispatcher_.reset(); + event_loop_.reset(); } -void QuicServer::OnEvent(int fd, QuicEpollEvent* event) { +void QuicServer::OnSocketEvent(QuicEventLoop* /*event_loop*/, + QuicUdpSocketFd fd, QuicSocketEventMask events) { QUICHE_DCHECK_EQ(fd, fd_); - event->out_ready_mask = 0; - if (event->in_events & EPOLLIN) { + if (events & kSocketEventReadable) { QUIC_DVLOG(1) << "EPOLLIN"; dispatcher_->ProcessBufferedChlos(kNumSessionsToCreatePerSocketEvent); @@ -194,19 +199,27 @@ bool more_to_read = true; while (more_to_read) { more_to_read = packet_reader_->ReadAndDispatchPackets( - fd_, port_, QuicEpollClock(&epoll_server_), dispatcher_.get(), + fd_, port_, *QuicDefaultClock::Get(), dispatcher_.get(), overflow_supported_ ? &packets_dropped_ : nullptr); } if (dispatcher_->HasChlosBuffered()) { // Register EPOLLIN event to consume buffered CHLO(s). - event->out_ready_mask |= EPOLLIN; + bool success = + event_loop_->ArtificiallyNotifyEvent(fd_, kSocketEventReadable); + QUICHE_DCHECK(success); + } + if (!event_loop_->SupportsEdgeTriggered()) { + bool success = event_loop_->RearmSocket(fd_, kSocketEventReadable); + QUICHE_DCHECK(success); } } - if (event->in_events & EPOLLOUT) { + if (events & kSocketEventWritable) { dispatcher_->OnCanWrite(); - if (dispatcher_->HasPendingWrites()) { - event->out_ready_mask |= EPOLLOUT; + if (!event_loop_->SupportsEdgeTriggered() && + dispatcher_->HasPendingWrites()) { + bool success = event_loop_->RearmSocket(fd_, kSocketEventWritable); + QUICHE_DCHECK(success); } } }
diff --git a/quiche/quic/tools/quic_server.h b/quiche/quic/tools/quic_server.h index 5c65fe0..61531fb 100644 --- a/quiche/quic/tools/quic_server.h +++ b/quiche/quic/tools/quic_server.h
@@ -15,8 +15,8 @@ #include "absl/strings/string_view.h" #include "quiche/quic/core/crypto/quic_crypto_server_config.h" +#include "quiche/quic/core/io/quic_event_loop.h" #include "quiche/quic/core/quic_config.h" -#include "quiche/quic/core/quic_epoll_connection_helper.h" #include "quiche/quic/core/quic_framer.h" #include "quiche/quic/core/quic_packet_writer.h" #include "quiche/quic/core/quic_udp_socket.h" @@ -35,8 +35,7 @@ class QuicDispatcher; class QuicPacketReader; -class QuicServer : public QuicSpdyServerBase, - public QuicEpollCallbackInterface { +class QuicServer : public QuicSpdyServerBase, public QuicSocketEventListener { public: QuicServer(std::unique_ptr<ProofSource> proof_source, QuicSimpleServerBackend* quic_simple_server_backend); @@ -54,8 +53,6 @@ ~QuicServer() override; - std::string Name() const override { return "QuicServer"; } - // Start listening on the specified address. bool CreateUDPSocketAndListen(const QuicSocketAddress& address) override; // Handles all events. Does not return. @@ -64,17 +61,12 @@ // Wait up to 50ms, and handle any events which occur. void WaitForEvents(); - // Server deletion is imminent. Start cleaning up the epoll server. + // Server deletion is imminent. Start cleaning up any pending sessions. virtual void Shutdown(); - // From EpollCallbackInterface - void OnRegistration(QuicEpollServer* /*eps*/, int /*fd*/, - int /*event_mask*/) override {} - void OnModification(int /*fd*/, int /*event_mask*/) override {} - void OnEvent(int /*fd*/, QuicEpollEvent* /*event*/) override; - void OnUnregistration(int /*fd*/, bool /*replaced*/) override {} - - void OnShutdown(QuicEpollServer* /*eps*/, int /*fd*/) override {} + // QuicSocketEventListener implementation. + void OnSocketEvent(QuicEventLoop* event_loop, QuicUdpSocketFd fd, + QuicSocketEventMask events) override; void SetChloMultiplier(size_t multiplier) { crypto_config_.set_chlo_multiplier(multiplier); @@ -90,13 +82,15 @@ int port() { return port_; } - QuicEpollServer* epoll_server() { return &epoll_server_; } + QuicEventLoop* event_loop() { return event_loop_.get(); } protected: virtual QuicPacketWriter* CreateWriter(int fd); virtual QuicDispatcher* CreateQuicDispatcher(); + virtual std::unique_ptr<QuicEventLoop> CreateEventLoop(); + const QuicConfig& config() const { return config_; } const QuicCryptoServerConfig& crypto_config() const { return crypto_config_; } @@ -120,10 +114,10 @@ // Initialize the internal state of the server. void Initialize(); + // Schedules alarms and notifies the server of the I/O events. + std::unique_ptr<QuicEventLoop> event_loop_; // Accepts data from the framer and demuxes clients to sessions. std::unique_ptr<QuicDispatcher> dispatcher_; - // Frames incoming packets and hands them to the dispatcher. - QuicEpollServer epoll_server_; // The port the server is listening on. int port_;
diff --git a/quiche/quic/tools/quic_server_test.cc b/quiche/quic/tools/quic_server_test.cc index b0094be..d193fd3 100644 --- a/quiche/quic/tools/quic_server_test.cc +++ b/quiche/quic/tools/quic_server_test.cc
@@ -4,10 +4,15 @@ #include "quiche/quic/tools/quic_server.h" +#include <memory> + #include "absl/base/macros.h" #include "quiche/quic/core/crypto/quic_random.h" -#include "quiche/quic/core/quic_epoll_alarm_factory.h" -#include "quiche/quic/core/quic_epoll_connection_helper.h" +#include "quiche/quic/core/io/quic_default_event_loop.h" +#include "quiche/quic/core/io/quic_event_loop.h" +#include "quiche/quic/core/quic_default_clock.h" +#include "quiche/quic/core/quic_default_connection_helper.h" +#include "quiche/quic/core/quic_default_packet_writer.h" #include "quiche/quic/core/quic_utils.h" #include "quiche/quic/platform/api/quic_flags.h" #include "quiche/quic/platform/api/quic_logging.h" @@ -62,14 +67,10 @@ QuicDispatcher* CreateQuicDispatcher() override { mock_dispatcher_ = new MockQuicSimpleDispatcher( &config(), &crypto_config(), version_manager(), - std::unique_ptr<QuicEpollConnectionHelper>( - new QuicEpollConnectionHelper(epoll_server(), - QuicAllocator::BUFFER_POOL)), + std::make_unique<QuicDefaultConnectionHelper>(), std::unique_ptr<QuicCryptoServerStreamBase::Helper>( new QuicSimpleCryptoServerStreamHelper()), - std::unique_ptr<QuicEpollAlarmFactory>( - new QuicEpollAlarmFactory(epoll_server())), - &quic_simple_server_backend_); + event_loop()->CreateAlarmFactory(), &quic_simple_server_backend_); return mock_dispatcher_; } @@ -147,14 +148,11 @@ crypto_test_utils::ProofSourceForTesting(), KeyExchangeSource::Default()), version_manager_(AllSupportedVersions()), + event_loop_(GetDefaultEventLoop()->Create(QuicDefaultClock::Get())), dispatcher_(&config_, &crypto_config_, &version_manager_, - std::unique_ptr<QuicEpollConnectionHelper>( - new QuicEpollConnectionHelper( - &eps_, QuicAllocator::BUFFER_POOL)), - std::unique_ptr<QuicCryptoServerStreamBase::Helper>( - new QuicSimpleCryptoServerStreamHelper()), - std::unique_ptr<QuicEpollAlarmFactory>( - new QuicEpollAlarmFactory(&eps_)), + std::make_unique<QuicDefaultConnectionHelper>(), + std::make_unique<QuicSimpleCryptoServerStreamHelper>(), + event_loop_->CreateAlarmFactory(), &quic_simple_server_backend_) { dispatcher_.InitializeWithWriter(new QuicDefaultPacketWriter(1234)); } @@ -168,7 +166,7 @@ QuicConfig config_; QuicCryptoServerConfig crypto_config_; QuicVersionManager version_manager_; - QuicEpollServer eps_; + std::unique_ptr<QuicEventLoop> event_loop_; QuicMemoryCacheBackend quic_simple_server_backend_; MockQuicDispatcher dispatcher_; };