ソースを参照

TURN Server Support

Murat Dogan 5 年 前
コミット
5fc6a1c8ad
4 ファイル変更83 行追加20 行削除
  1. 10 0
      include/rtc/configuration.hpp
  2. 11 4
      src/configuration.cpp
  3. 42 3
      src/icetransport.cpp
  4. 20 13
      test/main.cpp

+ 10 - 0
include/rtc/configuration.hpp

@@ -27,12 +27,22 @@
 namespace rtc {
 
 struct IceServer {
+	enum class Type { STUN, TURN };
+
+	enum class RelayType { RELAY_TYPE_TURN_UDP, RELAY_TYPE_TURN_TCP, RELAY_TYPE_TURN_TLS };
+
 	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_, Type type_, string username_,
+	          string password_, RelayType relayType_);
 
 	string hostname;
 	string service;
+	Type type;
+	string username;
+	string password;
+	RelayType relayType;
 };
 
 struct Configuration {

+ 11 - 4
src/configuration.cpp

@@ -22,8 +22,8 @@ namespace rtc {
 
 using std::to_string;
 
-IceServer::IceServer(const string &host) {
-	if(size_t pos = host.rfind(':'); pos != string::npos) {
+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);
 	} else {
@@ -32,8 +32,15 @@ IceServer::IceServer(const string &host) {
 	}
 }
 
-IceServer::IceServer(const string &hostname_, uint16_t port_) : IceServer(hostname_, to_string(port_)) {}
+IceServer::IceServer(const string &hostname_, uint16_t port_)
+    : IceServer(hostname_, to_string(port_)) {}
 
-IceServer::IceServer(const string &hostname_, const string &service_) : hostname(hostname_), service(service_) {}
+IceServer::IceServer(const string &hostname_, const string &service_)
+    : hostname(hostname_), service(service_), type(Type::STUN) {}
+
+IceServer::IceServer(const string &hostname_, const string &service_, Type type_, string username_,
+                     string password_, RelayType relayType_)
+    : hostname(hostname_), service(service_), type(type_), username(username_), password(password_),
+      relayType(relayType_) {}
 
 } // namespace rtc

+ 42 - 3
src/icetransport.cpp

@@ -34,8 +34,7 @@ using std::shared_ptr;
 using std::weak_ptr;
 
 IceTransport::IceTransport(const Configuration &config, Description::Role role,
-                           candidate_callback candidateCallback,
-                           state_callback stateChangeCallback,
+                           candidate_callback candidateCallback, state_callback stateChangeCallback,
                            gathering_state_callback gatheringStateChangeCallback)
     : mRole(role), mMid("0"), mState(State::Disconnected), mGatheringState(GatheringState::New),
       mNiceAgent(nullptr, nullptr), mMainLoop(nullptr, nullptr),
@@ -77,6 +76,8 @@ IceTransport::IceTransport(const Configuration &config, Description::Role role,
 	for (auto &server : servers) {
 		if (server.hostname.empty())
 			continue;
+		if (server.type == IceServer::Type::TURN)
+			continue;
 		if (server.service.empty())
 			server.service = "3478"; // STUN UDP port
 
@@ -128,6 +129,44 @@ IceTransport::IceTransport(const Configuration &config, Description::Role role,
 
 	nice_agent_attach_recv(mNiceAgent.get(), mStreamId, 1, g_main_loop_get_context(mMainLoop.get()),
 	                       RecvCallback, this);
+
+	// Add TURN Servers
+	for (auto &server : servers) {
+		if (server.hostname.empty())
+			continue;
+		if (server.type == IceServer::Type::STUN)
+			continue;
+		if (server.service.empty())
+			server.service = "3478"; // TURN UDP port
+
+		struct addrinfo hints = {};
+		hints.ai_family = AF_INET; // IPv4
+		hints.ai_socktype = SOCK_DGRAM;
+		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)
+			continue;
+
+		for (auto p = result; p; p = p->ai_next) {
+			if (p->ai_family == AF_INET) {
+				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) {
+					nice_agent_set_relay_info(mNiceAgent.get(), mStreamId, 1, nodebuffer,
+					                          std::stoul(servbuffer), server.username.c_str(),
+					                          server.password.c_str(),
+					                          (NiceRelayType)server.relayType);
+					break;
+				}
+			}
+		}
+
+		freeaddrinfo(result);
+	}
 }
 
 IceTransport::~IceTransport() {
@@ -277,7 +316,7 @@ void IceTransport::GatheringDoneCallback(NiceAgent *agent, guint streamId, gpoin
 }
 
 void IceTransport::StateChangeCallback(NiceAgent *agent, guint streamId, guint componentId,
-                                        guint state, gpointer userData) {
+                                       guint state, gpointer userData) {
 	auto iceTransport = static_cast<rtc::IceTransport *>(userData);
 	try {
 		iceTransport->processStateChange(state);

+ 20 - 13
test/main.cpp

@@ -26,26 +26,31 @@
 using namespace rtc;
 using namespace std;
 
-template <class T>
-weak_ptr<T> make_weak_ptr(shared_ptr<T> ptr) { return ptr; }
+template <class T> weak_ptr<T> make_weak_ptr(shared_ptr<T> ptr) { return ptr; }
 
 int main(int argc, char **argv) {
 	rtc::Configuration config;
 	// config.iceServers.emplace_back("stun.l.google.com:19302");
 
+	// IceServer turnServer("TURN_SERVER_URL", "PORT_NO", IceServer::Type::TURN, "USERNAME",
+	//                      "PASSWORD", IceServer::RelayType::RELAY_TYPE_TURN_TLS);
+	// config.iceServers.push_back(turnServer);
+
 	auto pc1 = std::make_shared<PeerConnection>(config);
 	auto pc2 = std::make_shared<PeerConnection>(config);
 
 	pc1->onLocalDescription([wpc2 = make_weak_ptr(pc2)](const Description &sdp) {
-    auto pc2 = wpc2.lock();
-    if (!pc2) return;
+		auto pc2 = wpc2.lock();
+		if (!pc2)
+			return;
 		cout << "Description 1: " << sdp << endl;
 		pc2->setRemoteDescription(sdp);
 	});
 
 	pc1->onLocalCandidate([wpc2 = make_weak_ptr(pc2)](const Candidate &candidate) {
-    auto pc2 = wpc2.lock();
-    if (!pc2) return;
+		auto pc2 = wpc2.lock();
+		if (!pc2)
+			return;
 		cout << "Candidate 1: " << candidate << endl;
 		pc2->addRemoteCandidate(candidate);
 	});
@@ -56,15 +61,17 @@ int main(int argc, char **argv) {
 	});
 
 	pc2->onLocalDescription([wpc1 = make_weak_ptr(pc1)](const Description &sdp) {
-    auto pc1 = wpc1.lock();
-    if (!pc1) return;
+		auto pc1 = wpc1.lock();
+		if (!pc1)
+			return;
 		cout << "Description 2: " << sdp << endl;
 		pc1->setRemoteDescription(sdp);
 	});
 
 	pc2->onLocalCandidate([wpc1 = make_weak_ptr(pc1)](const Candidate &candidate) {
-    auto pc1 = wpc1.lock();
-    if (!pc1) return;
+		auto pc1 = wpc1.lock();
+		if (!pc1)
+			return;
 		cout << "Candidate 2: " << candidate << endl;
 		pc1->addRemoteCandidate(candidate);
 	});
@@ -88,8 +95,9 @@ int main(int argc, char **argv) {
 
 	auto dc1 = pc1->createDataChannel("test");
 	dc1->onOpen([wdc1 = make_weak_ptr(dc1)]() {
-    auto dc1 = wdc1.lock();
-    if (!dc1) return;
+		auto dc1 = wdc1.lock();
+		if (!dc1)
+			return;
 		cout << "DataChannel open: " << dc1->label() << endl;
 		dc1->send("Hello from 1");
 	});
@@ -112,4 +120,3 @@ int main(int argc, char **argv) {
 		return 1;
 	}
 }
-