Skip to content

Commit 0fc5365

Browse files
committed
Add disableAutoGathering
When enabled PeerConnection::gatherLocalCandidates must be called explicitly to start the gathering process. This new API enabled ICE Servers to be used with WHIP/WHEP. For WHIP/WHEP the ICE Servers is only provided after the client makes the initial offer.
1 parent fbd8f23 commit 0fc5365

7 files changed

+112
-78
lines changed

.gitmodules

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
shallow = true
99
[submodule "deps/libjuice"]
1010
path = deps/libjuice
11-
url = https://github.com/paullouisageneau/libjuice.git
11+
url = https://github.com/sean-der/libjuice.git
1212
[submodule "deps/json"]
1313
path = deps/json
1414
url = https://github.com/nlohmann/json.git

include/rtc/configuration.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ struct RTC_CPP_EXPORT Configuration {
7575
bool enableIceTcp = false; // libnice only
7676
bool enableIceUdpMux = false; // libjuice only
7777
bool disableAutoNegotiation = false;
78+
bool disableAutoGathering = false;
7879
bool forceMediaTransport = false;
7980

8081
// Port range

include/rtc/peerconnection.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ class RTC_CPP_EXPORT PeerConnection final : CheshireCat<impl::PeerConnection> {
9393
void setLocalDescription(Description::Type type = Description::Type::Unspec);
9494
void setRemoteDescription(Description description);
9595
void addRemoteCandidate(Candidate candidate);
96+
void gatherLocalCandidates(std::vector<IceServer> additionalIceServers = {});
9697

9798
void setMediaHandler(shared_ptr<MediaHandler> handler);
9899
shared_ptr<MediaHandler> getMediaHandler();

src/impl/icetransport.cpp

+94-74
Original file line numberDiff line numberDiff line change
@@ -117,27 +117,6 @@ IceTransport::IceTransport(const Configuration &config, candidate_callback candi
117117
}
118118
}
119119

120-
juice_turn_server_t turn_servers[MAX_TURN_SERVERS_COUNT];
121-
std::memset(turn_servers, 0, sizeof(turn_servers));
122-
123-
// Add TURN servers
124-
int k = 0;
125-
for (auto &server : servers) {
126-
if (!server.hostname.empty() && server.type == IceServer::Type::Turn) {
127-
if (server.port == 0)
128-
server.port = 3478; // TURN UDP port
129-
PLOG_INFO << "Using TURN server \"" << server.hostname << ":" << server.port << "\"";
130-
turn_servers[k].host = server.hostname.c_str();
131-
turn_servers[k].username = server.username.c_str();
132-
turn_servers[k].password = server.password.c_str();
133-
turn_servers[k].port = server.port;
134-
if (++k >= MAX_TURN_SERVERS_COUNT)
135-
break;
136-
}
137-
}
138-
jconfig.turn_servers = k > 0 ? turn_servers : nullptr;
139-
jconfig.turn_servers_count = k;
140-
141120
// Bind address
142121
if (config.bindAddress) {
143122
jconfig.bind_address = config.bindAddress->c_str();
@@ -154,6 +133,32 @@ IceTransport::IceTransport(const Configuration &config, candidate_callback candi
154133
mAgent = decltype(mAgent)(juice_create(&jconfig), juice_destroy);
155134
if (!mAgent)
156135
throw std::runtime_error("Failed to create the ICE agent");
136+
137+
// Add TURN servers
138+
int k = 0;
139+
for (auto &server : servers) {
140+
addTURNServer(server);
141+
if (++k >= MAX_TURN_SERVERS_COUNT) {
142+
break;
143+
}
144+
}
145+
}
146+
147+
void IceTransport::addTURNServer(IceServer server) {
148+
if (!server.hostname.empty() && server.type == IceServer::Type::Turn) {
149+
if (server.port == 0)
150+
server.port = 3478; // TURN UDP port
151+
PLOG_INFO << "Using TURN server \"" << server.hostname << ":" << server.port << "\"";
152+
juice_turn_server_t turn_server = {};
153+
turn_server.host = server.hostname.c_str();
154+
turn_server.username = server.username.c_str();
155+
turn_server.password = server.password.c_str();
156+
turn_server.port = server.port;
157+
158+
if (juice_add_turn_server(mAgent.get(), &turn_server) != 0) {
159+
throw std::runtime_error("Failed to add TURN server");
160+
}
161+
}
157162
}
158163

159164
IceTransport::~IceTransport() {
@@ -210,9 +215,17 @@ bool IceTransport::addRemoteCandidate(const Candidate &candidate) {
210215
return juice_add_remote_candidate(mAgent.get(), string(candidate).c_str()) >= 0;
211216
}
212217

213-
void IceTransport::gatherLocalCandidates(string mid) {
218+
void IceTransport::gatherLocalCandidates(string mid, std::vector<IceServer> additionalIceServers) {
214219
mMid = std::move(mid);
215220

221+
int k = 0;
222+
for (auto &server : additionalIceServers) {
223+
addTURNServer(server);
224+
if (++k >= MAX_TURN_SERVERS_COUNT) {
225+
break;
226+
}
227+
}
228+
216229
// Change state now as candidates calls can be synchronous
217230
changeGatheringState(GatheringState::InProgress);
218231

@@ -535,57 +548,7 @@ IceTransport::IceTransport(const Configuration &config, candidate_callback candi
535548

536549
// Add TURN servers
537550
for (auto &server : servers) {
538-
if (server.hostname.empty())
539-
continue;
540-
if (server.type != IceServer::Type::Turn)
541-
continue;
542-
if (server.port == 0)
543-
server.port = server.relayType == IceServer::RelayType::TurnTls ? 5349 : 3478;
544-
545-
struct addrinfo hints = {};
546-
hints.ai_family = AF_UNSPEC;
547-
hints.ai_socktype =
548-
server.relayType == IceServer::RelayType::TurnUdp ? SOCK_DGRAM : SOCK_STREAM;
549-
hints.ai_protocol =
550-
server.relayType == IceServer::RelayType::TurnUdp ? IPPROTO_UDP : IPPROTO_TCP;
551-
hints.ai_flags = AI_ADDRCONFIG;
552-
struct addrinfo *result = nullptr;
553-
if (getaddrinfo(server.hostname.c_str(), std::to_string(server.port).c_str(), &hints,
554-
&result) != 0) {
555-
PLOG_WARNING << "Unable to resolve TURN server address: " << server.hostname << ':'
556-
<< server.port;
557-
continue;
558-
}
559-
560-
for (auto p = result; p; p = p->ai_next) {
561-
if (p->ai_family == AF_INET || p->ai_family == AF_INET6) {
562-
char nodebuffer[MAX_NUMERICNODE_LEN];
563-
char servbuffer[MAX_NUMERICSERV_LEN];
564-
if (getnameinfo(p->ai_addr, p->ai_addrlen, nodebuffer, MAX_NUMERICNODE_LEN,
565-
servbuffer, MAX_NUMERICSERV_LEN,
566-
NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
567-
PLOG_INFO << "Using TURN server \"" << server.hostname << ":" << server.port
568-
<< "\"";
569-
NiceRelayType niceRelayType;
570-
switch (server.relayType) {
571-
case IceServer::RelayType::TurnTcp:
572-
niceRelayType = NICE_RELAY_TYPE_TURN_TCP;
573-
break;
574-
case IceServer::RelayType::TurnTls:
575-
niceRelayType = NICE_RELAY_TYPE_TURN_TLS;
576-
break;
577-
default:
578-
niceRelayType = NICE_RELAY_TYPE_TURN_UDP;
579-
break;
580-
}
581-
nice_agent_set_relay_info(mNiceAgent.get(), mStreamId, 1, nodebuffer,
582-
std::stoul(servbuffer), server.username.c_str(),
583-
server.password.c_str(), niceRelayType);
584-
}
585-
}
586-
}
587-
588-
freeaddrinfo(result);
551+
addTURNServer(server);
589552
}
590553

591554
g_signal_connect(G_OBJECT(mNiceAgent.get()), "component-state-changed",
@@ -603,6 +566,59 @@ IceTransport::IceTransport(const Configuration &config, candidate_callback candi
603566
RecvCallback, this);
604567
}
605568

569+
void IceTransport::addTURNServer(IceServer iceServer) {
570+
if (server.hostname.empty())
571+
continue;
572+
if (server.type != IceServer::Type::Turn)
573+
continue;
574+
if (server.port == 0)
575+
server.port = server.relayType == IceServer::RelayType::TurnTls ? 5349 : 3478;
576+
577+
struct addrinfo hints = {};
578+
hints.ai_family = AF_UNSPEC;
579+
hints.ai_socktype =
580+
server.relayType == IceServer::RelayType::TurnUdp ? SOCK_DGRAM : SOCK_STREAM;
581+
hints.ai_protocol =
582+
server.relayType == IceServer::RelayType::TurnUdp ? IPPROTO_UDP : IPPROTO_TCP;
583+
hints.ai_flags = AI_ADDRCONFIG;
584+
struct addrinfo *result = nullptr;
585+
if (getaddrinfo(server.hostname.c_str(), std::to_string(server.port).c_str(), &hints,
586+
&result) != 0) {
587+
PLOG_WARNING << "Unable to resolve TURN server address: " << server.hostname << ':'
588+
<< server.port;
589+
continue;
590+
}
591+
592+
for (auto p = result; p; p = p->ai_next) {
593+
if (p->ai_family == AF_INET || p->ai_family == AF_INET6) {
594+
char nodebuffer[MAX_NUMERICNODE_LEN];
595+
char servbuffer[MAX_NUMERICSERV_LEN];
596+
if (getnameinfo(p->ai_addr, p->ai_addrlen, nodebuffer, MAX_NUMERICNODE_LEN, servbuffer,
597+
MAX_NUMERICSERV_LEN, NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
598+
PLOG_INFO << "Using TURN server \"" << server.hostname << ":" << server.port
599+
<< "\"";
600+
NiceRelayType niceRelayType;
601+
switch (server.relayType) {
602+
case IceServer::RelayType::TurnTcp:
603+
niceRelayType = NICE_RELAY_TYPE_TURN_TCP;
604+
break;
605+
case IceServer::RelayType::TurnTls:
606+
niceRelayType = NICE_RELAY_TYPE_TURN_TLS;
607+
break;
608+
default:
609+
niceRelayType = NICE_RELAY_TYPE_TURN_UDP;
610+
break;
611+
}
612+
nice_agent_set_relay_info(mNiceAgent.get(), mStreamId, 1, nodebuffer,
613+
std::stoul(servbuffer), server.username.c_str(),
614+
server.password.c_str(), niceRelayType);
615+
}
616+
}
617+
}
618+
619+
freeaddrinfo(result);
620+
}
621+
606622
IceTransport::~IceTransport() {
607623
PLOG_DEBUG << "Destroying ICE transport";
608624
nice_agent_attach_recv(mNiceAgent.get(), mStreamId, 1, g_main_loop_get_context(MainLoop.get()),
@@ -684,9 +700,13 @@ bool IceTransport::addRemoteCandidate(const Candidate &candidate) {
684700
return ret > 0;
685701
}
686702

687-
void IceTransport::gatherLocalCandidates(string mid) {
703+
void IceTransport::gatherLocalCandidates(string mid, std::vector<IceServer> additionalIceServers) {
688704
mMid = std::move(mid);
689705

706+
for (auto &server : additionalIceServers) {
707+
addTURNServer(server);
708+
}
709+
690710
// Change state now as candidates calls can be synchronous
691711
changeGatheringState(GatheringState::InProgress);
692712

src/impl/icetransport.hpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ class IceTransport : public Transport {
5050
Description getLocalDescription(Description::Type type) const;
5151
void setRemoteDescription(const Description &description);
5252
bool addRemoteCandidate(const Candidate &candidate);
53-
void gatherLocalCandidates(string mid);
53+
void gatherLocalCandidates(string mid, std::vector<IceServer> additionalIceServers = {});
5454

5555
optional<string> getLocalAddress() const;
5656
optional<string> getRemoteAddress() const;
@@ -69,6 +69,8 @@ class IceTransport : public Transport {
6969
void processGatheringDone();
7070
void processTimeout();
7171

72+
void addTURNServer(IceServer iceServer);
73+
7274
Description::Role mRole;
7375
string mMid;
7476
std::chrono::milliseconds mTrickleTimeout;

src/peerconnection.cpp

+11-1
Original file line numberDiff line numberDiff line change
@@ -146,11 +146,21 @@ void PeerConnection::setLocalDescription(Description::Type type) {
146146
impl()->changeSignalingState(newSignalingState);
147147
signalingLock.unlock();
148148

149-
if (impl()->gatheringState == GatheringState::New) {
149+
if (impl()->gatheringState == GatheringState::New && !impl()->config.disableAutoGathering) {
150150
iceTransport->gatherLocalCandidates(impl()->localBundleMid());
151151
}
152152
}
153153

154+
void PeerConnection::gatherLocalCandidates(std::vector<IceServer> additionalIceServers) {
155+
auto iceTransport = impl()->initIceTransport();
156+
if (!iceTransport)
157+
return; // closed
158+
159+
if (impl()->gatheringState == GatheringState::New) {
160+
iceTransport->gatherLocalCandidates(impl()->localBundleMid(), additionalIceServers);
161+
}
162+
}
163+
154164
void PeerConnection::setRemoteDescription(Description description) {
155165
std::unique_lock signalingLock(impl()->signalingMutex);
156166
PLOG_VERBOSE << "Setting remote description: " << string(description);

0 commit comments

Comments
 (0)