| // 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 |