Browse Source

Merge pull request #452 from paullouisageneau/transport-policy

Add ICE transport policy option
Paul-Louis Ageneau 4 years ago
parent
commit
fd299a11b0
6 changed files with 49 additions and 22 deletions
  1. 2 0
      DOC.md
  2. 6 0
      include/rtc/configuration.hpp
  3. 6 0
      include/rtc/rtc.h
  4. 1 0
      src/capi.cpp
  5. 9 2
      src/impl/peerconnection.cpp
  6. 25 20
      test/turn_connectivity.cpp

+ 2 - 0
DOC.md

@@ -72,6 +72,7 @@ typedef struct {
 	const char **iceServers;
 	const char **iceServers;
 	int iceServersCount;
 	int iceServersCount;
 	rtcCertificateType certificateType;
 	rtcCertificateType certificateType;
+	rtcTransportPolicy iceTransportPolicy;
 	bool enableIceTcp;
 	bool enableIceTcp;
 	bool disableAutoNegotiation;
 	bool disableAutoNegotiation;
 	uint16_t portRangeBegin;
 	uint16_t portRangeBegin;
@@ -88,6 +89,7 @@ Arguments:
   - `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)
   - `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)
   - `enableIceTcp`: if true, generate TCP candidates for ICE (ignored with libjuice as ICE backend)
   - `enableIceTcp`: if true, generate TCP candidates for ICE (ignored with libjuice as ICE backend)
   - `disableAutoNegotiation`: if true, the user is responsible for calling `rtcSetLocalDescription` after creating a Data Channel and after setting the remote description
   - `disableAutoNegotiation`: if true, the user is responsible for calling `rtcSetLocalDescription` after creating a Data Channel and after setting the remote description
   - `portRangeBegin` (optional): first port (included) of the allowed local port range (0 if unused)
   - `portRangeBegin` (optional): first port (included) of the allowed local port range (0 if unused)

+ 6 - 0
include/rtc/configuration.hpp

@@ -70,6 +70,11 @@ enum class CertificateType {
 	Rsa = RTC_CERTIFICATE_RSA
 	Rsa = RTC_CERTIFICATE_RSA
 };
 };
 
 
+enum class TransportPolicy {
+	All = RTC_TRANSPORT_POLICY_ALL,
+	Relay = RTC_TRANSPORT_POLICY_RELAY
+};
+
 struct RTC_CPP_EXPORT Configuration {
 struct RTC_CPP_EXPORT Configuration {
 	// ICE settings
 	// ICE settings
 	std::vector<IceServer> iceServers;
 	std::vector<IceServer> iceServers;
@@ -78,6 +83,7 @@ struct RTC_CPP_EXPORT Configuration {
 
 
 	// Options
 	// Options
 	CertificateType certificateType = CertificateType::Default;
 	CertificateType certificateType = CertificateType::Default;
+	TransportPolicy iceTransportPolicy = TransportPolicy::All;
 	bool enableIceTcp = false;
 	bool enableIceTcp = false;
 	bool disableAutoNegotiation = false;
 	bool disableAutoNegotiation = false;
 
 

+ 6 - 0
include/rtc/rtc.h

@@ -113,6 +113,11 @@ typedef enum {
 	RTC_DIRECTION_INACTIVE = 4
 	RTC_DIRECTION_INACTIVE = 4
 } rtcDirection;
 } rtcDirection;
 
 
+typedef enum {
+	RTC_TRANSPORT_POLICY_ALL = 0,
+	RTC_TRANSPORT_POLICY_RELAY = 1
+} rtcTransportPolicy;
+
 #define RTC_ERR_SUCCESS 0
 #define RTC_ERR_SUCCESS 0
 #define RTC_ERR_INVALID -1   // invalid argument
 #define RTC_ERR_INVALID -1   // invalid argument
 #define RTC_ERR_FAILURE -2   // runtime error
 #define RTC_ERR_FAILURE -2   // runtime error
@@ -152,6 +157,7 @@ typedef struct {
 	int iceServersCount;
 	int iceServersCount;
 	const char *bindAddress; // libjuice only, NULL means any
 	const char *bindAddress; // libjuice only, NULL means any
 	rtcCertificateType certificateType;
 	rtcCertificateType certificateType;
+	rtcTransportPolicy iceTransportPolicy;
 	bool enableIceTcp;
 	bool enableIceTcp;
 	bool disableAutoNegotiation;
 	bool disableAutoNegotiation;
 	uint16_t portRangeBegin; // 0 means automatic
 	uint16_t portRangeBegin; // 0 means automatic

+ 1 - 0
src/capi.cpp

@@ -343,6 +343,7 @@ int rtcCreatePeerConnection(const rtcConfiguration *config) {
 		}
 		}
 
 
 		c.certificateType = static_cast<CertificateType>(config->certificateType);
 		c.certificateType = static_cast<CertificateType>(config->certificateType);
+		c.iceTransportPolicy = static_cast<TransportPolicy>(config->iceTransportPolicy);
 		c.enableIceTcp = config->enableIceTcp;
 		c.enableIceTcp = config->enableIceTcp;
 		c.disableAutoNegotiation = config->disableAutoNegotiation;
 		c.disableAutoNegotiation = config->disableAutoNegotiation;
 
 

+ 9 - 2
src/impl/peerconnection.cpp

@@ -872,6 +872,8 @@ void PeerConnection::processLocalDescription(Description description) {
 	// Set local fingerprint (wait for certificate if necessary)
 	// Set local fingerprint (wait for certificate if necessary)
 	description.setFingerprint(mCertificate.get()->fingerprint());
 	description.setFingerprint(mCertificate.get()->fingerprint());
 
 
+	PLOG_VERBOSE << "Issuing local description: " << description;
+
 	{
 	{
 		// Set as local description
 		// Set as local description
 		std::lock_guard lock(mLocalDescriptionMutex);
 		std::lock_guard lock(mLocalDescriptionMutex);
@@ -886,7 +888,6 @@ void PeerConnection::processLocalDescription(Description description) {
 		mLocalDescription->addCandidates(std::move(existingCandidates));
 		mLocalDescription->addCandidates(std::move(existingCandidates));
 	}
 	}
 
 
-	PLOG_VERBOSE << "Issuing local description: " << description;
 	mProcessor->enqueue(localDescriptionCallback.wrap(), std::move(description));
 	mProcessor->enqueue(localDescriptionCallback.wrap(), std::move(description));
 
 
 	// Reciprocated tracks might need to be open
 	// Reciprocated tracks might need to be open
@@ -900,10 +901,16 @@ void PeerConnection::processLocalCandidate(Candidate candidate) {
 	if (!mLocalDescription)
 	if (!mLocalDescription)
 		throw std::logic_error("Got a local candidate without local description");
 		throw std::logic_error("Got a local candidate without local description");
 
 
+	if(config.iceTransportPolicy == TransportPolicy::Relay && candidate.type() != Candidate::Type::Relayed) {
+		PLOG_VERBOSE << "Not issuing local candidate because of transport policy: " << candidate;
+		return;
+	}
+
+	PLOG_VERBOSE << "Issuing local candidate: " << candidate;
+
 	candidate.resolve(Candidate::ResolveMode::Simple);
 	candidate.resolve(Candidate::ResolveMode::Simple);
 	mLocalDescription->addCandidate(candidate);
 	mLocalDescription->addCandidate(candidate);
 
 
-	PLOG_VERBOSE << "Issuing local candidate: " << candidate;
 	mProcessor->enqueue(localCandidateCallback.wrap(), std::move(candidate));
 	mProcessor->enqueue(localCandidateCallback.wrap(), std::move(candidate));
 }
 }
 
 

+ 25 - 20
test/turn_connectivity.cpp

@@ -33,6 +33,8 @@ void test_turn_connectivity() {
 	InitLogger(LogLevel::Debug);
 	InitLogger(LogLevel::Debug);
 
 
 	Configuration config1;
 	Configuration config1;
+	config1.iceTransportPolicy = TransportPolicy::Relay; // force relay
+
 	// STUN server example (not necessary, just here for testing)
 	// STUN server example (not necessary, just here for testing)
 	// Please do not use outside of libdatachannel tests
 	// Please do not use outside of libdatachannel tests
 	config1.iceServers.emplace_back("stun:stun.ageneau.net:3478");
 	config1.iceServers.emplace_back("stun:stun.ageneau.net:3478");
@@ -43,6 +45,8 @@ void test_turn_connectivity() {
 	PeerConnection pc1(config1);
 	PeerConnection pc1(config1);
 
 
 	Configuration config2;
 	Configuration config2;
+	config2.iceTransportPolicy = TransportPolicy::Relay; // force relay
+
 	// STUN server example (not necessary, just here for testing)
 	// STUN server example (not necessary, just here for testing)
 	// Please do not use outside of libdatachannel tests
 	// Please do not use outside of libdatachannel tests
 	config1.iceServers.emplace_back("stun:stun.ageneau.net:3478");
 	config1.iceServers.emplace_back("stun:stun.ageneau.net:3478");
@@ -58,12 +62,8 @@ void test_turn_connectivity() {
 	});
 	});
 
 
 	pc1.onLocalCandidate([&pc2](Candidate candidate) {
 	pc1.onLocalCandidate([&pc2](Candidate candidate) {
-		// For this test, filter out non-relay candidates to force TURN
-		string str(candidate);
-		if (str.find("relay") != string::npos) {
-			cout << "Candidate 1: " << str << endl;
-			pc2.addRemoteCandidate(str);
-		}
+		cout << "Candidate 1: " << candidate << endl;
+		pc2.addRemoteCandidate(string(candidate));
 	});
 	});
 
 
 	pc1.onStateChange([](PeerConnection::State state) { cout << "State 1: " << state << endl; });
 	pc1.onStateChange([](PeerConnection::State state) { cout << "State 1: " << state << endl; });
@@ -82,12 +82,8 @@ void test_turn_connectivity() {
 	});
 	});
 
 
 	pc2.onLocalCandidate([&pc1](Candidate candidate) {
 	pc2.onLocalCandidate([&pc1](Candidate candidate) {
-		// For this test, filter out non-relay candidates to force TURN
-		string str(candidate);
-		if (str.find("relay") != string::npos) {
-			cout << "Candidate 1: " << str << endl;
-			pc1.addRemoteCandidate(str);
-		}
+		cout << "Candidate 2: " << candidate << endl;
+		pc1.addRemoteCandidate(string(candidate));
 	});
 	});
 
 
 	pc2.onStateChange([](PeerConnection::State state) { cout << "State 2: " << state << endl; });
 	pc2.onStateChange([](PeerConnection::State state) { cout << "State 2: " << state << endl; });
@@ -160,14 +156,23 @@ void test_turn_connectivity() {
 		cout << "Remote address 2: " << *addr << endl;
 		cout << "Remote address 2: " << *addr << endl;
 
 
 	Candidate local, remote;
 	Candidate local, remote;
-	if (pc1.getSelectedCandidatePair(&local, &remote)) {
-		cout << "Local candidate 1:  " << local << endl;
-		cout << "Remote candidate 1: " << remote << endl;
-	}
-	if (pc2.getSelectedCandidatePair(&local, &remote)) {
-		cout << "Local candidate 2:  " << local << endl;
-		cout << "Remote candidate 2: " << remote << endl;
-	}
+	if (!pc1.getSelectedCandidatePair(&local, &remote))
+		throw runtime_error("getSelectedCabndidatePair failed");
+
+	cout << "Local candidate 1:  " << local << endl;
+	cout << "Remote candidate 1: " << remote << endl;
+
+	if(local.type() != Candidate::Type::Relayed || remote.type() != Candidate::Type::Relayed)
+		throw runtime_error("Connection is not relayed as expected");
+
+	if (!pc2.getSelectedCandidatePair(&local, &remote))
+		throw runtime_error("getSelectedCabndidatePair failed");
+
+	cout << "Local candidate 2:  " << local << endl;
+	cout << "Remote candidate 2: " << remote << endl;
+
+	if(local.type() != Candidate::Type::Relayed || remote.type() != Candidate::Type::Relayed)
+		throw runtime_error("Connection is not relayed as expected");
 
 
 	// Try to open a second data channel with another label
 	// Try to open a second data channel with another label
 	shared_ptr<DataChannel> second2;
 	shared_ptr<DataChannel> second2;