Browse Source

Merge pull request #599 from paullouisageneau/enhance-configuration

Refactor ProxyServer and expose missing settings in C API
Paul-Louis Ageneau 3 years ago
parent
commit
dd990c8252

+ 11 - 2
DOC.md

@@ -77,6 +77,7 @@ int rtcCreatePeerConnection(const rtcConfiguration *config)
 typedef struct {
 typedef struct {
 	const char **iceServers;
 	const char **iceServers;
 	int iceServersCount;
 	int iceServersCount;
+	const char *proxyServer;
 	const char *bindAddress;
 	const char *bindAddress;
 	rtcCertificateType certificateType;
 	rtcCertificateType certificateType;
 	rtcTransportPolicy iceTransportPolicy;
 	rtcTransportPolicy iceTransportPolicy;
@@ -95,8 +96,9 @@ Creates a Peer Connection.
 Arguments:
 Arguments:
 
 
 - `config`: the configuration structure, containing:
 - `config`: the configuration structure, containing:
-  - `iceServers` (optional): an array of pointers on null-terminated ice server URIs (NULL if unused)
+  - `iceServers` (optional): an array of pointers on null-terminated ICE server URIs (NULL if unused)
   - `iceServersCount` (optional): number of URLs in the array pointed by `iceServers` (0 if unused)
   - `iceServersCount` (optional): number of URLs in the array pointed by `iceServers` (0 if unused)
+  - `proxyServer` (optional): if non-NULL, specifies the proxy server URI to use for TURN relaying (ignored with libjuice as ICE backend)
   - `bindAddress` (optional): if non-NULL, bind only to the given local address (ignored with libnice as ICE backend)
   - `bindAddress` (optional): if non-NULL, bind only to the given local address (ignored with libnice as ICE backend)
   - `certificateType` (optional): certificate type, either `RTC_CERTIFICATE_ECDSA` or `RTC_CERTIFICATE_RSA` (0 or `RTC_CERTIFICATE_DEFAULT` if default)
   - `certificateType` (optional): certificate type, either `RTC_CERTIFICATE_ECDSA` or `RTC_CERTIFICATE_RSA` (0 or `RTC_CERTIFICATE_DEFAULT` if default)
   - `iceTransportPolicy` (optional): ICE transport policy, if set to `RTC_TRANSPORT_POLICY_RELAY`, the PeerConnection will emit only relayed candidates (0 or `RTC_TRANSPORT_POLICY_ALL` if default)
   - `iceTransportPolicy` (optional): ICE transport policy, if set to `RTC_TRANSPORT_POLICY_RELAY`, the PeerConnection will emit only relayed candidates (0 or `RTC_TRANSPORT_POLICY_ALL` if default)
@@ -112,7 +114,9 @@ Return value: the identifier of the new Peer Connection or a negative error code
 
 
 The Peer Connection must be deleted with `rtcDeletePeerConnection`.
 The Peer Connection must be deleted with `rtcDeletePeerConnection`.
 
 
-The format of each entry in `iceServers` must match the format `[("stun"|"turn"|"turns") ":"][login ":" password "@"]hostname[":" port]["?transport=" ("udp"|"tcp"|"tls")]`. The default scheme is STUN, the default port is 3478 (5349 over TLS), and the default transport is UDP.  For instance, a STUN server URI could be `mystunserver.org`, and a TURN server URI could be `turn:myuser:[email protected]`. Note transports TCP and TLS are only available for a TURN server with libnice as ICE backend and govern only the TURN control connection, meaning relaying is always performed over UDP.
+Each entry in `iceServers` must match the format `[("stun"|"turn"|"turns") (":"|"://")][username ":" password "@"]hostname[":" port]["?transport=" ("udp"|"tcp"|"tls")]`. The default scheme is STUN, the default port is 3478 (5349 over TLS), and the default transport is UDP.  For instance, a STUN server URI could be `mystunserver.org`, and a TURN server URI could be `turn:myuser:[email protected]`. Note transports TCP and TLS are only available for a TURN server with libnice as ICE backend and govern only the TURN control connection, meaning relaying is always performed over UDP.
+
+The `proxyServer` URI, if present, must match the format `[("http"|"socks5") (":"|"://")][username ":" password "@"]hostname["    :" port]`. The default scheme is HTTP, and the default port is 3128 for HTTP or 1080 for SOCKS5.
 
 
 #### rtcDeletePeerConnection
 #### rtcDeletePeerConnection
 
 
@@ -760,6 +764,8 @@ int rtcCreateWebSocketEx(const char *url, const rtcWsConfiguration *config)
 
 
 typedef struct {
 typedef struct {
 	bool disableTlsVerification;    // if true, disable TLS certificate verification
 	bool disableTlsVerification;    // if true, disable TLS certificate verification
+	const char **protocols;
+	int protocolsCount;
 } rtcWsConfiguration;
 } rtcWsConfiguration;
 ```
 ```
 
 
@@ -770,6 +776,9 @@ Arguments:
 - `url`: a null-terminated string representing the fully-qualified URL to open.
 - `url`: a null-terminated string representing the fully-qualified URL to open.
 - `config`: a structure with the following parameters:
 - `config`: a structure with the following parameters:
   - `bool disableTlsVerification`: if true, don't verify the TLS certificate, else try to verify it if possible
   - `bool disableTlsVerification`: if true, don't verify the TLS certificate, else try to verify it if possible
+  - `protocols` (optional): an array of pointers on null-terminated protocol names (NULL if unused)
+  - `protocolsCount` (optional): number of URLs in the array pointed by `protocols` (0 if unused)
+
 
 
 Return value: the identifier of the new WebSocket or a negative error code
 Return value: the identifier of the new WebSocket or a negative error code
 
 

+ 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 {

+ 4 - 0
include/rtc/rtc.h

@@ -152,6 +152,7 @@ RTC_EXPORT void *rtcGetUserPointer(int i);
 typedef struct {
 typedef struct {
 	const char **iceServers;
 	const char **iceServers;
 	int iceServersCount;
 	int iceServersCount;
+	const char *proxyServer; // libnice only
 	const char *bindAddress; // libjuice only, NULL means any
 	const char *bindAddress; // libjuice only, NULL means any
 	rtcCertificateType certificateType;
 	rtcCertificateType certificateType;
 	rtcTransportPolicy iceTransportPolicy;
 	rtcTransportPolicy iceTransportPolicy;
@@ -364,6 +365,9 @@ int rtcSetSsrcForType(const char *mediaType, const char *sdp, char *buffer, cons
 
 
 typedef struct {
 typedef struct {
 	bool disableTlsVerification; // if true, don't verify the TLS certificate
 	bool disableTlsVerification; // if true, don't verify the TLS certificate
+	const char *proxyServer;     // unsupported for now
+	const char **protocols;
+	int protocolsCount;
 } rtcWsConfiguration;
 } rtcWsConfiguration;
 
 
 RTC_EXPORT int rtcCreateWebSocket(const char *url); // returns ws id
 RTC_EXPORT int rtcCreateWebSocket(const char *url); // returns ws id

+ 2 - 0
include/rtc/websocket.hpp

@@ -23,6 +23,7 @@
 
 
 #include "channel.hpp"
 #include "channel.hpp"
 #include "common.hpp"
 #include "common.hpp"
+#include "configuration.hpp"
 
 
 namespace rtc {
 namespace rtc {
 
 
@@ -43,6 +44,7 @@ public:
 
 
 	struct Configuration {
 	struct Configuration {
 		bool disableTlsVerification = false; // if true, don't verify the TLS certificate
 		bool disableTlsVerification = false; // if true, don't verify the TLS certificate
+		optional<ProxyServer> proxyServer;   // unsupported for now
 		std::vector<string> protocols;
 		std::vector<string> protocols;
 	};
 	};
 
 

+ 12 - 2
pages/content/pages/reference.md

@@ -80,6 +80,7 @@ int rtcCreatePeerConnection(const rtcConfiguration *config)
 typedef struct {
 typedef struct {
 	const char **iceServers;
 	const char **iceServers;
 	int iceServersCount;
 	int iceServersCount;
+	const char *proxyServer;
 	const char *bindAddress;
 	const char *bindAddress;
 	rtcCertificateType certificateType;
 	rtcCertificateType certificateType;
 	rtcTransportPolicy iceTransportPolicy;
 	rtcTransportPolicy iceTransportPolicy;
@@ -98,8 +99,9 @@ Creates a Peer Connection.
 Arguments:
 Arguments:
 
 
 - `config`: the configuration structure, containing:
 - `config`: the configuration structure, containing:
-  - `iceServers` (optional): an array of pointers on null-terminated ice server URIs (NULL if unused)
+  - `iceServers` (optional): an array of pointers on null-terminated ICE server URIs (NULL if unused)
   - `iceServersCount` (optional): number of URLs in the array pointed by `iceServers` (0 if unused)
   - `iceServersCount` (optional): number of URLs in the array pointed by `iceServers` (0 if unused)
+  - `proxyServer` (optional): if non-NULL, specifies the proxy server URI to use for TURN relaying (ignored with libjuice as ICE backend)
   - `bindAddress` (optional): if non-NULL, bind only to the given local address (ignored with libnice as ICE backend)
   - `bindAddress` (optional): if non-NULL, bind only to the given local address (ignored with libnice as ICE backend)
   - `certificateType` (optional): certificate type, either `RTC_CERTIFICATE_ECDSA` or `RTC_CERTIFICATE_RSA` (0 or `RTC_CERTIFICATE_DEFAULT` if default)
   - `certificateType` (optional): certificate type, either `RTC_CERTIFICATE_ECDSA` or `RTC_CERTIFICATE_RSA` (0 or `RTC_CERTIFICATE_DEFAULT` if default)
   - `iceTransportPolicy` (optional): ICE transport policy, if set to `RTC_TRANSPORT_POLICY_RELAY`, the PeerConnection will emit only relayed candidates (0 or `RTC_TRANSPORT_POLICY_ALL` if default)
   - `iceTransportPolicy` (optional): ICE transport policy, if set to `RTC_TRANSPORT_POLICY_RELAY`, the PeerConnection will emit only relayed candidates (0 or `RTC_TRANSPORT_POLICY_ALL` if default)
@@ -115,7 +117,10 @@ Return value: the identifier of the new Peer Connection or a negative error code
 
 
 The Peer Connection must be deleted with `rtcDeletePeerConnection`.
 The Peer Connection must be deleted with `rtcDeletePeerConnection`.
 
 
-The format of each entry in `iceServers` must match the format `[("stun"|"turn"|"turns") ":"][login ":" password "@"]hostname[":" port]["?transport=" ("udp"|"tcp"|"tls")]`. The default scheme is STUN, the default port is 3478 (5349 over TLS), and the default transport is UDP.  For instance, a STUN server URI could be `mystunserver.org`, and a TURN server URI could be `turn:myuser:[email protected]`. Note transports TCP and TLS are only available for a TURN server with libnice as ICE backend and govern only the TURN control connection, meaning relaying is always performed over UDP.
+Each entry in `iceServers` must match the format `[("stun"|"turn"|"turns") (":"|"://")][username ":" password "@"]hostname[":" port]["?transport=" ("udp"|"tcp"|"tls")]`. The default scheme is STUN, the default port is 3478 (5349 over TLS), and the default transport is UDP.  For instance, a STUN server URI could be `mystunserver.org`, and a TURN server URI could be `turn:myuser:[email protected]`. Note transports TCP and TLS are only available for a TURN server with libnice as ICE backend and govern only the TURN control connection, meaning relaying is always performed over UDP.
+
+The `proxyServer` URI, if present, must match the format `[("http"|"socks5") (":"|"://")][username ":" password "@"]hostname["    :" port]`. The default scheme is HTTP, and the default port is 3128 for HTTP or 1080 for SOCKS5.
+
 
 
 #### rtcDeletePeerConnection
 #### rtcDeletePeerConnection
 
 
@@ -763,6 +768,8 @@ int rtcCreateWebSocketEx(const char *url, const rtcWsConfiguration *config)
 
 
 typedef struct {
 typedef struct {
 	bool disableTlsVerification;    // if true, disable TLS certificate verification
 	bool disableTlsVerification;    // if true, disable TLS certificate verification
+	const char **protocols;
+	int protocolsCount;
 } rtcWsConfiguration;
 } rtcWsConfiguration;
 ```
 ```
 
 
@@ -773,6 +780,9 @@ Arguments:
 - `url`: a null-terminated string representing the fully-qualified URL to open.
 - `url`: a null-terminated string representing the fully-qualified URL to open.
 - `config`: a structure with the following parameters:
 - `config`: a structure with the following parameters:
   - `bool disableTlsVerification`: if true, don't verify the TLS certificate, else try to verify it if possible
   - `bool disableTlsVerification`: if true, don't verify the TLS certificate, else try to verify it if possible
+  - `protocols` (optional): an array of pointers on null-terminated protocol names (NULL if unused)
+  - `protocolsCount` (optional): number of URLs in the array pointed by `protocols` (0 if unused)
+
 
 
 Return value: the identifier of the new WebSocket or a negative error code
 Return value: the identifier of the new WebSocket or a negative error code
 
 

+ 41 - 31
src/capi.cpp

@@ -354,6 +354,9 @@ int rtcCreatePeerConnection(const rtcConfiguration *config) {
 		for (int i = 0; i < config->iceServersCount; ++i)
 		for (int i = 0; i < config->iceServersCount; ++i)
 			c.iceServers.emplace_back(string(config->iceServers[i]));
 			c.iceServers.emplace_back(string(config->iceServers[i]));
 
 
+		if (config->proxyServer)
+			c.proxyServer.emplace(config->proxyServer);
+
 		if (config->bindAddress)
 		if (config->bindAddress)
 			c.bindAddress = string(config->bindAddress);
 			c.bindAddress = string(config->bindAddress);
 
 
@@ -769,37 +772,37 @@ int rtcReceiveMessage(int id, char *buffer, int *size) {
 			return RTC_ERR_NOT_AVAIL;
 			return RTC_ERR_NOT_AVAIL;
 
 
 		return std::visit( //
 		return std::visit( //
-		overloaded{
-			[&](binary b) {
-				int ret = copyAndReturn(std::move(b), buffer, *size);
-				if (ret >= 0) {
-					*size = ret;
-					if (buffer) {
-						channel->receive(); // discard
-					}
-					
-					return RTC_ERR_SUCCESS;
-				} else {
-					*size = int(b.size());
-					return ret;
-				}
-			},
-			[&](string s) {
-				int ret = copyAndReturn(std::move(s), buffer, *size);
-				if (ret >= 0) {
-					*size = -ret;
-					if (buffer) {
-						channel->receive(); // discard
-					}
-					
-					return RTC_ERR_SUCCESS;
-				} else {
-					*size = -int(s.size() + 1);
-					return ret;
-				}
-			},
-		},
-		*message);
+		    overloaded{
+		        [&](binary b) {
+			        int ret = copyAndReturn(std::move(b), buffer, *size);
+			        if (ret >= 0) {
+				        *size = ret;
+				        if (buffer) {
+					        channel->receive(); // discard
+				        }
+
+				        return RTC_ERR_SUCCESS;
+			        } else {
+				        *size = int(b.size());
+				        return ret;
+			        }
+		        },
+		        [&](string s) {
+			        int ret = copyAndReturn(std::move(s), buffer, *size);
+			        if (ret >= 0) {
+				        *size = -ret;
+				        if (buffer) {
+					        channel->receive(); // discard
+				        }
+
+				        return RTC_ERR_SUCCESS;
+			        } else {
+				        *size = -int(s.size() + 1);
+				        return ret;
+			        }
+		        },
+		    },
+		    *message);
 	});
 	});
 }
 }
 
 
@@ -1281,6 +1284,13 @@ int rtcCreateWebSocketEx(const char *url, const rtcWsConfiguration *config) {
 
 
 		WebSocket::Configuration c;
 		WebSocket::Configuration c;
 		c.disableTlsVerification = config->disableTlsVerification;
 		c.disableTlsVerification = config->disableTlsVerification;
+
+		if (config->proxyServer)
+			c.proxyServer.emplace(config->proxyServer);
+
+		for (int i = 0; i < config->protocolsCount; ++i)
+			c.protocols.emplace_back(string(config->protocols[i]));
+
 		auto webSocket = std::make_shared<WebSocket>(std::move(c));
 		auto webSocket = std::make_shared<WebSocket>(std::move(c));
 		webSocket->open(url);
 		webSocket->open(url);
 		return emplaceWebSocket(webSocket);
 		return emplaceWebSocket(webSocket);

+ 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) {

+ 10 - 0
src/impl/websocket.cpp

@@ -57,6 +57,10 @@ void WebSocket::open(const string &url) {
 	if (state != State::Closed)
 	if (state != State::Closed)
 		throw std::logic_error("WebSocket must be closed before opening");
 		throw std::logic_error("WebSocket must be closed before opening");
 
 
+	if (config.proxyServer) {
+		PLOG_WARNING << "Proxy server support for WebSocket is not implemented";
+	}
+
 	// 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}((([^:@]*)(:([^@]*))?)@)?(([^:/?#]*)(:([^/?#]*))?))?([^?#]*)(\?([^#]*))?(#(.*))?)";
@@ -76,6 +80,12 @@ void WebSocket::open(const string &url) {
 
 
 	mIsSecure = (scheme != "ws");
 	mIsSecure = (scheme != "ws");
 
 
+	string username = m[6];
+	string password = m[8];
+	if (!username.empty() || !password.empty()) {
+		PLOG_WARNING << "HTTP authentication support for WebSocket is not implemented";
+	}
+
 	string host;
 	string host;
 	string hostname = m[10];
 	string hostname = m[10];
 	string service = m[12];
 	string service = m[12];

+ 1 - 4
src/websocket.cpp

@@ -53,10 +53,7 @@ bool WebSocket::isClosed() const { return impl()->state.load() == State::Closed;
 
 
 size_t WebSocket::maxMessageSize() const { return DEFAULT_MAX_MESSAGE_SIZE; }
 size_t WebSocket::maxMessageSize() const { return DEFAULT_MAX_MESSAGE_SIZE; }
 
 
-void WebSocket::open(const string &url) {
-	PLOG_VERBOSE << "Opening WebSocket to URL: " << url;
-	impl()->open(url);
-}
+void WebSocket::open(const string &url) { impl()->open(url); }
 
 
 void WebSocket::close() { impl()->close(); }
 void WebSocket::close() { impl()->close(); }