diff --git a/.gitignore b/.gitignore
index cfb24dd..2ecbab1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,7 +5,7 @@ node_modules/
*.a
*.so
compile_commands.json
-tests
+/tests
.DS_Store
.idea
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e76c5e7..14bce3e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.7)
project(libdatachannel
- VERSION 0.11.0
+ VERSION 0.11.1
LANGUAGES CXX)
set(PROJECT_DESCRIPTION "WebRTC Data Channels Library")
@@ -135,6 +135,24 @@ set(TESTS_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/test/benchmark.cpp
)
+set(TESTS_UWP_RESOURCES
+ ${CMAKE_CURRENT_SOURCE_DIR}/test/uwp/tests/Logo.png
+ ${CMAKE_CURRENT_SOURCE_DIR}/test/uwp/tests/package.appxManifest
+ ${CMAKE_CURRENT_SOURCE_DIR}/test/uwp/tests/SmallLogo.png
+ ${CMAKE_CURRENT_SOURCE_DIR}/test/uwp/tests/SmallLogo44x44.png
+ ${CMAKE_CURRENT_SOURCE_DIR}/test/uwp/tests/SplashScreen.png
+ ${CMAKE_CURRENT_SOURCE_DIR}/test/uwp/tests/StoreLogo.png
+ ${CMAKE_CURRENT_SOURCE_DIR}/test/uwp/tests/Windows_TemporaryKey.pfx)
+
+set(BENCHMARK_UWP_RESOURCES
+ ${CMAKE_CURRENT_SOURCE_DIR}/test/uwp/benchmark/Logo.png
+ ${CMAKE_CURRENT_SOURCE_DIR}/test/uwp/benchmark/package.appxManifest
+ ${CMAKE_CURRENT_SOURCE_DIR}/test/uwp/benchmark/SmallLogo.png
+ ${CMAKE_CURRENT_SOURCE_DIR}/test/uwp/benchmark/SmallLogo44x44.png
+ ${CMAKE_CURRENT_SOURCE_DIR}/test/uwp/benchmark/SplashScreen.png
+ ${CMAKE_CURRENT_SOURCE_DIR}/test/uwp/benchmark/StoreLogo.png
+ ${CMAKE_CURRENT_SOURCE_DIR}/test/uwp/benchmark/Windows_TemporaryKey.pfx)
+
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
set(THREADS_PREFER_PTHREAD_FLAG TRUE)
find_package(Threads REQUIRED)
@@ -292,24 +310,30 @@ endif()
# Tests
if(NOT NO_TESTS)
- add_executable(datachannel-tests ${TESTS_SOURCES})
+ if(CMAKE_SYSTEM_NAME STREQUAL "WindowsStore")
+ # Add resource files needed for UWP apps.
+ add_executable(datachannel-tests ${TESTS_SOURCES} ${TESTS_UWP_RESOURCES})
+ else()
+ add_executable(datachannel-tests ${TESTS_SOURCES})
+ endif()
set_target_properties(datachannel-tests PROPERTIES
VERSION ${PROJECT_VERSION}
CXX_STANDARD 17)
- if(NOT CMAKE_SYSTEM_NAME STREQUAL "WindowsStore") # Prevent a bug in manifest generation for UWP
- set_target_properties(datachannel-tests PROPERTIES OUTPUT_NAME tests)
- endif()
+ set_target_properties(datachannel-tests PROPERTIES OUTPUT_NAME tests)
target_include_directories(datachannel-tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
target_link_libraries(datachannel-tests datachannel)
# Benchmark
- add_executable(datachannel-benchmark test/benchmark.cpp)
+ if(CMAKE_SYSTEM_NAME STREQUAL "WindowsStore")
+ # Add resource files needed for UWP apps.
+ add_executable(datachannel-benchmark test/benchmark.cpp ${BENCHMARK_UWP_RESOURCES})
+ else()
+ add_executable(datachannel-benchmark test/benchmark.cpp)
+ endif()
set_target_properties(datachannel-benchmark PROPERTIES
VERSION ${PROJECT_VERSION}
CXX_STANDARD 17)
- if(NOT CMAKE_SYSTEM_NAME STREQUAL "WindowsStore") # Prevent a bug in manifest generation for UWP
- set_target_properties(datachannel-benchmark PROPERTIES OUTPUT_NAME benchmark)
- endif()
+ set_target_properties(datachannel-benchmark PROPERTIES OUTPUT_NAME benchmark)
target_compile_definitions(datachannel-benchmark PRIVATE BENCHMARK_MAIN=1)
target_include_directories(datachannel-benchmark PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
target_link_libraries(datachannel-benchmark datachannel)
diff --git a/examples/streamer/client.js b/examples/streamer/client.js
index 6d040cd..1ba4b8c 100644
--- a/examples/streamer/client.js
+++ b/examples/streamer/client.js
@@ -54,12 +54,10 @@ function createPeerConnection() {
// connect audio / video
pc.addEventListener('track', function (evt) {
- if (evt.track.kind == 'video') {
- document.getElementById('media').style.display = 'block';
- document.getElementById('video').srcObject = evt.streams[0];
- } else {
- document.getElementById('audio').srcObject = evt.streams[0];
- }
+ document.getElementById('media').style.display = 'block';
+ const videoTag = document.getElementById('video');
+ videoTag.srcObject = evt.streams[0];
+ videoTag.play();
});
let time_start = null;
diff --git a/examples/streamer/index.html b/examples/streamer/index.html
index 0e28a24..ab7184c 100644
--- a/examples/streamer/index.html
+++ b/examples/streamer/index.html
@@ -52,7 +52,6 @@
diff --git a/examples/streamer/main.cpp b/examples/streamer/main.cpp
index 126aa20..6dac153 100644
--- a/examples/streamer/main.cpp
+++ b/examples/streamer/main.cpp
@@ -214,7 +214,7 @@ int main(int argc, char **argv) try {
shared_ptr addVideo(const shared_ptr pc, const uint8_t payloadType, const uint32_t ssrc, const string cname, const string msid, const function onOpen) {
auto video = Description::Video(cname);
video.addH264Codec(payloadType);
- video.addSSRC(ssrc, cname, msid);
+ video.addSSRC(ssrc, cname, msid, cname);
auto track = pc->addTrack(video);
// create RTP configuration
auto rtpConfig = shared_ptr(new RtpPacketizationConfig(ssrc, cname, payloadType, H264RtpPacketizer::defaultClockRate));
@@ -238,7 +238,7 @@ shared_ptr addVideo(const shared_ptr pc, const
shared_ptr addAudio(const shared_ptr pc, const uint8_t payloadType, const uint32_t ssrc, const string cname, const string msid, const function onOpen) {
auto audio = Description::Audio(cname);
audio.addOpusCodec(payloadType);
- audio.addSSRC(ssrc, cname, msid);
+ audio.addSSRC(ssrc, cname, msid, cname);
auto track = pc->addTrack(audio);
// create RTP configuration
auto rtpConfig = shared_ptr(new RtpPacketizationConfig(ssrc, cname, payloadType, OpusRtpPacketizer::defaultClockRate));
diff --git a/include/rtc/configuration.hpp b/include/rtc/configuration.hpp
index d22c18e..0c9693e 100644
--- a/include/rtc/configuration.hpp
+++ b/include/rtc/configuration.hpp
@@ -44,7 +44,7 @@ struct RTC_CPP_EXPORT IceServer {
RelayType relayType_ = RelayType::TurnUdp);
string hostname;
- string service;
+ uint16_t port;
Type type;
string username;
string password;
@@ -54,11 +54,11 @@ struct RTC_CPP_EXPORT IceServer {
struct RTC_CPP_EXPORT ProxyServer {
enum class Type { None = 0, Socks5, Http, Last = Http };
- ProxyServer(Type type_, string ip_, uint16_t port_, string username_ = "",
+ ProxyServer(Type type_, string hostname_, uint16_t port_, string username_ = "",
string password_ = "");
Type type;
- string ip;
+ string hostname;
uint16_t port;
string username;
string password;
diff --git a/include/rtc/description.hpp b/include/rtc/description.hpp
index 81d3589..a09c91b 100644
--- a/include/rtc/description.hpp
+++ b/include/rtc/description.hpp
@@ -141,9 +141,9 @@ public:
void removeFormat(const string &fmt);
void addSSRC(uint32_t ssrc, std::optional name,
- std::optional msid = nullopt);
+ std::optional msid = nullopt, std::optional trackID = nullopt);
void replaceSSRC(uint32_t oldSSRC, uint32_t ssrc, std::optional name,
- std::optional msid = nullopt);
+ std::optional msid = nullopt, std::optional trackID = nullopt);
bool hasSSRC(uint32_t ssrc);
std::vector getSSRCs();
diff --git a/include/rtc/h264rtppacketizer.hpp b/include/rtc/h264rtppacketizer.hpp
index 98d1156..f3376aa 100644
--- a/include/rtc/h264rtppacketizer.hpp
+++ b/include/rtc/h264rtppacketizer.hpp
@@ -16,8 +16,8 @@
* along with this program; If not, see .
*/
-#ifndef H264RtpPacketizer_hpp
-#define H264RtpPacketizer_hpp
+#ifndef H264_RTP_PACKETIZER_H
+#define H264_RTP_PACKETIZER_H
#if RTC_ENABLE_MEDIA
@@ -64,4 +64,4 @@ private:
#endif /* RTC_ENABLE_MEDIA */
-#endif /* H264RtpPacketizer_hpp */
+#endif /* H264_RTP_PACKETIZER_H */
diff --git a/include/rtc/nalunit.hpp b/include/rtc/nalunit.hpp
index 5970881..1012bf0 100644
--- a/include/rtc/nalunit.hpp
+++ b/include/rtc/nalunit.hpp
@@ -16,8 +16,8 @@
* along with this program; If not, see .
*/
-#ifndef NalUnit_hpp
-#define NalUnit_hpp
+#ifndef NAL_UNIT_H
+#define NAL_UNIT_H
#if RTC_ENABLE_MEDIA
@@ -152,4 +152,4 @@ public:
#endif /* RTC_ENABLE_MEDIA */
-#endif /* NalUnit_hpp */
+#endif /* NAL_UNIT_H */
diff --git a/include/rtc/rtc.h b/include/rtc/rtc.h
index e78e576..57293ad 100644
--- a/include/rtc/rtc.h
+++ b/include/rtc/rtc.h
@@ -216,8 +216,9 @@ RTC_EXPORT int rtcGetTrackDescription(int tr, char *buffer, int size);
/// @param _direction Direction
/// @param _name Name (optional)
/// @param _msid MSID (optional)
+/// @param _trackID Track ID used in MSID (optional)
/// @returns Track id
-RTC_EXPORT int rtcAddTrackEx(int pc, rtcCodec codec, int payloadType, uint32_t ssrc, const char *_mid, rtcDirection direction, const char *_name, const char *_msid);
+RTC_EXPORT int rtcAddTrackEx(int pc, rtcCodec codec, int payloadType, uint32_t ssrc, const char *_mid, rtcDirection direction, const char *_name, const char *_msid, const char *_trackID);
/// Set H264PacketizationHandler for track
/// @param tr Track id
diff --git a/src/candidate.cpp b/src/candidate.cpp
index 8fed5c0..eef2c4b 100644
--- a/src/candidate.cpp
+++ b/src/candidate.cpp
@@ -167,9 +167,12 @@ bool Candidate::resolve(ResolveMode mode) {
if (getnameinfo(p->ai_addr, socklen_t(p->ai_addrlen), nodebuffer,
MAX_NUMERICNODE_LEN, servbuffer, MAX_NUMERICSERV_LEN,
NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
-
+ try {
+ mPort = uint16_t(std::stoul(servbuffer));
+ } catch (...) {
+ return false;
+ }
mAddress = nodebuffer;
- mPort = uint16_t(std::stoul(servbuffer));
mFamily = p->ai_family == AF_INET6 ? Family::Ipv6 : Family::Ipv4;
PLOG_VERBOSE << "Resolved candidate: " << mAddress << ' ' << mPort;
break;
diff --git a/src/capi.cpp b/src/capi.cpp
index b961db5..cbff452 100644
--- a/src/capi.cpp
+++ b/src/capi.cpp
@@ -453,7 +453,7 @@ int rtcDeleteDataChannel(int dc) {
#if RTC_ENABLE_MEDIA
-void setSSRC(Description::Media *description, uint32_t ssrc, const char *_name, const char *_msid) {
+void setSSRC(Description::Media *description, uint32_t ssrc, const char *_name, const char *_msid, const char *_trackID) {
optional name = nullopt;
if (_name) {
@@ -465,11 +465,16 @@ void setSSRC(Description::Media *description, uint32_t ssrc, const char *_name,
msid = string(_msid);
}
- description->addSSRC(ssrc, name, msid);
+ optional trackID = nullopt;
+ if (_trackID) {
+ trackID = string(_trackID);
+ }
+
+ description->addSSRC(ssrc, name, msid, trackID);
}
int rtcAddTrackEx(int pc, rtcCodec codec, int payloadType, uint32_t ssrc, const char *_mid,
- rtcDirection _direction, const char *_name, const char *_msid) {
+ rtcDirection _direction, const char *_name, const char *_msid, const char *_trackID) {
return WRAP({
auto peerConnection = getPeerConnection(pc);
@@ -534,7 +539,7 @@ int rtcAddTrackEx(int pc, rtcCodec codec, int payloadType, uint32_t ssrc, const
throw std::invalid_argument("Unexpected codec");
} else {
auto description = optDescription.value();
- setSSRC(&description, ssrc, _name, _msid);
+ setSSRC(&description, ssrc, _name, _msid, _trackID);
int tr = emplaceTrack(peerConnection->addTrack(std::move(description)));
if (auto ptr = getUserPointer(pc)) {
diff --git a/src/configuration.cpp b/src/configuration.cpp
index bd918a9..be82575 100644
--- a/src/configuration.cpp
+++ b/src/configuration.cpp
@@ -60,32 +60,51 @@ IceServer::IceServer(const string &url) {
username = opt[6].value_or("");
password = opt[8].value_or("");
- hostname = opt[10].value();
- service = opt[12].value_or(relayType == RelayType::TurnTls ? "5349" : "3478");
+ hostname = opt[10].value();
while (!hostname.empty() && hostname.front() == '[')
hostname.erase(hostname.begin());
while (!hostname.empty() && hostname.back() == ']')
hostname.pop_back();
+
+ string service = opt[12].value_or(relayType == RelayType::TurnTls ? "5349" : "3478");
+ try {
+ port = uint16_t(std::stoul(service));
+ } catch (...) {
+ throw std::invalid_argument("Invalid ICE server port in URL: " + service);
+ }
}
IceServer::IceServer(string hostname_, uint16_t port_)
- : IceServer(std::move(hostname_), std::to_string(port_)) {}
+ : hostname(std::move(hostname_)), port(port_), type(Type::Stun) {}
IceServer::IceServer(string hostname_, string service_)
- : hostname(std::move(hostname_)), service(std::move(service_)), type(Type::Stun) {}
+ : hostname(std::move(hostname_)), type(Type::Stun) {
+ try {
+ port = uint16_t(std::stoul(service_));
+ } catch (...) {
+ throw std::invalid_argument("Invalid ICE server port: " + service_);
+ }
+}
IceServer::IceServer(string hostname_, uint16_t port_, string username_, string password_,
RelayType relayType_)
- : IceServer(hostname_, std::to_string(port_), std::move(username_), std::move(password_),
- relayType_) {}
+ : hostname(std::move(hostname_)), port(port_), type(Type::Turn), username(std::move(username_)),
+ password(std::move(password_)), relayType(relayType_) {}
IceServer::IceServer(string hostname_, string service_, string username_, string password_,
RelayType relayType_)
- : hostname(std::move(hostname_)), service(std::move(service_)), type(Type::Turn),
- username(std::move(username_)), password(std::move(password_)), relayType(relayType_) {}
+ : hostname(std::move(hostname_)), type(Type::Turn), username(std::move(username_)),
+ password(std::move(password_)), relayType(relayType_) {
+ try {
+ port = uint16_t(std::stoul(service_));
+ } catch (...) {
+ throw std::invalid_argument("Invalid ICE server port: " + service_);
+ }
+}
-ProxyServer::ProxyServer(Type type_, string ip_, uint16_t port_, string username_, string password_)
- : type(type_), ip(ip_), port(port_), username(username_), password(password_) {}
+ProxyServer::ProxyServer(Type type_, string hostname_, uint16_t port_, string username_,
+ string password_)
+ : type(type_), hostname(hostname_), port(port_), username(username_), password(password_) {}
} // namespace rtc
diff --git a/src/description.cpp b/src/description.cpp
index a2602c2..7e67ae2 100644
--- a/src/description.cpp
+++ b/src/description.cpp
@@ -59,7 +59,13 @@ inline std::pair parse_pair(string_view attr) {
}
template T to_integer(string_view s) {
- return std::is_signed::value ? T(std::stol(string(s))) : T(std::stoul(string(s)));
+ const string str(s);
+ try {
+ return std::is_signed::value ? T(std::stol(str)) : T(std::stoul(str));
+ }
+ catch(...) {
+ throw std::invalid_argument("Invalid integer \"" + str + "\" in description");
+ }
}
} // namespace
@@ -519,20 +525,20 @@ Description::Entry::removeAttribute(std::vector::iterator it) {
}
void Description::Media::addSSRC(uint32_t ssrc, std::optional name,
- std::optional msid) {
+ std::optional msid, std::optional trackID) {
if (name)
mAttributes.emplace_back("ssrc:" + std::to_string(ssrc) + " cname:" + *name);
else
mAttributes.emplace_back("ssrc:" + std::to_string(ssrc));
if (msid)
- mAttributes.emplace_back("ssrc:" + std::to_string(ssrc) + " msid:" + *msid + " " + *msid);
+ mAttributes.emplace_back("ssrc:" + std::to_string(ssrc) + " msid:" + *msid + " " + trackID.value_or(*msid));
mSsrcs.emplace_back(ssrc);
}
void Description::Media::replaceSSRC(uint32_t oldSSRC, uint32_t ssrc, std::optional name,
- std::optional msid) {
+ std::optional msid, std::optional trackID) {
auto it = mAttributes.begin();
while (it != mAttributes.end()) {
if (it->find("ssrc:" + std::to_string(oldSSRC)) == 0) {
@@ -540,7 +546,7 @@ void Description::Media::replaceSSRC(uint32_t oldSSRC, uint32_t ssrc, std::optio
} else
it++;
}
- addSSRC(ssrc, std::move(name), std::move(msid));
+ addSSRC(ssrc, std::move(name), std::move(msid), std::move(trackID));
}
void Description::Media::removeSSRC(uint32_t oldSSRC) {
@@ -823,7 +829,7 @@ void Description::Media::parseSdpLine(string_view line) {
} else if (key == "rtcp-mux") {
// always added
} else if (key == "ssrc") {
- mSsrcs.emplace_back(std::stoul(string(value)));
+ mSsrcs.emplace_back(to_integer(value));
} else {
Entry::parseSdpLine(line);
}
@@ -843,7 +849,7 @@ std::vector Description::Media::getSSRCs() {
for (auto &val : mAttributes) {
PLOG_DEBUG << val;
if (val.find("ssrc:") == 0) {
- vec.emplace_back(std::stoul(string(val.substr(5, val.find(" ")))));
+ vec.emplace_back(to_integer(val.substr(5, val.find(" "))));
}
}
return vec;
diff --git a/src/h264rtppacketizer.cpp b/src/h264rtppacketizer.cpp
index 779085c..51a141c 100644
--- a/src/h264rtppacketizer.cpp
+++ b/src/h264rtppacketizer.cpp
@@ -108,7 +108,7 @@ shared_ptr H264RtpPacketizer::splitMessage(binary_ptr message) {
break;
}
}
- index++;
+
unsigned long long naluStartIndex = index;
while (index < message->size()) {
diff --git a/src/icetransport.cpp b/src/icetransport.cpp
index 9afd53d..0037891 100644
--- a/src/icetransport.cpp
+++ b/src/icetransport.cpp
@@ -103,11 +103,11 @@ IceTransport::IceTransport(const Configuration &config, candidate_callback candi
// Pick a STUN server
for (auto &server : servers) {
if (!server.hostname.empty() && server.type == IceServer::Type::Stun) {
- if (server.service.empty())
- server.service = "3478"; // STUN UDP port
- PLOG_INFO << "Using STUN server \"" << server.hostname << ":" << server.service << "\"";
+ if (server.port == 0)
+ server.port = 3478; // STUN UDP port
+ PLOG_INFO << "Using STUN server \"" << server.hostname << ":" << server.port << "\"";
jconfig.stun_server_host = server.hostname.c_str();
- jconfig.stun_server_port = uint16_t(std::stoul(server.service));
+ jconfig.stun_server_port = server.port;
break;
}
}
@@ -119,13 +119,13 @@ IceTransport::IceTransport(const Configuration &config, candidate_callback candi
int k = 0;
for (auto &server : servers) {
if (!server.hostname.empty() && server.type == IceServer::Type::Turn) {
- if (server.service.empty())
- server.service = "3478"; // TURN UDP port
- PLOG_INFO << "Using TURN server \"" << server.hostname << ":" << server.service << "\"";
+ if (server.port == 0)
+ server.port = 3478; // TURN UDP port
+ PLOG_INFO << "Using TURN server \"" << server.hostname << ":" << server.port << "\"";
turn_servers[k].host = server.hostname.c_str();
turn_servers[k].username = server.username.c_str();
turn_servers[k].password = server.password.c_str();
- turn_servers[k].port = uint16_t(std::stoul(server.service));
+ turn_servers[k].port = server.port;
if (++k >= MAX_TURN_SERVERS_COUNT)
break;
}
@@ -402,7 +402,7 @@ IceTransport::IceTransport(const Configuration &config, candidate_callback candi
if (config.proxyServer.has_value()) {
ProxyServer proxyServer = config.proxyServer.value();
g_object_set(G_OBJECT(mNiceAgent.get()), "proxy-type", proxyServer.type, nullptr);
- g_object_set(G_OBJECT(mNiceAgent.get()), "proxy-ip", proxyServer.ip.c_str(), nullptr);
+ g_object_set(G_OBJECT(mNiceAgent.get()), "proxy-ip", proxyServer.hostname.c_str(), nullptr);
g_object_set(G_OBJECT(mNiceAgent.get()), "proxy-port", proxyServer.port, nullptr);
g_object_set(G_OBJECT(mNiceAgent.get()), "proxy-username", proxyServer.username.c_str(),
nullptr);
@@ -422,8 +422,8 @@ IceTransport::IceTransport(const Configuration &config, candidate_callback candi
continue;
if (server.type != IceServer::Type::Stun)
continue;
- if (server.service.empty())
- server.service = "3478"; // STUN UDP port
+ if (server.port == 0)
+ server.port = 3478; // STUN UDP port
struct addrinfo hints = {};
hints.ai_family = AF_INET; // IPv4
@@ -431,9 +431,10 @@ IceTransport::IceTransport(const Configuration &config, candidate_callback candi
hints.ai_protocol = IPPROTO_UDP;
hints.ai_flags = AI_ADDRCONFIG;
struct addrinfo *result = nullptr;
- if (getaddrinfo(server.hostname.c_str(), server.service.c_str(), &hints, &result) != 0) {
+ if (getaddrinfo(server.hostname.c_str(), std::to_string(server.port).c_str(), &hints,
+ &result) != 0) {
PLOG_WARNING << "Unable to resolve STUN server address: " << server.hostname << ':'
- << server.service;
+ << server.port;
continue;
}
@@ -444,7 +445,7 @@ IceTransport::IceTransport(const Configuration &config, candidate_callback candi
if (getnameinfo(p->ai_addr, p->ai_addrlen, nodebuffer, MAX_NUMERICNODE_LEN,
servbuffer, MAX_NUMERICNODE_LEN,
NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
- PLOG_INFO << "Using STUN server \"" << server.hostname << ":" << server.service
+ PLOG_INFO << "Using STUN server \"" << server.hostname << ":" << server.port
<< "\"";
g_object_set(G_OBJECT(mNiceAgent.get()), "stun-server", nodebuffer, nullptr);
g_object_set(G_OBJECT(mNiceAgent.get()), "stun-server-port",
@@ -466,8 +467,8 @@ IceTransport::IceTransport(const Configuration &config, candidate_callback candi
continue;
if (server.type != IceServer::Type::Turn)
continue;
- if (server.service.empty())
- server.service = server.relayType == IceServer::RelayType::TurnTls ? "5349" : "3478";
+ if (server.port == 0)
+ server.port = server.relayType == IceServer::RelayType::TurnTls ? 5349 : 3478;
struct addrinfo hints = {};
hints.ai_family = AF_UNSPEC;
@@ -477,9 +478,10 @@ IceTransport::IceTransport(const Configuration &config, candidate_callback candi
server.relayType == IceServer::RelayType::TurnUdp ? IPPROTO_UDP : IPPROTO_TCP;
hints.ai_flags = AI_ADDRCONFIG;
struct addrinfo *result = nullptr;
- if (getaddrinfo(server.hostname.c_str(), server.service.c_str(), &hints, &result) != 0) {
+ if (getaddrinfo(server.hostname.c_str(), std::to_string(server.port).c_str(), &hints,
+ &result) != 0) {
PLOG_WARNING << "Unable to resolve TURN server address: " << server.hostname << ':'
- << server.service;
+ << server.port;
continue;
}
@@ -490,7 +492,7 @@ IceTransport::IceTransport(const Configuration &config, candidate_callback candi
if (getnameinfo(p->ai_addr, p->ai_addrlen, nodebuffer, MAX_NUMERICNODE_LEN,
servbuffer, MAX_NUMERICNODE_LEN,
NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
- PLOG_INFO << "Using TURN server \"" << server.hostname << ":" << server.service
+ PLOG_INFO << "Using TURN server \"" << server.hostname << ":" << server.port
<< "\"";
NiceRelayType niceRelayType;
switch (server.relayType) {
diff --git a/src/processor.cpp b/src/processor.cpp
index 5e83e47..d5f98c4 100644
--- a/src/processor.cpp
+++ b/src/processor.cpp
@@ -25,18 +25,39 @@ Processor::Processor(size_t limit) : mTasks(limit) {}
Processor::~Processor() { join(); }
void Processor::join() {
- std::unique_lock lock(mMutex);
- mCondition.wait(lock, [this]() { return !mPending && mTasks.empty(); });
+ // We need to detect situations where the thread pool does not execute a pending task at exit
+ std::optional counter;
+ while (true) {
+ std::shared_future pending;
+ {
+ std::unique_lock lock(mMutex);
+ if (!mPending // no pending task
+ || (counter && *counter == mCounter)) { // or no scheduled task after the last one
+
+ // Processing is stopped, clear everything and return
+ mPending.reset();
+ while (!mTasks.empty())
+ mTasks.pop();
+
+ return;
+ }
+
+ pending = *mPending;
+ counter = mCounter;
+ }
+
+ // Wait for the pending task
+ pending.wait();
+ }
}
void Processor::schedule() {
std::unique_lock lock(mMutex);
if (auto next = mTasks.tryPop()) {
- ThreadPool::Instance().enqueue(std::move(*next));
+ mPending = ThreadPool::Instance().enqueue(std::move(*next)).share();
+ ++mCounter;
} else {
- // No more tasks
- mPending = false;
- mCondition.notify_all();
+ mPending.reset(); // No more tasks
}
}
diff --git a/src/processor.hpp b/src/processor.hpp
index a63259b..47a82bc 100644
--- a/src/processor.hpp
+++ b/src/processor.hpp
@@ -54,10 +54,10 @@ protected:
const init_token mInitToken = Init::Token();
Queue> mTasks;
- bool mPending = false; // true iff a task is pending in the thread pool
+ std::optional> mPending; // future of the pending task
+ unsigned int mCounter = 0; // Number of scheduled tasks
mutable std::mutex mMutex;
- std::condition_variable mCondition;
};
template void Processor::enqueue(F &&f, Args &&...args) {
@@ -65,12 +65,12 @@ template void Processor::enqueue(F &&f, Args &&...args)
auto bound = std::bind(std::forward(f), std::forward(args)...);
auto task = [this, bound = std::move(bound)]() mutable {
scope_guard guard(std::bind(&Processor::schedule, this)); // chain the next task
- return bound();
+ bound();
};
if (!mPending) {
- ThreadPool::Instance().enqueue(std::move(task));
- mPending = true;
+ mPending = ThreadPool::Instance().enqueue(std::move(task)).share();
+ ++mCounter;
} else {
mTasks.push(std::move(task));
}
diff --git a/src/sctptransport.cpp b/src/sctptransport.cpp
index 994eb20..2340ff4 100644
--- a/src/sctptransport.cpp
+++ b/src/sctptransport.cpp
@@ -588,7 +588,6 @@ int SctpTransport::handleWrite(byte *data, size_t len, uint8_t /*tos*/, uint8_t
std::unique_lock lock(mWriteMutex);
PLOG_VERBOSE << "Handle write, len=" << len;
- auto message = make_message(data, data + len);
if (!outgoing(make_message(data, data + len)))
return -1;
diff --git a/src/threadpool.cpp b/src/threadpool.cpp
index 261195e..9a7be69 100644
--- a/src/threadpool.cpp
+++ b/src/threadpool.cpp
@@ -96,6 +96,10 @@ std::function ThreadPool::dequeue() {
mCondition.wait(lock);
}
}
+
+ while (!mTasks.empty())
+ mTasks.pop();
+
return nullptr;
}
diff --git a/src/threadpool.hpp b/src/threadpool.hpp
index bb134a7..8f56894 100644
--- a/src/threadpool.hpp
+++ b/src/threadpool.hpp
@@ -100,8 +100,16 @@ auto ThreadPool::schedule(clock::duration delay, F &&f, Args &&...args)
template
auto ThreadPool::schedule(clock::time_point time, F &&f, Args &&...args)
-> invoke_future_t {
- std::unique_lock lock(mMutex);
using R = std::invoke_result_t, std::decay_t...>;
+ std::unique_lock lock(mMutex);
+ if (mJoining) {
+ std::promise promise;
+ std::future result = promise.get_future();
+ promise.set_exception(std::make_exception_ptr(
+ std::runtime_error("Scheduled a task while joining the thread pool")));
+ return result;
+ }
+
auto bound = std::bind(std::forward(f), std::forward(args)...);
auto task = std::make_shared>([bound = std::move(bound)]() mutable {
try {
diff --git a/test/uwp/benchmark/Logo.png b/test/uwp/benchmark/Logo.png
new file mode 100644
index 0000000..65f91ac
Binary files /dev/null and b/test/uwp/benchmark/Logo.png differ
diff --git a/test/uwp/benchmark/SmallLogo.png b/test/uwp/benchmark/SmallLogo.png
new file mode 100644
index 0000000..460c022
Binary files /dev/null and b/test/uwp/benchmark/SmallLogo.png differ
diff --git a/test/uwp/benchmark/SmallLogo44x44.png b/test/uwp/benchmark/SmallLogo44x44.png
new file mode 100644
index 0000000..c237458
Binary files /dev/null and b/test/uwp/benchmark/SmallLogo44x44.png differ
diff --git a/test/uwp/benchmark/SplashScreen.png b/test/uwp/benchmark/SplashScreen.png
new file mode 100644
index 0000000..8342565
Binary files /dev/null and b/test/uwp/benchmark/SplashScreen.png differ
diff --git a/test/uwp/benchmark/StoreLogo.png b/test/uwp/benchmark/StoreLogo.png
new file mode 100644
index 0000000..508c8a8
Binary files /dev/null and b/test/uwp/benchmark/StoreLogo.png differ
diff --git a/test/uwp/benchmark/Windows_TemporaryKey.pfx b/test/uwp/benchmark/Windows_TemporaryKey.pfx
new file mode 100644
index 0000000..1cad999
Binary files /dev/null and b/test/uwp/benchmark/Windows_TemporaryKey.pfx differ
diff --git a/test/uwp/benchmark/package.appxManifest b/test/uwp/benchmark/package.appxManifest
new file mode 100644
index 0000000..8cd7981
--- /dev/null
+++ b/test/uwp/benchmark/package.appxManifest
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+ datachannel-benchmark
+ CMake
+ StoreLogo.png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/uwp/tests/Logo.png b/test/uwp/tests/Logo.png
new file mode 100644
index 0000000..65f91ac
Binary files /dev/null and b/test/uwp/tests/Logo.png differ
diff --git a/test/uwp/tests/SmallLogo.png b/test/uwp/tests/SmallLogo.png
new file mode 100644
index 0000000..460c022
Binary files /dev/null and b/test/uwp/tests/SmallLogo.png differ
diff --git a/test/uwp/tests/SmallLogo44x44.png b/test/uwp/tests/SmallLogo44x44.png
new file mode 100644
index 0000000..c237458
Binary files /dev/null and b/test/uwp/tests/SmallLogo44x44.png differ
diff --git a/test/uwp/tests/SplashScreen.png b/test/uwp/tests/SplashScreen.png
new file mode 100644
index 0000000..8342565
Binary files /dev/null and b/test/uwp/tests/SplashScreen.png differ
diff --git a/test/uwp/tests/StoreLogo.png b/test/uwp/tests/StoreLogo.png
new file mode 100644
index 0000000..508c8a8
Binary files /dev/null and b/test/uwp/tests/StoreLogo.png differ
diff --git a/test/uwp/tests/Windows_TemporaryKey.pfx b/test/uwp/tests/Windows_TemporaryKey.pfx
new file mode 100644
index 0000000..1cad999
Binary files /dev/null and b/test/uwp/tests/Windows_TemporaryKey.pfx differ
diff --git a/test/uwp/tests/package.appxManifest b/test/uwp/tests/package.appxManifest
new file mode 100644
index 0000000..1da7e86
--- /dev/null
+++ b/test/uwp/tests/package.appxManifest
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+ datachannel-tests
+ CMake
+ StoreLogo.png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+