Browse Source

Added TURN server IPv6 support

Paul-Louis Ageneau 5 years ago
parent
commit
e11de119be
3 changed files with 77 additions and 47 deletions
  1. 9 5
      include/rtc/configuration.hpp
  2. 27 13
      src/configuration.cpp
  3. 41 29
      src/icetransport.cpp

+ 9 - 5
include/rtc/configuration.hpp

@@ -28,14 +28,18 @@ namespace rtc {
 
 struct IceServer {
 	enum class Type { Stun, Turn };
-
-	// Don' Change It! It should be same order as enum NiceRelayType
 	enum class RelayType { TurnUdp, TurnTcp, TurnTls };
 
 	IceServer(const string &host_);
-	IceServer(const string &hostname_, uint16_t port_);
-	IceServer(const string &hostname_, const string &service_);
-	IceServer(const string &hostname_, const string &service_, string username_, string password_,
+
+	// STUN
+	IceServer(string hostname_, uint16_t port_);
+	IceServer(string hostname_, string service_);
+
+	// TURN
+	IceServer(string hostname_, uint16_t port, string username_, string password_,
+	          RelayType relayType_);
+	IceServer(string hostname_, string service_, string username_, string password_,
 	          RelayType relayType_);
 
 	string hostname;

+ 27 - 13
src/configuration.cpp

@@ -20,27 +20,41 @@
 
 namespace rtc {
 
-using std::to_string;
-
 IceServer::IceServer(const string &host) : type(Type::Stun) {
-	if (size_t pos = host.rfind(':'); pos != string::npos) {
-		hostname = host.substr(0, pos);
-		service = host.substr(pos + 1);
+	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 &hostname_, uint16_t port_)
-    : IceServer(hostname_, to_string(port_)) {}
+IceServer::IceServer(string hostname_, uint16_t port_)
+    : IceServer(std::move(hostname_), std::to_string(port_)) {}
+
+IceServer::IceServer(string hostname_, string service_)
+    : hostname(std::move(hostname_)), service(std::move(service_)), type(Type::Stun) {}
 
-IceServer::IceServer(const string &hostname_, const string &service_)
-    : hostname(hostname_), service(service_), type(Type::Stun) {}
+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_) {}
 
-IceServer::IceServer(const string &hostname_, const string &service_, string username_,
-                     string password_, RelayType relayType_)
-    : hostname(hostname_), service(service_), type(Type::Turn), username(username_),
-      password(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_) {}
 
 } // namespace rtc

+ 41 - 29
src/icetransport.cpp

@@ -17,6 +17,7 @@
  */
 
 #include "icetransport.hpp"
+#include "configuration.hpp"
 
 #include <netdb.h>
 #include <netinet/in.h>
@@ -74,15 +75,17 @@ IceTransport::IceTransport(const Configuration &config, Description::Role role,
 	g_object_set(G_OBJECT(mNiceAgent.get()), "upnp", FALSE, nullptr);
 	g_object_set(G_OBJECT(mNiceAgent.get()), "upnp-timeout", 200, nullptr);
 
+	// Randomize order
 	std::vector<IceServer> servers = config.iceServers;
 	unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
 	std::shuffle(servers.begin(), servers.end(), std::default_random_engine(seed));
 
+	// Add one STUN server
 	bool success = false;
 	for (auto &server : servers) {
 		if (server.hostname.empty())
 			continue;
-		if (server.type == IceServer::Type::Turn)
+		if (server.type != IceServer::Type::Stun)
 			continue;
 		if (server.service.empty())
 			server.service = "3478"; // STUN UDP port
@@ -101,7 +104,6 @@ IceTransport::IceTransport(const Configuration &config, Description::Role role,
 				char nodebuffer[MAX_NUMERICNODE_LEN];
 				char servbuffer[MAX_NUMERICSERV_LEN];
 				if (getnameinfo(p->ai_addr, p->ai_addrlen, nodebuffer, MAX_NUMERICNODE_LEN,
-
 				                servbuffer, MAX_NUMERICNODE_LEN,
 				                NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
 					g_object_set(G_OBJECT(mNiceAgent.get()), "stun-server", nodebuffer, nullptr);
@@ -118,35 +120,17 @@ IceTransport::IceTransport(const Configuration &config, Description::Role role,
 			break;
 	}
 
-	g_signal_connect(G_OBJECT(mNiceAgent.get()), "component-state-changed",
-	                 G_CALLBACK(StateChangeCallback), this);
-	g_signal_connect(G_OBJECT(mNiceAgent.get()), "new-candidate-full",
-	                 G_CALLBACK(CandidateCallback), this);
-	g_signal_connect(G_OBJECT(mNiceAgent.get()), "candidate-gathering-done",
-	                 G_CALLBACK(GatheringDoneCallback), this);
-
-	mStreamId = nice_agent_add_stream(mNiceAgent.get(), 1);
-	if (!mStreamId)
-		throw std::runtime_error("Failed to add a stream");
-
-	nice_agent_set_stream_name(mNiceAgent.get(), mStreamId, "application");
-	nice_agent_set_port_range(mNiceAgent.get(), mStreamId, 1, config.portRangeBegin,
-	                          config.portRangeEnd);
-
-	nice_agent_attach_recv(mNiceAgent.get(), mStreamId, 1, g_main_loop_get_context(mMainLoop.get()),
-	                       RecvCallback, this);
-
-	// Add TURN Servers
+	// Add TURN servers
 	for (auto &server : servers) {
 		if (server.hostname.empty())
 			continue;
-		if (server.type == IceServer::Type::Stun)
+		if (server.type != IceServer::Type::Turn)
 			continue;
 		if (server.service.empty())
-			server.service = "3478"; // TURN UDP port
+			server.service = "3478"; // TURN port
 
 		struct addrinfo hints = {};
-		hints.ai_family = AF_INET; // IPv4
+		hints.ai_family = AF_UNSPEC;
 		hints.ai_socktype =
 		    server.relayType == IceServer::RelayType::TurnUdp ? SOCK_DGRAM : SOCK_STREAM;
 		hints.ai_protocol =
@@ -157,24 +141,52 @@ IceTransport::IceTransport(const Configuration &config, Description::Role role,
 			continue;
 
 		for (auto p = result; p; p = p->ai_next) {
-			if (p->ai_family == AF_INET) {
+			if (p->ai_family == AF_INET || p->ai_family == AF_INET6) {
 				char nodebuffer[MAX_NUMERICNODE_LEN];
 				char servbuffer[MAX_NUMERICSERV_LEN];
 				if (getnameinfo(p->ai_addr, p->ai_addrlen, nodebuffer, MAX_NUMERICNODE_LEN,
-
 				                servbuffer, MAX_NUMERICNODE_LEN,
 				                NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
+
+					NiceRelayType niceRelayType;
+					switch (server.relayType) {
+					case IceServer::RelayType::TurnTcp:
+						niceRelayType = NICE_RELAY_TYPE_TURN_TCP;
+						break;
+					case IceServer::RelayType::TurnTls:
+						niceRelayType = NICE_RELAY_TYPE_TURN_TLS;
+						break;
+					default:
+						niceRelayType = NICE_RELAY_TYPE_TURN_UDP;
+						break;
+					}
 					nice_agent_set_relay_info(mNiceAgent.get(), mStreamId, 1, nodebuffer,
 					                          std::stoul(servbuffer), server.username.c_str(),
-					                          server.password.c_str(),
-					                          static_cast<NiceRelayType>(server.relayType));
-					break;
+					                          server.password.c_str(), niceRelayType);
 				}
 			}
 		}
 
 		freeaddrinfo(result);
 	}
+
+	g_signal_connect(G_OBJECT(mNiceAgent.get()), "component-state-changed",
+	                 G_CALLBACK(StateChangeCallback), this);
+	g_signal_connect(G_OBJECT(mNiceAgent.get()), "new-candidate-full",
+	                 G_CALLBACK(CandidateCallback), this);
+	g_signal_connect(G_OBJECT(mNiceAgent.get()), "candidate-gathering-done",
+	                 G_CALLBACK(GatheringDoneCallback), this);
+
+	mStreamId = nice_agent_add_stream(mNiceAgent.get(), 1);
+	if (!mStreamId)
+		throw std::runtime_error("Failed to add a stream");
+
+	nice_agent_set_stream_name(mNiceAgent.get(), mStreamId, "application");
+	nice_agent_set_port_range(mNiceAgent.get(), mStreamId, 1, config.portRangeBegin,
+	                          config.portRangeEnd);
+
+	nice_agent_attach_recv(mNiceAgent.get(), mStreamId, 1, g_main_loop_get_context(mMainLoop.get()),
+	                       RecvCallback, this);
 }
 
 IceTransport::~IceTransport() { stop(); }