mirror of
https://github.com/mii443/libdatachannel.git
synced 2025-08-22 23:25:33 +00:00
Merge branch 'master' into dev
This commit is contained in:
@ -1,11 +1,14 @@
|
||||
name: Build and test
|
||||
on: [push, pull_request]
|
||||
|
||||
name: Build and test with GnuTLS
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: install packages
|
24
.github/workflows/build-nice.yml
vendored
Normal file
24
.github/workflows/build-nice.yml
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
name: Build and test with libnice
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: install packages
|
||||
run: sudo apt update && sudo apt install libgnutls28-dev libnice-dev
|
||||
- name: submodules
|
||||
run: git submodule update --init --recursive
|
||||
- name: cmake
|
||||
run: cmake -B build -DUSE_JUICE=0 -DUSE_GNUTLS=1
|
||||
- name: make
|
||||
run: (cd build; make)
|
||||
- name: test
|
||||
run: ./build/tests
|
||||
|
24
.github/workflows/build-openssl.yml
vendored
Normal file
24
.github/workflows/build-openssl.yml
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
name: Build and test with OpenSSL
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: install packages
|
||||
run: sudo apt update && sudo apt install libssl-dev
|
||||
- name: submodules
|
||||
run: git submodule update --init --recursive
|
||||
- name: cmake
|
||||
run: cmake -B build -DUSE_JUICE=1 -DUSE_GNUTLS=0
|
||||
- name: make
|
||||
run: (cd build; make)
|
||||
- name: test
|
||||
run: ./build/tests
|
||||
|
@ -1,7 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.7)
|
||||
project(libdatachannel
|
||||
DESCRIPTION "WebRTC DataChannels Library"
|
||||
VERSION 0.4.9
|
||||
VERSION 0.5.0
|
||||
LANGUAGES CXX)
|
||||
|
||||
option(USE_GNUTLS "Use GnuTLS instead of OpenSSL" OFF)
|
||||
@ -73,7 +73,8 @@ set(TESTS_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test/capi.cpp
|
||||
)
|
||||
|
||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
|
||||
set(THREADS_PREFER_PTHREAD_FLAG TRUE)
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
add_subdirectory(deps/usrsctp EXCLUDE_FROM_ALL)
|
||||
@ -114,21 +115,22 @@ set_target_properties(datachannel-static PROPERTIES
|
||||
CXX_STANDARD 17)
|
||||
|
||||
target_include_directories(datachannel PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
target_include_directories(datachannel PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/deps/plog/include)
|
||||
target_include_directories(datachannel PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include/rtc)
|
||||
target_include_directories(datachannel PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||
target_include_directories(datachannel PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/deps/plog/include)
|
||||
target_link_libraries(datachannel PUBLIC Threads::Threads)
|
||||
target_link_libraries(datachannel PRIVATE Usrsctp::UsrsctpStatic)
|
||||
|
||||
target_include_directories(datachannel-static PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
target_include_directories(datachannel-static PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/deps/plog/include)
|
||||
target_include_directories(datachannel-static PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include/rtc)
|
||||
target_include_directories(datachannel-static PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||
target_include_directories(datachannel-static PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/deps/plog/include)
|
||||
|
||||
target_link_libraries(datachannel Threads::Threads Usrsctp::UsrsctpStatic)
|
||||
target_link_libraries(datachannel-static Threads::Threads Usrsctp::UsrsctpStatic)
|
||||
target_link_libraries(datachannel-static PUBLIC Threads::Threads)
|
||||
target_link_libraries(datachannel-static PRIVATE Usrsctp::UsrsctpStatic)
|
||||
|
||||
if(WIN32)
|
||||
target_link_libraries(datachannel "wsock32" "ws2_32") # winsock2
|
||||
target_link_libraries(datachannel-static "wsock32" "ws2_32") # winsock2
|
||||
target_link_libraries(datachannel PRIVATE wsock32 ws2_32) # winsock2
|
||||
target_link_libraries(datachannel-static PRIVATE wsock32 ws2_32) # winsock2
|
||||
endif()
|
||||
|
||||
if (USE_GNUTLS)
|
||||
@ -142,29 +144,29 @@ if (USE_GNUTLS)
|
||||
IMPORTED_LOCATION "${GNUTLS_LIBRARIES}")
|
||||
endif()
|
||||
target_compile_definitions(datachannel PRIVATE USE_GNUTLS=1)
|
||||
target_link_libraries(datachannel GnuTLS::GnuTLS)
|
||||
target_link_libraries(datachannel PRIVATE GnuTLS::GnuTLS)
|
||||
target_compile_definitions(datachannel-static PRIVATE USE_GNUTLS=1)
|
||||
target_link_libraries(datachannel-static GnuTLS::GnuTLS)
|
||||
target_link_libraries(datachannel-static PRIVATE GnuTLS::GnuTLS)
|
||||
else()
|
||||
find_package(OpenSSL REQUIRED)
|
||||
target_compile_definitions(datachannel PRIVATE USE_GNUTLS=0)
|
||||
target_link_libraries(datachannel OpenSSL::SSL)
|
||||
target_link_libraries(datachannel PRIVATE OpenSSL::SSL)
|
||||
target_compile_definitions(datachannel-static PRIVATE USE_GNUTLS=0)
|
||||
target_link_libraries(datachannel-static OpenSSL::SSL)
|
||||
target_link_libraries(datachannel-static PRIVATE OpenSSL::SSL)
|
||||
endif()
|
||||
|
||||
if (USE_JUICE)
|
||||
add_subdirectory(deps/libjuice EXCLUDE_FROM_ALL)
|
||||
target_compile_definitions(datachannel PRIVATE USE_JUICE=1)
|
||||
target_link_libraries(datachannel LibJuice::LibJuiceStatic)
|
||||
target_link_libraries(datachannel PRIVATE LibJuice::LibJuiceStatic)
|
||||
target_compile_definitions(datachannel-static PRIVATE USE_JUICE=1)
|
||||
target_link_libraries(datachannel-static LibJuice::LibJuiceStatic)
|
||||
target_link_libraries(datachannel-static PRIVATE LibJuice::LibJuiceStatic)
|
||||
else()
|
||||
find_package(LibNice REQUIRED)
|
||||
target_compile_definitions(datachannel PRIVATE USE_JUICE=0)
|
||||
target_link_libraries(datachannel LibNice::LibNice)
|
||||
target_link_libraries(datachannel PRIVATE LibNice::LibNice)
|
||||
target_compile_definitions(datachannel-static PRIVATE USE_JUICE=0)
|
||||
target_link_libraries(datachannel-static LibNice::LibNice)
|
||||
target_link_libraries(datachannel-static PRIVATE LibNice::LibNice)
|
||||
endif()
|
||||
|
||||
add_library(LibDataChannel::LibDataChannel ALIAS datachannel)
|
||||
|
2
deps/libjuice
vendored
2
deps/libjuice
vendored
Submodule deps/libjuice updated: e56531c647...511b19f516
@ -31,6 +31,7 @@
|
||||
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
#include <future>
|
||||
#include <list>
|
||||
#include <mutex>
|
||||
#include <shared_mutex>
|
||||
@ -44,6 +45,9 @@ class IceTransport;
|
||||
class DtlsTransport;
|
||||
class SctpTransport;
|
||||
|
||||
using certificate_ptr = std::shared_ptr<Certificate>;
|
||||
using future_certificate_ptr = std::shared_future<certificate_ptr>;
|
||||
|
||||
class PeerConnection : public std::enable_shared_from_this<PeerConnection> {
|
||||
public:
|
||||
enum class State : int {
|
||||
@ -126,7 +130,7 @@ private:
|
||||
void resetCallbacks();
|
||||
|
||||
const Configuration mConfig;
|
||||
const std::shared_ptr<Certificate> mCertificate;
|
||||
const future_certificate_ptr mCertificate;
|
||||
|
||||
init_token mInitToken = Init::Token();
|
||||
|
||||
|
@ -141,14 +141,9 @@ string make_fingerprint(gnutls_x509_crt_t crt) {
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
shared_ptr<Certificate> make_certificate(const string &commonName) {
|
||||
static std::unordered_map<string, shared_ptr<Certificate>> cache;
|
||||
static std::mutex cacheMutex;
|
||||
|
||||
std::lock_guard lock(cacheMutex);
|
||||
if (auto it = cache.find(commonName); it != cache.end())
|
||||
return it->second;
|
||||
namespace {
|
||||
|
||||
certificate_ptr make_certificate_impl(string commonName) {
|
||||
std::unique_ptr<gnutls_x509_crt_t, decltype(&delete_crt)> crt(create_crt(), delete_crt);
|
||||
std::unique_ptr<gnutls_x509_privkey_t, decltype(&delete_privkey)> privkey(create_privkey(),
|
||||
delete_privkey);
|
||||
@ -174,11 +169,11 @@ shared_ptr<Certificate> make_certificate(const string &commonName) {
|
||||
check_gnutls(gnutls_x509_crt_sign2(*crt, *crt, *privkey, GNUTLS_DIG_SHA256, 0),
|
||||
"Unable to auto-sign certificate");
|
||||
|
||||
auto certificate = std::make_shared<Certificate>(*crt, *privkey);
|
||||
cache.emplace(std::make_pair(commonName, certificate));
|
||||
return certificate;
|
||||
return std::make_shared<Certificate>(*crt, *privkey);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
} // namespace rtc
|
||||
|
||||
#else
|
||||
@ -236,15 +231,9 @@ string make_fingerprint(X509 *x509) {
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
shared_ptr<Certificate> make_certificate(const string &commonName) {
|
||||
static std::unordered_map<string, shared_ptr<Certificate>> cache;
|
||||
static std::mutex cacheMutex;
|
||||
|
||||
std::lock_guard lock(cacheMutex);
|
||||
if (auto it = cache.find(commonName); it != cache.end())
|
||||
return it->second;
|
||||
|
||||
certificate_ptr make_certificate_impl(string commonName) {
|
||||
shared_ptr<X509> x509(X509_new(), X509_free);
|
||||
shared_ptr<EVP_PKEY> pkey(EVP_PKEY_new(), EVP_PKEY_free);
|
||||
|
||||
@ -281,12 +270,54 @@ shared_ptr<Certificate> make_certificate(const string &commonName) {
|
||||
if (!X509_sign(x509.get(), pkey.get(), EVP_sha256()))
|
||||
throw std::runtime_error("Unable to auto-sign certificate");
|
||||
|
||||
auto certificate = std::make_shared<Certificate>(x509, pkey);
|
||||
cache.emplace(std::make_pair(commonName, certificate));
|
||||
return certificate;
|
||||
return std::make_shared<Certificate>(x509, pkey);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
} // namespace rtc
|
||||
|
||||
#endif
|
||||
|
||||
// Common for GnuTLS and OpenSSL
|
||||
|
||||
namespace rtc {
|
||||
|
||||
namespace {
|
||||
|
||||
// Helper function roughly equivalent to std::async with policy std::launch::async
|
||||
// since std::async might be unreliable on some platforms (e.g. Mingw32 on Windows)
|
||||
template <class F, class... Args>
|
||||
std::future<std::result_of_t<std::decay_t<F>(std::decay_t<Args>...)>> thread_call(F &&f,
|
||||
Args &&... args) {
|
||||
using R = std::result_of_t<std::decay_t<F>(std::decay_t<Args>...)>;
|
||||
std::packaged_task<R()> task(std::bind(f, std::forward<Args>(args)...));
|
||||
std::future<R> future = task.get_future();
|
||||
std::thread t(std::move(task));
|
||||
t.detach();
|
||||
return future;
|
||||
}
|
||||
|
||||
static std::unordered_map<string, future_certificate_ptr> CertificateCache;
|
||||
static std::mutex CertificateCacheMutex;
|
||||
|
||||
} // namespace
|
||||
|
||||
future_certificate_ptr make_certificate(string commonName) {
|
||||
std::lock_guard lock(CertificateCacheMutex);
|
||||
|
||||
if (auto it = CertificateCache.find(commonName); it != CertificateCache.end())
|
||||
return it->second;
|
||||
|
||||
auto future = thread_call(make_certificate_impl, commonName);
|
||||
auto shared = future.share();
|
||||
CertificateCache.emplace(std::move(commonName), shared);
|
||||
return shared;
|
||||
}
|
||||
|
||||
void CleanupCertificateCache() {
|
||||
std::lock_guard lock(CertificateCacheMutex);
|
||||
CertificateCache.clear();
|
||||
}
|
||||
|
||||
} // namespace rtc
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
#include "include.hpp"
|
||||
|
||||
#include <future>
|
||||
#include <tuple>
|
||||
|
||||
#if USE_GNUTLS
|
||||
@ -62,7 +63,12 @@ string make_fingerprint(gnutls_x509_crt_t crt);
|
||||
string make_fingerprint(X509 *x509);
|
||||
#endif
|
||||
|
||||
std::shared_ptr<Certificate> make_certificate(const string &commonName);
|
||||
using certificate_ptr = std::shared_ptr<Certificate>;
|
||||
using future_certificate_ptr = std::shared_future<certificate_ptr>;
|
||||
|
||||
future_certificate_ptr make_certificate(string commonName); // cached
|
||||
|
||||
void CleanupCertificateCache();
|
||||
|
||||
} // namespace rtc
|
||||
|
||||
|
@ -61,7 +61,7 @@ void DtlsTransport::Cleanup() {
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
DtlsTransport::DtlsTransport(shared_ptr<IceTransport> lower, shared_ptr<Certificate> certificate,
|
||||
DtlsTransport::DtlsTransport(shared_ptr<IceTransport> lower, certificate_ptr certificate,
|
||||
verifier_callback verifierCallback, state_callback stateChangeCallback)
|
||||
: Transport(lower, std::move(stateChangeCallback)), mCertificate(certificate),
|
||||
mVerifierCallback(std::move(verifierCallback)) {
|
||||
|
@ -48,7 +48,7 @@ public:
|
||||
|
||||
using verifier_callback = std::function<bool(const std::string &fingerprint)>;
|
||||
|
||||
DtlsTransport(std::shared_ptr<IceTransport> lower, std::shared_ptr<Certificate> certificate,
|
||||
DtlsTransport(std::shared_ptr<IceTransport> lower, certificate_ptr certificate,
|
||||
verifier_callback verifierCallback, state_callback stateChangeCallback);
|
||||
~DtlsTransport();
|
||||
|
||||
@ -59,7 +59,7 @@ private:
|
||||
void incoming(message_ptr message) override;
|
||||
void runRecvLoop();
|
||||
|
||||
const std::shared_ptr<Certificate> mCertificate;
|
||||
const certificate_ptr mCertificate;
|
||||
|
||||
Queue<message_ptr> mIncomingQueue;
|
||||
std::thread mRecvThread;
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include "init.hpp"
|
||||
|
||||
#include "certificate.hpp"
|
||||
#include "dtlstransport.hpp"
|
||||
#include "sctptransport.hpp"
|
||||
|
||||
@ -81,6 +82,7 @@ Init::Init() {
|
||||
}
|
||||
|
||||
Init::~Init() {
|
||||
CleanupCertificateCache();
|
||||
SctpTransport::Cleanup();
|
||||
DtlsTransport::Cleanup();
|
||||
#if RTC_ENABLE_WEBSOCKET
|
||||
|
@ -251,9 +251,10 @@ shared_ptr<DtlsTransport> PeerConnection::initDtlsTransport() {
|
||||
if (auto transport = std::atomic_load(&mDtlsTransport))
|
||||
return transport;
|
||||
|
||||
auto certificate = mCertificate.get();
|
||||
auto lower = std::atomic_load(&mIceTransport);
|
||||
auto transport = std::make_shared<DtlsTransport>(
|
||||
lower, mCertificate, weak_bind(&PeerConnection::checkFingerprint, this, _1),
|
||||
lower, certificate, weak_bind(&PeerConnection::checkFingerprint, this, _1),
|
||||
[this, weak_this = weak_from_this()](DtlsTransport::State state) {
|
||||
auto shared_this = weak_this.lock();
|
||||
if (!shared_this)
|
||||
@ -495,9 +496,11 @@ void PeerConnection::processLocalDescription(Description description) {
|
||||
if (auto remote = remoteDescription())
|
||||
remoteSctpPort = remote->sctpPort();
|
||||
|
||||
auto certificate = mCertificate.get(); // wait for certificate if not ready
|
||||
|
||||
std::lock_guard lock(mLocalDescriptionMutex);
|
||||
mLocalDescription.emplace(std::move(description));
|
||||
mLocalDescription->setFingerprint(mCertificate->fingerprint());
|
||||
mLocalDescription->setFingerprint(certificate->fingerprint());
|
||||
mLocalDescription->setSctpPort(remoteSctpPort.value_or(DEFAULT_SCTP_PORT));
|
||||
mLocalDescription->setMaxMessageSize(LOCAL_MAX_MESSAGE_SIZE);
|
||||
|
||||
|
Reference in New Issue
Block a user