blob: 0c4a637a437c0fef9b2c501d82cf82707b7ec12c [file] [log] [blame] [edit]
// Copyright 2024 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_subscribe_windows.h"
#include <optional>
#include <vector>
#include "quiche/quic/moqt/moqt_messages.h"
#include "quiche/quic/platform/api/quic_bug_tracker.h"
#include "quiche/common/platform/api/quiche_logging.h"
#include "quiche/web_transport/web_transport.h"
namespace moqt {
bool SubscribeWindow::InWindow(const FullSequence& seq) const {
if (seq < start_) {
return false;
}
return (!end_.has_value() || seq <= *end_);
}
std::optional<webtransport::StreamId> SendStreamMap::GetStreamForSequence(
FullSequence sequence) const {
ReducedSequenceIndex index(sequence, forwarding_preference_);
auto stream_it = send_streams_.find(index);
if (stream_it == send_streams_.end()) {
return std::nullopt;
}
return stream_it->second;
}
void SendStreamMap::AddStream(FullSequence sequence,
webtransport::StreamId stream_id) {
ReducedSequenceIndex index(sequence, forwarding_preference_);
if (forwarding_preference_ == MoqtForwardingPreference::kDatagram) {
QUIC_BUG(quic_bug_moqt_draft_03_01) << "Adding a stream for datagram";
return;
}
auto [stream_it, success] = send_streams_.emplace(index, stream_id);
QUIC_BUG_IF(quic_bug_moqt_draft_03_02, !success) << "Stream already added";
}
void SendStreamMap::RemoveStream(FullSequence sequence,
webtransport::StreamId stream_id) {
ReducedSequenceIndex index(sequence, forwarding_preference_);
QUICHE_DCHECK(send_streams_.contains(index) &&
send_streams_.find(index)->second == stream_id)
<< "Requested to remove a stream ID that does not match the one in the "
"map";
send_streams_.erase(index);
}
bool SubscribeWindow::UpdateStartEnd(FullSequence start,
std::optional<FullSequence> end) {
// Can't make the subscription window bigger.
if (!InWindow(start)) {
return false;
}
if (end_.has_value() && (!end.has_value() || *end_ < *end)) {
return false;
}
start_ = start;
end_ = end;
return true;
}
bool SubscribeWindow::IsStreamProvokingObject(
FullSequence sequence, MoqtForwardingPreference preference) const {
if (sequence == start_) {
return true;
}
switch (preference) {
case MoqtForwardingPreference::kTrack:
return false;
case MoqtForwardingPreference::kGroup:
// Note: this assumes that the group starts with object 0.
return sequence.object == 0;
case MoqtForwardingPreference::kObject:
return true;
case MoqtForwardingPreference::kDatagram:
QUICHE_DCHECK(false);
return true;
}
}
ReducedSequenceIndex::ReducedSequenceIndex(
FullSequence sequence, MoqtForwardingPreference preference) {
switch (preference) {
case MoqtForwardingPreference::kTrack:
sequence_ = FullSequence(0, 0);
break;
case MoqtForwardingPreference::kGroup:
sequence_ = FullSequence(sequence.group, 0);
break;
case MoqtForwardingPreference::kObject:
case MoqtForwardingPreference::kDatagram:
sequence_ = sequence;
break;
}
}
std::vector<webtransport::StreamId> SendStreamMap::GetAllStreams() const {
std::vector<webtransport::StreamId> ids;
for (const auto& [index, id] : send_streams_) {
ids.push_back(id);
}
return ids;
}
} // namespace moqt