From 40f01e904e362871ba69e3c4d41cfa93547ad177 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Thu, 14 Jul 2022 10:43:09 +0000 Subject: [PATCH] webrtc: add new node and libdatachannel to build system Signed-off-by: Steffen Vogel --- CMakeLists.txt | 3 + include/villas/nodes/webrtc.hpp | 84 +++++++++++++++++ lib/nodes/CMakeLists.txt | 6 ++ lib/nodes/webrtc.cpp | 161 ++++++++++++++++++++++++++++++++ packaging/deps.sh | 18 +++- 5 files changed, 271 insertions(+), 1 deletion(-) create mode 100644 include/villas/nodes/webrtc.hpp create mode 100644 lib/nodes/webrtc.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 9a11c15aa..a26b89afa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -76,6 +76,7 @@ find_package(RDMACM) find_package(spdlog) find_package(Etherlab) find_package(Lua) +find_package(LibDataChannel) # For compat between libfmt 8 and 9 add_compile_definitions(FMT_DEPRECATED_OSTREAM) @@ -200,6 +201,7 @@ cmake_dependent_option(WITH_NODE_STATS "Build with stats node-type" cmake_dependent_option(WITH_NODE_TEMPER "Build with temper node-type" ON "LIBUSB_FOUND" OFF) cmake_dependent_option(WITH_NODE_TEST_RTT "Build with test_rtt node-type" ON "" OFF) cmake_dependent_option(WITH_NODE_ULDAQ "Build with uldaq node-type" ON "LIBULDAQ_FOUND" OFF) +cmake_dependent_option(WITH_NODE_WEBRTC "Build with webrtc node-type" ON "LibDataChannel_FOUND" OFF) cmake_dependent_option(WITH_NODE_WEBSOCKET "Build with websocket node-type" ON "WITH_WEB; LIBWEBSOCKETS_FOUND" OFF) cmake_dependent_option(WITH_NODE_ZEROMQ "Build with zeromq node-type" ON "LIBZMQ_FOUND;NOT WITHOUT_GPL" OFF) @@ -300,6 +302,7 @@ add_feature_info(NODE_STATS WITH_NODE_STATS "Build with add_feature_info(NODE_TEMPER WITH_NODE_TEMPER "Build with temper node-type") add_feature_info(NODE_TEST_RTT WITH_NODE_TEST_RTT "Build with test_rtt node-type") add_feature_info(NODE_ULDAQ WITH_NODE_ULDAQ "Build with uldaq node-type") +add_feature_info(NODE_WEBRTC WITH_NODE_WEBRTC "Build with webrtc node-type") add_feature_info(NODE_WEBSOCKET WITH_NODE_WEBSOCKET "Build with websocket node-type") add_feature_info(NODE_ZEROMQ WITH_NODE_ZEROMQ "Build with zeromq node-type") diff --git a/include/villas/nodes/webrtc.hpp b/include/villas/nodes/webrtc.hpp new file mode 100644 index 000000000..da46639a1 --- /dev/null +++ b/include/villas/nodes/webrtc.hpp @@ -0,0 +1,84 @@ +/** The WebRTC node-type. + * + * @file + * @author Steffen Vogel + * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC + * @license Apache 2.0 + *********************************************************************************/ + +#pragma once + +#include +#include +#include + +namespace villas { +namespace node { + +/* Forward declarations */ +struct Sample; + +class WebRTCNode : public Node { + +protected: + + virtual + int _read(struct Sample *smps[], unsigned cnt); + + virtual + int _write(struct Sample *smps[], unsigned cnt); + +public: + WebRTCNode(const std::string &name = ""); + + /* All of the following virtual-declared functions are optional. + * Have a look at node.hpp/node.cpp for the default behaviour. + */ + + virtual + ~WebRTCNode(); + + virtual + int prepare(); + + virtual + int parse(json_t *json, const uuid_t sn_uuid); + + /** Validate node configuration. */ + virtual + int check(); + + virtual + int start(); + + // virtual + // int stop(); + + // virtual + // int pause(); + + // virtual + // int resume(); + + // virtual + // int restart(); + + // virtual + // int reverse(); + + // virtual + // std::vector getPollFDs(); + + // virtual + // std::vector getNetemFDs(); + + // virtual + // struct villas::node::memory::Type * getMemoryType(); + + virtual + const std::string & getDetails(); +}; + + +} /* namespace node */ +} /* namespace villas */ diff --git a/lib/nodes/CMakeLists.txt b/lib/nodes/CMakeLists.txt index c0c526853..266c22ecb 100644 --- a/lib/nodes/CMakeLists.txt +++ b/lib/nodes/CMakeLists.txt @@ -186,6 +186,12 @@ if(WITH_NODE_REDIS) list(APPEND LIBRARIES PkgConfig::HIREDIS PkgConfig::REDISPP) endif() +# Enable WebRTC support +if(WITH_NODE_WEBRTC) + list(APPEND NODE_SRC webrtc.cpp) + list(APPEND LIBRARIES LibDataChannel::LibDataChannel) +endif() + add_library(nodes STATIC ${NODE_SRC}) target_include_directories(nodes PUBLIC ${INCLUDE_DIRS}) target_link_libraries(nodes PUBLIC ${LIBRARIES}) diff --git a/lib/nodes/webrtc.cpp b/lib/nodes/webrtc.cpp new file mode 100644 index 000000000..3f3ce1d52 --- /dev/null +++ b/lib/nodes/webrtc.cpp @@ -0,0 +1,161 @@ +/** The WebRTC node-type. + * + * @author Steffen Vogel + * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC + * @license Apache 2.0 + *********************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +using namespace villas; +using namespace villas::node; +using namespace villas::utils; + +WebRTCNode::WebRTCNode(const std::string &name) : + Node(name) +{ } + +WebRTCNode::~WebRTCNode() +{ } + +int WebRTCNode::prepare() +{ + // state1 = setting1; + + // if (setting2 == "double") + // state1 *= 2; + + return 0; +} + +int WebRTCNode::parse(json_t *json, const uuid_t sn_uuid) +{ + /* TODO: Add implementation here. The following is just an example */ + + // const char *setting2_str = nullptr; + + // json_error_t err; + // int ret = json_unpack_ex(json, &err, 0, "{ s?: i, s?: s }", + // "setting1", &setting1, + // "setting2", &setting2_str + // ); + // if (ret) + // throw ConfigError(json, err, "node-config-node-example"); + + // if (setting2_str) + // setting2 = setting2_str; + + return 0; +} + +int WebRTCNode::check() +{ + return 0; +} + +int WebRTCNode::start() +{ + // TODO add implementation here + + // start_time = time_now(); + + return 0; +} + +// int WebRTCNode::stop() +// { +// // TODO add implementation here +// return 0; +// } + +// int WebRTCNode::pause() +// { +// // TODO add implementation here +// return 0; +// } + +// int WebRTCNode::resume() +// { +// // TODO add implementation here +// return 0; +// } + +// int WebRTCNode::restart() +// { +// // TODO add implementation here +// return 0; +// } + +// int WebRTCNode::reverse() +// { +// // TODO add implementation here +// return 0; +// } + +// std::vector WebRTCNode::getPollFDs() +// { +// // TODO add implementation here +// return {}; +// } + +// std::vector WebRTCNode::getNetemFDs() +// { +// // TODO add implementation here +// return {}; +// } + +// struct villas::node::memory::Type * WebRTCNode::getMemoryType() +// { +// // TODO add implementation here +// } + +const std::string & WebRTCNode::getDetails() +{ + details = fmt::format(""); + return details; +} + +int WebRTCNode::_read(struct Sample *smps[], unsigned cnt) +{ + int read; + struct timespec now; + + /* TODO: Add implementation here. The following is just an example */ + + assert(cnt >= 1 && smps[0]->capacity >= 1); + + now = time_now(); + + // smps[0]->data[0].f = time_delta(&now, &start_time); + + /* Dont forget to set other flags in struct Sample::flags + * E.g. for sequence no, timestamps... */ + smps[0]->flags = (int) SampleFlags::HAS_DATA; + smps[0]->signals = getInputSignals(false); + + read = 1; /* The number of samples read */ + + return read; +} + +int WebRTCNode::_write(struct Sample *smps[], unsigned cnt) +{ + int written; + + /* TODO: Add implementation here. */ + + written = 0; /* The number of samples written */ + + return written; +} + + +static char n[] = "webrtc"; +static char d[] = "Web Real-time Communication"; +static NodePlugin p; diff --git a/packaging/deps.sh b/packaging/deps.sh index e4dfbecdf..19e761bfd 100644 --- a/packaging/deps.sh +++ b/packaging/deps.sh @@ -245,7 +245,7 @@ if ! pkg-config "libxil >= 1.0.0" && \ fi # Build & Install hiredis -if ! pkg-config "hiredis>1.0.0" && \ +if ! pkg-config "hiredis >= 1.0.0" && \ [ -z "${SKIP_HIREDIS}" -a -z "${SKIP_REDIS}" ]; then git clone ${GIT_OPTS} --branch v1.0.0 https://github.com/redis/hiredis.git mkdir -p hiredis/build @@ -316,6 +316,22 @@ if ! pkg-config "libwebsockets >= 4.3.0" && \ popd fi +# Build & Install libdatachannel +if ! cmake --find-package -DNAME=LibDataChannel -DCOMPILER_ID=GNU -DLANGUAGE=CXX -DMODE=EXIST && \ + [ -z "${SKIP_LIBDATACHANNEL}" ]; then + git clone ${GIT_OPTS} --branch v0.17.8 https://github.com/paullouisageneau/libdatachannel && pushd libdatachannel + git submodule update --init --recursive --depth 1 + mkdir build && pushd build + + cmake -DUSE_NICE=ON \ + -DNO_MEDIA=ON \ + -DNO_WEBSOCKET=ON \ + ${CMAKE_OPTS} .. + + make ${MAKE_OPTS} ${TARGET} + popd; popd +fi + popd rm -rf ${DIR}