blob: bfc0e3bf5603364530fac0cf07b102269782d0aa [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.
#ifndef QUICHE_QUIC_MOQT_MOQT_PUBLISHER_H_
#define QUICHE_QUIC_MOQT_MOQT_PUBLISHER_H_
#include <cstdint>
#include <memory>
#include <optional>
#include <vector>
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "quiche/quic/core/quic_time.h"
#include "quiche/quic/moqt/moqt_messages.h"
#include "quiche/quic/moqt/moqt_priority.h"
#include "quiche/common/platform/api/quiche_mem_slice.h"
#include "quiche/common/quiche_callbacks.h"
namespace moqt {
// PublishedObject is a description of an object that is sufficient to publish
// it on a given track.
struct PublishedObject {
FullSequence sequence;
MoqtObjectStatus status;
MoqtPriority publisher_priority;
quiche::QuicheMemSlice payload;
quic::QuicTime arrival_time = quic::QuicTime::Zero();
bool fin_after_this = false;
};
// MoqtObjectListener is an interface for any entity that is listening for
// incoming objects for a given track.
class MoqtObjectListener {
public:
virtual ~MoqtObjectListener() = default;
// Notifies that an object with the given sequence number has become
// available. The object payload itself may be retrieved via GetCachedObject
// method of the associated track publisher.
virtual void OnNewObjectAvailable(FullSequence sequence) = 0;
// Notifies that a pure FIN has arrived following |sequence|.
virtual void OnNewFinAvailable(FullSequence sequence) = 0;
// No further object will be published for the given group, usually due to a
// timeout. The owner of the Listener may want to reset the relevant streams.
virtual void OnGroupAbandoned(uint64_t group_id) = 0;
// Notifies that the Publisher is being destroyed, so no more objects are
// coming.
virtual void OnTrackPublisherGone() = 0;
};
// A handle representing a fetch in progress. The fetch in question can be
// cancelled by deleting the object.
class MoqtFetchTask {
public:
using ObjectsAvailableCallback = quiche::MultiUseCallback<void()>;
virtual ~MoqtFetchTask() = default;
// Potential results of a GetNextObject() call.
enum GetNextObjectResult {
// The next object is available, and is placed into the reference specified
// by the caller.
kSuccess,
// The next object is not yet available (equivalent of EAGAIN).
kPending,
// The end of fetch has been reached.
kEof,
// The fetch has failed; the error is available via GetStatus().
kError,
};
// Returns the next object received via the fetch, if available.
virtual GetNextObjectResult GetNextObject(PublishedObject& output) = 0;
// Sets the callback that is called when GetNextObject() has previously
// returned kPending, but now a new object (or potentially an error or an
// end-of-fetch) is available. The application is responsible for calling
// GetNextObject() until it gets kPending; no further callback will occur
// until then.
virtual void SetObjectAvailableCallback(
ObjectsAvailableCallback callback) = 0;
// Returns the error if fetch has completely failed, and OK otherwise.
virtual absl::Status GetStatus() = 0;
// Returns the highest sequence number that will be delivered by the fetch.
// It is the minimum of the end of the fetch range and the live edge.
virtual FullSequence GetLargestId() const = 0;
};
// MoqtTrackPublisher is an application-side API for an MoQT publisher
// of a single individual track.
class MoqtTrackPublisher {
public:
virtual ~MoqtTrackPublisher() = default;
// Returns the full name of the associated track.
virtual const FullTrackName& GetTrackName() const = 0;
// GetCachedObject lets the MoQT stack access the objects that are available
// in the track's built-in local cache. Retrieves the first object ID >=
// sequence.object that matches (sequence.group, sequence.subgroup).
//
// This implementation of MoQT does not store any objects within the MoQT
// stack itself, at least until the object is fully serialized and passed to
// the QUIC stack. Instead, it relies on individual tracks having a shared
// cache for recent objects, and objects are always pulled from that cache
// whenever they are sent. Once an object is not available via the cache, it
// can no longer be sent; this ensures that objects are not buffered forever.
//
// This method returns nullopt if the object is not currently available, but
// might become available in the future. If the object is gone forever,
// kGroupDoesNotExist/kObjectDoesNotExist has to be returned instead;
// otherwise, the corresponding QUIC streams will be stuck waiting for objects
// that will never arrive.
virtual std::optional<PublishedObject> GetCachedObject(
FullSequence sequence) const = 0;
// Returns a full list of objects available in the cache, to be used for
// SUBSCRIBEs with a backfill. Returned in order of worsening priority.
virtual std::vector<FullSequence> GetCachedObjectsInRange(
FullSequence start, FullSequence end) const = 0;
// TODO: add an API to fetch past objects that are out of cache and might
// require an upstream request to fill the relevant cache again. This is
// currently done since the specification does not clearly describe how this
// is supposed to be done, especially with respect to such things as
// backpressure.
// Registers a listener with the track. The listener will be notified of all
// newly arriving objects. The pointer to the listener must be valid until
// removed.
virtual void AddObjectListener(MoqtObjectListener* listener) = 0;
virtual void RemoveObjectListener(MoqtObjectListener* listener) = 0;
virtual absl::StatusOr<MoqtTrackStatusCode> GetTrackStatus() const = 0;
// Returns the largest sequence pair that has been published so far.
// This method may only be called if
// DoesTrackStatusImplyHavingData(GetTrackStatus()) is true.
virtual FullSequence GetLargestSequence() const = 0;
// Returns the forwarding preference of the track.
// This method may only be called if
// DoesTrackStatusImplyHavingData(GetTrackStatus()) is true.
virtual MoqtForwardingPreference GetForwardingPreference() const = 0;
// Returns the current forwarding priority of the track.
virtual MoqtPriority GetPublisherPriority() const = 0;
// Returns the publisher-preferred delivery order for the track.
virtual MoqtDeliveryOrder GetDeliveryOrder() const = 0;
// Performs a fetch for the specified range of objects.
virtual std::unique_ptr<MoqtFetchTask> Fetch(
FullSequence start, uint64_t end_group,
std::optional<uint64_t> end_object, MoqtDeliveryOrder order) = 0;
};
// MoqtPublisher is an interface to a publisher that allows it to publish
// multiple tracks.
class MoqtPublisher {
public:
virtual ~MoqtPublisher() = default;
virtual absl::StatusOr<std::shared_ptr<MoqtTrackPublisher>> GetTrack(
const FullTrackName& track_name) = 0;
};
} // namespace moqt
#endif // QUICHE_QUIC_MOQT_MOQT_PUBLISHER_H_