basic MacOS version

This commit is contained in:
Théo Monnom
2022-08-03 16:19:02 +02:00
parent 5c8841de1f
commit 5a84aaa3c9
31 changed files with 356 additions and 39516 deletions
+2 -6
View File
@@ -1,7 +1,3 @@
/target
cmake-build-debug
.idea
build
.vscode
# atm
thirdparty
.idea
-3
View File
@@ -1,3 +0,0 @@
[submodule "protocol"]
path = protocol
url = https://github.com/livekit/protocol
+9 -33
View File
@@ -1,40 +1,16 @@
# TODO
# This file clearly need rework
# Build system to make it works on every platform
# Also mb automatically download prebuild libwebrtc binary so the users can directly start coding..
# IMPORTANT NOTE
# This file is just used because some IDEs need to understand how to do autocompletion.
# This file is completely ignored by the library ( See build.rs for the build system )
cmake_minimum_required(VERSION 3.22)
project(livekit-native)
project(client_sdk_native)
set(CMAKE_BUILD_TYPE Release)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_definitions(-DWEBRTC_POSIX=1 -DWEBRTC_MAC=1 -DGLIBCXX_USE_CXX11_ABI=0)
add_definitions(-DWEBRTC_POSIX -DWEBRTC_MAC)
find_package(Boost COMPONENTS system REQUIRED)
include_directories(${Boost_INCLUDE_DIRS})
include_directories(include/)
include_directories(libwebrtc/include)
find_package(Protobuf REQUIRED)
include_directories(${Protobuf_INCLUDE_DIRS})
find_package(spdlog CONFIG REQUIRED)
include_directories(thirdparty/webrtc/include)
file(GLOB_RECURSE SRC src/*)
add_executable(livekit-native ${SRC} main.cpp)
# for cocoa
find_library(CORE_FOUNDATION Foundation)
find_library(APPLICATION_SERVICES ApplicationServices)
find_library(CORE_SERVICES CoreServices)
target_link_libraries(livekit-native PRIVATE
spdlog::spdlog
${Boost_LIBRARIES}
${Protobuf_LIBRARIES}
${CORE_FOUNDATION} ${APPLICATION_SERVICES} ${CORE_SERVICES}
${CMAKE_CURRENT_LIST_DIR}/thirdparty/webrtc/lib/libboringssl.a
${CMAKE_CURRENT_LIST_DIR}/thirdparty/webrtc/lib/libwebrtc.a
)
# Fake library
add_library(client_sdk_native src/peer_connection_factory.cpp)
Generated
+180
View File
@@ -0,0 +1,180 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "cc"
version = "1.0.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
[[package]]
name = "codespan-reporting"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e"
dependencies = [
"termcolor",
"unicode-width",
]
[[package]]
name = "cxx"
version = "1.0.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "873c2e83af70859af2aaecd1f5d862f3790b747b1f4f50fb45a931d000ac0422"
dependencies = [
"cc",
"cxxbridge-flags",
"cxxbridge-macro",
"link-cplusplus",
]
[[package]]
name = "cxx-build"
version = "1.0.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b49edea7163bbc7a39e3d829b4b0b66a9d30486973152842b7413f2c7b5632bf"
dependencies = [
"cc",
"codespan-reporting",
"once_cell",
"proc-macro2",
"quote",
"scratch",
"syn",
]
[[package]]
name = "cxxbridge-flags"
version = "1.0.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f46b787c15af80277db5c88c6ac6c502ae545e622f010e06f95e540d34931acf"
[[package]]
name = "cxxbridge-macro"
version = "1.0.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ba3f3a7efa46626878fb5d324fabca4d19d2956b6ae97ce43044ef4515f5abc"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "glob"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
[[package]]
name = "link-cplusplus"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8cae2cd7ba2f3f63938b9c724475dfb7b9861b545a90324476324ed21dbc8c8"
dependencies = [
"cc",
]
[[package]]
name = "livekit-native"
version = "0.1.0"
dependencies = [
"cxx",
"cxx-build",
"glob",
]
[[package]]
name = "once_cell"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1"
[[package]]
name = "proc-macro2"
version = "1.0.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c278e965f1d8cf32d6e0e96de3d3e79712178ae67986d9cf9151f51e95aac89b"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804"
dependencies = [
"proc-macro2",
]
[[package]]
name = "scratch"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96311ef4a16462c757bb6a39152c40f58f31cd2602a40fceb937e2bc34e6cbab"
[[package]]
name = "syn"
version = "1.0.98"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "termcolor"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
dependencies = [
"winapi-util",
]
[[package]]
name = "unicode-ident"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15c61ba63f9235225a22310255a29b806b907c9b8c964bcbd0a2c70f3f2deea7"
[[package]]
name = "unicode-width"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+14
View File
@@ -0,0 +1,14 @@
[package]
name = "livekit-native"
version = "0.1.0"
edition = "2021"
homepage = "https://livekit.io"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
cxx = "1.0"
[build-dependencies]
cxx-build = "1.0"
glob = "0.3.0"
+61
View File
@@ -0,0 +1,61 @@
fn main() {
let target_os = "macos";
//let target_arch = "arm64";
let libwebrtc_dir = std::path::PathBuf::from("./libwebrtc");
// Just required for the bridge build to succeed.
let includes = &[
std::path::PathBuf::from("./include"),
libwebrtc_dir.join("include/"),
libwebrtc_dir.join("include/third_party/abseil-cpp/"),
libwebrtc_dir.join("include/third_party/libc++/"),
];
let mut builder = cxx_build::bridges(&["src/main.rs"]);
builder.flag("-std=c++17"); // Not sure about this .. Shouldn't this be c++14 ?
builder.file("src/peer_connection_factory.cpp");
for include in includes {
builder.include(include);
}
match target_os {
"macos" => {
println!("cargo:rustc-link-lib=dylib=c++");
println!("cargo:rustc-link-lib=framework=Foundation");
println!("cargo:rustc-link-lib=framework=AVFoundation");
println!("cargo:rustc-link-lib=framework=CoreAudio");
println!("cargo:rustc-link-lib=framework=AudioToolbox");
println!("cargo:rustc-link-lib=framework=Appkit");
println!("cargo:rustc-link-lib=framework=CoreMedia");
println!("cargo:rustc-link-lib=framework=CoreGraphics");
builder.flag("-stdlib=libc++")
.define("WEBRTC_ENABLE_OBJC_SYMBOL_EXPORT", None)
.define("WEBRTC_POSIX", None)
.define("WEBRTC_MAC", None);
}
_ => {
eprintln!("Unsupported platform, {}", target_os);
std::process::exit(1);
}
}
builder.warnings(false).compile("lkwebrtc");
println!("cargo:rustc-link-search=native={}", libwebrtc_dir.canonicalize().unwrap().to_str().unwrap());
println!("cargo:rustc-link-lib=static=webrtc");
for entry in glob::glob("./src/**/*.cpp").unwrap() {
println!("cargo:rerun-if-changed={}", entry.unwrap().display().to_string());
}
for entry in glob::glob("./include/**/*.h").unwrap() {
println!("cargo:rerun-if-changed={}", entry.unwrap().display().to_string());
}
println!("cargo:rerun-if-changed=src/main.rs");
}
-1
View File
@@ -1 +0,0 @@
protoc -I=protocol --cpp_out=src/proto protocol/livekit_models.proto protocol/livekit_rtc.proto
+29
View File
@@ -0,0 +1,29 @@
//
// Created by Théo Monnom on 03/08/2022.
//
#ifndef PEER_CONNECTION_FACTORY_H
#define PEER_CONNECTION_FACTORY_H
#include "api/peer_connection_interface.h"
namespace lk {
class PeerConnectionFactory {
public:
PeerConnectionFactory();
private:
rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> peer_factory_;
std::unique_ptr<rtc::Thread> network_thread_;
std::unique_ptr<rtc::Thread> worker_thread_;
std::unique_ptr<rtc::Thread> signaling_thread_;
};
std::unique_ptr<PeerConnectionFactory> CreatePeerConnectionFactory();
}
#endif //PEER_CONNECTION_FACTORY_H
+2
View File
@@ -0,0 +1,2 @@
include/
libwebrtc.a
-17
View File
@@ -1,17 +0,0 @@
#include <iostream>
#include "src/rtc_engine.h"
#include "spdlog/spdlog.h"
#include <thread>
int main() {
spdlog::info("Starting LiveKit...");
livekit::RTCEngine engine;
engine.Join("ws://localhost:7880", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2NTY1MTUxOTcsImlzcyI6IkFQSUNrSG04M01oZ2hQeCIsIm5iZiI6MTY1MzkyMzE5Nywic3ViIjoidGVzdGlkZW50aXR5IiwidmlkZW8iOnsicm9vbSI6InRlc3Ryb29tIiwicm9vbUpvaW4iOnRydWV9fQ.M6gIwp_GBVLkE5NwQjGUykn9GDIGIq57Php0LYAk2F8");
while(true){
engine.Update();
}
return EXIT_SUCCESS;
}
Submodule protocol deleted from 51a8116f88
-8
View File
@@ -1,8 +0,0 @@
//
// Created by Théo Monnom on 30/05/2022.
//
#include "createsession_observer.h"
namespace livekit {
} // livekit
-26
View File
@@ -1,26 +0,0 @@
//
// Created by Théo Monnom on 30/05/2022.
//
#ifndef LIVEKIT_NATIVE_CREATESESSION_OBSERVER_H
#define LIVEKIT_NATIVE_CREATESESSION_OBSERVER_H
#include <api/peer_connection_interface.h>
namespace livekit {
class CreateSessionObserver : public webrtc::CreateSessionDescriptionObserver {
public:
void OnSuccess(webrtc::SessionDescriptionInterface *desc) override {
};
void OnFailure(webrtc::RTCError error) override {
};
};
} // livekit
#endif //LIVEKIT_NATIVE_CREATESESSION_OBSERVER_H
+20
View File
@@ -0,0 +1,20 @@
use std::thread::sleep;
use std::time;
#[cxx::bridge(namespace = "lk")]
mod ffi {
unsafe extern "C++" {
include!("peer_connection_factory.h");
type PeerConnectionFactory;
fn CreatePeerConnectionFactory() -> UniquePtr<PeerConnectionFactory>;
}
}
fn main() {
println!("Hello, world!");
let factory = ffi::CreatePeerConnectionFactory();
}
+39
View File
@@ -0,0 +1,39 @@
//
// Created by Théo Monnom on 03/08/2022.
//
#include "peer_connection_factory.h"
#include <iostream>
namespace lk{
PeerConnectionFactory::PeerConnectionFactory(){
rtc::LogMessage::LogToDebug(rtc::LS_INFO);
RTC_LOG(LS_INFO) << "PeerConnectionFactory::PeerConnectionFactory()";
network_thread_ = rtc::Thread::CreateWithSocketServer();
network_thread_->Start();
worker_thread_ = rtc::Thread::Create();
worker_thread_->Start();
signaling_thread_ = rtc::Thread::Create();
signaling_thread_->Start();
webrtc::PeerConnectionFactoryDependencies dependencies;
dependencies.network_thread = network_thread_.get();
dependencies.worker_thread = worker_thread_.get();
dependencies.signaling_thread = signaling_thread_.get();
peer_factory_ = webrtc::CreateModularPeerConnectionFactory(std::move(dependencies));
if (peer_factory_.get() == nullptr) {
RTC_LOG_ERR(LS_ERROR) << "Failed to create PeerConnectionFactory";
return;
}
// TODO(theomonnom) Close resources
}
std::unique_ptr<PeerConnectionFactory> CreatePeerConnectionFactory() {
return std::make_unique<PeerConnectionFactory>();
}
} // namespace lk
-10
View File
@@ -1,10 +0,0 @@
//
// Created by Théo Monnom on 21/05/2022.
//
#include "peer_observer.h"
namespace livekit {
} // livekit
-51
View File
@@ -1,51 +0,0 @@
//
// Created by Théo Monnom on 21/05/2022.
//
#ifndef LIVEKIT_NATIVE_PEER_OBSERVER_H
#define LIVEKIT_NATIVE_PEER_OBSERVER_H
#include <api/create_peerconnection_factory.h>
#include <spdlog/spdlog.h>
namespace livekit {
class PeerObserver : public webrtc::PeerConnectionObserver {
public:
void OnSignalingChange(webrtc::PeerConnectionInterface::SignalingState new_state) override {
spdlog::info("Received OnSignalingChange");
};
void OnAddStream(rtc::scoped_refptr<webrtc::MediaStreamInterface> stream) override {
spdlog::info("Received OnAddStream");
};
void OnRemoveStream(rtc::scoped_refptr<webrtc::MediaStreamInterface> stream) override {
spdlog::info("Received OnRemoveStream");
};
void OnDataChannel(rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel) override {
spdlog::info("Received OnDataChannel");
};
void OnRenegotiationNeeded() override {
spdlog::info("Received OnRenegotiationNeeded");
};
void OnIceConnectionChange(webrtc::PeerConnectionInterface::IceConnectionState new_state) override {
spdlog::info("Received OnIceConnectionChange");
};
void OnIceGatheringChange(webrtc::PeerConnectionInterface::IceGatheringState new_state) override {
spdlog::info("Received OnIceGatheringChange");
};
void OnIceCandidate(const webrtc::IceCandidateInterface *candidate) override {
spdlog::info("Received OnIceCandidate");
};
};
} // livekit
#endif //LIVEKIT_NATIVE_PEER_OBSERVER_H
-26
View File
@@ -1,26 +0,0 @@
//
// Created by Théo Monnom on 30/05/2022.
//
#include "peer_transport.h"
#include "rtc_engine.h"
namespace livekit {
PeerTransport::PeerTransport(const RTCEngine &rtc_engine) {
observer = std::make_unique<PeerObserver>();
webrtc::PeerConnectionDependencies peer_configuration{observer.get()};
webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::PeerConnectionInterface>> opt_peer = rtc_engine.peer_factory_->CreatePeerConnectionOrError(
rtc_engine.configuration_, std::move(peer_configuration));
if (!opt_peer.ok()) {
throw std::runtime_error{"Failed to create a peer connection"};
}
peer_connection = opt_peer.value();
}
void PeerTransport::Negotiate() {
}
} // livekit
-27
View File
@@ -1,27 +0,0 @@
//
// Created by Théo Monnom on 30/05/2022.
//
#ifndef LIVEKIT_NATIVE_PEER_TRANSPORT_H
#define LIVEKIT_NATIVE_PEER_TRANSPORT_H
#include <api/peer_connection_interface.h>
#include "peer_observer.h"
namespace livekit {
class RTCEngine;
class PeerTransport {
public:
explicit PeerTransport(const RTCEngine &rtc_engine);
void Negotiate();
private:
rtc::scoped_refptr<webrtc::PeerConnectionInterface> peer_connection;
std::unique_ptr<PeerObserver> observer;
};
} // livekit
#endif //LIVEKIT_NATIVE_PEER_TRANSPORT_H
-1
View File
@@ -1 +0,0 @@
* linguist-generated
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-5
View File
@@ -1,5 +0,0 @@
//
// Created by Théo Monnom on 07/05/2022.
//
#include "room.h"
-17
View File
@@ -1,17 +0,0 @@
//
// Created by Théo Monnom on 07/05/2022.
//
#ifndef LIVEKIT_NATIVE_ROOM_H
#define LIVEKIT_NATIVE_ROOM_H
#include <string>
#include "signal_client.h"
namespace livekit{
} // livekit
#endif //LIVEKIT_NATIVE_ROOM_H
-71
View File
@@ -1,71 +0,0 @@
//
// Created by Théo Monnom on 04/05/2022.
//
#include "rtc_engine.h"
#include <rtc_base/ssl_adapter.h>
#include <spdlog/spdlog.h>
#include "peer_transport.h"
namespace livekit{
RTCEngine::RTCEngine() {
}
void RTCEngine::Join(const std::string &url, const std::string &token){
client_.Connect(url, token);
}
void RTCEngine::Update(){
client_.update();
auto res = client_.poll();
if(res.has_join())
OnJoin(res.join());
}
void RTCEngine::OnJoin(const JoinResponse &res){
spdlog::info("OnJoin");
rtc::InitializeSSL();
for(auto& is : res.ice_servers()){
webrtc::PeerConnectionInterface::IceServer ice_server;
for(auto& url : is.urls())
ice_server.urls.push_back(url);
ice_server.username = is.username();
ice_server.password = is.credential();
configuration_.servers.push_back(ice_server);
}
network_thread_ = rtc::Thread::CreateWithSocketServer();
network_thread_->Start();
worker_thread_ = rtc::Thread::Create();
worker_thread_->Start();
signaling_thread_ = rtc::Thread::Create();
signaling_thread_->Start();
webrtc::PeerConnectionFactoryDependencies dependencies;
dependencies.network_thread = network_thread_.get();
dependencies.worker_thread = worker_thread_.get();
dependencies.signaling_thread = signaling_thread_.get();
peer_factory_ = webrtc::CreateModularPeerConnectionFactory(std::move(dependencies));
if (peer_factory_.get() == nullptr) {
// TODO Make error callback
spdlog::error("Error on CreateModularPeerConnectionFactory");
return;
}
subscriber_ = std::make_unique<PeerTransport>(*this);
publisher_ = std::make_unique<PeerTransport>(*this);
}
void RTCEngine::Configure() {
}
} // livekit
-43
View File
@@ -1,43 +0,0 @@
//
// Created by Théo Monnom on 04/05/2022.
//
#ifndef LIVEKIT_NATIVE_RTC_ENGINE_H
#define LIVEKIT_NATIVE_RTC_ENGINE_H
#include "signal_client.h"
#include "peer_observer.h"
#include "peer_transport.h"
#include <api/peer_connection_interface.h>
namespace livekit{
class RTCEngine {
public:
RTCEngine();
void Join(const std::string &url, const std::string &token);
void Update();
private:
void Configure();
void OnJoin(const JoinResponse &res);
private:
friend class PeerTransport;
SignalClient client_;
rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> peer_factory_;
webrtc::PeerConnectionInterface::RTCConfiguration configuration_;
std::unique_ptr<rtc::Thread> network_thread_;
std::unique_ptr<rtc::Thread> worker_thread_;
std::unique_ptr<rtc::Thread> signaling_thread_;
std::unique_ptr<PeerTransport> publisher_;
std::unique_ptr<PeerTransport> subscriber_;
};
} // livekit
#endif //LIVEKIT_NATIVE_RTC_ENGINE_H
-141
View File
@@ -1,141 +0,0 @@
//
// Created by Théo Monnom on 27/04/2022.
//
#include "signal_client.h"
#include <thread>
#include <spdlog/spdlog.h>
namespace livekit {
SignalClient::SignalClient() : connected_(false), writing_(false), reading_(false) {
}
SignalClient::~SignalClient() {
Disconnect();
}
void SignalClient::Connect(const std::string &url, const std::string &token) {
if (connected_)
throw std::runtime_error{"already connected"};
url_ = ParseURL(url);
token_ = token;
start(); // We don't need a thread, everything is async ( + easier to maintain )
}
void SignalClient::update() {
beast::error_code ec;
io_context_.poll(ec);
if (ec)
throw std::runtime_error{"SignalClient::Update - " + ec.message()};
if (connected_) {
if (!websocket_.is_open())
throw std::runtime_error{"Websocket isn't open"}; // TODO Start reconnect
if (!reading_) {
websocket_.async_read(read_buffer_, beast::bind_front_handler(&SignalClient::OnRead, this));
reading_ = true;
}
// Write pending messages
if (!writing_ && !write_queue_.empty()) {
auto req = write_queue_.front();
unsigned long len = req.ByteSizeLong();
uint8_t data[len];
req.SerializeToArray(data, len);
websocket_.async_write(net::buffer(&data, len),
beast::bind_front_handler(&SignalClient::OnWrite, this));
write_queue_.pop();
writing_ = true;
}
}
}
SignalResponse SignalClient::poll(){
if(read_queue_.empty())
return SignalResponse{};
auto r = read_queue_.front();
read_queue_.pop();
return r;
}
void SignalClient::start() {
resolver_.async_resolve(url_.host, url_.port, beast::bind_front_handler(&SignalClient::OnResolve, this));
}
void SignalClient::Disconnect() {
if (!connected_)
return;
connected_ = false;
work_guard_.reset();
//m_IOContext.stop();
websocket_.close(websocket::close_code::normal); // TODO Close should be async
}
void SignalClient::Send(SignalRequest req) {
write_queue_.emplace(req);
}
void SignalClient::OnResolve(beast::error_code ec, tcp::resolver::results_type results) {
if (ec)
throw std::runtime_error{"SignalClient::OnResolve - " + ec.message()};
auto &layer = beast::get_lowest_layer(websocket_);
layer.expires_after(std::chrono::seconds(15));
layer.async_connect(results, beast::bind_front_handler(&SignalClient::OnConnect, this));
}
void SignalClient::OnConnect(beast::error_code ec, tcp::resolver::results_type::endpoint_type ep) {
if (ec)
throw std::runtime_error{"SignalClient::OnConnect - " + ec.message()};
beast::get_lowest_layer(websocket_).expires_never();
websocket_.set_option(websocket::stream_base::timeout::suggested(beast::role_type::client));
websocket_.async_handshake(url_.host, "/rtc?access_token=" + token_ + "&protocol=7",
beast::bind_front_handler(&SignalClient::OnHandshake, this));
}
void SignalClient::OnHandshake(beast::error_code ec) {
if (ec)
throw std::runtime_error{
"SignalClient::OnHandshake - " + ec.message()}; // TODO Callback for handling errors
connected_ = true;
spdlog::info("Connected to Websocket");
}
void SignalClient::OnRead(beast::error_code ec, std::size_t bytesTransferred) {
reading_ = false;
if (ec)
throw std::runtime_error{"SignalClient::OnRead - " + ec.message()};
SignalResponse res{};
if (res.ParseFromArray(read_buffer_.cdata().data(), bytesTransferred)) {
spdlog::info("Received SignalResponse {}", bytesTransferred);
read_queue_.emplace(res);
} else {
spdlog::error("Failed to decode signal message");
}
read_buffer_.clear();
}
void SignalClient::OnWrite(beast::error_code ec, std::size_t bytesTransferred) {
writing_ = false;
if (ec)
throw std::runtime_error{"SignalClient::OnWrite - " + ec.message()};
}
} // livekit
-65
View File
@@ -1,65 +0,0 @@
//
// Created by Théo Monnom on 27/04/2022.
//
#ifndef LIVEKIT_NATIVE_SIGNAL_CLIENT_H
#define LIVEKIT_NATIVE_SIGNAL_CLIENT_H
#include <boost/beast/core.hpp>
#include <boost/beast/websocket.hpp>
#include <queue>
#include "proto/livekit_rtc.pb.h"
#include "utils.h"
namespace beast = boost::beast; // from <boost/beast.hpp>
namespace http = beast::http; // from <boost/beast/http.hpp>
namespace websocket = beast::websocket; // from <boost/beast/websocket.hpp>
namespace net = boost::asio; // from <boost/asio.hpp>
using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
// If we keep the code singled threaded here, it'll be easily used in wasm ( Need ws bindings ), tho not sure
namespace livekit {
class SignalClient {
public:
SignalClient();
~SignalClient();
void Connect(const std::string &url, const std::string &token);
void Disconnect();
void update();
void Send(SignalRequest req);
SignalResponse poll();
private:
void start();
// beast handlers
void OnResolve(beast::error_code ec, tcp::resolver::results_type results);
void OnConnect(beast::error_code ec, tcp::resolver::results_type::endpoint_type ep);
void OnHandshake(beast::error_code ec);
void OnRead(beast::error_code ec, std::size_t bytesTransferred);
void OnWrite(beast::error_code ec, std::size_t bytesTransferred);
private:
URL url_;
std::string token_;
std::queue<SignalResponse> read_queue_;
std::queue<SignalRequest> write_queue_;
bool connected_;
bool reading_, writing_;
beast::flat_buffer write_buffer_;
beast::flat_buffer read_buffer_;
// Keep order
net::io_context io_context_;
net::executor_work_guard <net::io_context::executor_type> work_guard_ = net::make_work_guard(
io_context_); // Prevent the IOContext from running out of work
tcp::resolver resolver_{io_context_};
websocket::stream <beast::tcp_stream> websocket_{io_context_};
};
} // livekit
#endif //LIVEKIT_NATIVE_SIGNAL_CLIENT_H
-36
View File
@@ -1,36 +0,0 @@
//
// Created by Théo Monnom on 01/05/2022.
//
#ifndef LIVEKIT_NATIVE_UTILS_H
#define LIVEKIT_NATIVE_UTILS_H
#include <string>
#include <boost/regex.hpp>
namespace livekit {
// TODO Do I need path + query ?
struct URL {
std::string protocol;
std::string host;
std::string port;
};
static URL ParseURL(const std::string &url) {
boost::regex reg("(ws|wss)://([^:]*):?(\\d*)(.*)");
boost::match_results<std::string::const_iterator> groups;
if (boost::regex_search(url, groups, reg)) {
return URL{
groups[1],
groups[2],
groups[3]
};
}
throw std::runtime_error{"failed to parse url"};
}
} // livekit
#endif //LIVEKIT_NATIVE_UTILS_H