From 6e8411e3f03880e084a63fb30c9bf8c35f227533 Mon Sep 17 00:00:00 2001 From: Tim Schneider Date: Tue, 18 Jun 2024 00:08:39 +0200 Subject: [PATCH] feat: add examples/signaling-server-libdatachannel-ws added simple signaling-server implemented using libdatachannel cpp-api --- CMakeLists.txt | 1 + .../CMakeLists.txt | 38 +++++ .../signaling-server.cpp | 161 ++++++++++++++++++ .../uwp/Logo.png | Bin 0 -> 488 bytes .../uwp/SmallLogo.png | Bin 0 -> 167 bytes .../uwp/SmallLogo44x44.png | Bin 0 -> 265 bytes .../uwp/SplashScreen.png | Bin 0 -> 909 bytes .../uwp/StoreLogo.png | Bin 0 -> 227 bytes .../uwp/Windows_TemporaryKey.pfx | Bin 0 -> 2560 bytes .../uwp/package.appxManifest | 42 +++++ 10 files changed, 242 insertions(+) create mode 100644 examples/signaling-server-libdatachannel-ws/CMakeLists.txt create mode 100644 examples/signaling-server-libdatachannel-ws/signaling-server.cpp create mode 100644 examples/signaling-server-libdatachannel-ws/uwp/Logo.png create mode 100644 examples/signaling-server-libdatachannel-ws/uwp/SmallLogo.png create mode 100644 examples/signaling-server-libdatachannel-ws/uwp/SmallLogo44x44.png create mode 100644 examples/signaling-server-libdatachannel-ws/uwp/SplashScreen.png create mode 100644 examples/signaling-server-libdatachannel-ws/uwp/StoreLogo.png create mode 100644 examples/signaling-server-libdatachannel-ws/uwp/Windows_TemporaryKey.pfx create mode 100644 examples/signaling-server-libdatachannel-ws/uwp/package.appxManifest diff --git a/CMakeLists.txt b/CMakeLists.txt index 981baa44e..b8d8b27d7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -544,6 +544,7 @@ if(NOT NO_EXAMPLES) if(NOT NO_WEBSOCKET) add_subdirectory(examples/client) add_subdirectory(examples/client-benchmark) + add_subdirectory(examples/signaling-server-libdatachannel-ws) endif() if(NOT NO_MEDIA) add_subdirectory(examples/media-receiver) diff --git a/examples/signaling-server-libdatachannel-ws/CMakeLists.txt b/examples/signaling-server-libdatachannel-ws/CMakeLists.txt new file mode 100644 index 000000000..0149e52ee --- /dev/null +++ b/examples/signaling-server-libdatachannel-ws/CMakeLists.txt @@ -0,0 +1,38 @@ +cmake_minimum_required(VERSION 3.15) +project(signaling-server-libdatachannel-ws + VERSION 0.1 + LANGUAGES CXX) + + set(MEDIA_UWP_RESOURCES + uwp/Logo.png + uwp/package.appxManifest + uwp/SmallLogo.png + uwp/SmallLogo44x44.png + uwp/SplashScreen.png + uwp/StoreLogo.png + uwp/Windows_TemporaryKey.pfx +) + +if(CMAKE_SYSTEM_NAME STREQUAL "WindowsStore") + add_executable(signaling-server-libdatachannel-ws signaling-server.cpp ${MEDIA_UWP_RESOURCES}) +else() + add_executable(signaling-server-libdatachannel-ws signaling-server.cpp) +endif() + +set_target_properties(signaling-server-libdatachannel-ws PROPERTIES + CXX_STANDARD 17 + OUTPUT_NAME signaling-server) + +set_target_properties(signaling-server-libdatachannel-ws PROPERTIES + XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER com.github.paullouisageneau.libdatachannel.examples.signaling-server-libdatachannel-ws) + +find_package(Threads REQUIRED) +target_link_libraries(signaling-server-libdatachannel-ws LibDataChannel::LibDataChannel Threads::Threads nlohmann_json::nlohmann_json) + +if(MSVC) + add_custom_command(TARGET signaling-server-libdatachannel-ws POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "$/datachannel.dll" + $ + ) +endif() diff --git a/examples/signaling-server-libdatachannel-ws/signaling-server.cpp b/examples/signaling-server-libdatachannel-ws/signaling-server.cpp new file mode 100644 index 000000000..774953a0e --- /dev/null +++ b/examples/signaling-server-libdatachannel-ws/signaling-server.cpp @@ -0,0 +1,161 @@ +/** + * signaling server example for libdatachannel + * Copyright (c) 2024 Tim Schneider + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#include "rtc/rtc.hpp" + +#include +#include +#include +#include +#include + +#include +using nlohmann::json; + + +using namespace std::chrono_literals; +using std::shared_ptr; +using std::weak_ptr; +template weak_ptr make_weak_ptr(shared_ptr ptr) { return ptr; } + +std::string get_user(weak_ptr wws) { + const auto &ws = wws.lock(); + const auto path_ = ws->path().value(); + const auto user = path_.substr(path_.rfind('/') + 1); + return user; +} + +void signalHandler(int signum) { + std::cout << "Interrupt signal (" << signum << ") received.\n"; + // terminate program + exit(signum); +} + +int main(int argc, char *argv[]) { + rtc::WebSocketServerConfiguration config; + config.port = 8000; + config.enableTls = false; + config.certificatePemFile = std::nullopt; + config.keyPemFile = std::nullopt; + config.keyPemPass = std::nullopt; + config.bindAddress = std::nullopt; + config.connectionTimeout = std::nullopt; + + // Check command line arguments. + for (int i = 1; i < argc; i++) { + if (strcmp(argv[i], "--help") == 0) { + const size_t len = strlen(argv[0]); + char *path = (char *)malloc(len + 1); + strcpy(path, argv[0]); + path[len] = 0; + + char *app_name = NULL; + // app_name = last_path_segment(path, "\\/"); + fprintf(stderr, + "Usage: %s [-p ] [-a ] [--connection-timeout ] " + "[--enable-tls] [--certificatePemFile ] [--keyPemFile ] " + "[--keyPemPass ]\n" + "Example:\n" + " %s -p 8000 -a 127.0.0.1 \n", + app_name, app_name); + free(path); + return EXIT_FAILURE; + } + if (strcmp(argv[i], "-p") == 0) { + config.port = atoi(argv[++i]); + continue; + } + if (strcmp(argv[i], "-a") == 0) { + config.bindAddress = argv[++i]; + continue; + } + if (strcmp(argv[i], "--connection-timeout") == 0) { + config.connectionTimeout = std::chrono::milliseconds(atoi(argv[++i])); + continue; + } + if (strcmp(argv[i], "--enable-tls") == 0) { + config.enableTls = true; + continue; + } + if (strcmp(argv[i], "--certificatePemFile") == 0) { + config.certificatePemFile = argv[++i]; + continue; + } + if (strcmp(argv[i], "--keyPemFile") == 0) { + config.keyPemFile = argv[++i]; + continue; + } + if (strcmp(argv[i], "--keyPemPass") == 0) { + config.keyPemPass = argv[++i]; + continue; + } + } + + auto wss = std::make_shared(config); + std::unordered_map> clients_map; + + wss->onClient([&clients_map](std::shared_ptr ws) { + std::promise wsPromise; + auto wsFuture = wsPromise.get_future(); + std::cout << "WebSocket client (remote-address: " << ws->remoteAddress().value() << ")" + << std::endl; + + ws->onOpen([&clients_map, &wsPromise, wws = make_weak_ptr(ws)]() { + const auto user = get_user(wws); + std::cout << "WebSocket connected (user: " << user << ")" << std::endl; + clients_map.insert_or_assign(user, wws.lock()); + wsPromise.set_value(); + }); + ws->onError([&clients_map, &wsPromise, wws = make_weak_ptr(ws)](std::string s) { + wsPromise.set_exception(std::make_exception_ptr(std::runtime_error(s))); + const auto user = get_user(wws); + std::cout << "WebSocket error (user: " << user << ")" << std::endl; + clients_map.erase(user); + }); + ws->onClosed([&clients_map, &wsPromise, wws = make_weak_ptr(ws)]() { + const auto user = get_user(wws); + std::cout << "WebSocket closed (user: " << user << ")" << std::endl; + clients_map.erase(user); + }); + ws->onMessage([&clients_map, wws = make_weak_ptr(ws)](auto data) { + // data holds either std::string or rtc::binary + if (!std::holds_alternative(data)) + return; + + json message = json::parse(std::get(data)); + + auto it = message.find("id"); + if (it == message.end()) + return; + + auto id = it->get(); + + auto client_dst = clients_map.find(id); + if (client_dst == clients_map.end()) { + std::cout << "not found" << std::endl; + } else { + const auto user = get_user(wws); + + message["id"] = user; + auto &[id_dst, ws_dst] = *client_dst; + std::cout << user << "->" << id << ": " << message.dump() << std::endl; + ws_dst->send(message.dump()); + } + }); + std::cout << "Waiting for client to be connected..." << std::endl; + wsFuture.get(); + }); + + signal(SIGINT, signalHandler); + while (true) { + std::this_thread::sleep_for(1s); + } + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/examples/signaling-server-libdatachannel-ws/uwp/Logo.png b/examples/signaling-server-libdatachannel-ws/uwp/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..65f91ac0f9664b9536897aa76c7859d4a03bffca GIT binary patch literal 488 zcmeAS@N?(olHy`uVBq!ia0vp^(?FPm8Ax*9Z@d7c6a#!hT!Hj|yx_dz>z^P!B|(0{ z4Er~$@XYooPiQvS^y}gy1_s7#PZ!6Kid%1Q9d%?)5IFMS|IRP>_4$gqcQvbu)?A;O zng$2;8_q8OEvXZE`|dA?-ER%JV;4xJ=H5KI%JN!Y%o;1cO=3GEwyH%wNxG`h9kWI% zbz*nuVx5ACs}3-UuXKxi;1t?;blsNzRR@#8L)uqxfn*K?nYm)S7iDdJloZ;1blr+` zt4{)jmS0WVsJ%+BJ2tR1@=e#O(?FqEpsH7!Zit3X2dX-yQ{s9xZQ*O7(3!34R@~Al z+PLbJ*L3!4@7g!|-F*Hfa!uFjGfr0@?&@8A%IRv|+efQ5MQnYfwK+mGeD={*J8tQO z9R*sTwa%WYmG3we{Z!J%~>llH1y5OdKj zU5#~2+#wINHaM`ZW9klhAeFX|D`vA!SY!5-qgqA2n<84*If|{m@pbV(g-22;8@pob hR8AThBZ19T+hyuF*UZXWJsB7q44$rjF6*2UngBAc?0f(K literal 0 HcmV?d00001 diff --git a/examples/signaling-server-libdatachannel-ws/uwp/SmallLogo.png b/examples/signaling-server-libdatachannel-ws/uwp/SmallLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..460c0222d4bef2d8bbdd0e87307365bcda988257 GIT binary patch literal 167 zcmeAS@N?(olHy`uVBq!ia0vp^av;pX0wgC|rfCAHJWm(LkcwMZubh;0R^(uF;9BsX z`{)vr;D*V2p4xMo+aHg8^&(<^`p(CZwU(ai1?37Z-z=Qn{H<;E3CGn9CmlNvdiI{Z z$kcOg(XmGhz-W=>x#@G|BkDpwDs#?Tu37Oz^>fmM=?nKT*qyer+;>-Whs9)pk}{yp N44$rjF6*2UngCJjLzw^o literal 0 HcmV?d00001 diff --git a/examples/signaling-server-libdatachannel-ws/uwp/SmallLogo44x44.png b/examples/signaling-server-libdatachannel-ws/uwp/SmallLogo44x44.png new file mode 100644 index 0000000000000000000000000000000000000000..c2374581a814b456888af693afe4d50b97ff420d GIT binary patch literal 265 zcmV+k0rvihP)Kxd&NV8_^BdpF!ah*@<^!Q|)v%@ORT@$OFF&+FS$0(P(U zqBVW>T?5A6cM-W3_M*NLn;{GoHJx(U|?Y|n5DU}UR3f!9;etFpa2j|s13}^yFYvO z?Asr_j++QDIWVy3-&bVuZV}R)ap1l7j3=vNS)K zsuet#whzc(n$N_Z_j2}u#^_&c1rM(6W0cvkHJ^b!@2xaY=r>lON7ME(&H-vp^UFR?il zr76!_X)VolbY^eWw0AiMEa_&SBzJ9ocwzR<7wON>sJY~&DKD65JX>h%)U!=t>v95) zq?rjx?cA7nQ0hj8$KwlZY+32bN}b-)QcLFcc8T!i7BrNZ83|czGL$)Y?pVPW-drB` z&6^EnDy^jtZ;Vb)wkYGyGcmyP&P)+o8EvWBK!!+?)16?Y%y8{egey*k>}Qn5M=|;GMS8Ni4RF|E~L7 z!IIq4DRtyy8Xl8ulb%uXKkYU<^XGcw#xTT!A-xQuP+wjhk=|$L+B{NP>W^R2K zac=I;F3Wi@jy)5Z-97hk-@E^}b~l64BU|IYYnEU3akv#EtJ!2XT{O%URy(t~M8f5A zUQ(Q`cF#t$T&rdGHw#Ekx_mEXn%(QE6RmR-)jn@tBl+O6U-~)w)%TAd{L}Vf<;Q&< zH9O9{m!9wVKKrEm)!*Mfb(-yaQuE>Nd#CyR|Fth4fAK%VuC=SnP;8v}$5p9b^;FzDpBX3PcNF`#A5hl#Kj-&@>+kLB ajL)^*3yOFV&Ta>EHG`+CpUXO@geCx`QC<`P literal 0 HcmV?d00001 diff --git a/examples/signaling-server-libdatachannel-ws/uwp/Windows_TemporaryKey.pfx b/examples/signaling-server-libdatachannel-ws/uwp/Windows_TemporaryKey.pfx new file mode 100644 index 0000000000000000000000000000000000000000..1cad9993d6abdb0e1bc1456b2470dd386f8f3ef2 GIT binary patch literal 2560 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 literal 0 HcmV?d00001 diff --git a/examples/signaling-server-libdatachannel-ws/uwp/package.appxManifest b/examples/signaling-server-libdatachannel-ws/uwp/package.appxManifest new file mode 100644 index 000000000..2fd7736f1 --- /dev/null +++ b/examples/signaling-server-libdatachannel-ws/uwp/package.appxManifest @@ -0,0 +1,42 @@ + + + + + + + datachannel-client + CMake + StoreLogo.png + + + + + + + + + + + + + + +