LibQuicR
simple_subscribe/main.cpp
// SPDX-FileCopyrightText: Copyright (c) 2026 Cisco Systems
// SPDX-License-Identifier: BSD-2-Clause
#include <csignal>
#include <cstdint>
#include <iostream>
#include <string>
class SimpleClientCallbacks : public quicr::Session::ClientCallbacks
{
struct Private
{
explicit Private() = default;
};
public:
SimpleClientCallbacks(Private) {}
static std::shared_ptr<SimpleClientCallbacks> Create()
{
return std::make_shared<SimpleClientCallbacks>(Private{});
}
const std::shared_ptr<quicr::Session>&,
const quicr::SetupAttributes& setup_attributes) override
{
std::cerr << "Setup received from '" << setup_attributes.endpoint_id << "'" << std::endl;
return {};
}
};
class SimpleSubscribeTrackHandler : public quicr::SubscribeTrackHandler
{
struct Private
{
explicit Private() = default;
};
public:
SimpleSubscribeTrackHandler(Private, const quicr::FullTrackName& full_track_name, std::uint8_t priority)
: quicr::SubscribeTrackHandler(full_track_name, priority, quicr::messages::GroupOrder::kAscending)
{
}
static std::shared_ptr<SimpleSubscribeTrackHandler> Create(const quicr::FullTrackName& full_track_name,
std::uint8_t priority)
{
return std::make_shared<SimpleSubscribeTrackHandler>(Private{}, full_track_name, priority);
}
void ObjectReceived(const quicr::ObjectHeaders& headers,
std::span<const std::uint8_t> data,
std::optional<quicr::messages::StreamHeaderProperties>) override
{
std::cerr << "Received data: " << std::string(data.begin(), data.end()) << std::endl;
}
private:
};
volatile std::sig_atomic_t stop = 0;
void
HandleSignal(int)
{
stop = 1;
}
int
main()
try {
std::cerr << "Enter relay URI (prefixed with either moq:// or moqt://): ";
std::getline(std::cin, config.connect_uri);
quicr::SessionManager session_mgr;
auto weak_session = session_mgr.AddTransport(config, SimpleClientCallbacks::Create());
auto session = weak_session.lock();
if (!session) {
std::cerr << "Failed to connect" << std::endl;
return EXIT_FAILURE;
}
while (session->GetStatus() != quicr::Session::Status::kReady) {
const auto status = session->GetStatus();
std::cerr << "Failed to connect" << std::endl;
return EXIT_FAILURE;
}
std::this_thread::sleep_for(std::chrono::milliseconds(20));
}
quicr::TrackNamespace track_namespace = [] {
std::string str;
std::cerr << "Enter track namespace entries delimited by / (e.g. test/track): ";
std::cin >> str;
std::vector<std::string> entries;
std::size_t pos = 0;
while ((pos = str.find('/')) != std::string::npos) {
entries.emplace_back(str.substr(0, pos));
str.erase(0, pos + 1);
}
entries.emplace_back(std::move(str));
return quicr::TrackNamespace{ entries };
}();
std::string str;
std::cerr << "Enter a name for the track: ";
std::cin >> str;
}(track_namespace);
auto handler = SimpleSubscribeTrackHandler::Create(ftn, 127);
session_mgr.AddHandler(session, handler);
std::cerr << "Waiting for data (Ctrl+C to stop)" << std::endl;
std::signal(SIGINT, HandleSignal);
while (!stop) {
std::this_thread::sleep_for(std::chrono::milliseconds(20));
}
std::cerr << "\rDone subscribing! Goodbye" << std::endl;
return EXIT_SUCCESS;
} catch (const std::exception& e) {
std::cerr << "Caught exception: " << e.what() << std::endl;
return EXIT_FAILURE;
}
Holds either a success value or an error value.
Definition: expected.h:65
Owns transports and sessions and routes generic track handlers to a session.
Definition: session_manager.h:29
void AddHandler(const std::shared_ptr< Session > &session, std::shared_ptr< TrackHandler > handler)
Register a concrete track or namespace handler with a session.
std::weak_ptr< Session > AddTransport(const ClientConfig &config, std::shared_ptr< Session::ClientCallbacks > callbacks=nullptr)
Create a client transport and wait for its session to be established.
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
@ kReady
Setup is complete and the session is ready.
@ kNotConnected
No active underlying connection exists.
@ kFailedToConnect
Underlying connection establishment failed.
@ kInvalidParams
Session configuration or peer parameters are invalid.
@ kNotReady
Session is not ready for protocol operations.
@ kInternalError
Session encountered an internal failure.
MOQ track handler for subscribed track.
Definition: subscribe_track_handler.h:25
static std::shared_ptr< SubscribeTrackHandler > Create(const FullTrackName &full_track_name, std::uint8_t priority, std::optional< messages::GroupOrder > group_order=messages::GroupOrder::kAscending, const messages::Filter &filter=std::monostate{}, bool publisher_initiated=false)
Create shared Subscribe track handler.
Definition: subscribe_track_handler.h:112
virtual void ObjectReceived([[maybe_unused]] const ObjectHeaders &object_headers, [[maybe_unused]] BytesSpan data, std::optional< messages::StreamHeaderProperties > stream_mode=std::nullopt)
Notification of received [full] data object.
An N-tuple representation of a MOQ namespace.
Definition: track_name.h:22
GroupOrder
Requested group traversal order.
Definition: ctrl_message_types.h:532
@ kAscending
Increasing group identifiers.
Definition: attributes.h:13
requires std::is_standard_layout_v< T > std::is_same_v< std::decay_t< T >, std::string > Bytes AsOwnedBytes(const T &value)
Copies a value's native object representation into an owning byte buffer.
Definition: bytes.h:60
Configuration for an outbound client session.
Definition: config.h:78
std::string connect_uri
Destination URI using moq://, moqt://, or https://.
Definition: config.h:79
quicr::TransportConfig transport_config
Underlying QUIC transport configuration.
Definition: config.h:72
Full track name struct.
Definition: track_name.h:436
Object headers struct.
Definition: object.h:49
virtual Expected< void, Error< ErrorCode > > SetupReceived(const std::shared_ptr< Session > &session, const SetupAttributes &setup_attributes)
Callback on receipt of the peer's SETUP message.
Callback interface for session events specific to client mode.
Definition: session_callbacks.h:266
Peer setup attributes.
Definition: attributes.h:39
std::string endpoint_id
Endpoint identifier advertised by the peer, or an empty string if absent.
Definition: attributes.h:41
std::string tls_cert_filename
Path to the external PEM certificate chain used by a server.
Definition: config.h:30
std::string tls_key_filename
Path to the external private-key file corresponding to tls_cert_filename.
Definition: config.h:35
uint32_t time_queue_max_duration
Maximum time-queue duration in milliseconds.
Definition: config.h:38