Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions cpp/moq/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ find_program(UNIFFI_BINDGEN_CPP uniffi-bindgen-cpp REQUIRED)
# Rendered to a scratch directory and copied only when changed, so a no-op cargo build does
# not recompile the bindings.
set(_generated "${CMAKE_CURRENT_BINARY_DIR}/include/moq/ffi")
# moq::IMPLEMENTATION names this package's version, which lives in VERSION.
set(_version_header "${CMAKE_CURRENT_BINARY_DIR}/include/moq/version.hpp")
configure_file(cmake/version.hpp.in "${_version_header}" @ONLY)
set(_generated_files moq.hpp moq.cpp moq_scaffolding.hpp uniffi_expected.hpp)
list(TRANSFORM _generated_files PREPEND "${_generated}/" OUTPUT_VARIABLE _generated_paths)
set(_render "${CMAKE_CURRENT_BINARY_DIR}/render")
Expand Down Expand Up @@ -151,6 +154,7 @@ if(PROJECT_IS_TOP_LEVEL)

install(DIRECTORY include/moq DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
install(FILES ${_generated_paths} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/moq/ffi)
install(FILES "${_version_header}" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/moq)
install(FILES src/moq.cpp DESTINATION ${CMAKE_INSTALL_DATADIR}/moq-cpp)
install(FILES "${MOQ_FFI_LIB}" DESTINATION ${CMAKE_INSTALL_LIBDIR})

Expand Down
5 changes: 5 additions & 0 deletions cpp/moq/cmake/version.hpp.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// Generated by CMake from cpp/moq/VERSION.
#pragma once

// The moq C++ package version.
#define MOQ_CPP_VERSION "@PROJECT_VERSION@"
5 changes: 5 additions & 0 deletions cpp/moq/include/moq/moq.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#pragma once

#include <moq/ffi/moq.hpp>
#include <moq/version.hpp>

#include <chrono>
#include <functional>
Expand All @@ -23,6 +24,10 @@ extern "C" void moq_ffi_shutdown(void);

namespace moq {

// This package's product token. Every type is generated, so nothing sets it for you: put it in
// ClientConfig::implementation and ServerConfig::implementation, after your own tokens.
inline constexpr const char *IMPLEMENTATION = "moq-cpp/" MOQ_CPP_VERSION;

// The value of a fallible call, or the Error that stopped it. tl::expected at every standard.
template <typename T>
using expected = ::uniffi::expected<T, Error>;
Expand Down
4 changes: 4 additions & 0 deletions cpp/moq/test/probe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -217,11 +217,15 @@ int main() {
// thread blocks on one at a time.
moq::ClientConfig client_config;
client_config.tls.insecure = true;
client_config.implementation = moq::IMPLEMENTATION;
auto client = ok(moq::Client::init(client_config), "client init");
auto accepting = server->accept();
auto connecting = client->connect("https://" + addr);
auto request = ok(accepting.get(), "accept");
CHECK(request != nullptr);
// The package names itself ahead of moq-ffi, so a server can tell bindings apart.
auto implementation = request->peer_implementation();
CHECK(implementation && implementation->rfind("moq-cpp/", 0) == 0);
auto served = ok(request->accept(nullptr, nullptr).get(), "request accept");
auto session = ok(connecting.get(), "connect");

Expand Down
8 changes: 4 additions & 4 deletions cpp/obs/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ target_sources(
src/obs-moq.cpp
src/moq-audio-encoder.cpp
src/moq-audio-encoder.h
src/moq-implementation.h
src/moq-worker.h
src/moq-output.h
src/moq-service.h
Expand All @@ -170,16 +171,15 @@ target_sources(
src/moq-source.cpp
src/moq-source.h
)
# Sessions advertise it in SETUP (moq-implementation.h); the dock also displays it.
target_compile_definitions(obs-moq PRIVATE PLUGIN_VERSION_STRING="${PLUGIN_VERSION}")

# The dock requires both the frontend API (to register it) and Qt (to build it).
# The advanced settings dialog is Qt-only, so it ships with the dock that opens it;
# without Qt the same settings are still reachable through the service properties.
if(ENABLE_FRONTEND_API AND ENABLE_QT)
target_sources(obs-moq PRIVATE src/moq-dock.cpp src/moq-dock.h src/moq-advanced-dialog.cpp src/moq-advanced-dialog.h)
target_compile_definitions(
obs-moq
PRIVATE MOQ_FRONTEND_ENABLED MOQ_VERSION_STRING="${_moq_link_version}" PLUGIN_VERSION_STRING="${PLUGIN_VERSION}"
)
target_compile_definitions(obs-moq PRIVATE MOQ_FRONTEND_ENABLED MOQ_VERSION_STRING="${_moq_link_version}")
endif()

if(${BUILD_PLUGIN})
Expand Down
17 changes: 17 additions & 0 deletions cpp/obs/src/moq-implementation.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once

#include <moq/moq.hpp>

#include <string>

// CMake defines it from the plugin's VERSION; a build outside CMake reports dev.
#ifndef PLUGIN_VERSION_STRING
#define PLUGIN_VERSION_STRING "dev"
#endif

// What the plugin's sessions advertise in SETUP ahead of moq-ffi's: itself, then the C++ package.
inline std::string MoQImplementation()
{
return std::string("moq-obs/" PLUGIN_VERSION_STRING " ") + moq::IMPLEMENTATION;
}
2 changes: 2 additions & 0 deletions cpp/obs/src/moq-output.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "moq-output.h"
#include "moq-error.h"
#include "moq-implementation.h"
#include "moq-settings.h"
#include "moq-url.h"
#include "logger.h"
Expand Down Expand Up @@ -186,6 +187,7 @@ bool MoQOutput::Start()
// switched off the client keeps the library defaults.
moq::ClientConfig config;
config.publish = next_origin;
config.implementation = MoQImplementation();
OBSDataAutoRelease service_settings = obs_service_get_settings(service);
std::string invalid = MoQSettings::Configure(service_settings, config);
std::shared_ptr<moq::Client> client;
Expand Down
2 changes: 2 additions & 0 deletions cpp/obs/src/moq-source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ extern "C" {
#include <libswscale/swscale.h>
}

#include "moq-implementation.h"
#include "moq-source.h"
#include "moq-url.h"
#include "moq-worker.h"
Expand Down Expand Up @@ -361,6 +362,7 @@ static moq::ClientConfig moq_source_client_config(bool keylog)
{
moq::ClientConfig config;
config.quic.keylog = keylog;
config.implementation = MoQImplementation();
return config;
}

Expand Down
2 changes: 2 additions & 0 deletions cpp/obs/test/moq-output-test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,8 @@ int main()
CHECK(first.has_value());
CHECK(first == output.GetEpoch());
CHECK(WaitFor([&] { return output.IsLiveSession() && relay.Accepted() == 1; }));
// The plugin names itself ahead of the C++ package, so a relay can tell it apart.
CHECK(relay.Advertised("moq-obs/dev moq-cpp/"));
relay.DropSessions();
CHECK(WaitFor([&] { return output.GetReconnectCount() == 1 && output.IsLiveSession(); }));
CHECK(MoQOutputStatsTest::Epoch(output) == first);
Expand Down
2 changes: 2 additions & 0 deletions cpp/obs/test/moq-source-test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -672,6 +672,8 @@ int main()
};
CHECK(on_grid(g_last_timestamp));
CHECK(on_grid(audio.timestamp));
// The plugin names itself ahead of the C++ package, so a relay can tell it apart.
CHECK(relay.Advertised("moq-obs/dev moq-cpp/"));
destroySource(source);
}
report("plays video and audio");
Expand Down
12 changes: 12 additions & 0 deletions cpp/obs/test/moq-test-relay.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <sys/socket.h>
#include <unistd.h>

#include <algorithm>
#include <chrono>
#include <cstdio>
#include <cstdlib>
Expand Down Expand Up @@ -134,6 +135,14 @@ class TestRelay {
return accepted;
}

// Whether a session the relay accepted advertised an implementation starting with `prefix`.
bool Advertised(const std::string &prefix)
{
std::lock_guard<std::mutex> lock(mutex);
return std::any_of(implementations.begin(), implementations.end(),
[&](const std::string &value) { return value.rfind(prefix, 0) == 0; });
}

std::shared_ptr<moq::OriginProducer> origin;

private:
Expand All @@ -143,11 +152,13 @@ class TestRelay {
auto request = server->accept().get();
if (!request || !*request)
return;
const auto implementation = (*request)->peer_implementation();
auto session = (*request)->accept(nullptr, nullptr).get();
if (!session)
continue;
std::lock_guard<std::mutex> lock(mutex);
sessions.push_back(*session);
implementations.push_back(implementation.value_or(""));
accepted++;
}
}
Expand Down Expand Up @@ -196,6 +207,7 @@ class TestRelay {

std::mutex mutex;
std::vector<std::shared_ptr<moq::Session>> sessions;
std::vector<std::string> implementations;
size_t accepted = 0;
std::thread sessions_thread;

Expand Down
2 changes: 2 additions & 0 deletions dart/moq/lib/src/client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'package:moq_ffi/moq_ffi.dart';

import 'aliases.dart';
import 'stream.dart';
import 'version.dart';

/// Scope for discovering announcements.
final class AnnounceOptions {
Expand Down Expand Up @@ -91,6 +92,7 @@ final class ConnectOptions {
websocket: (websocket ?? const WebSocketConfig())._ffi,
once: once,
backoff: backoff ?? MoqBackoff(),
implementation: implementation,
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved
publish: publish,
consume: consume,
);
Expand Down
2 changes: 2 additions & 0 deletions dart/moq/lib/src/server.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'package:moq_ffi/moq_ffi.dart';

import 'aliases.dart';
import 'stream.dart';
import 'version.dart';

/// Everything [Server.listen] can be told.
///
Expand Down Expand Up @@ -95,6 +96,7 @@ final class Server {
maxStreams: options.maxStreams,
keylog: options.keylog,
),
implementation: implementation,
publish: publishOrigin,
consume: options.consume ?? shared,
),
Expand Down
7 changes: 7 additions & 0 deletions dart/moq/lib/src/version.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/// This package's version, which its sessions advertise in SETUP ahead of moq-ffi's.
///
/// `sh/dart/package.sh` stamps the released version; a source checkout reports `dev`.
const packageVersion = 'dev';

/// This package's product token.
const implementation = 'moq-dart/$packageVersion';
2 changes: 2 additions & 0 deletions dart/moq/test/moq_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,8 @@ void main() {

final accepted = () async {
final request = await server.requests().first.timeout(timeout);
// The wrapper names itself ahead of moq-ffi, so a server can tell bindings apart.
expect(request.peerImplementation(), startsWith('moq-dart/'));
return request.accept().timeout(timeout);
}();

Expand Down
Loading
Loading