| // Copyright (c) 2021 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "quic/test_tools/web_transport_resets_backend.h" |
| |
| #include <memory> |
| |
| #include "quic/core/web_transport_interface.h" |
| #include "quic/tools/web_transport_test_visitors.h" |
| #include "common/quiche_circular_deque.h" |
| |
| namespace quic { |
| namespace test { |
| |
| namespace { |
| |
| class ResetsVisitor; |
| |
| class BidirectionalEchoVisitorWithLogging |
| : public WebTransportBidirectionalEchoVisitor { |
| public: |
| BidirectionalEchoVisitorWithLogging(WebTransportStream* stream, |
| ResetsVisitor* session_visitor) |
| : WebTransportBidirectionalEchoVisitor(stream), |
| session_visitor_(session_visitor) {} |
| |
| void OnResetStreamReceived(WebTransportStreamError error) override; |
| void OnStopSendingReceived(WebTransportStreamError error) override; |
| |
| private: |
| ResetsVisitor* session_visitor_; // Not owned. |
| }; |
| |
| class ResetsVisitor : public WebTransportVisitor { |
| public: |
| ResetsVisitor(WebTransportSession* session) : session_(session) {} |
| |
| void OnSessionReady(const spdy::SpdyHeaderBlock& /*headers*/) override {} |
| void OnSessionClosed(WebTransportSessionError /*error_code*/, |
| const std::string& /*error_message*/) override {} |
| |
| void OnIncomingBidirectionalStreamAvailable() override { |
| while (true) { |
| WebTransportStream* stream = |
| session_->AcceptIncomingBidirectionalStream(); |
| if (stream == nullptr) { |
| return; |
| } |
| stream->SetVisitor( |
| std::make_unique<BidirectionalEchoVisitorWithLogging>(stream, this)); |
| stream->visitor()->OnCanRead(); |
| } |
| } |
| void OnIncomingUnidirectionalStreamAvailable() override {} |
| |
| void OnDatagramReceived(absl::string_view /*datagram*/) override {} |
| |
| void OnCanCreateNewOutgoingBidirectionalStream() override {} |
| void OnCanCreateNewOutgoingUnidirectionalStream() override { |
| MaybeSendLogsBack(); |
| } |
| |
| void Log(std::string line) { |
| log_.push_back(std::move(line)); |
| MaybeSendLogsBack(); |
| } |
| |
| private: |
| void MaybeSendLogsBack() { |
| while (!log_.empty() && |
| session_->CanOpenNextOutgoingUnidirectionalStream()) { |
| WebTransportStream* stream = session_->OpenOutgoingUnidirectionalStream(); |
| stream->SetVisitor( |
| std::make_unique<WebTransportUnidirectionalEchoWriteVisitor>( |
| stream, log_.front())); |
| log_.pop_front(); |
| stream->visitor()->OnCanWrite(); |
| } |
| } |
| |
| WebTransportSession* session_; // Not owned. |
| quiche::QuicheCircularDeque<std::string> log_; |
| }; |
| |
| void BidirectionalEchoVisitorWithLogging::OnResetStreamReceived( |
| WebTransportStreamError error) { |
| session_visitor_->Log(absl::StrCat("Received reset for stream ", |
| stream()->GetStreamId(), |
| " with error code ", error)); |
| WebTransportBidirectionalEchoVisitor::OnResetStreamReceived(error); |
| } |
| void BidirectionalEchoVisitorWithLogging::OnStopSendingReceived( |
| WebTransportStreamError error) { |
| session_visitor_->Log(absl::StrCat("Received stop sending for stream ", |
| stream()->GetStreamId(), |
| " with error code ", error)); |
| WebTransportBidirectionalEchoVisitor::OnStopSendingReceived(error); |
| } |
| |
| } // namespace |
| |
| QuicSimpleServerBackend::WebTransportResponse WebTransportResetsBackend( |
| const spdy::Http2HeaderBlock& /*request_headers*/, |
| WebTransportSession* session) { |
| QuicSimpleServerBackend::WebTransportResponse response; |
| response.response_headers[":status"] = "200"; |
| response.visitor = std::make_unique<ResetsVisitor>(session); |
| return response; |
| } |
| |
| } // namespace test |
| } // namespace quic |