Browse Source

Refactored ProxyServer interface

Paul-Louis Ageneau 3 years ago
parent
commit
4d9576bfc1
3 changed files with 91 additions and 20 deletions
  1. 7 5
      include/rtc/configuration.hpp
  2. 57 7
      src/configuration.cpp
  3. 27 8
      src/impl/icetransport.cpp

+ 7 - 5
include/rtc/configuration.hpp

@@ -51,16 +51,18 @@ struct RTC_CPP_EXPORT IceServer {
 };
 };
 
 
 struct RTC_CPP_EXPORT ProxyServer {
 struct RTC_CPP_EXPORT ProxyServer {
-	enum class Type { None = 0, Socks5, Http, Last = Http };
+	enum class Type { Http, Socks5 };
 
 
-	ProxyServer(Type type_, string hostname_, uint16_t port_, string username_ = "",
-	            string password_ = "");
+	ProxyServer(const string &url);
+
+	ProxyServer(Type type_, string hostname_, uint16_t port_);
+	ProxyServer(Type type_, string hostname_, uint16_t port_, string username_, string password_);
 
 
 	Type type;
 	Type type;
 	string hostname;
 	string hostname;
 	uint16_t port;
 	uint16_t port;
-	string username;
-	string password;
+	optional<string> username;
+	optional<string> password;
 };
 };
 
 
 enum class CertificateType {
 enum class CertificateType {

+ 57 - 7
src/configuration.cpp

@@ -18,11 +18,14 @@
 
 
 #include "configuration.hpp"
 #include "configuration.hpp"
 
 
+#include <cassert>
 #include <regex>
 #include <regex>
 
 
-namespace rtc {
+#include <iostream>
 
 
-IceServer::IceServer(const string &url) {
+namespace {
+
+bool parse_url(const std::string &url, std::vector<std::optional<std::string>> &result) {
 	// Modified regex from RFC 3986, see https://www.rfc-editor.org/rfc/rfc3986.html#appendix-B
 	// Modified regex from RFC 3986, see https://www.rfc-editor.org/rfc/rfc3986.html#appendix-B
 	static const char *rs =
 	static const char *rs =
 	    R"(^(([^:.@/?#]+):)?(/{0,2}((([^:@]*)(:([^@]*))?)@)?(([^:/?#]*)(:([^/?#]*))?))?([^?#]*)(\?([^#]*))?(#(.*))?)";
 	    R"(^(([^:.@/?#]+):)?(/{0,2}((([^:@]*)(:([^@]*))?)@)?(([^:/?#]*)(:([^/?#]*))?))?([^?#]*)(\?([^#]*))?(#(.*))?)";
@@ -30,13 +33,26 @@ IceServer::IceServer(const string &url) {
 
 
 	std::smatch m;
 	std::smatch m;
 	if (!std::regex_match(url, m, r) || m[10].length() == 0)
 	if (!std::regex_match(url, m, r) || m[10].length() == 0)
-		throw std::invalid_argument("Invalid ICE server URL: " + url);
+		return false;
 
 
-	std::vector<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;
+	result.resize(m.size());
+	std::transform(m.begin(), m.end(), result.begin(), [](const auto &sm) {
+		return sm.length() > 0 ? std::make_optional(std::string(sm)) : std::nullopt;
 	});
 	});
 
 
+	assert(result.size() == 18);
+	return true;
+}
+
+} // namespace
+
+namespace rtc {
+
+IceServer::IceServer(const string &url) {
+	std::vector<optional<string>> opt;
+	if (!parse_url(url, opt))
+		throw std::invalid_argument("Invalid ICE server URL: " + url);
+
 	string scheme = opt[2].value_or("stun");
 	string scheme = opt[2].value_or("stun");
 	relayType = RelayType::TurnUdp;
 	relayType = RelayType::TurnUdp;
 	if (scheme == "stun" || scheme == "STUN")
 	if (scheme == "stun" || scheme == "STUN")
@@ -103,8 +119,42 @@ IceServer::IceServer(string hostname_, string service_, string username_, string
 	}
 	}
 }
 }
 
 
+ProxyServer::ProxyServer(const string &url) {
+	std::vector<optional<string>> opt;
+	if (!parse_url(url, opt))
+		throw std::invalid_argument("Invalid proxy server URL: " + url);
+
+	string scheme = opt[2].value_or("http");
+	if (scheme == "http" || scheme == "HTTP")
+		type = Type::Http;
+	else if (scheme == "socks5" || scheme == "SOCKS5")
+		type = Type::Socks5;
+	else
+		throw std::invalid_argument("Unknown proxy server protocol: " + scheme);
+
+	username = opt[6];
+	password = opt[8];
+
+	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(type == Type::Socks5 ? "1080" : "3128");
+	try {
+		port = uint16_t(std::stoul(service));
+	} catch (...) {
+		throw std::invalid_argument("Invalid proxy server port in URL: " + service);
+	}
+}
+
+ProxyServer::ProxyServer(Type type_, string hostname_, uint16_t port_)
+    : type(type_), hostname(std::move(hostname_)), port(port_) {}
+
 ProxyServer::ProxyServer(Type type_, string hostname_, uint16_t port_, string username_,
 ProxyServer::ProxyServer(Type type_, string hostname_, uint16_t port_, string username_,
                          string password_)
                          string password_)
-    : type(type_), hostname(hostname_), port(port_), username(username_), password(password_) {}
+    : type(type_), hostname(std::move(hostname_)), port(port_), username(std::move(username_)),
+      password(std::move(password_)) {}
 
 
 } // namespace rtc
 } // namespace rtc

+ 27 - 8
src/impl/icetransport.cpp

@@ -417,15 +417,34 @@ IceTransport::IceTransport(const Configuration &config, candidate_callback candi
 	g_object_set(G_OBJECT(mNiceAgent.get()), "upnp-timeout", 200, nullptr);
 	g_object_set(G_OBJECT(mNiceAgent.get()), "upnp-timeout", 200, nullptr);
 
 
 	// Proxy
 	// Proxy
-	if (config.proxyServer.has_value()) {
-		ProxyServer proxyServer = config.proxyServer.value();
-		g_object_set(G_OBJECT(mNiceAgent.get()), "proxy-type", proxyServer.type, nullptr);
+	if (config.proxyServer) {
+		const auto &proxyServer = *config.proxyServer;
+
+		NiceProxyType type;
+		switch (proxyServer.type) {
+		case ProxyServer::Type::Http:
+			type = NICE_PROXY_TYPE_HTTP;
+			break;
+		case ProxyServer::Type::Socks5:
+			type = NICE_PROXY_TYPE_SOCKS5;
+			break;
+		default:
+			PLOG_WARNING << "Proxy server type is not supported";
+			type = NICE_PROXY_TYPE_NONE;
+			break;
+		}
+
+		g_object_set(G_OBJECT(mNiceAgent.get()), "proxy-type", type, nullptr);
 		g_object_set(G_OBJECT(mNiceAgent.get()), "proxy-ip", proxyServer.hostname.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);
-		g_object_set(G_OBJECT(mNiceAgent.get()), "proxy-password", proxyServer.password.c_str(),
-		             nullptr);
+		g_object_set(G_OBJECT(mNiceAgent.get()), "proxy-port", guint(proxyServer.port), nullptr);
+
+		if (proxyServer.username)
+			g_object_set(G_OBJECT(mNiceAgent.get()), "proxy-username",
+			             proxyServer.username->c_str(), nullptr);
+
+		if (proxyServer.password)
+			g_object_set(G_OBJECT(mNiceAgent.get()), "proxy-password",
+			             proxyServer.password->c_str(), nullptr);
 	}
 	}
 
 
 	if (config.enableIceUdpMux) {
 	if (config.enableIceUdpMux) {