2

我使用 PJSIP/PJNATH 端口打孔库(用于 STUN/TURN/ICE)并希望在打孔端口上创建我自己的基于 UDP 的传输。

找不到保存NAT 映射内部端口的数据结构。我需要内部端口(两侧)的原因是将 UDP 套接字绑定到内部端口(而不是操作系统选择随机端口)。请看图。

我意识到icedemo示例应用程序能够在互联网上来回发送数据(在打孔之后);所以它必须绑定到内部 UDP 端口。我只需要知道哪个数据结构包含内部端口。 NAT映射的内部端口

文件中的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:Port 随时可用。

背景
PJNATH 库实现了基于标准的 STUN/TURN/ICE 协议,并在从双方交换主机/服务器自反/中继 IP:Port 后使用 ICE-UDP 检查对 UDP 端口进行穿孔。

4

2 回答 2

1

它看起来像是结构bound_addr中的 pj_sockaddr pj_stun_sock_cfg

根据文档,“如果端口设置为零,则套接字将绑定在任何端口(由操作系统选择)。”

于 2014-07-15T04:48:42.320 回答
0

我发现,在 ICE“完整”上,lcand数据结构的一部分确实保存了本地绑定的 IP 和端口。在大多数消费者 NAT 中,这是令人费解的相同端口号(确实如此)。在尝试了一些企业级 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;
    }
}
于 2014-07-25T00:43:33.927 回答