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_;
};