blob: b2b984faf87f5ff00812039f57a1049cb3722853 [file]
// Copyright 2026 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/moqt/moqt_control_message_queue.h"
#include <array>
#include <utility>
#include "absl/status/status.h"
#include "absl/types/span.h"
#include "quiche/common/quiche_buffer_allocator.h"
#include "quiche/common/quiche_mem_slice.h"
#include "quiche/web_transport/stream_helpers.h"
#include "quiche/web_transport/web_transport.h"
namespace moqt {
absl::Status MoqtControlMessageQueue::OnCanWrite() {
if (stream_ == nullptr) {
return absl::InternalError("OnCanWrite() called when no stream is bound");
}
if (pending_messages_.empty() && fin_queued_) {
return webtransport::SendFinOnStream(*stream_);
}
while (!pending_messages_.empty() && stream_->CanWrite()) {
absl::Status status =
SendMessage(*stream_, std::move(pending_messages_.front()),
fin_queued_ && pending_messages_.size() == 1);
pending_messages_.pop_front();
if (!status.ok()) {
return status;
}
}
return absl::OkStatus();
}
absl::Status MoqtControlMessageQueue::SendOrBufferMessage(
quiche::QuicheBuffer message, bool fin) {
if (fin_queued_) {
return absl::InternalError(
"Trying to send data when a FIN has been already queued");
}
if (stream_ == nullptr || !stream_->CanWrite()) {
fin_queued_ = fin;
return AddToQueue(std::move(message));
}
return SendMessage(*stream_, std::move(message), fin);
}
absl::Status MoqtControlMessageQueue::Fin() {
fin_queued_ = true;
if (stream_ != nullptr) {
return OnCanWrite();
}
return absl::OkStatus();
}
absl::Status MoqtControlMessageQueue::AddToQueue(quiche::QuicheBuffer message) {
if (pending_messages_.size() == kMaxPendingMessages) {
return absl::ResourceExhaustedError(
"Not enough flow credit on the control stream");
}
pending_messages_.push_back(std::move(message));
return absl::OkStatus();
}
absl::Status MoqtControlMessageQueue::SendMessage(webtransport::Stream& stream,
quiche::QuicheBuffer message,
bool fin) {
webtransport::StreamWriteOptions options;
options.set_send_fin(fin);
std::array write_vector = {quiche::QuicheMemSlice(std::move(message))};
return stream.Writev(absl::MakeSpan(write_vector), options);
}
} // namespace moqt