场景
调用eXosip库跟国标下级进行交互的时候,抓包发现,INVITE请求,前面是添加了jaK.字符串,导致对方解析异常,目前暂时不清楚对方是如何解析的。通过追踪源码,发现是底层做了一个UDP心跳保活的机制,实际上没有这个必要,注释屏蔽掉
jaK.INVITE sip:13010600002000110002@11.11.52.129:5061 SIP/2.0
Via: SIP/2.0/UDP 11.11.54.174:5060;rport;branch=z9hG4bK1153031278
From: <sip:13010600002000110003@11.11.54.174:5060>;tag=364366442
To: <sip:13010600002000110002@11.11.52.129:5061>
Call-ID: 328977807
CSeq: 20 INVITE
Contact: <sip:13010600002000110003@11.11.54.174:5060>
Content-Type: application/sdp
Max-Forwards: 70
User-Agent: eXosip/4.1.0
Subject: 13010462001310110752:0-1,44010000008100000089:1
Supported: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO
Content-Length: 244
v=0
o=13010600002000110003 0 0 IN IP4 11.11.54.174
s=Play
c=IN IP4 11.11.54.174
t=0 0
m=video 36332 TCP/RTP/AVP 96 97 98
a=recvonly
a=setup:active
a=connection:new
a=rtpmap:96 PS/90000
a=rtpmap:97 MPEG4/90000
a=rtpmap:98 H264/90000
SIP/2.0 100 Trying
Via: SIP/2.0/UDP 11.11.54.174:5060;branch=z9hG4bK1153031278;rport=5060
Call-ID: 328977807
From: <sip:13010600002000110003@11.11.54.174:5060>;tag=364366442
To: <sip:13010600002000110002@11.11.52.129:5061>
CSeq: 20 INVITE
Content-Length: 0
SIP/2.0 400 Bad Request
Via: SIP/2.0/UDP 11.11.54.174:5060;branch=z9hG4bK1153031278
Call-ID: 328977807
From: <sip:13010600002000110003@11.11.54.174:5060>;tag=364366442
To: <sip:13010600002000110002@11.11.52.129:5061>;tag=b6f9298b91c94fcda50b7d93d90c7eac-1666774978452
CSeq: 20 INVITE
Max-Forwards: 70
Contact: <sip:13010600002000110002@11.11.52.129:5061>
Content-Length: 0
代码剖析
libeXosip2-4.1.0
src/eXtl_udp.c
static int
udp_tl_keepalive (struct eXosip_t *excontext)
{
struct eXtludp *reserved = (struct eXtludp *) excontext->eXtludp_reserved;
char buf[4] = "jaK";
eXosip_reg_t *jr;
if (reserved == NULL) {
OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "wrong state: create transport layer first\n"));
return OSIP_WRONG_STATE;
}
if (excontext->keep_alive <= 0) {
return 0;
}
if (reserved->udp_socket <= 0)
return OSIP_UNDEFINED_ERROR;
for (jr = excontext->j_reg; jr != NULL; jr = jr->next) {
if (jr->len > 0) {
if (sendto (reserved->udp_socket, (const void *) buf, 4, 0, (struct sockaddr *) &(jr->addr), jr->len) > 0) {
OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL, "eXosip: Keep Alive sent on UDP!\n"));
}
}
}
return OSIP_SUCCESS;
}
libexosip2-5.1.0
src/eXtl_udp.c通过发送/r/n/r/n实现UDP的心跳保活
char ka_crlf[5];
snprintf (excontext->ka_crlf, sizeof (excontext->ka_crlf), "\r\n\r\n");
static int
udp_tl_keepalive (struct eXosip_t *excontext)
{
struct eXtludp *reserved = (struct eXtludp *) excontext->eXtludp_reserved;
eXosip_reg_t *jr;
if (reserved == NULL) {
OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "wrong state: create transport layer first\n"));
return OSIP_WRONG_STATE;
}
if (excontext->ka_interval <= 0) {
return 0;
}
if (reserved->udp_socket < 0)
return OSIP_UNDEFINED_ERROR;
for (jr = excontext->j_reg; jr != NULL; jr = jr->next) {
if (jr->len > 0) {
if (sendto (reserved->udp_socket, (const void *) excontext->ka_crlf, 4, 0, (struct sockaddr *) &(jr->addr), jr->len) > 0) {
OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL, "eXosip: Keep Alive sent on UDP!\n"));
}
}
}
return OSIP_SUCCESS;
}
static int
udp_tl_keepalive (struct eXosip_t *excontext)
{
struct eXtludp *reserved = (struct eXtludp *) excontext->eXtludp_reserved;
eXosip_reg_t *jr;
if (reserved == NULL) {
OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "wrong state: create transport layer first\n"));
return OSIP_WRONG_STATE;
}
if (excontext->ka_interval <= 0) {
return 0;
}
if (reserved->udp_socket < 0)
return OSIP_UNDEFINED_ERROR;
for (jr = excontext->j_reg; jr != NULL; jr = jr->next) {
if (jr->len > 0) {
if (sendto (reserved->udp_socket, (const void *) excontext->ka_crlf, 4, 0, (struct sockaddr *) &(jr->addr), jr->len) > 0) {
OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL, "eXosip: Keep Alive sent on UDP!\n"));
}
}
}
return OSIP_SUCCESS;
}
libexosip2-5.3.0
src/eXtl_udp.c
static int udp_tl_keepalive(struct eXosip_t *excontext) {
struct eXtludp *reserved = (struct eXtludp *) excontext->eXtludp_reserved;
eXosip_reg_t *jr;
if (reserved == NULL) {
OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL, "[eXosip] [UDP] wrong state: create transport layer first\n"));
return OSIP_WRONG_STATE;
}
if (excontext->ka_interval <= 0) {
return 0;
}
if (reserved->udp_socket < 0)
return OSIP_UNDEFINED_ERROR;
for (jr = excontext->j_reg; jr != NULL; jr = jr->next) {
if (jr->stun_len > 0) {
int idx;
jr->stun_binding.type = htons(0x0001); // STUN_METHOD_BINDING|STUN_REQUEST
jr->stun_binding.length = htons(0);
jr->stun_binding.magic_cookie = htonl(0x2112A442);
for (idx = 0; idx < 12; idx = idx + 4) {
/* assert(i+3<16); */
int r = osip_build_random_number();
jr->stun_binding.tr_id[idx + 0] = r >> 0;
jr->stun_binding.tr_id[idx + 1] = r >> 8;
jr->stun_binding.tr_id[idx + 2] = r >> 16;
jr->stun_binding.tr_id[idx + 3] = r >> 24;
}
if (sendto(reserved->udp_socket, (const void *) &jr->stun_binding, sizeof(jr->stun_binding), 0, (struct sockaddr *) &(jr->stun_addr), jr->stun_len) > 0) {
OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO1, NULL, "[eXosip] [UDP] [keepalive] STUN sent on UDP\n"));
jr->ping_rfc5626 = osip_getsystemtime(NULL) + 9;
} else {
char eb[ERRBSIZ];
OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO1, NULL, "[eXosip] [UDP] [keepalive] failure %s\n", _ex_strerror(ex_errno, eb, ERRBSIZ)));
}
}
}
return OSIP_SUCCESS;
}
尝试方法
m_ctx = eXosip_malloc();
int iRet = eXosip_init(m_ctx);
m_ctx->ka_interval = 0;//禁用心跳保活
编译提示出错:
使用了未定义类型“eXosip_t”
“->ka_interval”的左边必须指向类/结构/联合/泛型类型
解决
m_ctx = eXosip_malloc();
int iRet = eXosip_init(m_ctx);
if (iRet != 0)
{
return iRet;
}
int nKeepAliveInterval = 0;
eXosip_set_option(m_ctx, EXOSIP_OPT_UDP_KEEP_ALIVE, &nKeepAliveInterval);