Skip to content

Commit e3cfd0e

Browse files
authored
Add manual host candidates for ICE (#4618)
1 parent 86505a7 commit e3cfd0e

File tree

7 files changed

+136
-0
lines changed

7 files changed

+136
-0
lines changed

pjnath/include/pjnath/ice_strans.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,19 @@ typedef struct pj_ice_strans_stun_cfg
247247
*/
248248
unsigned max_host_cands;
249249

250+
/**
251+
* Number of manual host candidates. This must be equal or less than
252+
* \a max_host_cands.
253+
*/
254+
unsigned manual_host_cnt;
255+
256+
/**
257+
* Optional configuration to manually specify host candidates.
258+
* Each candidate will use the same port as the automatic/base host
259+
* candidate.
260+
*/
261+
pj_sockaddr manual_host[PJ_ICE_ST_MAX_CAND];
262+
250263
/**
251264
* Include loopback addresses in the host candidates.
252265
*

pjnath/src/pjnath/ice_strans.c

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,7 @@ static pj_status_t add_stun_and_host(pj_ice_strans *ice_st,
653653
pj_bool_t cand_duplicate = PJ_FALSE;
654654
char addrinfo[PJ_INET6_ADDRSTRLEN+10];
655655
const pj_sockaddr *addr = &stun_sock_info.aliases[i];
656+
pj_bool_t manual_host_added = PJ_FALSE;
656657

657658
if (max_cand_cnt==0) {
658659
PJ_LOG(4,(ice_st->obj_name, "Too many host candidates"));
@@ -686,6 +687,68 @@ static pj_status_t add_stun_and_host(pj_ice_strans *ice_st,
686687
continue;
687688
}
688689

690+
/* Add manual host candidates. */
691+
if (!manual_host_added && stun_cfg->manual_host_cnt) {
692+
manual_host_added = PJ_TRUE;
693+
694+
pj_assert(stun_cfg->manual_host_cnt < PJ_ARRAY_SIZE(
695+
stun_cfg->manual_host));
696+
for (j=0; j<stun_cfg->manual_host_cnt &&
697+
max_cand_cnt && cand_cnt < stun_cfg->max_host_cands;
698+
j++)
699+
{
700+
701+
/* Only add the same address family */
702+
if (stun_cfg->manual_host[j].addr.sa_family !=
703+
stun_cfg->af ||
704+
!pj_sockaddr_has_addr(&stun_cfg->manual_host[j]))
705+
{
706+
continue;
707+
}
708+
709+
cand = &comp->cand_list[comp->cand_cnt];
710+
711+
cand->type = PJ_ICE_CAND_TYPE_HOST;
712+
cand->status = PJ_SUCCESS;
713+
cand->local_pref = (pj_uint16_t)(HOST_PREF - cand_cnt);
714+
cand->transport_id = CREATE_TP_ID(TP_STUN, idx);
715+
cand->comp_id = (pj_uint8_t) comp->comp_id;
716+
pj_sockaddr_cp(&cand->addr, &stun_cfg->manual_host[j]);
717+
pj_sockaddr_set_port(&cand->addr,
718+
pj_sockaddr_get_port(addr));
719+
pj_sockaddr_cp(&cand->base_addr, addr);
720+
pj_bzero(&cand->rel_addr, sizeof(cand->rel_addr));
721+
722+
comp->cand_cnt+=1;
723+
cand_cnt++;
724+
max_cand_cnt--;
725+
pj_ice_calc_foundation(ice_st->pool, &cand->foundation,
726+
cand->type, &cand->base_addr);
727+
728+
/* Set default candidate with the preferred default
729+
* address family
730+
*/
731+
if (comp->ice_st->cfg.af != pj_AF_UNSPEC() &&
732+
cand->addr.addr.sa_family == comp->ice_st->cfg.af &&
733+
comp->cand_list[comp->default_cand].base_addr.addr.
734+
sa_family != ice_st->cfg.af)
735+
{
736+
comp->default_cand = (unsigned)
737+
(cand - comp->cand_list);
738+
}
739+
740+
PJ_LOG(4,(ice_st->obj_name,
741+
"Comp %d/%d: host candidate %s (tpid=%d) added",
742+
comp->comp_id, comp->cand_cnt-1,
743+
pj_sockaddr_print(&cand->addr, addrinfo,
744+
sizeof(addrinfo), 3),
745+
cand->transport_id));
746+
}
747+
748+
if (max_cand_cnt == 0 || cand_cnt >= stun_cfg->max_host_cands)
749+
break;
750+
}
751+
689752
cand = &comp->cand_list[comp->cand_cnt];
690753

691754
cand->type = PJ_ICE_CAND_TYPE_HOST;

pjsip/include/pjsua-lib/pjsua.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3911,6 +3911,19 @@ typedef struct pjsua_ice_config
39113911
*/
39123912
int ice_max_host_cands;
39133913

3914+
/**
3915+
* Number of manual host candidates. This must be equal or less than
3916+
* \a ice_max_host_cands.
3917+
*/
3918+
unsigned ice_manual_host_cnt;
3919+
3920+
/**
3921+
* Optional configuration to manually specify host candidates.
3922+
* Each candidate will use the same port as the automatic/base host
3923+
* candidate.
3924+
*/
3925+
pj_sockaddr ice_manual_host[PJ_ICE_ST_MAX_CAND];
3926+
39143927
/**
39153928
* ICE session options.
39163929
*/

pjsip/include/pjsua2/account.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,14 @@ struct AccountNatConfig : public PersistentObject
584584
*/
585585
int iceMaxHostCands;
586586

587+
/**
588+
* Optional configuration to manually specify host candidates.
589+
* Each candidate will use the same port as the automatic/base host
590+
* candidate. The number of entries in this array must be equal or less
591+
* than \a iceMaxHostCands.
592+
*/
593+
SocketAddressVector iceManualHost;
594+
587595
/**
588596
* Specify whether to use aggressive nomination.
589597
*

pjsip/include/pjsua2/types.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ typedef void *Token;
7171
*/
7272
typedef string SocketAddress;
7373

74+
/** Array of socket address */
75+
typedef StringVector SocketAddressVector;
76+
7477
/**
7578
* Transport ID is an integer.
7679
*/

pjsip/src/pjsua-lib/pjsua_media.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1267,6 +1267,13 @@ static pj_status_t create_ice_media_transport(
12671267

12681268
/* Configure max packet size */
12691269
ice_cfg.stun_tp[i].cfg.max_pkt_size = PJMEDIA_MAX_MRU;
1270+
1271+
/* Configure manual host candidates */
1272+
ice_cfg.stun_tp[i].manual_host_cnt =
1273+
acc_cfg->ice_cfg.ice_manual_host_cnt;
1274+
pj_memcpy(&ice_cfg.stun_tp[i].manual_host,
1275+
&acc_cfg->ice_cfg.ice_manual_host,
1276+
sizeof(ice_cfg.stun_tp[i].manual_host));
12701277
}
12711278
}
12721279

pjsip/src/pjsua2/account.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,7 @@ void AccountNatConfig::readObject(const ContainerNode &node)
497497
NODE_READ_UNSIGNED( this_node, udpKaIntervalSec);
498498
NODE_READ_STRING ( this_node, udpKaData);
499499
NODE_READ_INT ( this_node, contactUseSrcPort);
500+
NODE_READ_STRINGV ( this_node, iceManualHost);
500501
}
501502

502503
void AccountNatConfig::writeObject(ContainerNode &node) const
@@ -534,6 +535,7 @@ void AccountNatConfig::writeObject(ContainerNode &node) const
534535
NODE_WRITE_UNSIGNED( this_node, udpKaIntervalSec);
535536
NODE_WRITE_STRING ( this_node, udpKaData);
536537
NODE_WRITE_INT ( this_node, contactUseSrcPort);
538+
NODE_WRITE_STRINGV (this_node, iceManualHost);
537539
}
538540

539541
///////////////////////////////////////////////////////////////////////////////
@@ -758,6 +760,25 @@ void AccountConfig::toPj(pjsua_acc_config &ret) const
758760
ret.ice_cfg.enable_ice = natConfig.iceEnabled;
759761
ret.ice_cfg.ice_opt.trickle = natConfig.iceTrickle;
760762
ret.ice_cfg.ice_max_host_cands = natConfig.iceMaxHostCands;
763+
ret.ice_cfg.ice_manual_host_cnt = 0;
764+
if (natConfig.iceManualHost.size() >
765+
PJ_ARRAY_SIZE(ret.ice_cfg.ice_manual_host))
766+
{
767+
PJSUA2_RAISE_ERROR(PJ_ETOOMANY);
768+
}
769+
for (i=0; i<natConfig.iceManualHost.size(); ++i) {
770+
pj_str_t tmp = pj_str(const_cast<char*>
771+
(natConfig.iceManualHost[i].c_str()));
772+
pj_sockaddr* addr =
773+
&ret.ice_cfg.ice_manual_host[ret.ice_cfg.ice_manual_host_cnt];
774+
if (pj_sockaddr_set_str_addr(pj_AF_INET(), addr, &tmp)==PJ_SUCCESS ||
775+
pj_sockaddr_set_str_addr(pj_AF_INET6(), addr, &tmp)==PJ_SUCCESS)
776+
{
777+
ret.ice_cfg.ice_manual_host_cnt++;
778+
} else {
779+
PJSUA2_RAISE_ERROR(PJ_EINVAL);
780+
}
781+
}
761782
ret.ice_cfg.ice_opt.aggressive = natConfig.iceAggressiveNomination;
762783
ret.ice_cfg.ice_opt.nominated_check_delay =
763784
natConfig.iceNominatedCheckDelayMsec;
@@ -933,6 +954,14 @@ void AccountConfig::fromPj(const pjsua_acc_config &prm,
933954
natConfig.iceEnabled = PJ2BOOL(prm.ice_cfg.enable_ice);
934955
natConfig.iceTrickle = prm.ice_cfg.ice_opt.trickle;
935956
natConfig.iceMaxHostCands = prm.ice_cfg.ice_max_host_cands;
957+
natConfig.iceManualHost.clear();
958+
for (i=0; i<prm.ice_cfg.ice_manual_host_cnt; ++i) {
959+
char buf[PJ_INET6_ADDRSTRLEN];
960+
const pj_sockaddr *addr = &prm.ice_cfg.ice_manual_host[i];
961+
if (pj_sockaddr_print(addr, buf, sizeof(buf), 0) != NULL) {
962+
natConfig.iceManualHost.push_back(std::string(buf));
963+
}
964+
}
936965
natConfig.iceAggressiveNomination =
937966
PJ2BOOL(prm.ice_cfg.ice_opt.aggressive);
938967
natConfig.iceNominatedCheckDelayMsec =

0 commit comments

Comments
 (0)