朋友委托分析一下,吾让其抓了两个报文(成功与失败)对比。
第一步,看报文的差异
经过分析,流程上无明显差异,最大的不同是失败报文中没有Data Indication报文。
学习一下TURN
要想由TURN服务器转发,必须终端发Data Indication报文,服务器回一个Send Indication报文。这样看来,就是终端的报文有问题。
分析Data Indication
失败报文多了32字节。其中有内容:
IM-client/OMA1.0 doubango/v2.0.0
看看代码,哪里使用这个字串。
搜索字串 $ grep -rn "OMA1.0" tinynet_config.h:124:#define TNET_SOFTWARE "IM-client/OMA1.0 doubango/v2.0.0" $ grep -rn TNET_SOFTWARE stun/tnet_stun_types.h:78:# define kStunSoftware TNET_SOFTWARE $ grep -rn kStunSoftware # stun stun/tnet_stun_binding.c:74: TNET_STUN_PKT_ATTR_ADD_SOFTWARE_ZT(kStunSoftware), # turn turn/tnet_turn_session.c:635: TNET_STUN_PKT_ATTR_ADD_SOFTWARE_ZT(kStunSoftware), // recommended for Alloc and Refresh turn/tnet_turn_session.c:1396: TNET_STUN_PKT_ATTR_ADD_SOFTWARE_ZT(kStunSoftware), // recommended for Alloc and Refresh # ice ice/tnet_ice_candidate.c:576: TNET_STUN_PKT_ATTR_ADD_SOFTWARE_ZT(kStunSoftware), ice/tnet_ice_pair.c:287: TNET_STUN_PKT_ATTR_ADD_SOFTWARE_ZT(kStunSoftware), ice/tnet_ice_pair.c:421: TNET_STUN_PKT_ATTR_ADD_SOFTWARE_ZT(kStunSoftware), ice/tnet_ice_ctx.c:620:
已知服务器是TURN,自然就知道应该是tnet_net_session.c
再搜索ndication
$ grep -rn ndication # send indication tnet_turn_session.c:1054: /*** Send indication ***/ tnet_turn_session.c:1056: if ((ret = tnet_stun_pkt_create_empty(tnet_stun_pkt_type_send_indication, &pc_peer->p_pkt_sendind))) { tnet_turn_session.c:1057: TSK_DEBUG_ERROR("Failed to create TURN SendIndication request"); tnet_turn.c:211://tnet_stun_pkt_req_t* tnet_turn_create_request_sendindication(const tnet_nat_context_t* context, tnet_turn_allocation_t* allocation, va_list *app) tnet_turn.c:213:// tnet_stun_pkt_req_t* request = tnet_turn_create_request(context, allocation, stun_send_indication); tnet_turn.c:221:// draft-ietf-behave-turn-16 - 10.1. Forming a Send Indication tnet_turn.c:223:// When forming a Send indication, the client MUST include a XOR-PEER- tnet_turn.c:497:// if(indication) tnet_turn.c:499:// if((ret = tnet_turn_send_request(nat_context, (tnet_turn_allocation_t*)channel_bind->allocation, tnet_turn_create_request_sendindication, channel_bind->xpeer, data, size))) tnet_turn.c:501:// TSK_DEBUG_ERROR("TURN channel send indication failed with error code:%d.", ret); # data indication tnet_turn_session.c:1963: case tnet_stun_pkt_type_data_indication: { tnet_turn_session.c:2220: if (p_pkt->e_type == tnet_stun_pkt_type_data_indication) { tnet_turn.h:168://int tnet_turn_channel_senddata(const struct struct tnet_nat_ctx_s* nat_context, const tnet_turn_channel_binding_t * channel_bind, const void* data, tsk_size_t size, int indication); tnet_turn.c:488://int tnet_turn_channel_senddata(const struct struct tnet_nat_ctx_s* nat_context, const tnet_turn_channel_binding_t * channel_bind, const void* data, tsk_size_t size, int indication) # ignore tnet_turn_session.c:157: tsk_timer_id_t u_timer_id_refresh; // To refresh Alloc (Send Refresh Indication) tnet_turn_session.c:1375: // create RefreshIndication Request tnet_turn_session.c:1379: TSK_DEBUG_ERROR("Failed to create TURN RefreshIndication request"); tnet_turn_session.c:1949: case tnet_stun_pkt_type_connectionattempt_indication: { tnet_turn_session.c:1990: if (pc_pkt->e_type != tnet_stun_pkt_type_connectionattempt_indication && !TNET_STUN_PKT_RESP_IS_SUCCESS(pc_pkt)) {