mirror of
https://github.com/mii443/libdatachannel.git
synced 2025-08-23 23:49:21 +00:00
Compare commits
31 Commits
Author | SHA1 | Date | |
---|---|---|---|
495b389e05 | |||
e83494df09 | |||
7bf87c6989 | |||
cb591de15f | |||
eb4540e319 | |||
5d34439cb7 | |||
b19e9077af | |||
4ff010b20b | |||
442e50825c | |||
9f2801b7b9 | |||
3b0bf3a152 | |||
fe4a9ec453 | |||
dc1d14adf1 | |||
14918c16e8 | |||
a023acfa33 | |||
f098019c1f | |||
a67ca9da9b | |||
613ebf2564 | |||
dc6427770c | |||
81e0a05a1a | |||
9ea613f05f | |||
eb4a764648 | |||
baf8a3adce | |||
d9aec59352 | |||
3ff5801512 | |||
fcc2577e11 | |||
b4865f26e4 | |||
fc6d5afdd9 | |||
7a49c0b88b | |||
679c0ccd2e | |||
12098e7c41 |
@ -1,6 +1,6 @@
|
|||||||
cmake_minimum_required(VERSION 3.7)
|
cmake_minimum_required(VERSION 3.7)
|
||||||
project(libdatachannel
|
project(libdatachannel
|
||||||
VERSION 0.10.2
|
VERSION 0.10.3
|
||||||
LANGUAGES CXX)
|
LANGUAGES CXX)
|
||||||
set(PROJECT_DESCRIPTION "WebRTC Data Channels Library")
|
set(PROJECT_DESCRIPTION "WebRTC Data Channels Library")
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/Modules)
|
|||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
add_definitions(-DWIN32_LEAN_AND_MEAN)
|
add_definitions(-DWIN32_LEAN_AND_MEAN)
|
||||||
if (MSVC)
|
if(MSVC)
|
||||||
add_definitions(-DNOMINMAX)
|
add_definitions(-DNOMINMAX)
|
||||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||||
add_definitions(-D_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING)
|
add_definitions(-D_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING)
|
||||||
@ -163,8 +163,8 @@ target_link_libraries(datachannel-static PUBLIC Threads::Threads plog::plog)
|
|||||||
target_link_libraries(datachannel-static PRIVATE Usrsctp::Usrsctp)
|
target_link_libraries(datachannel-static PRIVATE Usrsctp::Usrsctp)
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
target_link_libraries(datachannel PRIVATE ws2_32) # winsock2
|
target_link_libraries(datachannel PUBLIC ws2_32) # winsock2
|
||||||
target_link_libraries(datachannel-static PRIVATE ws2_32) # winsock2
|
target_link_libraries(datachannel-static PUBLIC ws2_32) # winsock2
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(NO_MEDIA)
|
if(NO_MEDIA)
|
||||||
@ -272,11 +272,7 @@ if(NOT NO_TESTS)
|
|||||||
set_target_properties(datachannel-tests PROPERTIES OUTPUT_NAME tests)
|
set_target_properties(datachannel-tests PROPERTIES OUTPUT_NAME tests)
|
||||||
endif()
|
endif()
|
||||||
target_include_directories(datachannel-tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
target_include_directories(datachannel-tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||||
if(WIN32)
|
target_link_libraries(datachannel-tests datachannel)
|
||||||
target_link_libraries(datachannel-tests datachannel-static) # DLL exports only the C API
|
|
||||||
else()
|
|
||||||
target_link_libraries(datachannel-tests datachannel)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Benchmark
|
# Benchmark
|
||||||
add_executable(datachannel-benchmark test/benchmark.cpp)
|
add_executable(datachannel-benchmark test/benchmark.cpp)
|
||||||
@ -288,11 +284,7 @@ if(NOT NO_TESTS)
|
|||||||
endif()
|
endif()
|
||||||
target_compile_definitions(datachannel-benchmark PRIVATE BENCHMARK_MAIN=1)
|
target_compile_definitions(datachannel-benchmark PRIVATE BENCHMARK_MAIN=1)
|
||||||
target_include_directories(datachannel-benchmark PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
target_include_directories(datachannel-benchmark PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||||
if(WIN32)
|
target_link_libraries(datachannel-benchmark datachannel)
|
||||||
target_link_libraries(datachannel-benchmark datachannel-static) # DLL exports only the C API
|
|
||||||
else()
|
|
||||||
target_link_libraries(datachannel-benchmark datachannel)
|
|
||||||
endif()
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Examples
|
# Examples
|
||||||
|
@ -27,8 +27,9 @@ Features:
|
|||||||
- Full IPv6 support
|
- Full IPv6 support
|
||||||
- Trickle ICE ([draft-ietf-ice-trickle-21](https://tools.ietf.org/html/draft-ietf-ice-trickle-21))
|
- Trickle ICE ([draft-ietf-ice-trickle-21](https://tools.ietf.org/html/draft-ietf-ice-trickle-21))
|
||||||
- JSEP compatible ([draft-ietf-rtcweb-jsep-26](https://tools.ietf.org/html/draft-ietf-rtcweb-jsep-26))
|
- JSEP compatible ([draft-ietf-rtcweb-jsep-26](https://tools.ietf.org/html/draft-ietf-rtcweb-jsep-26))
|
||||||
- SRTP and SRTCP key derivation from DTLS ([RFC5764](https://tools.ietf.org/html/rfc5764))
|
|
||||||
- Multicast DNS candidates ([draft-ietf-rtcweb-mdns-ice-candidates-04](https://tools.ietf.org/html/draft-ietf-rtcweb-mdns-ice-candidates-04))
|
- Multicast DNS candidates ([draft-ietf-rtcweb-mdns-ice-candidates-04](https://tools.ietf.org/html/draft-ietf-rtcweb-mdns-ice-candidates-04))
|
||||||
|
- SRTP and SRTCP key derivation from DTLS ([RFC5764](https://tools.ietf.org/html/rfc5764))
|
||||||
|
- Differentiated Services QoS ([draft-ietf-tsvwg-rtcweb-qos-18](https://tools.ietf.org/html/draft-ietf-tsvwg-rtcweb-qos-18))
|
||||||
- TURN relaying ([RFC5766](https://tools.ietf.org/html/rfc5766)) with [libnice](https://github.com/libnice/libnice) as ICE backend
|
- TURN relaying ([RFC5766](https://tools.ietf.org/html/rfc5766)) with [libnice](https://github.com/libnice/libnice) as ICE backend
|
||||||
|
|
||||||
Note only SDP BUNDLE mode is supported for media multiplexing ([draft-ietf-mmusic-sdp-bundle-negotiation-54](https://tools.ietf.org/html/draft-ietf-mmusic-sdp-bundle-negotiation-54)). The behavior is equivalent to the JSEP bundle-only policy: the library always negociates one unique network component, where SRTP media streams are multiplexed with SRTCP control packets ([RFC5761](https://tools.ietf.org/html/rfc5761)) and SCTP/DTLS data traffic ([RFC5764](https://tools.ietf.org/html/rfc5764)).
|
Note only SDP BUNDLE mode is supported for media multiplexing ([draft-ietf-mmusic-sdp-bundle-negotiation-54](https://tools.ietf.org/html/draft-ietf-mmusic-sdp-bundle-negotiation-54)). The behavior is equivalent to the JSEP bundle-only policy: the library always negociates one unique network component, where SRTP media streams are multiplexed with SRTCP control packets ([RFC5761](https://tools.ietf.org/html/rfc5761)) and SCTP/DTLS data traffic ([RFC5764](https://tools.ietf.org/html/rfc5764)).
|
||||||
|
2
deps/libjuice
vendored
2
deps/libjuice
vendored
Submodule deps/libjuice updated: 7afe3940dd...ea96b88635
2
deps/libsrtp
vendored
2
deps/libsrtp
vendored
Submodule deps/libsrtp updated: d02d21111e...f379f48412
@ -9,14 +9,9 @@ target_compile_definitions(datachannel-client PUBLIC STATIC_GETOPT)
|
|||||||
else()
|
else()
|
||||||
add_executable(datachannel-client main.cpp parse_cl.cpp parse_cl.h)
|
add_executable(datachannel-client main.cpp parse_cl.cpp parse_cl.h)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set_target_properties(datachannel-client PROPERTIES
|
set_target_properties(datachannel-client PROPERTIES
|
||||||
CXX_STANDARD 17
|
CXX_STANDARD 17
|
||||||
OUTPUT_NAME client)
|
OUTPUT_NAME client)
|
||||||
|
|
||||||
if(WIN32)
|
|
||||||
target_link_libraries(datachannel-client datachannel-static) # DLL exports only the C API
|
|
||||||
else()
|
|
||||||
target_link_libraries(datachannel-client datachannel)
|
|
||||||
endif()
|
|
||||||
target_link_libraries(datachannel-client datachannel nlohmann_json)
|
target_link_libraries(datachannel-client datachannel nlohmann_json)
|
||||||
|
|
||||||
|
@ -4,19 +4,11 @@ add_executable(datachannel-copy-paste-offerer offerer.cpp)
|
|||||||
set_target_properties(datachannel-copy-paste-offerer PROPERTIES
|
set_target_properties(datachannel-copy-paste-offerer PROPERTIES
|
||||||
CXX_STANDARD 17
|
CXX_STANDARD 17
|
||||||
OUTPUT_NAME offerer)
|
OUTPUT_NAME offerer)
|
||||||
if(WIN32)
|
target_link_libraries(datachannel-copy-paste-offerer datachannel)
|
||||||
target_link_libraries(datachannel-copy-paste-offerer datachannel-static) # DLL exports only the C API
|
|
||||||
else()
|
|
||||||
target_link_libraries(datachannel-copy-paste-offerer datachannel)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_executable(datachannel-copy-paste-answerer answerer.cpp)
|
add_executable(datachannel-copy-paste-answerer answerer.cpp)
|
||||||
set_target_properties(datachannel-copy-paste-answerer PROPERTIES
|
set_target_properties(datachannel-copy-paste-answerer PROPERTIES
|
||||||
CXX_STANDARD 17
|
CXX_STANDARD 17
|
||||||
OUTPUT_NAME answerer)
|
OUTPUT_NAME answerer)
|
||||||
if(WIN32)
|
target_link_libraries(datachannel-copy-paste-answerer datachannel)
|
||||||
target_link_libraries(datachannel-copy-paste-answerer datachannel-static) # DLL exports only the C API
|
|
||||||
else()
|
|
||||||
target_link_libraries(datachannel-copy-paste-answerer datachannel)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
|
@ -4,11 +4,5 @@ add_executable(datachannel-media main.cpp)
|
|||||||
set_target_properties(datachannel-media PROPERTIES
|
set_target_properties(datachannel-media PROPERTIES
|
||||||
CXX_STANDARD 17
|
CXX_STANDARD 17
|
||||||
OUTPUT_NAME media)
|
OUTPUT_NAME media)
|
||||||
|
target_link_libraries(datachannel-media datachannel nlohmann_json)
|
||||||
|
|
||||||
if(WIN32)
|
|
||||||
target_link_libraries(datachannel-media datachannel-static) # DLL exports only the C API
|
|
||||||
else()
|
|
||||||
target_link_libraries(datachannel-media datachannel)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
target_link_libraries(datachannel-media datachannel nlohmann_json)
|
|
@ -4,12 +4,5 @@ add_executable(datachannel-sfu-media main.cpp)
|
|||||||
set_target_properties(datachannel-sfu-media PROPERTIES
|
set_target_properties(datachannel-sfu-media PROPERTIES
|
||||||
CXX_STANDARD 17
|
CXX_STANDARD 17
|
||||||
OUTPUT_NAME sfu-media)
|
OUTPUT_NAME sfu-media)
|
||||||
|
|
||||||
if(WIN32)
|
|
||||||
target_link_libraries(datachannel-sfu-media datachannel-static) # DLL exports only the C API
|
|
||||||
else()
|
|
||||||
target_link_libraries(datachannel-sfu-media datachannel)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
target_link_libraries(datachannel-sfu-media datachannel nlohmann_json)
|
target_link_libraries(datachannel-sfu-media datachannel nlohmann_json)
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
namespace rtc {
|
namespace rtc {
|
||||||
|
|
||||||
class Candidate {
|
class RTC_CPP_EXPORT Candidate {
|
||||||
public:
|
public:
|
||||||
enum class Family { Unresolved, Ipv4, Ipv6 };
|
enum class Family { Unresolved, Ipv4, Ipv6 };
|
||||||
enum class Type { Unknown, Host, ServerReflexive, PeerReflexive, Relayed };
|
enum class Type { Unknown, Host, ServerReflexive, PeerReflexive, Relayed };
|
||||||
@ -76,8 +76,8 @@ private:
|
|||||||
|
|
||||||
} // namespace rtc
|
} // namespace rtc
|
||||||
|
|
||||||
std::ostream &operator<<(std::ostream &out, const rtc::Candidate &candidate);
|
RTC_CPP_EXPORT std::ostream &operator<<(std::ostream &out, const rtc::Candidate &candidate);
|
||||||
std::ostream &operator<<(std::ostream &out, const rtc::Candidate::Type &type);
|
RTC_CPP_EXPORT std::ostream &operator<<(std::ostream &out, const rtc::Candidate::Type &type);
|
||||||
std::ostream &operator<<(std::ostream &out, const rtc::Candidate::TransportType &transportType);
|
RTC_CPP_EXPORT std::ostream &operator<<(std::ostream &out, const rtc::Candidate::TransportType &transportType);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
namespace rtc {
|
namespace rtc {
|
||||||
|
|
||||||
class Channel {
|
class RTC_CPP_EXPORT Channel {
|
||||||
public:
|
public:
|
||||||
Channel() = default;
|
Channel() = default;
|
||||||
virtual ~Channel() = default;
|
virtual ~Channel() = default;
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
|
|
||||||
namespace rtc {
|
namespace rtc {
|
||||||
|
|
||||||
struct IceServer {
|
struct RTC_CPP_EXPORT IceServer {
|
||||||
enum class Type { Stun, Turn };
|
enum class Type { Stun, Turn };
|
||||||
enum class RelayType { TurnUdp, TurnTcp, TurnTls };
|
enum class RelayType { TurnUdp, TurnTcp, TurnTls };
|
||||||
|
|
||||||
@ -51,7 +51,7 @@ struct IceServer {
|
|||||||
RelayType relayType;
|
RelayType relayType;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ProxyServer {
|
struct RTC_CPP_EXPORT ProxyServer {
|
||||||
enum class Type { None = 0, Socks5, Http, Last = Http };
|
enum class Type { None = 0, Socks5, Http, Last = Http };
|
||||||
|
|
||||||
ProxyServer(Type type_, string ip_, uint16_t port_, string username_ = "",
|
ProxyServer(Type type_, string ip_, uint16_t port_, string username_ = "",
|
||||||
@ -64,7 +64,7 @@ struct ProxyServer {
|
|||||||
string password;
|
string password;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Configuration {
|
struct RTC_CPP_EXPORT Configuration {
|
||||||
std::vector<IceServer> iceServers;
|
std::vector<IceServer> iceServers;
|
||||||
std::optional<ProxyServer> proxyServer;
|
std::optional<ProxyServer> proxyServer;
|
||||||
bool enableIceTcp = false;
|
bool enableIceTcp = false;
|
||||||
|
@ -36,7 +36,7 @@ namespace rtc {
|
|||||||
class SctpTransport;
|
class SctpTransport;
|
||||||
class PeerConnection;
|
class PeerConnection;
|
||||||
|
|
||||||
class DataChannel : public std::enable_shared_from_this<DataChannel>, public Channel {
|
class RTC_CPP_EXPORT DataChannel : public std::enable_shared_from_this<DataChannel>, public Channel {
|
||||||
public:
|
public:
|
||||||
DataChannel(std::weak_ptr<PeerConnection> pc, uint16_t stream, string label, string protocol,
|
DataChannel(std::weak_ptr<PeerConnection> pc, uint16_t stream, string label, string protocol,
|
||||||
Reliability reliability);
|
Reliability reliability);
|
||||||
@ -87,7 +87,7 @@ private:
|
|||||||
friend class PeerConnection;
|
friend class PeerConnection;
|
||||||
};
|
};
|
||||||
|
|
||||||
class NegociatedDataChannel final : public DataChannel {
|
class RTC_CPP_EXPORT NegociatedDataChannel final : public DataChannel {
|
||||||
public:
|
public:
|
||||||
NegociatedDataChannel(std::weak_ptr<PeerConnection> pc, uint16_t stream, string label,
|
NegociatedDataChannel(std::weak_ptr<PeerConnection> pc, uint16_t stream, string label,
|
||||||
string protocol, Reliability reliability);
|
string protocol, Reliability reliability);
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
|
|
||||||
namespace rtc {
|
namespace rtc {
|
||||||
|
|
||||||
class Description {
|
class RTC_CPP_EXPORT Description {
|
||||||
public:
|
public:
|
||||||
enum class Type { Unspec, Offer, Answer, Pranswer, Rollback };
|
enum class Type { Unspec, Offer, Answer, Pranswer, Rollback };
|
||||||
enum class Role { ActPass, Passive, Active };
|
enum class Role { ActPass, Passive, Active };
|
||||||
@ -63,7 +63,7 @@ public:
|
|||||||
string generateSdp(string_view eol) const;
|
string generateSdp(string_view eol) const;
|
||||||
string generateApplicationSdp(string_view eol) const;
|
string generateApplicationSdp(string_view eol) const;
|
||||||
|
|
||||||
class Entry {
|
class RTC_CPP_EXPORT Entry {
|
||||||
public:
|
public:
|
||||||
virtual ~Entry() = default;
|
virtual ~Entry() = default;
|
||||||
|
|
||||||
@ -95,7 +95,7 @@ public:
|
|||||||
Direction mDirection;
|
Direction mDirection;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Application : public Entry {
|
struct RTC_CPP_EXPORT Application : public Entry {
|
||||||
public:
|
public:
|
||||||
Application(string mid = "data");
|
Application(string mid = "data");
|
||||||
virtual ~Application() = default;
|
virtual ~Application() = default;
|
||||||
@ -120,7 +120,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Media (non-data)
|
// Media (non-data)
|
||||||
class Media : public Entry {
|
class RTC_CPP_EXPORT Media : public Entry {
|
||||||
public:
|
public:
|
||||||
Media(const string &sdp);
|
Media(const string &sdp);
|
||||||
Media(const string &mline, string mid, Direction dir = Direction::SendOnly);
|
Media(const string &mline, string mid, Direction dir = Direction::SendOnly);
|
||||||
@ -183,7 +183,7 @@ public:
|
|||||||
void addRTPMap(const RTPMap &map);
|
void addRTPMap(const RTPMap &map);
|
||||||
};
|
};
|
||||||
|
|
||||||
class Audio : public Media {
|
class RTC_CPP_EXPORT Audio : public Media {
|
||||||
public:
|
public:
|
||||||
Audio(string mid = "audio", Direction dir = Direction::SendOnly);
|
Audio(string mid = "audio", Direction dir = Direction::SendOnly);
|
||||||
|
|
||||||
@ -191,7 +191,7 @@ public:
|
|||||||
void addOpusCodec(int payloadType);
|
void addOpusCodec(int payloadType);
|
||||||
};
|
};
|
||||||
|
|
||||||
class Video : public Media {
|
class RTC_CPP_EXPORT Video : public Media {
|
||||||
public:
|
public:
|
||||||
Video(string mid = "video", Direction dir = Direction::SendOnly);
|
Video(string mid = "video", Direction dir = Direction::SendOnly);
|
||||||
|
|
||||||
@ -245,8 +245,8 @@ private:
|
|||||||
|
|
||||||
} // namespace rtc
|
} // namespace rtc
|
||||||
|
|
||||||
std::ostream &operator<<(std::ostream &out, const rtc::Description &description);
|
RTC_CPP_EXPORT std::ostream &operator<<(std::ostream &out, const rtc::Description &description);
|
||||||
std::ostream &operator<<(std::ostream &out, rtc::Description::Type type);
|
RTC_CPP_EXPORT std::ostream &operator<<(std::ostream &out, rtc::Description::Type type);
|
||||||
std::ostream &operator<<(std::ostream &out, rtc::Description::Role role);
|
RTC_CPP_EXPORT std::ostream &operator<<(std::ostream &out, rtc::Description::Role role);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -28,9 +28,15 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
#define RTC_CPP_EXPORT __declspec(dllexport)
|
||||||
#ifndef _WIN32_WINNT
|
#ifndef _WIN32_WINNT
|
||||||
#define _WIN32_WINNT 0x0602 // Windows 8
|
#define _WIN32_WINNT 0x0602 // Windows 8
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(disable:4251) // disable "X needs to have dll-interface..."
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define RTC_CPP_EXPORT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "log.hpp"
|
#include "log.hpp"
|
||||||
|
@ -27,7 +27,7 @@ namespace rtc {
|
|||||||
|
|
||||||
using init_token = std::shared_ptr<void>;
|
using init_token = std::shared_ptr<void>;
|
||||||
|
|
||||||
class Init {
|
class RTC_CPP_EXPORT Init {
|
||||||
public:
|
public:
|
||||||
static init_token Token();
|
static init_token Token();
|
||||||
static void Preload();
|
static void Preload();
|
||||||
|
@ -35,6 +35,8 @@
|
|||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "include.hpp"
|
||||||
|
|
||||||
namespace rtc {
|
namespace rtc {
|
||||||
|
|
||||||
enum class LogLevel { // Don't change, it must match plog severity
|
enum class LogLevel { // Don't change, it must match plog severity
|
||||||
@ -47,8 +49,8 @@ enum class LogLevel { // Don't change, it must match plog severity
|
|||||||
Verbose = 6
|
Verbose = 6
|
||||||
};
|
};
|
||||||
|
|
||||||
void InitLogger(LogLevel level);
|
RTC_CPP_EXPORT void InitLogger(LogLevel level);
|
||||||
void InitLogger(plog::Severity severity, plog::IAppender *appender = nullptr);
|
RTC_CPP_EXPORT void InitLogger(plog::Severity severity, plog::IAppender *appender = nullptr);
|
||||||
} // namespace rtc
|
} // namespace rtc
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
namespace rtc {
|
namespace rtc {
|
||||||
|
|
||||||
struct Message : binary {
|
struct RTC_CPP_EXPORT Message : binary {
|
||||||
enum Type { Binary, String, Control, Reset };
|
enum Type { Binary, String, Control, Reset };
|
||||||
|
|
||||||
Message(const Message &message) = default;
|
Message(const Message &message) = default;
|
||||||
@ -42,7 +42,8 @@ struct Message : binary {
|
|||||||
Message(binary &&data, Type type_ = Binary) : binary(std::move(data)), type(type_) {}
|
Message(binary &&data, Type type_ = Binary) : binary(std::move(data)), type(type_) {}
|
||||||
|
|
||||||
Type type;
|
Type type;
|
||||||
unsigned int stream = 0;
|
unsigned int stream = 0; // Stream id (SCTP stream or SSRC)
|
||||||
|
unsigned int dscp = 0; // Differentiated Services Code Point
|
||||||
std::shared_ptr<Reliability> reliability;
|
std::shared_ptr<Reliability> reliability;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -50,14 +50,14 @@ class SctpTransport;
|
|||||||
using certificate_ptr = std::shared_ptr<Certificate>;
|
using certificate_ptr = std::shared_ptr<Certificate>;
|
||||||
using future_certificate_ptr = std::shared_future<certificate_ptr>;
|
using future_certificate_ptr = std::shared_future<certificate_ptr>;
|
||||||
|
|
||||||
struct DataChannelInit {
|
struct RTC_CPP_EXPORT DataChannelInit {
|
||||||
Reliability reliability = {};
|
Reliability reliability = {};
|
||||||
bool negotiated = false;
|
bool negotiated = false;
|
||||||
std::optional<uint16_t> id = nullopt;
|
std::optional<uint16_t> id = nullopt;
|
||||||
string protocol = "";
|
string protocol = "";
|
||||||
};
|
};
|
||||||
|
|
||||||
class PeerConnection final : public std::enable_shared_from_this<PeerConnection> {
|
class RTC_CPP_EXPORT PeerConnection final : public std::enable_shared_from_this<PeerConnection> {
|
||||||
public:
|
public:
|
||||||
enum class State : int {
|
enum class State : int {
|
||||||
New = RTC_NEW,
|
New = RTC_NEW,
|
||||||
@ -203,8 +203,8 @@ private:
|
|||||||
|
|
||||||
} // namespace rtc
|
} // namespace rtc
|
||||||
|
|
||||||
std::ostream &operator<<(std::ostream &out, rtc::PeerConnection::State state);
|
RTC_CPP_EXPORT std::ostream &operator<<(std::ostream &out, rtc::PeerConnection::State state);
|
||||||
std::ostream &operator<<(std::ostream &out, rtc::PeerConnection::GatheringState state);
|
RTC_CPP_EXPORT std::ostream &operator<<(std::ostream &out, rtc::PeerConnection::GatheringState state);
|
||||||
std::ostream &operator<<(std::ostream &out, rtc::PeerConnection::SignalingState state);
|
RTC_CPP_EXPORT std::ostream &operator<<(std::ostream &out, rtc::PeerConnection::SignalingState state);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
namespace rtc {
|
namespace rtc {
|
||||||
|
|
||||||
class RtcpHandler {
|
class RTC_CPP_EXPORT RtcpHandler {
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* Use this callback when trying to send custom data (such as RTCP) to the client.
|
* Use this callback when trying to send custom data (such as RTCP) to the client.
|
||||||
@ -64,7 +64,7 @@ public:
|
|||||||
class Track;
|
class Track;
|
||||||
|
|
||||||
// An RtcpSession can be plugged into a Track to handle the whole RTCP session
|
// An RtcpSession can be plugged into a Track to handle the whole RTCP session
|
||||||
class RtcpReceivingSession : public RtcpHandler {
|
class RTC_CPP_EXPORT RtcpReceivingSession : public RtcpHandler {
|
||||||
public:
|
public:
|
||||||
rtc::message_ptr incoming(rtc::message_ptr ptr) override;
|
rtc::message_ptr incoming(rtc::message_ptr ptr) override;
|
||||||
rtc::message_ptr outgoing(rtc::message_ptr ptr) override;
|
rtc::message_ptr outgoing(rtc::message_ptr ptr) override;
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
#ifndef RTC_RTP_HPP
|
#ifndef RTC_RTP_HPP
|
||||||
#define RTC_RTP_HPP
|
#define RTC_RTP_HPP
|
||||||
|
|
||||||
#include <rtc/log.hpp>
|
#include "log.hpp"
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
@ -75,19 +75,15 @@ public:
|
|||||||
inline void setPayloadType(uint8_t newPayloadType) {
|
inline void setPayloadType(uint8_t newPayloadType) {
|
||||||
_payloadType = (_payloadType & 0b10000000u) | (0b01111111u & newPayloadType);
|
_payloadType = (_payloadType & 0b10000000u) | (0b01111111u & newPayloadType);
|
||||||
}
|
}
|
||||||
inline void setSsrc(uint32_t ssrc) { _ssrc = htonl(ssrc); }
|
inline void setSsrc(uint32_t in_ssrc) { _ssrc = htonl(in_ssrc); }
|
||||||
|
|
||||||
void setTimestamp(uint32_t i) { _timestamp = htonl(i); }
|
void setTimestamp(uint32_t i) { _timestamp = htonl(i); }
|
||||||
|
|
||||||
void log() {
|
void log() {
|
||||||
PLOG_VERBOSE << "RTP V: " << (int) version()
|
PLOG_VERBOSE << "RTP V: " << (int)version() << " P: " << (padding() ? "P" : " ")
|
||||||
<< " P: " << (padding() ? "P" : " ")
|
<< " X: " << (extension() ? "X" : " ") << " CC: " << (int)csrcCount()
|
||||||
<< " X: " << (extension() ? "X" : " ")
|
<< " M: " << (marker() ? "M" : " ") << " PT: " << (int)payloadType()
|
||||||
<< " CC: " << (int) csrcCount()
|
<< " SEQNO: " << seqNumber() << " TS: " << timestamp();
|
||||||
<< " M: " << (marker() ? "M" : " ")
|
|
||||||
<< " PT: " << (int) payloadType()
|
|
||||||
<< " SEQNO: " << seqNumber()
|
|
||||||
<< " TS: " << timestamp();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -103,13 +99,13 @@ private:
|
|||||||
uint32_t _delaySinceLastReport;
|
uint32_t _delaySinceLastReport;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
inline void preparePacket(SSRC ssrc, [[maybe_unused]] unsigned int packetsLost,
|
inline void preparePacket(SSRC in_ssrc, [[maybe_unused]] unsigned int packetsLost,
|
||||||
[[maybe_unused]] unsigned int totalPackets, uint16_t highestSeqNo,
|
[[maybe_unused]] unsigned int totalPackets, uint16_t highestSeqNo,
|
||||||
uint16_t seqNoCycles, uint32_t jitter, uint64_t lastSR_NTP,
|
uint16_t seqNoCycles, uint32_t jitter, uint64_t lastSR_NTP,
|
||||||
uint64_t lastSR_DELAY) {
|
uint64_t lastSR_DELAY) {
|
||||||
setSeqNo(highestSeqNo, seqNoCycles);
|
setSeqNo(highestSeqNo, seqNoCycles);
|
||||||
setJitter(jitter);
|
setJitter(jitter);
|
||||||
setSSRC(ssrc);
|
setSSRC(in_ssrc);
|
||||||
|
|
||||||
// Middle 32 bits of NTP Timestamp
|
// Middle 32 bits of NTP Timestamp
|
||||||
// this->lastReport = lastSR_NTP >> 16u;
|
// this->lastReport = lastSR_NTP >> 16u;
|
||||||
@ -120,7 +116,7 @@ public:
|
|||||||
// this->delaySinceLastReport = lastSR_DELAY;
|
// this->delaySinceLastReport = lastSR_DELAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void setSSRC(SSRC ssrc) { this->ssrc = htonl(ssrc); }
|
inline void setSSRC(SSRC in_ssrc) { this->ssrc = htonl(in_ssrc); }
|
||||||
inline SSRC getSSRC() const { return ntohl(ssrc); }
|
inline SSRC getSSRC() const { return ntohl(ssrc); }
|
||||||
|
|
||||||
inline void setPacketsLost([[maybe_unused]] unsigned int packetsLost,
|
inline void setPacketsLost([[maybe_unused]] unsigned int packetsLost,
|
||||||
@ -199,9 +195,9 @@ public:
|
|||||||
|
|
||||||
inline void log() const {
|
inline void log() const {
|
||||||
PLOG_VERBOSE << "RTCP header: "
|
PLOG_VERBOSE << "RTCP header: "
|
||||||
<< "version=" << unsigned(version()) << ", padding=" << padding()
|
<< "version=" << unsigned(version()) << ", padding=" << padding()
|
||||||
<< ", reportCount=" << unsigned(reportCount())
|
<< ", reportCount=" << unsigned(reportCount())
|
||||||
<< ", payloadType=" << unsigned(payloadType()) << ", length=" << length();
|
<< ", payloadType=" << unsigned(payloadType()) << ", length=" << length();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -337,7 +333,7 @@ struct RTCP_REMB {
|
|||||||
return sizeof(uint32_t) * (1 + header.header.length());
|
return sizeof(uint32_t) * (1 + header.header.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
void preparePacket(SSRC senderSSRC, unsigned int numSSRC, unsigned int bitrate) {
|
void preparePacket(SSRC senderSSRC, unsigned int numSSRC, unsigned int in_bitrate) {
|
||||||
|
|
||||||
// Report Count becomes the format here.
|
// Report Count becomes the format here.
|
||||||
header.header.prepareHeader(206, 15, 0);
|
header.header.prepareHeader(206, 15, 0);
|
||||||
@ -352,21 +348,21 @@ struct RTCP_REMB {
|
|||||||
id[2] = 'M';
|
id[2] = 'M';
|
||||||
id[3] = 'B';
|
id[3] = 'B';
|
||||||
|
|
||||||
setBitrate(numSSRC, bitrate);
|
setBitrate(numSSRC, in_bitrate);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setBitrate(unsigned int numSSRC, unsigned int bitrate) {
|
void setBitrate(unsigned int numSSRC, unsigned int in_bitrate) {
|
||||||
unsigned int exp = 0;
|
unsigned int exp = 0;
|
||||||
while (bitrate > pow(2, 18) - 1) {
|
while (in_bitrate > pow(2, 18) - 1) {
|
||||||
exp++;
|
exp++;
|
||||||
bitrate /= 2;
|
in_bitrate /= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// "length" in packet is one less than the number of 32 bit words in the packet.
|
// "length" in packet is one less than the number of 32 bit words in the packet.
|
||||||
header.header.setLength(
|
header.header.setLength(
|
||||||
uint16_t((offsetof(RTCP_REMB, ssrc) / sizeof(uint32_t)) - 1 + numSSRC));
|
uint16_t((offsetof(RTCP_REMB, ssrc) / sizeof(uint32_t)) - 1 + numSSRC));
|
||||||
|
|
||||||
this->bitrate = htonl((numSSRC << (32u - 8u)) | (exp << (32u - 8u - 6u)) | bitrate);
|
this->bitrate = htonl((numSSRC << (32u - 8u)) | (exp << (32u - 8u - 6u)) | in_bitrate);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setSsrc(int iterator, SSRC newSssrc) { ssrc[iterator] = htonl(newSssrc); }
|
void setSsrc(int iterator, SSRC newSssrc) { ssrc[iterator] = htonl(newSssrc); }
|
||||||
@ -428,7 +424,7 @@ public:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
void preparePacket(SSRC ssrc, unsigned int discreteSeqNoCount) {
|
void preparePacket(SSRC ssrc, unsigned int discreteSeqNoCount) {
|
||||||
header.header.prepareHeader(205, 1, 2 + discreteSeqNoCount);
|
header.header.prepareHeader(205, 1, 2 + uint16_t(discreteSeqNoCount));
|
||||||
header.setMediaSourceSSRC(ssrc);
|
header.setMediaSourceSSRC(ssrc);
|
||||||
header.setPacketSenderSSRC(ssrc);
|
header.setPacketSenderSSRC(ssrc);
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ namespace rtc {
|
|||||||
class DtlsSrtpTransport;
|
class DtlsSrtpTransport;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class Track final : public std::enable_shared_from_this<Track>, public Channel {
|
class RTC_CPP_EXPORT Track final : public std::enable_shared_from_this<Track>, public Channel {
|
||||||
public:
|
public:
|
||||||
Track(Description::Media description);
|
Track(Description::Media description);
|
||||||
~Track() = default;
|
~Track() = default;
|
||||||
@ -70,8 +70,8 @@ private:
|
|||||||
std::weak_ptr<DtlsSrtpTransport> mDtlsSrtpTransport;
|
std::weak_ptr<DtlsSrtpTransport> mDtlsSrtpTransport;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool outgoing(message_ptr message);
|
|
||||||
void incoming(message_ptr message);
|
void incoming(message_ptr message);
|
||||||
|
bool outgoing(message_ptr message);
|
||||||
|
|
||||||
Description::Media mMediaDescription;
|
Description::Media mMediaDescription;
|
||||||
std::atomic<bool> mIsClosed = false;
|
std::atomic<bool> mIsClosed = false;
|
||||||
|
@ -38,7 +38,7 @@ class TcpTransport;
|
|||||||
class TlsTransport;
|
class TlsTransport;
|
||||||
class WsTransport;
|
class WsTransport;
|
||||||
|
|
||||||
class WebSocket final : public Channel, public std::enable_shared_from_this<WebSocket> {
|
class RTC_CPP_EXPORT WebSocket final : public Channel, public std::enable_shared_from_this<WebSocket> {
|
||||||
public:
|
public:
|
||||||
enum class State : int {
|
enum class State : int {
|
||||||
Connecting = 0,
|
Connecting = 0,
|
||||||
|
@ -141,7 +141,14 @@ bool DtlsSrtpTransport::sendMedia(message_ptr message) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message->resize(size);
|
message->resize(size);
|
||||||
return outgoing(message);
|
|
||||||
|
if (message->dscp == 0) { // Track might override the value
|
||||||
|
// Set recommended medium-priority DSCP value
|
||||||
|
// See https://tools.ietf.org/html/draft-ietf-tsvwg-rtcweb-qos-18
|
||||||
|
message->dscp = 36; // AF42: Assured Forwarding class 4, medium drop probability
|
||||||
|
}
|
||||||
|
|
||||||
|
return Transport::outgoing(message); // bypass DTLS DSCP marking
|
||||||
}
|
}
|
||||||
|
|
||||||
void DtlsSrtpTransport::incoming(message_ptr message) {
|
void DtlsSrtpTransport::incoming(message_ptr message) {
|
||||||
|
@ -53,7 +53,7 @@ DtlsTransport::DtlsTransport(shared_ptr<IceTransport> lower, certificate_ptr cer
|
|||||||
verifier_callback verifierCallback, state_callback stateChangeCallback)
|
verifier_callback verifierCallback, state_callback stateChangeCallback)
|
||||||
: Transport(lower, std::move(stateChangeCallback)), mCertificate(certificate),
|
: Transport(lower, std::move(stateChangeCallback)), mCertificate(certificate),
|
||||||
mVerifierCallback(std::move(verifierCallback)),
|
mVerifierCallback(std::move(verifierCallback)),
|
||||||
mIsClient(lower->role() == Description::Role::Active) {
|
mIsClient(lower->role() == Description::Role::Active), mCurrentDscp(0) {
|
||||||
|
|
||||||
PLOG_DEBUG << "Initializing DTLS transport (GnuTLS)";
|
PLOG_DEBUG << "Initializing DTLS transport (GnuTLS)";
|
||||||
|
|
||||||
@ -122,6 +122,7 @@ bool DtlsTransport::send(message_ptr message) {
|
|||||||
|
|
||||||
PLOG_VERBOSE << "Send size=" << message->size();
|
PLOG_VERBOSE << "Send size=" << message->size();
|
||||||
|
|
||||||
|
mCurrentDscp = message->dscp;
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
do {
|
do {
|
||||||
ret = gnutls_record_send(mSession, message->data(), message->size());
|
ret = gnutls_record_send(mSession, message->data(), message->size());
|
||||||
@ -143,6 +144,13 @@ void DtlsTransport::incoming(message_ptr message) {
|
|||||||
mIncomingQueue.push(message);
|
mIncomingQueue.push(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DtlsTransport::outgoing(message_ptr message) {
|
||||||
|
if (message->dscp == 0)
|
||||||
|
message->dscp = mCurrentDscp;
|
||||||
|
|
||||||
|
return Transport::outgoing(std::move(message));
|
||||||
|
}
|
||||||
|
|
||||||
void DtlsTransport::postHandshake() {
|
void DtlsTransport::postHandshake() {
|
||||||
// Dummy
|
// Dummy
|
||||||
}
|
}
|
||||||
@ -309,7 +317,7 @@ DtlsTransport::DtlsTransport(shared_ptr<IceTransport> lower, shared_ptr<Certific
|
|||||||
verifier_callback verifierCallback, state_callback stateChangeCallback)
|
verifier_callback verifierCallback, state_callback stateChangeCallback)
|
||||||
: Transport(lower, std::move(stateChangeCallback)), mCertificate(certificate),
|
: Transport(lower, std::move(stateChangeCallback)), mCertificate(certificate),
|
||||||
mVerifierCallback(std::move(verifierCallback)),
|
mVerifierCallback(std::move(verifierCallback)),
|
||||||
mIsClient(lower->role() == Description::Role::Active) {
|
mIsClient(lower->role() == Description::Role::Active), mCurrentDscp(0) {
|
||||||
PLOG_DEBUG << "Initializing DTLS transport (OpenSSL)";
|
PLOG_DEBUG << "Initializing DTLS transport (OpenSSL)";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -405,6 +413,7 @@ bool DtlsTransport::send(message_ptr message) {
|
|||||||
|
|
||||||
PLOG_VERBOSE << "Send size=" << message->size();
|
PLOG_VERBOSE << "Send size=" << message->size();
|
||||||
|
|
||||||
|
mCurrentDscp = message->dscp;
|
||||||
int ret = SSL_write(mSsl, message->data(), int(message->size()));
|
int ret = SSL_write(mSsl, message->data(), int(message->size()));
|
||||||
return openssl::check(mSsl, ret);
|
return openssl::check(mSsl, ret);
|
||||||
}
|
}
|
||||||
@ -419,6 +428,13 @@ void DtlsTransport::incoming(message_ptr message) {
|
|||||||
mIncomingQueue.push(message);
|
mIncomingQueue.push(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DtlsTransport::outgoing(message_ptr message) {
|
||||||
|
if (message->dscp == 0)
|
||||||
|
message->dscp = mCurrentDscp;
|
||||||
|
|
||||||
|
return Transport::outgoing(std::move(message));
|
||||||
|
}
|
||||||
|
|
||||||
void DtlsTransport::postHandshake() {
|
void DtlsTransport::postHandshake() {
|
||||||
// Dummy
|
// Dummy
|
||||||
}
|
}
|
||||||
|
@ -53,6 +53,7 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void incoming(message_ptr message) override;
|
virtual void incoming(message_ptr message) override;
|
||||||
|
virtual bool outgoing(message_ptr message) override;
|
||||||
virtual void postHandshake();
|
virtual void postHandshake();
|
||||||
void runRecvLoop();
|
void runRecvLoop();
|
||||||
|
|
||||||
@ -62,6 +63,7 @@ protected:
|
|||||||
|
|
||||||
Queue<message_ptr> mIncomingQueue;
|
Queue<message_ptr> mIncomingQueue;
|
||||||
std::thread mRecvThread;
|
std::thread mRecvThread;
|
||||||
|
std::atomic<unsigned int> mCurrentDscp;
|
||||||
|
|
||||||
#if USE_GNUTLS
|
#if USE_GNUTLS
|
||||||
gnutls_session_t mSession;
|
gnutls_session_t mSession;
|
||||||
|
@ -222,8 +222,10 @@ bool IceTransport::send(message_ptr message) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool IceTransport::outgoing(message_ptr message) {
|
bool IceTransport::outgoing(message_ptr message) {
|
||||||
return juice_send(mAgent.get(), reinterpret_cast<const char *>(message->data()),
|
// Explicit Congestion Notification takes the least-significant 2 bits of the DS field
|
||||||
message->size()) >= 0;
|
int ds = int(message->dscp << 2);
|
||||||
|
return juice_send_diffserv(mAgent.get(), reinterpret_cast<const char *>(message->data()),
|
||||||
|
message->size(), ds) >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IceTransport::changeGatheringState(GatheringState state) {
|
void IceTransport::changeGatheringState(GatheringState state) {
|
||||||
@ -330,7 +332,7 @@ IceTransport::IceTransport(const Configuration &config, candidate_callback candi
|
|||||||
mMid("0"), mGatheringState(GatheringState::New),
|
mMid("0"), mGatheringState(GatheringState::New),
|
||||||
mCandidateCallback(std::move(candidateCallback)),
|
mCandidateCallback(std::move(candidateCallback)),
|
||||||
mGatheringStateChangeCallback(std::move(gatheringStateChangeCallback)),
|
mGatheringStateChangeCallback(std::move(gatheringStateChangeCallback)),
|
||||||
mNiceAgent(nullptr, nullptr), mMainLoop(nullptr, nullptr) {
|
mNiceAgent(nullptr, nullptr), mMainLoop(nullptr, nullptr), mOutgoingDscp(0) {
|
||||||
|
|
||||||
PLOG_DEBUG << "Initializing ICE transport (libnice)";
|
PLOG_DEBUG << "Initializing ICE transport (libnice)";
|
||||||
|
|
||||||
@ -617,6 +619,13 @@ bool IceTransport::send(message_ptr message) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool IceTransport::outgoing(message_ptr message) {
|
bool IceTransport::outgoing(message_ptr message) {
|
||||||
|
std::lock_guard lock(mOutgoingMutex);
|
||||||
|
if (mOutgoingDscp != message->dscp) {
|
||||||
|
mOutgoingDscp = message->dscp;
|
||||||
|
// Explicit Congestion Notification takes the least-significant 2 bits of the DS field
|
||||||
|
int ds = int(message->dscp << 2);
|
||||||
|
nice_agent_set_stream_tos(mNiceAgent.get(), mStreamId, ds); // ToS is the legacy name for DS
|
||||||
|
}
|
||||||
return nice_agent_send(mNiceAgent.get(), mStreamId, 1, message->size(),
|
return nice_agent_send(mNiceAgent.get(), mStreamId, 1, message->size(),
|
||||||
reinterpret_cast<const char *>(message->data())) >= 0;
|
reinterpret_cast<const char *>(message->data())) >= 0;
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
namespace rtc {
|
namespace rtc {
|
||||||
|
|
||||||
@ -99,6 +100,8 @@ private:
|
|||||||
std::unique_ptr<GMainLoop, void (*)(GMainLoop *)> mMainLoop;
|
std::unique_ptr<GMainLoop, void (*)(GMainLoop *)> mMainLoop;
|
||||||
std::thread mMainLoopThread;
|
std::thread mMainLoopThread;
|
||||||
guint mTimeoutId = 0;
|
guint mTimeoutId = 0;
|
||||||
|
std::mutex mOutgoingMutex;
|
||||||
|
unsigned int mOutgoingDscp;
|
||||||
|
|
||||||
static string AddressToString(const NiceAddress &addr);
|
static string AddressToString(const NiceAddress &addr);
|
||||||
|
|
||||||
|
@ -369,7 +369,7 @@ void PeerConnection::onSignalingStateChange(std::function<void(SignalingState st
|
|||||||
std::shared_ptr<Track> PeerConnection::addTrack(Description::Media description) {
|
std::shared_ptr<Track> PeerConnection::addTrack(Description::Media description) {
|
||||||
#if !RTC_ENABLE_MEDIA
|
#if !RTC_ENABLE_MEDIA
|
||||||
if (mTracks.empty()) {
|
if (mTracks.empty()) {
|
||||||
PLOG_WARNING << "Tracks will be inative (not compiled with SRTP support)";
|
PLOG_WARNING << "Tracks will be inative (not compiled with media support)";
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -503,7 +503,7 @@ shared_ptr<DtlsTransport> PeerConnection::initDtlsTransport() {
|
|||||||
lower, certificate, verifierCallback,
|
lower, certificate, verifierCallback,
|
||||||
std::bind(&PeerConnection::forwardMedia, this, _1), stateChangeCallback);
|
std::bind(&PeerConnection::forwardMedia, this, _1), stateChangeCallback);
|
||||||
#else
|
#else
|
||||||
PLOG_WARNING << "Ignoring media support (not compiled with SRTP support)";
|
PLOG_WARNING << "Ignoring media support (not compiled with media support)";
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -872,7 +872,7 @@ void PeerConnection::incomingTrack(Description::Media description) {
|
|||||||
std::unique_lock lock(mTracksMutex); // we are going to emplace
|
std::unique_lock lock(mTracksMutex); // we are going to emplace
|
||||||
#if !RTC_ENABLE_MEDIA
|
#if !RTC_ENABLE_MEDIA
|
||||||
if (mTracks.empty()) {
|
if (mTracks.empty()) {
|
||||||
PLOG_WARNING << "Tracks will be inative (not compiled with SRTP support)";
|
PLOG_WARNING << "Tracks will be inative (not compiled with media support)";
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (mTracks.find(description.mid()) == mTracks.end()) {
|
if (mTracks.find(description.mid()) == mTracks.end()) {
|
||||||
|
@ -325,6 +325,13 @@ void SctpTransport::incoming(message_ptr message) {
|
|||||||
usrsctp_conninput(this, message->data(), message->size(), 0);
|
usrsctp_conninput(this, message->data(), message->size(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SctpTransport::outgoing(message_ptr message) {
|
||||||
|
// Set recommended medium-priority DSCP value
|
||||||
|
// See https://tools.ietf.org/html/draft-ietf-tsvwg-rtcweb-qos-18
|
||||||
|
message->dscp = 10; // AF11: Assured Forwarding class 1, low drop probability
|
||||||
|
return Transport::outgoing(std::move(message));
|
||||||
|
}
|
||||||
|
|
||||||
void SctpTransport::doRecv() {
|
void SctpTransport::doRecv() {
|
||||||
std::lock_guard lock(mRecvMutex);
|
std::lock_guard lock(mRecvMutex);
|
||||||
--mPendingRecvCount;
|
--mPendingRecvCount;
|
||||||
@ -554,6 +561,7 @@ int SctpTransport::handleWrite(byte *data, size_t len, uint8_t /*tos*/, uint8_t
|
|||||||
std::unique_lock lock(mWriteMutex);
|
std::unique_lock lock(mWriteMutex);
|
||||||
PLOG_VERBOSE << "Handle write, len=" << len;
|
PLOG_VERBOSE << "Handle write, len=" << len;
|
||||||
|
|
||||||
|
auto message = make_message(data, data + len);
|
||||||
if (!outgoing(make_message(data, data + len)))
|
if (!outgoing(make_message(data, data + len)))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@ -77,6 +77,7 @@ private:
|
|||||||
void shutdown();
|
void shutdown();
|
||||||
void close();
|
void close();
|
||||||
void incoming(message_ptr message) override;
|
void incoming(message_ptr message) override;
|
||||||
|
bool outgoing(message_ptr message) override;
|
||||||
|
|
||||||
void doRecv();
|
void doRecv();
|
||||||
bool trySendQueue();
|
bool trySendQueue();
|
||||||
|
110
src/track.cpp
110
src/track.cpp
@ -45,12 +45,30 @@ void Track::close() {
|
|||||||
setRtcpHandler(nullptr);
|
setRtcpHandler(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Track::send(message_variant data) { return outgoing(make_message(std::move(data))); }
|
bool Track::send(message_variant data) {
|
||||||
|
if (mIsClosed)
|
||||||
|
throw std::runtime_error("Track is closed");
|
||||||
|
|
||||||
bool Track::send(const byte *data, size_t size) {
|
auto direction = mMediaDescription.direction();
|
||||||
return outgoing(std::make_shared<Message>(data, data + size, Message::Binary));
|
if ((direction == Description::Direction::RecvOnly ||
|
||||||
|
direction == Description::Direction::Inactive)) {
|
||||||
|
PLOG_WARNING << "Track media direction does not allow transmission, dropping";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto message = make_message(std::move(data));
|
||||||
|
|
||||||
|
if (mRtcpHandler) {
|
||||||
|
message = mRtcpHandler->outgoing(message);
|
||||||
|
if (!message)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return outgoing(std::move(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Track::send(const byte *data, size_t size) { return send(binary(data, data + size)); }
|
||||||
|
|
||||||
std::optional<message_variant> Track::receive() {
|
std::optional<message_variant> Track::receive() {
|
||||||
if (auto next = mRecvQueue.tryPop())
|
if (auto next = mRecvQueue.tryPop())
|
||||||
return to_variant(std::move(**next));
|
return to_variant(std::move(**next));
|
||||||
@ -88,50 +106,10 @@ void Track::open(shared_ptr<DtlsSrtpTransport> transport) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool Track::outgoing(message_ptr message) {
|
|
||||||
|
|
||||||
if (mRtcpHandler) {
|
|
||||||
message = mRtcpHandler->outgoing(message);
|
|
||||||
if (!message)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto direction = mMediaDescription.direction();
|
|
||||||
if ((direction == Description::Direction::RecvOnly ||
|
|
||||||
direction == Description::Direction::Inactive) &&
|
|
||||||
message->type != Message::Control) {
|
|
||||||
PLOG_WARNING << "Track media direction does not allow transmission, dropping";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mIsClosed)
|
|
||||||
throw std::runtime_error("Track is closed");
|
|
||||||
|
|
||||||
if (message->size() > maxMessageSize())
|
|
||||||
throw std::runtime_error("Message size exceeds limit");
|
|
||||||
|
|
||||||
#if RTC_ENABLE_MEDIA
|
|
||||||
auto transport = mDtlsSrtpTransport.lock();
|
|
||||||
if (!transport)
|
|
||||||
throw std::runtime_error("Track transport is not open");
|
|
||||||
|
|
||||||
return transport->sendMedia(message);
|
|
||||||
#else
|
|
||||||
PLOG_WARNING << "Ignoring track send (not compiled with SRTP support)";
|
|
||||||
return false;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void Track::incoming(message_ptr message) {
|
void Track::incoming(message_ptr message) {
|
||||||
if (!message)
|
if (!message)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (mRtcpHandler) {
|
|
||||||
message = mRtcpHandler->incoming(message);
|
|
||||||
if (!message)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto direction = mMediaDescription.direction();
|
auto direction = mMediaDescription.direction();
|
||||||
if ((direction == Description::Direction::SendOnly ||
|
if ((direction == Description::Direction::SendOnly ||
|
||||||
direction == Description::Direction::Inactive) &&
|
direction == Description::Direction::Inactive) &&
|
||||||
@ -140,30 +118,46 @@ void Track::incoming(message_ptr message) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mRtcpHandler) {
|
||||||
|
message = mRtcpHandler->incoming(message);
|
||||||
|
if (!message)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Tail drop if queue is full
|
// Tail drop if queue is full
|
||||||
if (mRecvQueue.full())
|
if (mRecvQueue.full()) {
|
||||||
|
PLOG_WARNING << "Track incoming queue is full, dropping";
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
mRecvQueue.push(message);
|
mRecvQueue.push(message);
|
||||||
triggerAvailable(mRecvQueue.size());
|
triggerAvailable(mRecvQueue.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Track::outgoing([[maybe_unused]] message_ptr message) {
|
||||||
|
#if RTC_ENABLE_MEDIA
|
||||||
|
auto transport = mDtlsSrtpTransport.lock();
|
||||||
|
if (!transport)
|
||||||
|
throw std::runtime_error("Track transport is not open");
|
||||||
|
|
||||||
|
// Set recommended medium-priority DSCP value
|
||||||
|
// See https://tools.ietf.org/html/draft-ietf-tsvwg-rtcweb-qos-18
|
||||||
|
if (mMediaDescription.type() == "audio")
|
||||||
|
message->dscp = 46; // EF: Expedited Forwarding
|
||||||
|
else
|
||||||
|
message->dscp = 36; // AF42: Assured Forwarding class 4, medium drop probability
|
||||||
|
|
||||||
|
return transport->sendMedia(message);
|
||||||
|
#else
|
||||||
|
PLOG_WARNING << "Ignoring track send (not compiled with media support)";
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void Track::setRtcpHandler(std::shared_ptr<RtcpHandler> handler) {
|
void Track::setRtcpHandler(std::shared_ptr<RtcpHandler> handler) {
|
||||||
mRtcpHandler = std::move(handler);
|
mRtcpHandler = std::move(handler);
|
||||||
if (mRtcpHandler) {
|
if (mRtcpHandler)
|
||||||
mRtcpHandler->onOutgoing([&]([[maybe_unused]] const rtc::message_ptr &message) {
|
mRtcpHandler->onOutgoing(std::bind(&Track::outgoing, this, std::placeholders::_1));
|
||||||
#if RTC_ENABLE_MEDIA
|
|
||||||
auto transport = mDtlsSrtpTransport.lock();
|
|
||||||
if (!transport)
|
|
||||||
throw std::runtime_error("Track transport is not open");
|
|
||||||
|
|
||||||
return transport->sendMedia(message);
|
|
||||||
#else
|
|
||||||
PLOG_WARNING << "Ignoring track send (not compiled with SRTP support)";
|
|
||||||
return false;
|
|
||||||
#endif
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Track::requestKeyframe() {
|
bool Track::requestKeyframe() {
|
||||||
|
@ -28,8 +28,6 @@
|
|||||||
|
|
||||||
namespace rtc {
|
namespace rtc {
|
||||||
|
|
||||||
using namespace std::placeholders;
|
|
||||||
|
|
||||||
class Transport {
|
class Transport {
|
||||||
public:
|
public:
|
||||||
enum class State { Disconnected, Connecting, Connected, Completed, Failed };
|
enum class State { Disconnected, Connecting, Connected, Completed, Failed };
|
||||||
@ -57,7 +55,7 @@ public:
|
|||||||
void registerIncoming() {
|
void registerIncoming() {
|
||||||
if (mLower) {
|
if (mLower) {
|
||||||
PLOG_VERBOSE << "Registering incoming callback";
|
PLOG_VERBOSE << "Registering incoming callback";
|
||||||
mLower->onRecv(std::bind(&Transport::incoming, this, _1));
|
mLower->onRecv(std::bind(&Transport::incoming, this, std::placeholders::_1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
namespace rtc {
|
namespace rtc {
|
||||||
|
|
||||||
using std::shared_ptr;
|
using std::shared_ptr;
|
||||||
|
using namespace std::placeholders;
|
||||||
|
|
||||||
WebSocket::WebSocket(std::optional<Configuration> config)
|
WebSocket::WebSocket(std::optional<Configuration> config)
|
||||||
: mConfig(config ? std::move(*config) : Configuration()),
|
: mConfig(config ? std::move(*config) : Configuration()),
|
||||||
|
@ -161,6 +161,7 @@ static Peer *createPeer(const rtcConfiguration *config) {
|
|||||||
rtcSetLocalCandidateCallback(peer->pc, candidateCallback);
|
rtcSetLocalCandidateCallback(peer->pc, candidateCallback);
|
||||||
rtcSetStateChangeCallback(peer->pc, stateChangeCallback);
|
rtcSetStateChangeCallback(peer->pc, stateChangeCallback);
|
||||||
rtcSetGatheringStateChangeCallback(peer->pc, gatheringStateCallback);
|
rtcSetGatheringStateChangeCallback(peer->pc, gatheringStateCallback);
|
||||||
|
rtcSetSignalingStateChangeCallback(peer->pc, signalingStateCallback);
|
||||||
|
|
||||||
return peer;
|
return peer;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user