| // Copyright 2026 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef QUICHE_QUIC_QBONE_TEST_TOOLS_BASIC_QUIC_SERVER_H_ |
| #define QUICHE_QUIC_QBONE_TEST_TOOLS_BASIC_QUIC_SERVER_H_ |
| |
| #include <cstddef> |
| #include <memory> |
| #include <vector> |
| |
| #include "absl/base/nullability.h" |
| #include "absl/status/status.h" |
| #include "absl/status/statusor.h" |
| #include "absl/strings/string_view.h" |
| #include "absl/types/span.h" |
| #include "quiche/quic/core/crypto/proof_source.h" |
| #include "quiche/quic/core/quic_connection.h" |
| #include "quiche/quic/core/quic_connection_id.h" |
| #include "quiche/quic/core/quic_dispatcher.h" |
| #include "quiche/quic/core/quic_session.h" |
| #include "quiche/quic/core/quic_stream_sequencer.h" |
| #include "quiche/quic/core/quic_types.h" |
| #include "quiche/quic/core/tls_server_handshaker.h" |
| #include "quiche/common/quiche_callbacks.h" |
| #include "quiche/common/quiche_mem_slice.h" |
| #include "quiche/common/quiche_socket_address.h" |
| |
| namespace quic::test { |
| |
| // Lightweight QUIC (not necessarily HTTP/3) server for tests and experiments, |
| // especially for simulating QBONE Terminator functionality. Receives traffic |
| // over a socket on the given socket address, which may be a loopback interface |
| // for same-machine (or same-process) testing. Runs on its own dedicated server |
| // thread for ease of running same-process as a client. |
| class BasicQuicServer final { |
| public: |
| // Interface for handling server events. All calls will be made on the server |
| // thread. |
| class Handler { |
| public: |
| virtual ~Handler() = default; |
| |
| // Called on construction of a new QuicSession. Returns the QuicCryptoStream |
| // to use for the session. |
| virtual std::unique_ptr<QuicCryptoStream> OnNewSession( |
| QuicSession* session, const QuicCryptoServerConfig* crypto_config) { |
| return std::make_unique<TlsServerHandshaker>(session, crypto_config); |
| } |
| |
| virtual void OnSessionEnd(QuicConnectionId server_connection_id) {} |
| |
| // See QuicSession::SelectAlpn. |
| virtual std::vector<absl::string_view>::const_iterator SelectAlpn( |
| QuicConnectionId server_connection_id, |
| const std::vector<absl::string_view>& alpns) const { |
| return alpns.cbegin(); |
| } |
| |
| // Called on initiation of a new stream from the peer. Returns true iff the |
| // stream should be accepted and created. |
| virtual bool OnNewStream(QuicConnectionId server_connection_id, |
| QuicStreamId stream_id) { |
| return true; |
| } |
| |
| // Called when new data is available on a stream. Returns the number of |
| // bytes that were successfully processed and that should be consumed from |
| // stream buffers. |
| virtual int OnStreamDataAvailable( |
| QuicConnectionId server_connection_id, QuicStreamId stream_id, |
| const QuicStreamSequencer& data_sequencer) { |
| return data_sequencer.ReadableBytes(); |
| } |
| |
| virtual void OnDatagramReceived(QuicConnectionId server_connection_id, |
| absl::Span<const std::byte> data) {} |
| }; |
| |
| BasicQuicServer(quiche::QuicheSocketAddress socket_address, |
| std::unique_ptr<ProofSource> absl_nonnull proof_source); |
| ~BasicQuicServer(); |
| |
| absl::Status Start(std::unique_ptr<Handler> absl_nonnull handler); |
| absl::Status Stop(); |
| |
| // The following interactions should be safe from any thread, and will |
| // marshall to the server thread as necessary. |
| |
| // Not guaranteed to run if the server is stopped. |
| void Schedule(quiche::SingleUseCallback<void()> callback); |
| // Not guaranteed to ever return if the server is stopped. |
| void ScheduleAndWaitForCompletion(quiche::SingleUseCallback<void()> callback); |
| |
| absl::StatusOr<quiche::QuicheSocketAddress> bound_address(); |
| |
| // Returns the number of bytes consumed into the stream (written or buffered). |
| absl::StatusOr<int> SendStreamData(QuicConnectionId server_connection_id, |
| QuicStreamId stream_id, |
| absl::Span<const std::byte> data, |
| bool fin = false); |
| absl::StatusOr<int> SendStreamData(QuicConnectionId server_connection_id, |
| QuicStreamId stream_id, |
| absl::Span<quiche::QuicheMemSlice> data, |
| bool fin = false); |
| |
| absl::Status SendDatagram(QuicConnectionId server_connection_id, |
| absl::Span<const std::byte> data); |
| absl::Status SendDatagram(QuicConnectionId server_connection_id, |
| absl::Span<quiche::QuicheMemSlice> data); |
| |
| private: |
| class ServerThread; |
| |
| const quiche::QuicheSocketAddress socket_address_; |
| |
| const QuicConfig config_; |
| const std::unique_ptr<QuicCryptoServerConfig> crypto_config_; |
| std::unique_ptr<ServerThread> server_thread_; |
| }; |
| |
| } // namespace quic::test |
| |
| #endif // QUICHE_QUIC_QBONE_TEST_TOOLS_BASIC_QUIC_SERVER_H_ |