开源库 pjnath的改造,异步接口 修改 为 同步 超时返回 接口

提供一种思路,将pjnath非阻塞函数改造为阻塞函数,同样适用其他非阻塞接口。

背景:

开源库有时候提供的接口并不人性化,例如:

pjnath里的pj_ice_strans_create用来创建一个ice,它调用了sess_init_update(用来检测ice的候选candidate的)。

我们知道本机客户端获取的自身candidate一般需要两个以上才能够有效的实现对remote实现negotiationnegotiation成功之后才能进行NAT的数据发送。

其中一个是自己局域网地址信息,另一个是外网的地址信息,前者是实现局域网连接,后者是实现外网NAT的关键。

针对turn类型的server时:

pj_ice_strans_create-》pj_ice_strans_init_ice-》pj_ice_strans_enum_cands

按上面的顺序调用时,获得的candidate只有一个本机地址信息,没有外网地址信息,无法用于NAT negotiatioin。

而我在跟踪时发现是函数是异步所导致的。stun_on_status和turn_on_state是回调函数,收到socket信息后被才调用,因此存在网络延时,不能及时将外网的candidate更新。

stun_on_status中运行到/* Otherwise update the address */ 后面的cand->status = PJ_SUCCESS;对candidate进行了修改。

turn_on_state 的old_state new_state状态改变时会对candidate进行修改,阻塞可选在函数末尾。

我们要做的就是阻塞这两个位置进行标志变量修改为1,意思是外网candidate已更新。

static void turn_on_state(pj_turn_sock *turn_sock, pj_turn_state_t old_state,  pj_turn_state_t new_state)

ice_strans.c的前边加入

static char stun_cand_update;
static char turn_cand_update;
#define BLOCK_MS_COUNT 8000//stun协议默认7秒

在stun_on_status中

      /* Otherwise update the address */
      pj_sockaddr_cp(&cand->addr, &info.mapped_addr);
      cand->status = PJ_SUCCESS;

后面加入

	stun_cand_update = 1;


于是在此turn_on_state函数最后加入

if (old_state == PJ_TURN_STATE_ALLOCATING && new_state == PJ_TURN_STATE_READY)
{
	turn_cand_update = 1;
}
	

在pj_ice_strans_create末尾部分改为

stun_cand_update = 0;
	turn_cand_update = 0;
	while(stun_cand_update == 0 && turn_cand_update == 0 && ++cnt < BLOCK_MS_COUNT)
	{
		pj_thread_sleep(1);
	}
    /* Check if all candidates are ready (this may call callback) */
    sess_init_update(ice_st);

    pj_log_pop_indent();
	if(stun_cand_update == 1 || turn_cand_update == 1)
	{
		stun_cand_update = stun_cand_update ? 0 : 1;
		turn_cand_update = turn_cand_update ? 0 : 1;
		return PJ_SUCCESS;
	}
	return PJ_FALSE;

 

原理很简单,就是用循环sleep1毫秒来阻塞sess_init_update的执行,使它在turn_on_state获取外网candidate之后才执行。

同步阻塞超时模式的好处:1、不会永远阻塞 2、满足条件时会立即返回,不影响效率。只提供一种思路,要注意多线程等情况,具体情况要具体改动。

你可能感兴趣的:(开源库 pjnath的改造,异步接口 修改 为 同步 超时返回 接口)