blob: 5083a09e87bba442e88e9d81276690d3ed1ad474 [file] [log] [blame]
// Copyright 2023 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.
#ifndef QUICHE_QUIC_MOQT_MOQT_SESSION_INTERFACE_H_
#define QUICHE_QUIC_MOQT_MOQT_SESSION_INTERFACE_H_
#include <cstdint>
#include <memory>
#include <optional>
#include "absl/strings/string_view.h"
#include "quiche/quic/core/quic_time.h"
#include "quiche/quic/moqt/moqt_fetch_task.h"
#include "quiche/quic/moqt/moqt_messages.h"
#include "quiche/quic/moqt/moqt_object.h"
#include "quiche/quic/moqt/moqt_priority.h"
#include "quiche/quic/moqt/moqt_session_callbacks.h"
#include "quiche/common/quiche_callbacks.h"
#include "quiche/common/quiche_weak_ptr.h"
namespace moqt {
// The callback we'll use for all request types going forward. Can only be used
// once; if the argument is nullopt, an OK response was received. Otherwise, an
// ERROR response was received.
using MoqtRequestCallback =
quiche::SingleUseCallback<void(std::optional<MoqtRequestError>)>;
using MoqtObjectAckFunction =
quiche::MultiUseCallback<void(uint64_t group_id, uint64_t object_id,
quic::QuicTimeDelta delta_from_deadline)>;
class SubscribeVisitor {
public:
virtual ~SubscribeVisitor() = default;
// Called when the session receives a response to the SUBSCRIBE, unless it's
// a SUBSCRIBE_ERROR with a new track_alias. In that case, the session will
// automatically retry.
virtual void OnReply(
const FullTrackName& full_track_name,
std::optional<Location> largest_location,
std::optional<absl::string_view> error_reason_phrase) = 0;
// Called when the subscription process is far enough that it is possible to
// send OBJECT_ACK messages; provides a callback to do so. The callback is
// valid for as long as the session is valid.
virtual void OnCanAckObjects(MoqtObjectAckFunction ack_function) = 0;
// Called when an object fragment (or an entire object) is received.
virtual void OnObjectFragment(const FullTrackName& full_track_name,
const PublishedObjectMetadata& metadata,
absl::string_view object,
bool end_of_message) = 0;
virtual void OnSubscribeDone(FullTrackName full_track_name) = 0;
// Called when the track is malformed per Section 2.5 of
// draft-ietf-moqt-moq-transport-12. If the application is a relay, it MUST
// terminate downstream delivery of the track.
virtual void OnMalformedTrack(const FullTrackName& full_track_name) = 0;
};
// MoqtSession calls this when a FETCH_OK or FETCH_ERROR is received. The
// destination of the callback owns |fetch_task| and MoqtSession will react
// safely if the owner destroys it.
using FetchResponseCallback =
quiche::SingleUseCallback<void(std::unique_ptr<MoqtFetchTask> fetch_task)>;
// TODO(martinduke): MoqtOutgoingAnnounceCallback and
// MoqtOutgoingSubscribeNamespaceCallback are deprecated. Remove.
// If |error_message| is nullopt, this is triggered by an ANNOUNCE_OK.
// Otherwise, it is triggered by ANNOUNCE_ERROR or ANNOUNCE_CANCEL. For
// ERROR or CANCEL, MoqtSession is deleting all ANNOUNCE state immediately
// after calling this callback. Alternatively, the application can call
// Unannounce() to delete the state.
using MoqtOutgoingAnnounceCallback = quiche::MultiUseCallback<void(
TrackNamespace track_namespace,
std::optional<MoqtAnnounceErrorReason> error)>;
using MoqtOutgoingSubscribeNamespaceCallback = quiche::SingleUseCallback<void(
TrackNamespace track_namespace, std::optional<RequestErrorCode> error,
absl::string_view reason)>;
class MoqtSessionInterface {
public:
virtual ~MoqtSessionInterface() = default;
// TODO: move ANNOUNCE logic here.
// Callbacks for session-level events.
virtual MoqtSessionCallbacks& callbacks() = 0;
// Close the session with a fatal error.
virtual void Error(MoqtError code, absl::string_view error) = 0;
// Methods below send a SUBSCRIBE for the specified track, and return true if
// SUBSCRIBE was actually sent.
// Subscribe from (start_group, start_object) to the end of the track.
virtual bool SubscribeAbsolute(const FullTrackName& name,
uint64_t start_group, uint64_t start_object,
SubscribeVisitor* visitor,
VersionSpecificParameters parameters) = 0;
// Subscribe from (start_group, start_object) to the end of end_group.
virtual bool SubscribeAbsolute(const FullTrackName& name,
uint64_t start_group, uint64_t start_object,
uint64_t end_group, SubscribeVisitor* visitor,
VersionSpecificParameters parameters) = 0;
// Subscribe to all objects that are larger than the current Largest
// Group/Object ID.
virtual bool SubscribeCurrentObject(const FullTrackName& name,
SubscribeVisitor* visitor,
VersionSpecificParameters parameters) = 0;
// Start with the first group after the current Largest Group/Object ID.
virtual bool SubscribeNextGroup(const FullTrackName& name,
SubscribeVisitor* visitor,
VersionSpecificParameters parameters) = 0;
// If an argument is nullopt, there is no change to the current value.
virtual bool SubscribeUpdate(const FullTrackName& name,
std::optional<Location> start,
std::optional<uint64_t> end_group,
std::optional<MoqtPriority> subscriber_priority,
std::optional<bool> forward,
VersionSpecificParameters parameters) = 0;
// Sends an UNSUBSCRIBE message and removes all of the state related to the
// subscription. Returns false if the subscription is not found.
virtual void Unsubscribe(const FullTrackName& name) = 0;
// Sends a FETCH for a pre-specified object range. Once a FETCH_OK or a
// FETCH_ERROR is received, `callback` is called with a MoqtFetchTask that can
// be used to process the FETCH further. To cancel a FETCH, simply destroy
// the MoqtFetchTask.
virtual bool Fetch(const FullTrackName& name, FetchResponseCallback callback,
Location start, uint64_t end_group,
std::optional<uint64_t> end_object, MoqtPriority priority,
std::optional<MoqtDeliveryOrder> delivery_order,
VersionSpecificParameters parameters) = 0;
// Sends both a SUBSCRIBE and a joining FETCH, beginning `num_previous_groups`
// groups before the current group. The Fetch will not be flow controlled,
// instead using |visitor| to deliver fetched objects when they arrive. Gaps
// in the FETCH will not be filled by with ObjectDoesNotExist. If the FETCH
// fails for any reason, the application will not receive a notification; it
// will just appear to be missing objects.
virtual bool RelativeJoiningFetch(const FullTrackName& name,
SubscribeVisitor* visitor,
uint64_t num_previous_groups,
VersionSpecificParameters parameters) = 0;
// Sends both a SUBSCRIBE and a joining FETCH, beginning `num_previous_groups`
// groups before the current group. `callback` acts the same way as the
// callback for the regular Fetch() call.
virtual bool RelativeJoiningFetch(
const FullTrackName& name, SubscribeVisitor* visitor,
FetchResponseCallback callback, uint64_t num_previous_groups,
MoqtPriority priority, std::optional<MoqtDeliveryOrder> delivery_order,
VersionSpecificParameters parameters) = 0;
// TODO(martinduke): Add an API for absolute joining fetch.
// TODO: Add SubscribeNamespace, UnsubscribeNamespace method.
// TODO: Add Announce, Unannounce method.
// TODO: Add AnnounceCancel method.
// TODO: Add TrackStatusRequest method.
// TODO: Add SubscribeUpdate, SubscribeDone method.
virtual quiche::QuicheWeakPtr<MoqtSessionInterface> GetWeakPtr() = 0;
};
} // namespace moqt
#endif // QUICHE_QUIC_MOQT_MOQT_SESSION_INTERFACE_H_