From ae6726731cefe4206b5a4ae0d780b85a603b4bb0 Mon Sep 17 00:00:00 2001 From: Heikki Tampio Date: Mon, 3 Apr 2023 11:48:14 +0300 Subject: [PATCH] multiplex: add socket factory --- CMakeLists.txt | 2 + include/uvgrtp/session.hh | 4 ++ src/session.cc | 118 +++++++++++++++++++++++++++++++++++++- src/socketfactory.cc | 4 ++ src/socketfactory.hh | 18 ++++++ 5 files changed, 145 insertions(+), 1 deletion(-) create mode 100644 src/socketfactory.cc create mode 100644 src/socketfactory.hh diff --git a/CMakeLists.txt b/CMakeLists.txt index 334ca85..8db85d7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -68,6 +68,7 @@ target_sources(${PROJECT_NAME} PRIVATE src/srtp/srtp.cc src/srtp/srtcp.cc src/wrapper_c.cc + src/socketfactory.cc ) source_group(src/srtp src/srtp/.*) @@ -118,6 +119,7 @@ target_sources(${PROJECT_NAME} PRIVATE src/srtp/base.hh src/srtp/srtp.hh src/srtp/srtcp.hh + src/socketfactory.hh include/uvgrtp/util.hh include/uvgrtp/clock.hh diff --git a/include/uvgrtp/session.hh b/include/uvgrtp/session.hh index 86ac059..fa5b50c 100644 --- a/include/uvgrtp/session.hh +++ b/include/uvgrtp/session.hh @@ -12,6 +12,7 @@ namespace uvgrtp { class media_stream; class zrtp; + class socketfactory; /** \brief Provides ZRTP synchronization and can be used to create uvgrtp::media_stream objects * @@ -61,6 +62,9 @@ namespace uvgrtp { */ uvgrtp::media_stream *create_stream(uint16_t src_port, uint16_t dst_port, rtp_format_t fmt, int rce_flags); + // socket factory, add docs + uvgrtp::media_stream* create_stream(uint16_t src_port, uint16_t dst_port, rtp_format_t fmt, int rce_flags, uvgrtp::socketfactory sf); + /** * \brief Create a unidirectional media_stream for an RTP session * diff --git a/src/session.cc b/src/session.cc index ef57e23..15802a5 100644 --- a/src/session.cc +++ b/src/session.cc @@ -1,7 +1,7 @@ #include "uvgrtp/session.hh" #include "uvgrtp/media_stream.hh" - +#include "socketfactory.hh" #include "crypto.hh" #include "zrtp.hh" #include "debug.hh" @@ -163,6 +163,122 @@ uvgrtp::media_stream* uvgrtp::session::create_stream(uint16_t src_port, uint16_t return stream; } +uvgrtp::media_stream* uvgrtp::session::create_stream(uint16_t src_port, uint16_t dst_port, rtp_format_t fmt, int rce_flags, uvgrtp::socketfactory sf) +{ + if (rce_flags & RCE_OBSOLETE) { + UVG_LOG_WARN("You are using a flag that has either been removed or has been enabled by default. Consider updating RCE flags"); + } + + if ((rce_flags & RCE_SEND_ONLY) && (rce_flags & RCE_RECEIVE_ONLY)) { + UVG_LOG_ERROR("Cannot both use RCE_SEND_ONLY and RCE_RECEIVE_ONLY!"); + rtp_errno = RTP_NOT_SUPPORTED; + return nullptr; + } + + // select which address the one address we got as a parameter is + if (generic_address_ != "") + { + if (rce_flags & RCE_RECEIVE_ONLY) + { + local_address_ = generic_address_; + } + else + { + remote_address_ = generic_address_; + } + } + else if ((rce_flags & RCE_RECEIVE_ONLY) && local_address_ == "") + { + UVG_LOG_ERROR("RCE_RECEIVE_ONLY requires local address!"); + rtp_errno = RTP_INVALID_VALUE; + return nullptr; + } + else if ((rce_flags & RCE_SEND_ONLY) && remote_address_ == "") + { + UVG_LOG_ERROR("RCE_SEND_ONLY requires remote address!"); + rtp_errno = RTP_INVALID_VALUE; + return nullptr; + } + + if ((rce_flags & RCE_RECEIVE_ONLY) && src_port == 0) + { + UVG_LOG_ERROR("RCE_RECEIVE_ONLY requires source port!"); + rtp_errno = RTP_INVALID_VALUE; + return nullptr; + } + + if ((rce_flags & RCE_SEND_ONLY) && dst_port == 0) + { + UVG_LOG_ERROR("RCE_SEND_ONLY requires destination port!"); + rtp_errno = RTP_INVALID_VALUE; + return nullptr; + } + + uvgrtp::media_stream* stream = + new uvgrtp::media_stream(cname_, remote_address_, local_address_, src_port, dst_port, fmt, rce_flags); + + if (rce_flags & RCE_SRTP) { + if (!uvgrtp::crypto::enabled()) { + UVG_LOG_ERROR("Recompile uvgRTP with -D__RTP_CRYPTO__"); + delete stream; + rtp_errno = RTP_GENERIC_ERROR; + return nullptr; + } + + if (rce_flags & RCE_SRTP_REPLAY_PROTECTION) + rce_flags |= RCE_SRTP_AUTHENTICATE_RTP; + + if (rce_flags & RCE_SRTP_KMNGMNT_ZRTP) { + + if (rce_flags & (RCE_SRTP_KEYSIZE_192 | RCE_SRTP_KEYSIZE_256)) { + UVG_LOG_ERROR("Only 128-bit keys are supported with ZRTP"); + delete stream; + return nullptr; + } + + if (!(rce_flags & RCE_ZRTP_DIFFIE_HELLMAN_MODE) && + !(rce_flags & RCE_ZRTP_MULTISTREAM_MODE)) { + UVG_LOG_INFO("ZRTP mode not selected, using Diffie-Hellman mode"); + rce_flags |= RCE_ZRTP_DIFFIE_HELLMAN_MODE; + } + + session_mtx_.lock(); + if (!zrtp_) { + zrtp_ = std::shared_ptr(new uvgrtp::zrtp()); + } + session_mtx_.unlock(); + + if (stream->init(zrtp_) != RTP_OK) { + UVG_LOG_ERROR("Failed to initialize media stream %s:%d/%d", remote_address_.c_str(), src_port, dst_port); + delete stream; + return nullptr; + } + } + else if (rce_flags & RCE_SRTP_KMNGMNT_USER) { + UVG_LOG_DEBUG("SRTP with user-managed keys enabled, postpone initialization"); + } + else { + UVG_LOG_ERROR("SRTP key management scheme not specified!"); + rtp_errno = RTP_INVALID_VALUE; + delete stream; + return nullptr; + } + } + else { + if (stream->init() != RTP_OK) { + UVG_LOG_ERROR("Failed to initialize media stream %s:%d/%d", remote_address_.c_str(), src_port, dst_port); + delete stream; + return nullptr; + } + } + + session_mtx_.lock(); + streams_.insert(std::make_pair(stream->get_key(), stream)); + session_mtx_.unlock(); + + return stream; +} + rtp_error_t uvgrtp::session::destroy_stream(uvgrtp::media_stream *stream) { if (!stream) diff --git a/src/socketfactory.cc b/src/socketfactory.cc new file mode 100644 index 0000000..78fd693 --- /dev/null +++ b/src/socketfactory.cc @@ -0,0 +1,4 @@ +#include "socketfactory.hh" + +uvgrtp::socketfactory::socketfactory() +{} \ No newline at end of file diff --git a/src/socketfactory.hh b/src/socketfactory.hh new file mode 100644 index 0000000..ef8ee76 --- /dev/null +++ b/src/socketfactory.hh @@ -0,0 +1,18 @@ +#pragma once + +#include "uvgrtp/util.hh" +#include + +namespace uvgrtp { + + class socketfactory { + + public: + socketfactory(); + + private: + std::string local_address_; + uint16_t local_port_; + + }; +}