30 #include <string_view>
44 std::optional<std::chrono::milliseconds>
expires{};
67 ,
public std::enable_shared_from_this<Session>
69 static constexpr std::size_t kControlMessageBufferSize = 4096;
96 struct ClientCallbacks;
97 struct ServerCallbacks;
164 std::shared_ptr<Transport> transport,
165 std::shared_ptr<Connection> connection,
166 std::shared_ptr<ClientCallbacks> callbacks,
167 std::shared_ptr<Clock> clock,
168 std::shared_ptr<Logger> logger =
nullptr)
170 return std::shared_ptr<Session>(
new Session(cfg,
171 std::move(transport),
172 std::move(connection),
173 std::move(callbacks),
190 std::shared_ptr<Transport> transport,
191 std::shared_ptr<Connection> connection,
192 std::shared_ptr<ServerCallbacks> callbacks,
193 std::shared_ptr<Clock> clock,
194 std::shared_ptr<Logger> logger =
nullptr)
196 return std::shared_ptr<Session>(
new Session(cfg,
197 std::move(transport),
198 std::move(connection),
199 std::move(callbacks),
217 const std::shared_ptr<Logger>&
GetLogger() const noexcept {
return logger_; }
283 void PublishNamespace(std::shared_ptr<PublishNamespaceHandler> ns_handler,
bool passive =
false);
334 void FetchTrack(std::shared_ptr<FetchTrackHandler> track_handler);
360 void GoAway(
const std::string& new_session_uri,
361 std::chrono::milliseconds timeout,
362 std::optional<std::uint64_t> first_unprocessed_request_id = std::nullopt);
371 void GoAway(
const std::string& new_session_uri,
372 std::chrono::milliseconds timeout,
373 const std::shared_ptr<TrackHandler>& handler);
395 const std::shared_ptr<PublishTrackHandler>& track_handler,
396 bool ephemeral =
false);
410 const std::shared_ptr<PublishTrackHandler>& track_handler,
411 bool send_publish_done =
false);
448 std::shared_ptr<Transport> transport,
449 std::shared_ptr<Connection> connection,
450 std::shared_ptr<ClientCallbacks> callbacks,
451 std::shared_ptr<Logger> logger);
463 std::shared_ptr<Transport> transport,
464 std::shared_ptr<Connection> connection,
465 std::shared_ptr<ServerCallbacks> callbacks,
466 std::shared_ptr<Logger> logger);
479 std::shared_ptr<Transport> transport,
480 std::shared_ptr<Connection> connection,
481 std::shared_ptr<ClientCallbacks> callbacks,
482 std::shared_ptr<Clock> clock,
483 std::shared_ptr<Logger> logger);
496 std::shared_ptr<Transport> transport,
497 std::shared_ptr<Connection> connection,
498 std::shared_ptr<ServerCallbacks> callbacks,
499 std::shared_ptr<Clock> clock,
500 std::shared_ptr<Logger> logger);
514 void OnConnectionStatus(
const std::shared_ptr<Connection>& connection,
Connection::Status status)
override;
516 bool OnRecvStream(
const std::shared_ptr<Stream>& stream)
override;
518 void OnRecvDgram(
const std::shared_ptr<Connection>& connection)
override;
520 void OnConnectionMetricsSampled(
const std::shared_ptr<Connection>& connection,
521 MetricsTimeStamp sample_time,
525 void OnStreamMetricsStampled(
const std::shared_ptr<Connection>& connection,
526 MetricsTimeStamp sample_time,
527 std::uint64_t stream_id,
529 bool is_final)
override;
537 void CheckReady(
const std::shared_ptr<Connection>& connection);
539 std::shared_ptr<Connection> GetConnection(std::uint64_t connection_id)
const;
540 std::shared_ptr<Connection> GetConnectionForStream(
const std::shared_ptr<Stream>& stream)
const;
542 std::shared_ptr<Session> GetSharedPtr();
544 bool ProcessRequestMessage(
const std::shared_ptr<Connection>& connection,
545 const std::shared_ptr<Stream>& stream,
549 bool ProcessCtrlMessage(
const std::shared_ptr<Connection>& connection,
550 const std::shared_ptr<Stream>& stream,
554 void SetStatus(
Status status);
556 template<
typename... Fields>
559 SendCtrlMsg(stream,
false, msg_type, std::forward<Fields>(args)...);
562 template<
typename... Fields>
563 void SendCtrlMsg(
const std::shared_ptr<Stream>& stream,
572 if (stream ==
nullptr) {
573 throw std::logic_error(
"Stream cannot be null");
576 const auto connection = GetConnectionForStream(stream);
578 throw std::invalid_argument(
"Stream has no connection");
580 auto result = quic_transport_->Enqueue(
581 connection, stream, msg.
ToBytes(), 0, 2000, { true, close_stream, false, false });
589 void SendSetup(
const std::shared_ptr<Connection>& connection,
const std::string& connect_uri);
595 void SendTrackStatusOk(
const std::shared_ptr<Stream>& stream,
const TrackStatusResponse& response);
597 void SendSubscribeNamespaceOk(
const std::shared_ptr<Stream>& stream);
599 void SendSubscribeTracksOk(
const std::shared_ptr<Stream>& stream) { SendSubscribeNamespaceOk(stream); }
601 void SendPublishNamespaceOk(
const std::shared_ptr<Stream>& stream) { SendSubscribeNamespaceOk(stream); }
603 void SendRequestUpdateOk(
const std::shared_ptr<Stream>& stream,
604 std::optional<std::uint64_t> expires,
605 const std::optional<messages::Location>& largest_object);
608 void SendRequestOk(
const std::shared_ptr<Stream>& stream,
610 const messages::TrackExtensions& track_properties = {},
611 bool close_stream =
false);
613 void SendRequestUpdate(
const std::shared_ptr<Stream>& stream,
615 std::optional<std::uint64_t> end_group_id,
616 std::uint8_t priority,
619 void SendRequestError(
const std::shared_ptr<Stream>& stream,
620 std::uint64_t request_id,
622 std::chrono::milliseconds retry_interval,
623 const std::string& reason,
624 bool close_stream =
true,
625 std::optional<Redirect> redirect = std::nullopt);
631 bool SendPublishNamespace(
const std::shared_ptr<Stream>& stream,
632 std::uint64_t request_id,
633 const TrackNamespace& track_namespace);
639 bool SendSubscribeNamespace(
const std::shared_ptr<Stream>& stream,
640 std::uint64_t request_id,
641 const TrackNamespace& prefix,
651 bool SendSubscribe(
const std::shared_ptr<Stream>& stream,
652 std::uint64_t request_id,
653 const FullTrackName& tfn,
655 std::uint8_t priority,
656 std::optional<messages::GroupOrder> group_order,
658 std::optional<std::chrono::milliseconds> delivery_timeout,
659 std::chrono::milliseconds rendezvous_timeout);
661 void SendSubscribeOk(
const std::shared_ptr<Stream>& stream,
662 std::uint64_t request_id,
663 uint64_t track_alias,
664 const SubscribeResponse& response);
670 bool SendPublish(
const std::shared_ptr<Stream>& stream,
671 std::uint64_t request_id,
672 const PublishAttributes& publish);
674 void SendPublishDone(
const std::shared_ptr<Stream>& stream,
675 std::uint64_t request_id,
677 const std::string& reason);
679 void SendPublishOk(
const std::shared_ptr<Stream>& stream,
const PublishOkAttributes& attributes);
681 std::shared_ptr<Stream> FindSubscribeNamespaceStream(
const TrackNamespace& track_namespace)
const;
683 std::optional<std::uint64_t> FindRequestIdByStream(
const Stream& stream)
QUICR_EXCLUDES(state_mutex_);
685 bool IsCurrentRequestStream(std::uint64_t request_id,
const std::shared_ptr<Stream>& stream)
692 void SendTrackStatus(
const std::shared_ptr<Stream>& stream, std::uint64_t request_id,
const FullTrackName& tfn);
698 void ResolveFetch(uint64_t request_id,
699 std::optional<messages::GroupOrder> group_order,
700 const FetchResponse& response);
702 bool SendFetch(
const std::shared_ptr<Stream>& stream,
703 std::uint64_t request_id,
704 const FullTrackName& tfn,
705 std::uint8_t priority,
706 std::optional<messages::GroupOrder> group_order,
707 const messages::Location& start_location,
708 const messages::FetchEndLocation& end_location);
710 void SendJoiningFetch(
const std::shared_ptr<Stream>& stream,
711 std::uint64_t request_id,
712 std::uint8_t priority,
713 std::optional<messages::GroupOrder> group_order,
714 std::uint64_t joining_request_id,
715 std::uint64_t joining_start,
718 void SendFetchOk(
const std::shared_ptr<Stream>& stream,
721 messages::Location end_location);
729 void CloseRequestHandler(std::uint64_t request_id,
const std::shared_ptr<Stream>& stream,
StreamClosedFlag flag)
732 std::shared_ptr<PublishTrackHandler> GetPubTrackHandler(TrackHash& th);
734 void RemoveTracksForConnectionClose(
const std::shared_ptr<Connection>& connection);
736 [[nodiscard]] uint64_t GetNextRequestID();
747 bool BindRecvStream(Stream& stream);
761 bool RecvCtrlMessage(
const std::shared_ptr<Connection>& connection,
762 const std::shared_ptr<Stream>& stream,
763 bool is_request_stream);
781 bool ForwardSubgroupBytes(Stream& stream, ForwardingSubscribeTrackHandler& handler);
783 bool OnRecvSubgroup(std::uint64_t track_alias, Stream& stream);
785 bool OnRecvFetch(std::uint64_t request_id, Stream& stream);
794 std::shared_ptr<Stream> CreateStream(
const std::shared_ptr<Connection>& connection,
795 std::uint64_t request_id,
809 bool Enqueue(
const std::shared_ptr<Connection>& connection,
810 const std::shared_ptr<Stream>& stream,
811 std::shared_ptr<
const std::vector<uint8_t>> bytes,
812 const uint8_t priority,
813 const uint32_t ttl_ms,
814 const Transport::EnqueueFlags flags);
817 void SetConnectionAddedCallback(
818 std::function<
void(
const std::shared_ptr<Connection>&,
const std::shared_ptr<Session>&)> callback)
820 connection_added_callback_ = std::move(callback);
823 enum class MigrationRequestType : std::uint8_t
832 struct PendingMigration
834 MigrationRequestType type;
835 std::shared_ptr<Stream> request_stream;
841 std::shared_ptr<Connection> source_connection;
842 std::shared_ptr<Connection> candidate_connection;
843 std::map<std::uint64_t, PendingMigration> pending;
846 using MigrationKey = std::pair<std::uint64_t, std::optional<std::uint64_t>>;
847 using MigrationMap = std::map<MigrationKey, Migration>;
849 void Migrate(
const std::shared_ptr<Connection>& source_connection,
const Redirect& redirect);
851 void StartMigrationRequests(
const std::shared_ptr<Connection>& connection);
853 void CompleteMigration(
const std::shared_ptr<Connection>& connection,
854 std::uint64_t request_id,
855 MigrationRequestType type,
856 std::optional<std::uint64_t> received_track_alias = std::nullopt);
858 bool FailMigration(
const std::shared_ptr<Connection>& connection, std::uint64_t request_id);
860 bool MatchesRedirect(
const TrackHandler& handler,
const Redirect& redirect)
const;
862 MigrationMap::iterator FindMigration(
const Connection& candidate)
QUICR_REQUIRES(state_mutex_);
864 void ResetSubgroup(
const std::shared_ptr<Stream>& stream);
867 mutable std::mutex connections_mutex_;
868 std::map<std::uint64_t, std::shared_ptr<Connection>> connections_
QUICR_GUARDED_BY(connections_mutex_);
870 std::shared_ptr<Connection> default_connection_
QUICR_GUARDED_BY(state_mutex_);
871 std::function<void(
const std::shared_ptr<Connection>&,
const std::shared_ptr<Session>&)>
872 connection_added_callback_;
874 const std::shared_ptr<Callbacks> callbacks_;
880 std::atomic<uint64_t> next_request_id_;
882 std::map<std::uint64_t, SubscribeContext> recv_req_id;
886 std::uint64_t request_id;
894 bool is_request_stream;
898 using StreamKey = std::pair<std::uint64_t, std::uint64_t>;
899 std::map<StreamKey, StreamRequest> request_by_stream
QUICR_GUARDED_BY(state_mutex_);
901 std::vector<std::uint64_t>
902 recv_publish_namespaces;
905 std::vector<std::uint64_t> recv_subscribe_namespaces;
907 std::map<std::uint64_t, std::shared_ptr<TrackHandler>> request_handlers;
915 std::map<std::pair<std::uint64_t, std::uint64_t>, std::shared_ptr<SubscribeTrackHandler>>
916 sub_by_recv_track_alias;
922 std::map<std::uint64_t, std::map<std::uint64_t, std::shared_ptr<PublishTrackHandler>>> pub_tracks_by_name;
925 std::map<std::uint64_t, std::map<uint64_t, std::shared_ptr<PublishTrackHandler>>> pub_tracks_by_track_alias
928 std::map<std::uint64_t, std::shared_ptr<PublishTrackHandler>>
929 pub_fetch_tracks_by_request_id;
931 mutable std::mutex state_mutex_;
933 const bool client_mode_;
935 const std::shared_ptr<Logger> logger_;
939 const ServerConfig server_config_;
941 const ClientConfig client_config_;
945 const std::shared_ptr<Clock> clock_;
947 const std::shared_ptr<Transport> quic_transport_;
Monotonic microsecond clock abstraction.
Definition: clock.h:14
Async Callback API on the transport.
Definition: connection.h:62
Status
Connection lifecycle state.
Definition: connection.h:48
Publishes the ordered object stream that answers a FETCH.
Definition: publish_fetch_handler.h:18
MOQ track handler for published track.
Definition: publish_track_handler.h:25
Owns transports and sessions and routes generic track handlers to a session.
Definition: session_manager.h:29
MoQ Session endpoint supporting connection-explicit operations.
Definition: session.h:68
ConnectionStatus
Connection status codes.
Definition: session.h:120
@ kIdleTimeout
Connection closed after an idle timeout.
@ kNotConnected
No active connection.
@ kConnected
Connection is active.
@ kClosedByRemote
Connection was closed by the peer.
@ kConnecting
Connection establishment is in progress.
StreamDataMessageStatus
Reserved status type for stream-data parsing.
Definition: session.h:113
Session(const ClientConfig &cfg, std::shared_ptr< Transport > transport, std::shared_ptr< Connection > connection, std::shared_ptr< ClientCallbacks > callbacks, std::shared_ptr< Clock > clock, std::shared_ptr< Logger > logger)
Client mode constructor with explicit tick service.
void GoAway(const std::string &new_session_uri, std::chrono::milliseconds timeout, std::optional< std::uint64_t > first_unprocessed_request_id=std::nullopt)
Send GOAWAY on this session's control stream.
void CancelFetchTrack(std::shared_ptr< FetchTrackHandler > track_handler)
Cancel Fetch track.
Session()=delete
Default construction is disabled; use a mode-specific constructor.
void SendNamespace(const TrackNamespace &track_namespace)
Tell subscribe-namespace subscribers on this connection that a namespace is active.
Session(const ClientConfig &cfg, std::shared_ptr< Transport > transport, std::shared_ptr< Connection > connection, std::shared_ptr< ClientCallbacks > callbacks, std::shared_ptr< Logger > logger)
Client mode constructor.
void UpdateTrackSubscription(std::shared_ptr< SubscribeTrackHandler > track_handler)
Update Subscription to a track.
void OnStreamClosed(const std::shared_ptr< Stream > &stream, StreamClosedFlag flag) override
Handle closure of a stream delegated by the connection.
std::shared_ptr< Connection > GetDefaultConnection() const noexcept
Return shared ownership of the session's default connection.
static std::shared_ptr< Session > Create(const ServerConfig &cfg, std::shared_ptr< Transport > transport, std::shared_ptr< Connection > connection, std::shared_ptr< ServerCallbacks > callbacks, std::shared_ptr< Clock > clock, std::shared_ptr< Logger > logger=nullptr)
Create a server-mode endpoint.
Definition: session.h:189
void BindPublisherTrack(std::uint64_t src_id, uint64_t request_id, const std::shared_ptr< PublishTrackHandler > &track_handler, bool ephemeral=false)
Bind a server publish track handler based on a subscribe.
Session(const ServerConfig &cfg, std::shared_ptr< Transport > transport, std::shared_ptr< Connection > connection, std::shared_ptr< ServerCallbacks > callbacks, std::shared_ptr< Logger > logger)
Server mode constructor.
void SubscribeTrack(std::shared_ptr< SubscribeTrackHandler > track_handler)
Subscribe to a track.
void GoAway(const std::string &new_session_uri, std::chrono::milliseconds timeout, const std::shared_ptr< TrackHandler > &handler)
Send GOAWAY on one request stream.
friend class SubscribeTrackHandler
Definition: session.h:951
void FetchTrack(std::shared_ptr< FetchTrackHandler > track_handler)
Fetch track.
const std::shared_ptr< Clock > & GetTickService() const noexcept
Return shared ownership of the tick service used by the session.
Definition: session.h:213
void UnbindFetchTrack(const std::shared_ptr< PublishFetchHandler > &track_handler)
Unbind a server fetch publisher track handler.
ControlMessageStatus
Control message status codes.
Definition: session.h:103
@ kMessageIncomplete
control message is incomplete and more data is needed
@ kUnsupportedMessageType
Unsupported MOQT message type.
@ kStreamBufferCannotBeZero
stream buffer cannot be zero when parsing message type
@ kMessageComplete
control message is complete and stream buffer get any has complete message
@ kStreamBufferMissingType
connection context is missing message type
void SubscribeNamespace(std::shared_ptr< SubscribeNamespaceHandler > handler)
Subscribe to a prefix namespace on a specific connection.
void UnsubscribeNamespace(const std::shared_ptr< SubscribeNamespaceHandler > &handler)
Unsubscribe from a prefix namespace on a specific connection.
static std::shared_ptr< Session > Create(const ClientConfig &cfg, std::shared_ptr< Transport > transport, std::shared_ptr< Connection > connection, std::shared_ptr< ClientCallbacks > callbacks, std::shared_ptr< Clock > clock, std::shared_ptr< Logger > logger=nullptr)
Create a client-mode endpoint.
Definition: session.h:163
void UnbindPublisherTrack(std::uint64_t src_id, const std::shared_ptr< PublishTrackHandler > &track_handler, bool send_publish_done=false)
Unbind a server publish track handler.
void PublishTrack(std::shared_ptr< PublishTrackHandler > track_handler)
Publish to a track.
Status
Status of the transport.
Definition: session.h:76
@ kReady
Setup is complete and the session is ready.
@ kNotConnected
No active underlying connection exists.
@ kFailedToConnect
Underlying connection establishment failed.
@ kPendingPeerSetup
Local setup was sent and peer setup is still pending.
@ kInvalidParams
Session configuration or peer parameters are invalid.
@ kDisconnecting
Session teardown is in progress.
@ kNotReady
Session is not ready for protocol operations.
@ kConnecting
Underlying connection establishment is in progress.
@ kInternalError
Session encountered an internal failure.
Status GetStatus() const noexcept
Return the current session status.
Definition: session.h:221
const std::shared_ptr< Logger > & GetLogger() const noexcept
Return the optional logger used by the session.
Definition: session.h:217
void SendNamespaceDone(const TrackNamespace &track_namespace)
Tell subscribe-namespace subscribers on this connection that a namespace is no longer active.
void RequestTrackStatus(std::shared_ptr< TrackStatusHandler > handler)
Request track status.
void UnsubscribeTrack(const std::shared_ptr< SubscribeTrackHandler > &track_handler)
Unsubscribe track.
virtual ~Session()
Destroy the session after detaching and releasing its owned state.
void UnpublishTrack(const std::shared_ptr< PublishTrackHandler > &track_handler)
Unpublish track.
void PublishNamespaceDone(const std::shared_ptr< PublishNamespaceHandler > &track_handler)
Unpublish track namespace.
void Disconnect()
Close the underlying transport connection and detach this session as delegate.
void BindFetchTrack(std::shared_ptr< PublishFetchHandler > track_handler)
Bind a server fetch publisher track handler.
Session(const ServerConfig &cfg, std::shared_ptr< Transport > transport, std::shared_ptr< Connection > connection, std::shared_ptr< ServerCallbacks > callbacks, std::shared_ptr< Clock > clock, std::shared_ptr< Logger > logger)
Server mode constructor with explicit tick service.
void PublishNamespace(std::shared_ptr< PublishNamespaceHandler > ns_handler, bool passive=false)
Publish a track namespace.
MOQ track handler for subscribed track.
Definition: subscribe_track_handler.h:25
An N-tuple representation of a MOQ namespace.
Definition: track_name.h:22
Generic message buffer formatting class.
Definition: message.h:23
requires std::is_enum_v< T > std::is_integral_v< T > Message & PrependType(T type)
Prepends a message type at the front of the byte buffer.
Definition: message.h:56
Message & Append(std::uint8_t byte) noexcept
Definition: message.h:94
const std::shared_ptr< std::vector< uint8_t > > & ToBytes() const noexcept
Definition: message.h:133
Message & ReserveLength()
Inserts a std::uint16_t near the front of the byte buffer for the payload length.
Definition: message.h:72
PublishDoneStatusCode
Publish-done status codes.
Definition: ctrl_message_types.h:757
std::variant< std::monostate, SubscriptionFilter, TrackFilter > Filter
Any supported filter representation; monostate means no/unsupported filter.
Definition: ctrl_message_types.h:677
ControlMessageType
MoQ control-message wire type codes.
Definition: ctrl_message_types.h:42
@ kPublishNamespace
PUBLISH_NAMESPACE.
@ kSubscribeNamespace
SUBSCRIBE_NAMESPACE.
GroupOrder
Requested group traversal order.
Definition: ctrl_message_types.h:532
@ kAscending
Increasing group identifiers.
quicr::messages::ParameterList< quicr::messages::ParameterType > Parameters
Standard message-parameter list.
Definition: parameters.h:469
Definition: attributes.h:13
std::span< const Byte > BytesSpan
Non-owning, read-only view of contiguous bytes.
Definition: bytes.h:21
@ kInvalidStreamId
The stream handle or identifier is invalid.
StreamClosedFlag
Peer or transport event that closed a stream direction.
Definition: connection.h:29
ErrorCode
MOQT error code, as carried by REQUEST_ERROR.
Definition: errors.h:33
Configuration for an outbound client session.
Definition: config.h:78
Response to a received MOQT Fetch message.
Definition: session.h:51
messages::GroupOrder publisher_default_group_order
Publisher's default group delivery order.
Definition: session.h:55
std::optional< messages::Location > largest_location
Largest object available to the fetch, when known.
Definition: session.h:53
Full track name struct.
Definition: track_name.h:436
QUIC connection counters and period aggregates.
Definition: metrics.h:85
Metrics produced by a single QUIC stream over one sample period.
Definition: metrics.h:136
Configuration for a listening server transport.
Definition: config.h:85
Connection remote information.
Definition: session.h:132
std::string ip
remote IPv4/v6 address
Definition: session.h:133
uint16_t port
remote port
Definition: session.h:134
Definition: session.h:140
std::optional< messages::Location > largest_location
Largest object location advertised for the request, when present.
Definition: session.h:146
TrackHash track_hash
Cached hashes used to index the track.
Definition: session.h:143
FullTrackName track_full_name
Full name of the subscribed or published track.
Definition: session.h:141
std::shared_ptr< Stream > stream
Bidirectional request stream associated with the context.
Definition: session.h:148
Response to a received SUBSCRIBE.
Definition: session.h:40
bool is_publisher_initiated
Whether the accepted subscription was initiated by the publisher.
Definition: session.h:41
std::optional< std::chrono::milliseconds > expires
Accepted subscription lifetime, when bounded.
Definition: session.h:44
Cached hashes for a full track name and its components.
Definition: track_name.h:475
Response to a received TRACK_STATUS.
Definition: attributes.h:18
#define QUICR_EXCLUDES(...)
No-op lock-exclusion annotation when thread-safety annotations are disabled.
Definition: thread_safety.h:55
#define QUICR_REQUIRES(...)
No-op lock-requirement annotation when thread-safety annotations are disabled.
Definition: thread_safety.h:52
#define QUICR_GUARDED_BY(...)
No-op guarded-field annotation when thread-safety annotations are disabled.
Definition: thread_safety.h:64