2
0
Эх сурвалжийг харах

Extended STUN server URL parsing to TURN server URLs

Paul-Louis Ageneau 5 жил өмнө
parent
commit
a683b76a21

+ 3 - 3
include/rtc/configuration.hpp

@@ -30,7 +30,7 @@ struct IceServer {
 	enum class Type { Stun, Turn };
 	enum class RelayType { TurnUdp, TurnTcp, TurnTls };
 
-	IceServer(const string &host_);
+	IceServer(const string &url);
 
 	// STUN
 	IceServer(string hostname_, uint16_t port_);
@@ -38,9 +38,9 @@ struct IceServer {
 
 	// TURN
 	IceServer(string hostname_, uint16_t port, string username_, string password_,
-	          RelayType relayType_);
+	          RelayType relayType_ = RelayType::TurnUdp);
 	IceServer(string hostname_, string service_, string username_, string password_,
-	          RelayType relayType_);
+	          RelayType relayType_ = RelayType::TurnUdp);
 
 	string hostname;
 	string service;

+ 46 - 18
src/configuration.cpp

@@ -18,27 +18,55 @@
 
 #include "configuration.hpp"
 
+#include <iostream>
+#include <regex>
+
 namespace rtc {
 
-IceServer::IceServer(const string &host) : type(Type::Stun) {
-	if (size_t serviceSep = host.rfind(':'); serviceSep != string::npos) {
-		if (size_t protocolSep = host.rfind(':', serviceSep - 1); protocolSep != string::npos) {
-			string protocol = host.substr(0, protocolSep);
-			if (protocol == "stun" || protocol == "STUN")
-				type = Type::Stun;
-			else if (protocol == "turn" || protocol == "TURN")
-				type = Type::Turn;
-			else
-				throw std::invalid_argument("Unknown ICE server protocol: " + protocol);
-			hostname = host.substr(protocolSep + 1, serviceSep - (protocolSep + 1));
-		} else {
-			hostname = host.substr(0, serviceSep);
-		}
-		service = host.substr(serviceSep + 1);
-	} else {
-		hostname = host;
-		service = "3478"; // STUN UDP port
+IceServer::IceServer(const string &url) {
+	// Modified regex from RFC 3986, see https://tools.ietf.org/html/rfc3986#appendix-B
+	static const char *rs =
+	    R"(^(([^:.@/?#]+):)?(/{0,2}((([^:@]*)(:([^@]*))?)@)?(([^:/?#]*)(:([^/?#]*))?))?([^?#]*)(\?([^#]*))?(#(.*))?)";
+	static const std::regex r(rs, std::regex::extended);
+
+	std::smatch m;
+	if (!std::regex_match(url, m, r) || m[10].length() == 0)
+		throw std::invalid_argument("Invalid ICE server URL: " + url);
+
+	std::vector<std::optional<string>> opt(m.size());
+	std::transform(m.begin(), m.end(), opt.begin(), [](const auto &sm) {
+		return sm.length() > 0 ? std::make_optional(string(sm)) : nullopt;
+	});
+
+	string scheme = opt[2].value_or("stun");
+	if (scheme == "stun" || scheme == "STUN")
+		type = Type::Stun;
+	else if (scheme == "turn" || scheme == "TURN")
+		type = Type::Turn;
+	else if (scheme == "turns" || scheme == "TURNS")
+		type = Type::Turn;
+	else
+		throw std::invalid_argument("Unknown ICE server protocol: " + scheme);
+
+	relayType = RelayType::TurnUdp;
+	if (auto &query = opt[15]) {
+		if (query->find("transport=udp") != string::npos)
+			relayType = RelayType::TurnUdp;
+		if (query->find("transport=tcp") != string::npos)
+			relayType = RelayType::TurnTcp;
+		if (query->find("transport=tls") != string::npos)
+			relayType = RelayType::TurnTls;
 	}
+
+	username = opt[6].value_or("");
+	password = opt[8].value_or("");
+	hostname = opt[10].value();
+	service = opt[12].value_or(relayType == RelayType::TurnTls ? "5349" : "3478");
+
+	while (!hostname.empty() && hostname.front() == '[')
+		hostname.erase(hostname.begin());
+	while (!hostname.empty() && hostname.back() == ']')
+		hostname.pop_back();
 }
 
 IceServer::IceServer(string hostname_, uint16_t port_)

+ 4 - 4
test/main.cpp

@@ -30,14 +30,14 @@ template <class T> weak_ptr<T> make_weak_ptr(shared_ptr<T> ptr) { return ptr; }
 
 int main(int argc, char **argv) {
 	// InitLogger(LogLevel::Debug);
-	Configuration config;
 
-	// config.iceServers.emplace_back("stun.l.google.com:19302");
+	Configuration config;
+	// config.iceServers.emplace_back("stun:stun.l.google.com:19302");
 	// config.enableIceTcp = true;
 
-	// Add TURN Server Example
+	// TURN server example
 	// IceServer turnServer("TURN_SERVER_URL", "PORT_NO", "USERNAME", "PASSWORD",
-	//							IceServer::RelayType::TurnTls);
+	//							IceServer::RelayType::TurnUdp);
 	// config.iceServers.push_back(turnServer);
 
 	auto pc1 = std::make_shared<PeerConnection>(config);

+ 3 - 2
test/p2p/answerer.cpp

@@ -29,13 +29,14 @@ template <class T> weak_ptr<T> make_weak_ptr(shared_ptr<T> ptr) { return ptr; }
 
 int main(int argc, char **argv) {
 	// InitLogger(LogLevel::Debug);
+
 	Configuration config;
 	// config.iceServers.emplace_back("stun.l.google.com:19302");
 	// config.enableIceTcp = true;
 
-	// Add TURN Server Example
+	// TURN Server example
 	// IceServer turnServer("TURN_SERVER_URL", "PORT_NO", "USERNAME", "PASSWORD",
-	//							IceServer::RelayType::TurnTls);
+	//							IceServer::RelayType::TurnUdp);
 	// config.iceServers.push_back(turnServer);
 
 	auto pc = std::make_shared<PeerConnection>(config);

+ 3 - 2
test/p2p/offerer.cpp

@@ -29,13 +29,14 @@ template <class T> weak_ptr<T> make_weak_ptr(shared_ptr<T> ptr) { return ptr; }
 
 int main(int argc, char **argv) {
 	// InitLogger(LogLevel::Debug);
+
 	Configuration config;
 	// config.iceServers.emplace_back("stun.l.google.com:19302");
 	// config.enableIceTcp = true;
 
-	// Add TURN Server Example
+	// TURN server example
 	// IceServer turnServer("TURN_SERVER_URL", "PORT_NO", "USERNAME", "PASSWORD",
-	//							IceServer::RelayType::TurnTls);
+	//							IceServer::RelayType::TurnUdp);
 	// config.iceServers.push_back(turnServer);
 
 	auto pc = std::make_shared<PeerConnection>(config);