我使用PJSIP / PJNATH端口打孔库(用于STUN / TURN / ICE),并希望通过打孔端口创建自己的基于UDP的传输。
我无法查找包含NAT映射的内部端口的数据结构。我需要内部端口(两侧)的原因是将UDP套接字绑定到内部端口(而不是操作系统选择随机端口)。请参见图表。
我意识到icedemo
示例应用程序能够在互联网上来回发送数据(在打完端口之后);所以它必须绑定到内部UDP端口。我只需要知道哪个数据结构保存内部端口。
pj_ice_sess_send_data
文件中的ice_session.c
函数看起来像是一个很有希望转储变量的地方。但是没有一个包含NAT映射的内部端口。
//my attempt did *not* work
pj_ice_sess_cand *cand;
cand = comp->valid_check->lcand;
char addrinfo[80];
pj_sockaddr_print(&cand->base_addr, addrinfo, sizeof(addrinfo), 3);
printf("***Local address %s\n", addrinfo);
仅供参考,公共IP:端口随时可用。
背景
PJNATH库实现了基于标准的STUN / TURN / ICE协议,并在交换了主机/服务器反身/中继IP:端口之后,使用ICE-UDP检查来打击UDP端口。
答案 0 :(得分:1)
它看起来像是bound_addr
结构中的pj_stun_sock_cfg
pj_sockaddr。
根据the docs,"如果端口设置为零,则套接字将绑定在任何端口(由OS选择)。"
答案 1 :(得分:0)
我发现,在ICE"完成",数据结构的lcand
部分确实保存了本地绑定的IP和端口。在大多数消费者NAT中,这是一个令人费解的端口号(确实如此)。在尝试了几个enterprice NAT之后,我发现映射的两端的端口号都不同。
你可以用这样的东西打印出来......
static void cb_on_ice_complete(pj_ice_strans *ice_st,
pj_ice_strans_op op,
pj_status_t status)
{
const char *opname =
(op==PJ_ICE_STRANS_OP_INIT? "initialization" :
(op==PJ_ICE_STRANS_OP_NEGOTIATION ? "negotiation" : "unknown_op"));
if (status == PJ_SUCCESS)
{
PJ_LOG(3,(THIS_FILE, "ICE %s successful", opname));
if ( op == PJ_ICE_STRANS_OP_NEGOTIATION )
{
const pj_ice_sess_check *check;
check = pj_ice_strans_get_valid_pair(icedemo.icest, 1);
if ((check != NULL) && (check->nominated == PJ_TRUE)) { //local (l) and remote(r) candidate
pj_sockaddr_print(&check->lcand->addr, icedemo.local_ip_port,
sizeof(icedemo.local_ip_port), 3);
pj_sockaddr_print(&check->rcand->addr, icedemo.remote_ip_port,
sizeof(icedemo.remote_ip_port), 3);
pj_sockaddr_print(&check->lcand->base_addr, icedemo.local_bound_ip_port, sizeof(icedemo.local_bound_ip_port), 3);
}
else
{
PJ_LOG(3,(THIS_FILE, "err: unable to get valid pair for ice1 "
"component %d", icedemo.icest, 1));
}
}
}
else
{
char errmsg[PJ_ERR_MSG_SIZE];
pj_strerror(status, errmsg, sizeof(errmsg));
PJ_LOG(1,(THIS_FILE, "ICE %s failed: %s", opname, errmsg));
pj_ice_strans_destroy(ice_st);
icedemo.icest = NULL;
}
}