blob: 63bb8422bd28a77cd69349844e30f342b415ceb0 [file] [log] [blame]
// 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 "quiche/quic/test_tools/web_transport_resets_backend.h"
#include <memory>
#include "quiche/quic/core/web_transport_interface.h"
#include "quiche/quic/tools/web_transport_test_visitors.h"
#include "quiche/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::Http2HeaderBlock& /*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