2981 lines
64 KiB
C++
2981 lines
64 KiB
C++
/***************************************************************************************
|
||
*
|
||
* IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||
*
|
||
* By downloading, copying, installing or using the software you agree to this license.
|
||
* If you do not agree to this license, do not download, install,
|
||
* copy or use the software.
|
||
*
|
||
* Copyright (C) 2014-2022, Happytimesoft Corporation, all rights reserved.
|
||
*
|
||
* Redistribution and use in binary forms, with or without modification, are permitted.
|
||
*
|
||
* Unless required by applicable law or agreed to in writing, software distributed
|
||
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||
* CONDITIONS OF ANY KIND, either express or implied. See the License for the specific
|
||
* language governing permissions and limitations under the License.
|
||
*
|
||
****************************************************************************************/
|
||
|
||
#include "sys_inc.h"
|
||
#include "word_analyse.h"
|
||
#include "hsip.h"
|
||
#include "sua.h"
|
||
#include "sip_rx.h"
|
||
#include "sip_parse.h"
|
||
|
||
|
||
/***************************************************************************************
|
||
全局数据
|
||
***************************************************************************************/
|
||
extern HSIP_CLASS hsip;
|
||
extern PPSN_CTX * hdrv_buf_fl;
|
||
|
||
/***************************************************************************************
|
||
请求消息对应表
|
||
****************************************************************************************/
|
||
const REQMTV req_mtvs[] =
|
||
{
|
||
{SIP_MT_SUB, "SUBSCRIBE", 9},
|
||
{SIP_MT_REG, "REGISTER", 8},
|
||
{SIP_MT_OPT, "OPTIONS", 7},
|
||
{SIP_MT_MSG, "MESSAGE", 7},
|
||
{SIP_MT_INV, "INVITE", 6},
|
||
{SIP_MT_CAN, "CANCEL", 6},
|
||
{SIP_MT_NTF, "NOTIFY", 6},
|
||
{SIP_MT_UPD, "UPDATE", 6},
|
||
{SIP_MT_PRACK, "PRACK", 5},
|
||
{SIP_MT_REF, "REFER", 5},
|
||
{SIP_MT_INFO, "INFO", 4},
|
||
{SIP_MT_ACK, "ACK", 3},
|
||
{SIP_MT_BYE, "BYE", 3}
|
||
};
|
||
|
||
/***************************************************************************************
|
||
SIP消息最简单判断
|
||
***************************************************************************************/
|
||
BOOL sip_is_sip_msg(char * msg_buf)
|
||
{
|
||
uint32 i;
|
||
|
||
for (i=0; i<sizeof(req_mtvs)/sizeof(REQMTV); i++)
|
||
{
|
||
if (memcmp(msg_buf, req_mtvs[i].msg_str, req_mtvs[i].msg_len) == 0)
|
||
{
|
||
return TRUE;
|
||
}
|
||
}
|
||
|
||
if (memcmp(msg_buf, "SIP/2.0", strlen("SIP/2.0")) == 0)
|
||
{
|
||
return TRUE;
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
void sip_headl_parse(char * pline, int llen, HSIP_MSG * p_msg)
|
||
{
|
||
char word_buf[256];
|
||
int word_len;
|
||
int next_word_offset;
|
||
BOOL bHaveNextWord;
|
||
|
||
bHaveNextWord = GetLineWord(pline, 0, llen, word_buf, sizeof(word_buf), &next_word_offset, WORD_TYPE_STRING);
|
||
word_len = strlen(word_buf);
|
||
|
||
if (word_len > 0 && word_len < 31)
|
||
{
|
||
// 保存第一行信息
|
||
memcpy(p_msg->first_line.header, pline, word_len);
|
||
p_msg->first_line.header[word_len] = '\0';
|
||
|
||
while (pline[next_word_offset] == ' ')
|
||
{
|
||
next_word_offset++;
|
||
}
|
||
|
||
p_msg->first_line.value_string = pline + next_word_offset;
|
||
|
||
if (strcasecmp(word_buf, "SIP/2.0") == 0)
|
||
{
|
||
// 继续取状态码
|
||
|
||
if (bHaveNextWord)
|
||
{
|
||
word_len = sizeof(word_buf);
|
||
bHaveNextWord = GetLineWord(pline, next_word_offset, llen,
|
||
word_buf,sizeof(word_buf), &next_word_offset, WORD_TYPE_NUM);
|
||
word_len = strlen(word_buf);
|
||
if (word_len > 0)
|
||
{
|
||
p_msg->msg_type = 1;
|
||
p_msg->msg_sub_type = atoi(word_buf);
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
uint32 i;
|
||
|
||
p_msg->msg_type = 0;
|
||
|
||
for (i=0; i<sizeof(req_mtvs)/sizeof(REQMTV); i++)
|
||
{
|
||
if (strcasecmp(word_buf, (char *)(req_mtvs[i].msg_str)) == 0)
|
||
{
|
||
p_msg->msg_sub_type = req_mtvs[i].msg_type;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/***********************************************************************\
|
||
消息解析,返回值:
|
||
>0 --- 分析成功,返回值是已经通过实际报文长度
|
||
-1 --- 分析失败
|
||
0 --- 接收数据长度不够
|
||
\***********************************************************************/
|
||
int sip_line_parse(char * p_buf, int max_len, char sep_char, PPSN_CTX * p_ctx)
|
||
{
|
||
char word_buf[256];
|
||
BOOL bHaveNextLine = TRUE;
|
||
int line_len = 0;
|
||
int parse_len = 0;
|
||
|
||
char * ptr = p_buf;
|
||
|
||
do {
|
||
if (GetSipLine(ptr, max_len, &line_len, &bHaveNextLine) == FALSE)
|
||
{
|
||
log_print(HT_LOG_ERR, "%s, get sip line error!!!\r\n", __FUNCTION__);
|
||
return -1;
|
||
}
|
||
|
||
if (line_len == 2) // <CR><LF>空行, 分析结束
|
||
{
|
||
return (parse_len + 2);
|
||
}
|
||
|
||
int next_word_offset = 0;
|
||
GetLineWord(ptr, 0, line_len-2, word_buf, sizeof(word_buf), &next_word_offset, WORD_TYPE_STRING);
|
||
char nchar = *(ptr + next_word_offset);
|
||
if (nchar != sep_char) // SIP is ':',SDP is '='
|
||
{
|
||
log_print(HT_LOG_ERR, "%s, format error!!!\r\n", __FUNCTION__);
|
||
return -1;
|
||
}
|
||
|
||
next_word_offset++;
|
||
while (ptr[next_word_offset] == ' ')
|
||
{
|
||
next_word_offset++;
|
||
}
|
||
|
||
// 保存每行的信息
|
||
HDRV * pHdrV = hdrv_buf_get_idle();
|
||
if (pHdrV == NULL)
|
||
{
|
||
log_print(HT_LOG_ERR, "%s, get_hdrv_buf return NULL!!!\r\n", __FUNCTION__);
|
||
return -1;
|
||
}
|
||
|
||
strncpy(pHdrV->header, word_buf, 32);
|
||
pHdrV->value_string = ptr+next_word_offset;
|
||
pps_ctx_ul_add(p_ctx, pHdrV);
|
||
|
||
ptr += line_len;
|
||
max_len -= line_len;
|
||
parse_len += line_len;
|
||
|
||
}while(bHaveNextLine);
|
||
|
||
return parse_len;
|
||
}
|
||
|
||
BOOL sip_ctx_is_xml(char * ctx_type)
|
||
{
|
||
// 模式:application/xxx+xml
|
||
|
||
const char * p_ctx_const = "application/";
|
||
int len_const = strlen(p_ctx_const);
|
||
int len = strlen(ctx_type);
|
||
|
||
if (len < (len_const + 3))
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
char bufs[256];
|
||
memcpy(bufs, ctx_type, len_const);
|
||
bufs[len_const] = '\0';
|
||
|
||
if (strcasecmp(bufs, p_ctx_const) != 0)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
char * ptr = ctx_type + len - 3;
|
||
|
||
if (strcasecmp(ptr, "xml") != 0)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
int sip_ctx_parse(HSIP_MSG * p_msg)
|
||
{
|
||
SIPCTXT w_ctx_type;
|
||
|
||
HDRV * pHdrV = (HDRV *)pps_lookup_start(&(p_msg->sip_ctx));
|
||
while (pHdrV != NULL)
|
||
{
|
||
if (strcasecmp(pHdrV->header, "Content-Length") == 0)
|
||
{
|
||
p_msg->ctx_len = atol(pHdrV->value_string);
|
||
}
|
||
else if (strcasecmp(pHdrV->header, "Content-Type") == 0)
|
||
{
|
||
int next_tmp;
|
||
char type_word[64];
|
||
|
||
GetLineWord(pHdrV->value_string, 0, strlen(pHdrV->value_string),
|
||
type_word, sizeof(type_word), &next_tmp, WORD_TYPE_STRING);
|
||
|
||
if (strcasecmp(type_word, "application/sdp") == 0)
|
||
{
|
||
w_ctx_type = SIP_CTX_SDP;
|
||
}
|
||
else if (strcasecmp(type_word, "application/MANSRTSP") == 0)
|
||
{
|
||
w_ctx_type = SIP_CTX_MANSRTSP;
|
||
}
|
||
else if (strcasecmp(type_word, "application/alarm") == 0)
|
||
{
|
||
w_ctx_type = SIP_CTX_ALARM;
|
||
}
|
||
else if (strcasecmp(type_word, "application/ptz") == 0)
|
||
{
|
||
w_ctx_type = SIP_CTX_PTZ;
|
||
}
|
||
else if (strcasecmp(type_word, "application/vrf") == 0)
|
||
{
|
||
w_ctx_type = SIP_CTX_VRF;
|
||
}
|
||
else if (strcasecmp(type_word, "text/plain") == 0)
|
||
{
|
||
w_ctx_type = SIP_CTX_TXT;
|
||
}
|
||
else if (strcasecmp(type_word, "text/html") == 0)
|
||
{
|
||
w_ctx_type = SIP_CTX_HTM;
|
||
}
|
||
else if (strcasecmp(type_word, "text/xml") == 0)
|
||
{
|
||
w_ctx_type = SIP_CTX_XML;
|
||
}
|
||
else if (sip_ctx_is_xml(type_word)) // "application/MANSCDP+xml"
|
||
{
|
||
w_ctx_type = SIP_CTX_XML;
|
||
}
|
||
else
|
||
{
|
||
w_ctx_type = SIP_CTX_NULL;
|
||
}
|
||
|
||
p_msg->ctx_type = w_ctx_type;
|
||
}
|
||
else if (strcasecmp(pHdrV->header, "Via") == 0)
|
||
{
|
||
// 分析Via
|
||
HSIP_VIAH * via_hdr = sip_msg_via_parse(pHdrV->value_string);
|
||
if (via_hdr != NULL)
|
||
{
|
||
via_hdr->via_string = pHdrV->value_string;
|
||
// 将Via信息加入到via_list而不是sip_line_list
|
||
pps_ctx_ul_add(&(p_msg->via_ctx), via_hdr);
|
||
}
|
||
|
||
HDRV * pDelHdrv = pHdrV;
|
||
pHdrV = (HDRV *)pps_ctx_ul_del_unlock(&(p_msg->sip_ctx), pHdrV);
|
||
hdrv_buf_free(pDelHdrv);
|
||
continue;
|
||
}
|
||
|
||
pHdrV = (HDRV *)pps_lookup_next(&(p_msg->sip_ctx), pHdrV);
|
||
}
|
||
pps_lookup_end(&(p_msg->sip_ctx));
|
||
|
||
if (p_msg->ctx_type && p_msg->ctx_len)
|
||
{
|
||
return 1;
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
int sip_msg_parse(char * msg_buf, int msg_buf_len, HSIP_MSG * msg)
|
||
{
|
||
int line_len = 0;
|
||
BOOL bHaveNextLine;
|
||
char * p_buf = msg_buf;
|
||
|
||
msg->msg_type = (uint32) -1; // 先将消息类型置为无效
|
||
|
||
if (GetSipLine(p_buf, msg_buf_len, &line_len, &bHaveNextLine) == FALSE)
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
if (line_len > 0) // 分析第一行判断是请求还是应答
|
||
{
|
||
sip_headl_parse(p_buf, line_len-2, msg);
|
||
}
|
||
|
||
if (msg->msg_type == (uint32) -1) // 错误消息
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
p_buf += line_len;
|
||
msg->sip_len = sip_line_parse(p_buf, msg_buf_len-line_len, ':', &(msg->sip_ctx));
|
||
if (msg->sip_len <= 0)
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
p_buf += msg->sip_len;
|
||
|
||
if (sip_ctx_parse(msg) == 1 && msg->ctx_len > 0)
|
||
{
|
||
if (msg->ctx_type == SIP_CTX_TXT || msg->ctx_type == SIP_CTX_XML || msg->ctx_type == SIP_CTX_MANSRTSP)
|
||
{
|
||
HDRV * pHdrV = hdrv_buf_get_idle();
|
||
if (pHdrV == NULL)
|
||
{
|
||
log_print(HT_LOG_ERR, "%s, get_hdrv_buf return NULL!!!\r\n", __FUNCTION__);
|
||
return -1;
|
||
}
|
||
|
||
strcpy(pHdrV->header, "");
|
||
pHdrV->value_string = p_buf;
|
||
pps_ctx_ul_add(&(msg->sdp_ctx), pHdrV);
|
||
|
||
int slen = strlen(p_buf);
|
||
msg->sdp_len = msg->ctx_len;
|
||
if (slen != msg->ctx_len)
|
||
{
|
||
log_print(HT_LOG_WARN, "%s, strlen[%d] != ctx len[%d]!!!\r\n", __FUNCTION__, slen, msg->ctx_len);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
msg->sdp_len = sip_line_parse(p_buf, msg->ctx_len, '=', &(msg->sdp_ctx));
|
||
if (msg->sdp_len < 0)
|
||
{
|
||
return -1;
|
||
}
|
||
}
|
||
}
|
||
|
||
return (line_len + msg->sip_len + msg->sdp_len);
|
||
}
|
||
|
||
int sip_msg_parse_part1(char * p_buf, int buf_len, HSIP_MSG * msg)
|
||
{
|
||
int line_len = 0;
|
||
BOOL bHaveNextLine;
|
||
|
||
msg->msg_type = (uint32) -1; // 先将消息类型置为无效
|
||
|
||
if (GetSipLine(p_buf, buf_len, &line_len, &bHaveNextLine) == FALSE)
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
if (line_len > 0) // 分析第一行判断是请求还是应答
|
||
{
|
||
sip_headl_parse(p_buf, line_len-2, msg);
|
||
}
|
||
|
||
if (msg->msg_type == (uint32) -1) // 错误消息
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
p_buf += line_len;
|
||
msg->sip_len = sip_line_parse(p_buf, buf_len-line_len, ':', &(msg->sip_ctx));
|
||
if (msg->sip_len <= 0)
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
sip_ctx_parse(msg);
|
||
|
||
return (line_len + msg->sip_len);
|
||
}
|
||
|
||
int sip_msg_parse_part2(char * p_buf, int buf_len, HSIP_MSG * msg)
|
||
{
|
||
if (msg->ctx_type == SIP_CTX_TXT || msg->ctx_type == SIP_CTX_XML)
|
||
{
|
||
HDRV * pHdrV = hdrv_buf_get_idle();
|
||
if (pHdrV == NULL)
|
||
{
|
||
log_print(HT_LOG_ERR, "%s, get_hdrv_buf return NULL!!!\r\n", __FUNCTION__);
|
||
return -1;
|
||
}
|
||
|
||
strcpy(pHdrV->header, "");
|
||
pHdrV->value_string = p_buf;
|
||
pps_ctx_ul_add(&(msg->sdp_ctx), pHdrV);
|
||
|
||
int slen = strlen(p_buf);
|
||
msg->sdp_len = msg->ctx_len;
|
||
|
||
if (slen != msg->ctx_len)
|
||
{
|
||
log_print(HT_LOG_ERR, "%s, strlen[%d] != ctx len[%d]!!!\r\n", __FUNCTION__, slen, msg->ctx_len);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
msg->sdp_len = sip_line_parse(p_buf, buf_len, '=', &(msg->sdp_ctx));
|
||
if (msg->sdp_len < 0)
|
||
{
|
||
return -1;
|
||
}
|
||
}
|
||
|
||
return msg->sdp_len;
|
||
}
|
||
|
||
/***********************************************************************\
|
||
消息中Via部分解析,结果存放到via_list中
|
||
\***********************************************************************/
|
||
HSIP_VIAH * sip_msg_via_parse(char * via_content_buf)
|
||
{
|
||
int next_offset,str_len;
|
||
char tmp_buf[128];
|
||
|
||
HSIP_VIAH * via_hdr = sip_get_via_buf();
|
||
if (via_hdr == NULL)
|
||
{
|
||
return NULL;
|
||
}
|
||
|
||
memset(via_hdr, 0, sizeof(HSIP_VIAH));
|
||
|
||
str_len = strlen(via_content_buf);
|
||
|
||
GetLineWord(via_content_buf, 0, str_len, via_hdr->sip_ver,
|
||
sizeof(via_hdr->sip_ver), &next_offset, WORD_TYPE_STRING);
|
||
if ((strcasecmp(via_hdr->sip_ver,"SIP/2.0/UDP") != 0) &&
|
||
(strcasecmp(via_hdr->sip_ver,"SIP/2.0/TCP") != 0) &&
|
||
(memcmp(via_hdr->sip_ver,"SIP/2.0", 7) != 0))
|
||
{
|
||
sip_free_via_buf(via_hdr);
|
||
return NULL;
|
||
}
|
||
|
||
GetLineWord(via_content_buf, next_offset, str_len, via_hdr->domain,
|
||
sizeof(via_hdr->domain), &next_offset, WORD_TYPE_STRING);
|
||
if (isalpha(via_hdr->domain[0]))
|
||
{
|
||
via_hdr->ip = 0; // 域名有效,ip无效
|
||
}
|
||
else
|
||
{
|
||
via_hdr->ip = inet_addr(via_hdr->domain); // ip有效
|
||
}
|
||
|
||
if (via_content_buf[next_offset] == ':')
|
||
{
|
||
next_offset++;
|
||
GetLineWord(via_content_buf, next_offset, str_len, tmp_buf,
|
||
sizeof(tmp_buf), &next_offset, WORD_TYPE_STRING);
|
||
via_hdr->port = (uint16)atol(tmp_buf);
|
||
}
|
||
else // 没有端口描述,作缺省处理5060
|
||
{
|
||
via_hdr->port = 5060;
|
||
}
|
||
|
||
if (via_content_buf[next_offset] == ';')
|
||
{
|
||
next_offset++;
|
||
}
|
||
else if (via_content_buf[next_offset] == '\0')
|
||
{
|
||
return via_hdr; // 分析结束
|
||
}
|
||
else
|
||
{
|
||
sip_free_via_buf(via_hdr); // 格式错误
|
||
return NULL;
|
||
}
|
||
|
||
// 分析可能的rport=...;received=...,有必要吗???
|
||
if (GetNameValuePair(via_content_buf+next_offset, str_len-next_offset, "rport", tmp_buf, sizeof(tmp_buf)))
|
||
{
|
||
if (strlen(tmp_buf) > 0)
|
||
{
|
||
via_hdr->real_port = (uint16)atol(tmp_buf);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
via_hdr->real_port = 0;
|
||
}
|
||
|
||
if (GetNameValuePair(via_content_buf+next_offset, str_len-next_offset, "received", tmp_buf, sizeof(tmp_buf)))
|
||
{
|
||
via_hdr->real_ip = inet_addr(tmp_buf);
|
||
}
|
||
else
|
||
{
|
||
via_hdr->real_ip = 0;
|
||
}
|
||
|
||
if (GetNameValuePair(via_content_buf+next_offset, str_len-next_offset, "branch", tmp_buf, sizeof(tmp_buf)))
|
||
{
|
||
strcpy(via_hdr->branch, tmp_buf);
|
||
}
|
||
else
|
||
{
|
||
via_hdr->branch[0] = '\0';
|
||
}
|
||
|
||
return via_hdr;
|
||
}
|
||
|
||
/***********************************************************************\
|
||
实用函数: 从消息头域SIP部分链表中查找需要的行
|
||
\***********************************************************************/
|
||
HDRV * sip_find_headline(HSIP_MSG * msg, const char * head)
|
||
{
|
||
if (msg == NULL || head == NULL)
|
||
{
|
||
return NULL;
|
||
}
|
||
|
||
HDRV * line = (HDRV *)pps_lookup_start(&(msg->sip_ctx));
|
||
while (line != NULL)
|
||
{
|
||
if (strcasecmp(line->header, head) == 0)
|
||
{
|
||
return line;
|
||
}
|
||
|
||
line = (HDRV *)pps_lookup_next(&(msg->sip_ctx), line);
|
||
}
|
||
pps_lookup_end(&(msg->sip_ctx));
|
||
|
||
return NULL;
|
||
}
|
||
|
||
/***********************************************************************\
|
||
实用函数: 从消息头域SDP部分链表中查找需要的行
|
||
\***********************************************************************/
|
||
HDRV * sip_find_sdp_headline(HSIP_MSG * msg, const char * head)
|
||
{
|
||
if (msg == NULL || head == NULL)
|
||
{
|
||
return NULL;
|
||
}
|
||
|
||
HDRV * line = (HDRV *)pps_lookup_start(&(msg->sdp_ctx));
|
||
while (line != NULL)
|
||
{
|
||
if (strcasecmp(line->header, head) == 0)
|
||
{
|
||
return line;
|
||
}
|
||
|
||
line = (HDRV *)pps_lookup_next(&(msg->sdp_ctx), line);
|
||
}
|
||
pps_lookup_end(&(msg->sdp_ctx));
|
||
|
||
return NULL;
|
||
}
|
||
|
||
/***********************************************************************\
|
||
实用函数: 检查消息中是否有SDP部分
|
||
\***********************************************************************/
|
||
BOOL sip_msg_with_sdp(HSIP_MSG * msg)
|
||
{
|
||
if (msg == NULL)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
if (msg->sdp_ctx.node_num == 0)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
/***********************************************************************\
|
||
实用函数: 取出消息中的Call-ID,Call-ID不同表示两个完全不同的呼叫
|
||
\***********************************************************************/
|
||
BOOL sip_get_msg_call_id(HSIP_MSG * rx_msg, char * callid_buf, int len)
|
||
{
|
||
callid_buf[0] = '\0';
|
||
|
||
HDRV * rx_id = sip_find_headline(rx_msg, "Call-Id");
|
||
if (rx_id == NULL || len <= 0)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
// 某些平台 Call-ID: 536870917@192.168.4.59:0 (:被当作分隔符,导致解析不完整)
|
||
|
||
#if 0
|
||
int next_word_offset;
|
||
|
||
GetLineWord(rx_id->value_string, 0, strlen(rx_id->value_string), callid_buf, len, &next_word_offset, WORD_TYPE_STRING);
|
||
#else
|
||
strncpy(callid_buf, rx_id->value_string, len);
|
||
#endif
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
/***********************************************************************\
|
||
实用函数: 取出消息中的CSeq
|
||
\***********************************************************************/
|
||
BOOL sip_get_msg_cseq(HSIP_MSG * rx_msg, char * cseq_buf, int len)
|
||
{
|
||
HDRV * rx_cseq = sip_find_headline(rx_msg, "CSeq");
|
||
if ((rx_cseq == NULL) || len <= 0)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
int next_offset;
|
||
|
||
GetLineWord(rx_cseq->value_string, 0, strlen(rx_cseq->value_string), cseq_buf, len, &next_offset, WORD_TYPE_NUM);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
/***********************************************************************\
|
||
实用函数: 取出消息中的CSeq后面的字符:Invite,Bye,...
|
||
\***********************************************************************/
|
||
BOOL sip_get_msg_cseq_type(HSIP_MSG * rx_msg, char *type_buf, int len)
|
||
{
|
||
type_buf[0] = '\0';
|
||
|
||
HDRV * rx_cseq = sip_find_headline(rx_msg, "CSeq");
|
||
if ((rx_cseq == NULL) || len <= 0)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
int next_offset;
|
||
|
||
GetLineWord(rx_cseq->value_string, 0, strlen(rx_cseq->value_string), type_buf, len, &next_offset, WORD_TYPE_NUM);
|
||
GetLineWord(rx_cseq->value_string, next_offset, strlen(rx_cseq->value_string), type_buf, len, &next_offset, WORD_TYPE_STRING);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
/***********************************************************************\
|
||
实用函数: 取出消息中的会话保活信息
|
||
Supported:timer
|
||
Require:timer
|
||
Session-Expires:200;refresher=uac
|
||
Min-SE:90
|
||
\***********************************************************************/
|
||
BOOL sip_get_session_timer_info(HSIP_MSG * rx_msg, int * expires, int * min_se, int * refresher)
|
||
{
|
||
int next_offset;
|
||
BOOL b_timer = FALSE;
|
||
int SessionExpires = 0;
|
||
int MinSE = 0;
|
||
int Refresher = 0;
|
||
char bufs[32];
|
||
|
||
HDRV * line = (HDRV *)pps_lookup_start(&(rx_msg->sip_ctx));
|
||
while (line != NULL)
|
||
{
|
||
if(strcasecmp(line->header, "Supported") == 0)
|
||
{
|
||
if (strcasecmp(line->value_string, "timer") == 0)
|
||
{
|
||
b_timer = TRUE;
|
||
break;
|
||
}
|
||
}
|
||
|
||
line = (HDRV *)pps_lookup_next(&(rx_msg->sip_ctx), line);
|
||
}
|
||
pps_lookup_end(&(rx_msg->sip_ctx));
|
||
|
||
if (b_timer == FALSE)
|
||
return FALSE;
|
||
|
||
line = sip_find_headline(rx_msg, "Session-Expires");
|
||
if (line == NULL)
|
||
return FALSE;
|
||
|
||
BOOL bHaveNext = GetLineWord(line->value_string, 0, strlen(line->value_string),
|
||
bufs, sizeof(bufs) - 1, &next_offset, WORD_TYPE_NUM);
|
||
if (bufs[0] == '\0')
|
||
return FALSE;
|
||
|
||
SessionExpires = atoi(bufs);
|
||
if (SessionExpires < 0)
|
||
return FALSE;
|
||
|
||
if (bHaveNext)
|
||
{
|
||
char * ptr = line->value_string + next_offset;
|
||
if (GetNameValuePair(ptr, strlen(ptr), "refresher", bufs, sizeof(bufs) - 1))
|
||
{
|
||
if (strcasecmp(bufs, "uac") == 0)
|
||
Refresher = 1;
|
||
else if (strcasecmp(bufs, "uas") == 0)
|
||
Refresher = 2;
|
||
}
|
||
}
|
||
|
||
line = sip_find_headline(rx_msg, "Min-SE");
|
||
if (line)
|
||
{
|
||
GetLineWord(line->value_string, 0, strlen(line->value_string),
|
||
bufs, sizeof(bufs), &next_offset, WORD_TYPE_NUM);
|
||
if (bufs[0] == '\0')
|
||
return FALSE;
|
||
|
||
MinSE = atoi(bufs);
|
||
if (MinSE < 0)
|
||
return FALSE;
|
||
}
|
||
|
||
*expires = SessionExpires;
|
||
*min_se = MinSE;
|
||
*refresher = Refresher;
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
/***********************************************************************\
|
||
实用函数: 取出消息中的Expires
|
||
\***********************************************************************/
|
||
BOOL sip_get_msg_expires(HSIP_MSG * rx_msg, char * expires_buf, int len)
|
||
{
|
||
int next_offset;
|
||
|
||
if ((expires_buf == NULL) || len <= 0)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
expires_buf[0] = '\0';
|
||
|
||
HDRV * rx_expires = sip_find_headline(rx_msg, "Expires");
|
||
if (rx_expires != NULL)
|
||
{
|
||
GetLineWord(rx_expires->value_string, 0, strlen(rx_expires->value_string),
|
||
expires_buf, len, &next_offset, WORD_TYPE_NUM);
|
||
|
||
return TRUE;
|
||
}
|
||
else
|
||
{
|
||
/*
|
||
没有 Expires: 这一行, 可能存在
|
||
Contact: <sip:22100745@61.145.139.168:63947;user=phone>;expires=300
|
||
*/
|
||
|
||
rx_expires = sip_find_headline(rx_msg, "Contact");
|
||
if (rx_expires == NULL)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
char * p_epr = strstr(rx_expires->value_string, "expires=");
|
||
if (p_epr == NULL)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
p_epr += strlen("expires=");
|
||
|
||
GetLineWord(p_epr, 0, strlen(p_epr), expires_buf, len, &next_offset, WORD_TYPE_NUM);
|
||
|
||
return TRUE;
|
||
}
|
||
}
|
||
|
||
/***********************************************************************\
|
||
实用函数: 从 From/To 中取出显示名称
|
||
\***********************************************************************/
|
||
BOOL sip_get_disp_name(HSIP_MSG * rx_msg, const char * ft, char * disp_name, int len)
|
||
{
|
||
disp_name[0] = '\0'; // 先把返回缓冲区清空
|
||
|
||
HDRV * rx_line = sip_find_headline(rx_msg, ft);
|
||
if (rx_line == NULL)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
int cur_offset = 0;
|
||
|
||
while (rx_line->value_string[cur_offset] == ' ')
|
||
{
|
||
cur_offset++;
|
||
}
|
||
|
||
if (rx_line->value_string[cur_offset] == '\0')
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
if (rx_line->value_string[cur_offset] == '"')
|
||
{
|
||
cur_offset++;
|
||
}
|
||
|
||
char * end_ptr = strchr(rx_line->value_string + cur_offset, '<');
|
||
if (end_ptr == NULL)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
int rlen = end_ptr - (rx_line->value_string + cur_offset);
|
||
if (rlen > len)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
memcpy(disp_name, rx_line->value_string + cur_offset, rlen);
|
||
|
||
while (rlen > 0 && disp_name[rlen-1] == ' ')
|
||
{
|
||
rlen--;
|
||
}
|
||
|
||
if (rlen == 0)
|
||
{
|
||
disp_name[0] = '\0';
|
||
return FALSE;
|
||
}
|
||
|
||
if (disp_name[rlen - 1] == '"')
|
||
{
|
||
rlen--;
|
||
}
|
||
|
||
disp_name[rlen] = '\0';
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
/***********************************************************************\
|
||
实用函数: 从 From/To 中取出用户名
|
||
\***********************************************************************/
|
||
BOOL sip_get_user_name(HSIP_MSG * rx_msg, const char * ft, char * user_name, int len)
|
||
{
|
||
char * p_sip = NULL;
|
||
int bracket_flag = 0;
|
||
int cur_offset = 0;
|
||
|
||
user_name[0] = '\0'; // 先把返回缓冲区清空
|
||
|
||
HDRV * rx_line = sip_find_headline(rx_msg, ft);
|
||
if (rx_line == NULL)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
p_sip = strstr(rx_line->value_string, "<sip:");
|
||
if (p_sip == NULL)
|
||
{
|
||
p_sip = strstr(rx_line->value_string, "sip:");
|
||
if (p_sip == NULL)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
p_sip += 4;
|
||
}
|
||
else
|
||
{
|
||
p_sip += 5;
|
||
bracket_flag = 1;
|
||
}
|
||
|
||
if (bracket_flag == 1)
|
||
{
|
||
while ((p_sip[cur_offset] != '>') && (p_sip[cur_offset] != '\0'))
|
||
{
|
||
cur_offset++;
|
||
}
|
||
|
||
if (p_sip[cur_offset] == '\0')
|
||
{
|
||
return FALSE;
|
||
}
|
||
}
|
||
|
||
cur_offset = 0;
|
||
|
||
while ((p_sip[cur_offset] != '@') && (p_sip[cur_offset] != '\0'))
|
||
{
|
||
cur_offset++;
|
||
}
|
||
|
||
if (p_sip[cur_offset] == '\0')
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
if (cur_offset >= len) // 缓冲区长度不够
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
memcpy(user_name, p_sip, cur_offset);
|
||
user_name[cur_offset] = '\0';
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
/***********************************************************************\
|
||
实用函数: 从 From/To 中取出域名
|
||
\***********************************************************************/
|
||
BOOL sip_get_user_domain(HSIP_MSG * rx_msg, const char * ft, char * domain, int len)
|
||
{
|
||
char * p_sip = NULL;
|
||
int cur_offset = 0;
|
||
|
||
domain[0] = '\0'; // 先把返回缓冲区清空
|
||
|
||
HDRV * rx_line = sip_find_headline(rx_msg, ft);
|
||
if (rx_line == NULL)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
p_sip = strstr(rx_line->value_string, "<sip:");
|
||
if (p_sip == NULL)
|
||
{
|
||
p_sip = strstr(rx_line->value_string,"sip:");
|
||
}
|
||
|
||
if (p_sip == NULL)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
while ((*p_sip != ':') && (*p_sip != '\0'))
|
||
p_sip++;
|
||
while ((*p_sip != '@') && (*p_sip != '\0'))
|
||
p_sip++;
|
||
|
||
if (*p_sip == '@')
|
||
{
|
||
p_sip++;
|
||
}
|
||
else
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
while ((p_sip[cur_offset] != '>') && (p_sip[cur_offset] != ':')
|
||
&& (p_sip[cur_offset] != '\0') && (p_sip[cur_offset] != ';'))
|
||
{
|
||
cur_offset++;
|
||
}
|
||
|
||
if (p_sip[cur_offset] == '\0')
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
if (cur_offset >= len) // 缓冲区长度不够
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
memcpy(domain, p_sip, cur_offset);
|
||
domain[cur_offset] = '\0';
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
/***********************************************************************\
|
||
实用函数: 从 From/To 中取出SIP地址
|
||
|
||
From: 801001 <sip:801001@192.168.1.3>;tag=HKQf2-AdQN
|
||
To: sip:888888@192.168.1.3;tag=xxx
|
||
\***********************************************************************/
|
||
BOOL sip_get_sip_address(HSIP_MSG * rx_msg, const char * ft, char * sip_address, int len)
|
||
{
|
||
char * p_sip = NULL;
|
||
int bracket_flag = 0;
|
||
int cur_offset = 0;
|
||
|
||
sip_address[0] = '\0'; // 先把返回缓冲区清空
|
||
|
||
HDRV * rx_line = sip_find_headline(rx_msg, ft);
|
||
if (rx_line == NULL)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
p_sip = strstr(rx_line->value_string, "<sip:");
|
||
if (p_sip == NULL)
|
||
{
|
||
p_sip = strstr(rx_line->value_string, "sip:");
|
||
}
|
||
|
||
if (p_sip == NULL)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
if (p_sip[0] == '<')
|
||
{
|
||
p_sip++;
|
||
bracket_flag = 1;
|
||
}
|
||
|
||
if (bracket_flag == 1)
|
||
{
|
||
while ((p_sip[cur_offset] != '>') && (p_sip[cur_offset] != '\0'))
|
||
cur_offset++;
|
||
|
||
if (p_sip[cur_offset] != '>')
|
||
return FALSE;
|
||
}
|
||
else
|
||
{
|
||
while ((p_sip[cur_offset] != ';') && (p_sip[cur_offset] != '\0'))
|
||
cur_offset++;
|
||
}
|
||
|
||
if (cur_offset >= len) // 缓冲区长度不够
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
memcpy(sip_address, p_sip, cur_offset);
|
||
sip_address[cur_offset] = '\0';
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
/***********************************************************************\
|
||
实用函数: 从 From/To 中取出TAG
|
||
|
||
From: "test" <sip:96123001@124.42.124.82:8080;user=phone>;tag=12fddc2f8060842f
|
||
To: <sip:96123001@124.42.124.82:8080;user=phone>
|
||
Contact: <sip:96123001@192.168.0.150:8080;user=phone>
|
||
\***********************************************************************/
|
||
BOOL sip_get_user_tag(HSIP_MSG * rx_msg, const char * ft,char * tag, int len)
|
||
{
|
||
int bracket_flag = 0;
|
||
char * p_sip = NULL;
|
||
|
||
tag[0] = '\0'; // 先把返回缓冲区清空
|
||
|
||
HDRV * rx_line = sip_find_headline(rx_msg, ft);
|
||
if (rx_line == NULL)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
int cur_offset=0;
|
||
|
||
p_sip = strstr(rx_line->value_string, "<sip:");
|
||
if (p_sip == NULL)
|
||
{
|
||
p_sip = strstr(rx_line->value_string, "sip:");
|
||
}
|
||
|
||
if (p_sip == NULL)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
if (p_sip[cur_offset] == '<')
|
||
{
|
||
cur_offset++;
|
||
bracket_flag = 1;
|
||
}
|
||
|
||
cur_offset += 4;
|
||
|
||
if (bracket_flag == 1)
|
||
{
|
||
while ((p_sip[cur_offset] != '>') && (p_sip[cur_offset] != '\0'))
|
||
cur_offset++;
|
||
|
||
if (p_sip[cur_offset] != '>')
|
||
return FALSE;
|
||
|
||
cur_offset++; // --> 分号; 或者是'\0'
|
||
}
|
||
else
|
||
{
|
||
while ((p_sip[cur_offset] != ';') && (p_sip[cur_offset] != '\0'))
|
||
cur_offset++;
|
||
}
|
||
|
||
if (p_sip[cur_offset] != ';')
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
cur_offset++; // --> tag= ...
|
||
|
||
int real_len = strlen(p_sip + cur_offset);
|
||
if (real_len >= len) // 缓冲区长度不够
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
strcpy(tag, p_sip+cur_offset);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
BOOL sip_get_req_name(HSIP_MSG * rx_msg, char * req_name, int len)
|
||
{
|
||
char * p_sip = NULL;
|
||
int bracket_flag = 0;
|
||
int cur_offset = 0;
|
||
char * value_string;
|
||
|
||
req_name[0] = '\0'; // 先把返回缓冲区清空
|
||
|
||
if (rx_msg == NULL)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
value_string = rx_msg->first_line.value_string;
|
||
if (value_string == NULL)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
p_sip = strstr(value_string, "<sip:");
|
||
if (p_sip == NULL)
|
||
{
|
||
p_sip = strstr(value_string, "sip:");
|
||
if (p_sip == NULL)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
p_sip += 4;
|
||
}
|
||
else
|
||
{
|
||
p_sip += 5;
|
||
bracket_flag = 1;
|
||
}
|
||
|
||
if (bracket_flag == 1)
|
||
{
|
||
while ((p_sip[cur_offset] != '>') && (p_sip[cur_offset] != '\0'))
|
||
{
|
||
cur_offset++;
|
||
}
|
||
|
||
if (p_sip[cur_offset] == '\0')
|
||
{
|
||
return FALSE;
|
||
}
|
||
}
|
||
|
||
cur_offset = 0;
|
||
|
||
while ((p_sip[cur_offset] != '@') && (p_sip[cur_offset] != '\0'))
|
||
{
|
||
cur_offset++;
|
||
}
|
||
|
||
if (p_sip[cur_offset] == '\0')
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
if (cur_offset >= len) // 缓冲区长度不够
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
memcpy(req_name, p_sip, cur_offset);
|
||
req_name[cur_offset] = '\0';
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
BOOL sip_get_user_contact_uri(HSIP_MSG * rx_msg, char * uri_buf, int max_len)
|
||
{
|
||
char * p_sip = NULL;
|
||
int end_offset = 0;
|
||
|
||
uri_buf[0] = '\0';
|
||
|
||
HDRV * rx_line = sip_find_headline(rx_msg, "Contact");
|
||
if (rx_line == NULL)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
p_sip = strstr(rx_line->value_string, "<sip:");
|
||
if (p_sip == NULL)
|
||
{
|
||
p_sip = strstr(rx_line->value_string, "sip:");
|
||
if (p_sip == NULL)
|
||
{
|
||
return FALSE;
|
||
}
|
||
}
|
||
|
||
if (p_sip[0] == '<')
|
||
{
|
||
p_sip++;
|
||
|
||
while((p_sip[end_offset] != '>') && (p_sip[end_offset] != ';') && (p_sip[end_offset] != '\0'))
|
||
end_offset++;
|
||
|
||
if (p_sip[end_offset] != '>' && p_sip[end_offset] != ';')
|
||
return FALSE;
|
||
}
|
||
else
|
||
{
|
||
while((p_sip[end_offset] != ';') && (p_sip[end_offset] != '\0'))
|
||
end_offset++;
|
||
}
|
||
|
||
if (end_offset > (max_len -1))
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
memcpy(uri_buf, p_sip, end_offset);
|
||
uri_buf[end_offset] = '\0';
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
BOOL sip_get_server_info(HSIP_MSG * rx_msg, char * srv_buf, int max_len)
|
||
{
|
||
if (srv_buf == NULL || max_len <= 0)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
srv_buf[0] = '\0';
|
||
|
||
HDRV * rx_line = sip_find_headline(rx_msg, "Server");
|
||
if (rx_line == NULL)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
strncpy(srv_buf, rx_line->value_string, max_len);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
/***********************************************************************\
|
||
实用函数: 获取消息内容类型
|
||
\***********************************************************************/
|
||
BOOL sip_get_content_type(HSIP_MSG * rx_msg, char * bufs, int len)
|
||
{
|
||
HDRV * rx_line = sip_find_headline(rx_msg, "Content-Type");
|
||
if (rx_line == NULL)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
strncpy(bufs, rx_line->value_string, len);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
/***********************************************************************\
|
||
实用函数: 加入消息行到一个发送消息中
|
||
\***********************************************************************/
|
||
void sip_add_tx_msg_line(HSIP_MSG * tx_msg, const char * msg_hdr, const char * msg_fmt,...)
|
||
{
|
||
int slen;
|
||
va_list argptr;
|
||
|
||
if (tx_msg == NULL || tx_msg->msg_buf == NULL)
|
||
{
|
||
return;
|
||
}
|
||
|
||
HDRV *pHdrV = hdrv_buf_get_idle();
|
||
if (pHdrV == NULL)
|
||
{
|
||
log_print(HT_LOG_ERR, "%s, get_hdrv_buf return NULL!!!\r\n", __FUNCTION__);
|
||
return;
|
||
}
|
||
|
||
pHdrV->value_string = tx_msg->msg_buf + tx_msg->buf_offset;
|
||
|
||
strncpy(pHdrV->header, msg_hdr, 31);
|
||
|
||
va_start(argptr, msg_fmt);
|
||
#if __LINUX_OS__
|
||
slen = vsnprintf(pHdrV->value_string, tx_msg->buf_mlen-tx_msg->buf_offset, msg_fmt, argptr);
|
||
#else
|
||
slen = vsprintf(pHdrV->value_string, msg_fmt, argptr);
|
||
#endif
|
||
va_end(argptr);
|
||
|
||
if (slen < 0)
|
||
{
|
||
log_print(HT_LOG_ERR, "%s, vsnprintf return %d !!!\r\n", __FUNCTION__, slen);
|
||
hdrv_buf_free(pHdrV);
|
||
return;
|
||
}
|
||
|
||
pHdrV->value_string[slen] = '\0';
|
||
tx_msg->buf_offset += slen + 1;
|
||
|
||
pps_ctx_ul_add(&(tx_msg->sip_ctx), pHdrV);
|
||
}
|
||
|
||
/***********************************************************************\
|
||
实用函数: 加入SDP消息行到一个发送消息中
|
||
\***********************************************************************/
|
||
void sip_add_tx_msg_sdp_line(HSIP_MSG * tx_msg, const char * msg_hdr, const char * msg_fmt,...)
|
||
{
|
||
int slen;
|
||
va_list argptr;
|
||
|
||
if (tx_msg == NULL || tx_msg->msg_buf == NULL)
|
||
{
|
||
return;
|
||
}
|
||
|
||
HDRV *pHdrV = hdrv_buf_get_idle();
|
||
if (pHdrV == NULL)
|
||
{
|
||
log_print(HT_LOG_ERR, "%s, get_hdrv_buf return NULL!!!\r\n", __FUNCTION__);
|
||
return;
|
||
}
|
||
|
||
pHdrV->value_string = tx_msg->msg_buf + tx_msg->buf_offset;
|
||
|
||
strncpy(pHdrV->header, msg_hdr, 31);
|
||
|
||
va_start(argptr, msg_fmt);
|
||
#if __LINUX_OS__
|
||
slen = vsnprintf(pHdrV->value_string, tx_msg->buf_mlen-tx_msg->buf_offset, msg_fmt, argptr);
|
||
#else
|
||
slen = vsprintf(pHdrV->value_string, msg_fmt, argptr);
|
||
#endif
|
||
va_end(argptr);
|
||
|
||
if (slen < 0)
|
||
{
|
||
log_print(HT_LOG_ERR, "%s, vsnprintf return %d !!!\r\n", __FUNCTION__, slen);
|
||
hdrv_buf_free(pHdrV);
|
||
return;
|
||
}
|
||
|
||
pHdrV->value_string[slen] = '\0';
|
||
tx_msg->buf_offset += slen + 1;
|
||
|
||
pps_ctx_ul_add(&(tx_msg->sdp_ctx), pHdrV);
|
||
}
|
||
|
||
/***********************************************************************\
|
||
实用函数: 加入首行到一个发送消息中
|
||
\***********************************************************************/
|
||
void sip_add_tx_msg_fline(HSIP_MSG * tx_msg, const char * msg_hdr, const char * msg_fmt,...)
|
||
{
|
||
int slen;
|
||
va_list argptr;
|
||
|
||
if (tx_msg == NULL || tx_msg->msg_buf == NULL)
|
||
{
|
||
return;
|
||
}
|
||
|
||
strcpy(tx_msg->first_line.header, msg_hdr);
|
||
tx_msg->first_line.value_string = tx_msg->msg_buf + tx_msg->buf_offset;
|
||
|
||
va_start(argptr, msg_fmt);
|
||
#if __LINUX_OS__
|
||
slen = vsnprintf(tx_msg->first_line.value_string, tx_msg->buf_mlen-tx_msg->buf_offset, msg_fmt, argptr);
|
||
#else
|
||
slen = vsprintf(tx_msg->first_line.value_string, msg_fmt, argptr);
|
||
#endif
|
||
va_end(argptr);
|
||
|
||
if (slen < 0)
|
||
{
|
||
log_print(HT_LOG_ERR, "%s, vsnprintf return %d !!!\r\n", __FUNCTION__, slen);
|
||
return;
|
||
}
|
||
|
||
tx_msg->first_line.value_string[slen] = '\0';
|
||
tx_msg->buf_offset += slen + 1;
|
||
}
|
||
|
||
/***********************************************************************\
|
||
实用函数: 加入VIA信息到一个发送消息中;
|
||
这里有两种情况:
|
||
1. Proxy 的情况,一般是Proxy Server的地址信息
|
||
2. Register的情况,一般Via中直接是用户的Via
|
||
注意: 这里总是将一个新的Via放在最前面
|
||
\***********************************************************************/
|
||
void sip_add_tx_msg_via(HSIP_MSG * tx_msg, const char * msg_fmt,...)
|
||
{
|
||
int slen;
|
||
va_list argptr;
|
||
|
||
HSIP_VIAH * via_hdr = sip_get_via_buf();
|
||
if (via_hdr == NULL)
|
||
{
|
||
log_print(HT_LOG_ERR, "%s, sip_get_via_buf return NULL!!!\r\n", __FUNCTION__);
|
||
return;
|
||
}
|
||
|
||
via_hdr->via_string = tx_msg->msg_buf + tx_msg->buf_offset;
|
||
|
||
va_start(argptr,msg_fmt);
|
||
slen = vsprintf(via_hdr->via_string, msg_fmt, argptr);
|
||
va_end(argptr);
|
||
|
||
if (slen < 0)
|
||
{
|
||
log_print(HT_LOG_ERR, "%s, vsnprintf return %d !!!\r\n", __FUNCTION__, slen);
|
||
sip_free_via_buf(via_hdr);
|
||
return;
|
||
}
|
||
|
||
via_hdr->via_string[slen] = '\0';
|
||
tx_msg->buf_offset += slen + 1;
|
||
|
||
pps_ctx_ul_add(&(tx_msg->via_ctx), via_hdr);
|
||
}
|
||
|
||
void sip_copy_msg_via(HSIP_MSG * src_msg, HSIP_MSG * dst_msg)
|
||
{
|
||
if (src_msg == NULL || dst_msg == NULL)
|
||
{
|
||
return;
|
||
}
|
||
|
||
sip_copy_via_tx(&(src_msg->via_ctx),dst_msg);
|
||
}
|
||
|
||
void sip_save_rx_via(HSIP_MSG * rx_msg, PPSN_CTX * dst_ctx)
|
||
{
|
||
if (rx_msg == NULL || dst_ctx == NULL)
|
||
{
|
||
return;
|
||
}
|
||
|
||
HSIP_VIAH * src_via_hdr = (HSIP_VIAH *)pps_lookup_start(&(rx_msg->via_ctx));
|
||
|
||
while (src_via_hdr != NULL)
|
||
{
|
||
HSIP_VIAH * dst_via_hdr = sip_get_via_buf();
|
||
if (dst_via_hdr == NULL)
|
||
{
|
||
pps_lookup_end(&(rx_msg->via_ctx));
|
||
return;
|
||
}
|
||
|
||
memcpy(dst_via_hdr, src_via_hdr, sizeof(HSIP_VIAH));
|
||
|
||
if (src_via_hdr->via_string != NULL)
|
||
{
|
||
int slen = strlen(src_via_hdr->via_string);
|
||
dst_via_hdr->via_string = (char *)malloc(slen+1);
|
||
if (dst_via_hdr->via_string == NULL)
|
||
{
|
||
log_print(HT_LOG_ERR, "%s, memory error!!\r\n", __FUNCTION__);
|
||
pps_lookup_end(&(rx_msg->via_ctx));
|
||
sip_free_via_buf(dst_via_hdr);
|
||
return;
|
||
}
|
||
|
||
memcpy(dst_via_hdr->via_string, src_via_hdr->via_string, slen);
|
||
dst_via_hdr->via_string[slen] = '\0';
|
||
}
|
||
|
||
pps_ctx_ul_add(dst_ctx, dst_via_hdr);
|
||
|
||
src_via_hdr = (HSIP_VIAH *)pps_lookup_next(&(rx_msg->via_ctx), src_via_hdr);
|
||
}
|
||
|
||
pps_lookup_end(&(rx_msg->via_ctx));
|
||
}
|
||
|
||
void sip_copy_via_tx(PPSN_CTX * src_ctx, HSIP_MSG * tx_msg)
|
||
{
|
||
if (src_ctx == NULL || tx_msg == NULL)
|
||
{
|
||
return;
|
||
}
|
||
|
||
HSIP_VIAH * src_via_hdr = (HSIP_VIAH *)pps_lookup_start(src_ctx);
|
||
|
||
while (src_via_hdr != NULL)
|
||
{
|
||
HSIP_VIAH * dst_via_hdr = sip_get_via_buf();
|
||
if (dst_via_hdr == NULL)
|
||
{
|
||
pps_lookup_end(src_ctx);
|
||
return;
|
||
}
|
||
|
||
memcpy(dst_via_hdr, src_via_hdr, sizeof(HSIP_VIAH));
|
||
|
||
if (src_via_hdr->via_string != NULL)
|
||
{
|
||
int slen = strlen(src_via_hdr->via_string);
|
||
dst_via_hdr->via_string = tx_msg->msg_buf + tx_msg->buf_offset;
|
||
memcpy(dst_via_hdr->via_string, src_via_hdr->via_string, slen);
|
||
dst_via_hdr->via_string[slen] = '\0';
|
||
tx_msg->buf_offset += slen + 1;
|
||
}
|
||
|
||
pps_ctx_ul_add(&(tx_msg->via_ctx), dst_via_hdr);
|
||
|
||
src_via_hdr = (HSIP_VIAH *)pps_lookup_next(src_ctx, src_via_hdr);
|
||
}
|
||
|
||
pps_lookup_end(src_ctx);
|
||
}
|
||
|
||
void sip_new_ua_via(PPSN_CTX * dst_ctx, char * ua_ipstr, uint16 ua_port, int is_tcp)
|
||
{
|
||
HSIP_VIAH * via_hdr = sip_get_via_buf();
|
||
if (via_hdr == NULL)
|
||
{
|
||
return;
|
||
}
|
||
|
||
sprintf(via_hdr->branch, "z9hG4bK%08x%08x", sys_os_get_uptime(), rand());
|
||
strcpy(via_hdr->domain, ua_ipstr);
|
||
via_hdr->ip = inet_addr(ua_ipstr);
|
||
via_hdr->port = ua_port;
|
||
strcpy(via_hdr->sip_ver, "SIP/2.0");
|
||
|
||
char tmp_buf[512];
|
||
|
||
if (is_tcp == 1)
|
||
{
|
||
sprintf(tmp_buf, "SIP/2.0/TCP %s:%u;branch=%s", ua_ipstr, ua_port, via_hdr->branch);
|
||
}
|
||
else
|
||
{
|
||
sprintf(tmp_buf, "SIP/2.0/UDP %s:%u;branch=%s", ua_ipstr, ua_port, via_hdr->branch);
|
||
}
|
||
|
||
int len = strlen(tmp_buf);
|
||
via_hdr->via_string = (char *)malloc(len + 1);
|
||
if (via_hdr->via_string == NULL)
|
||
{
|
||
sip_free_via_buf(via_hdr);
|
||
return;
|
||
}
|
||
|
||
memcpy(via_hdr->via_string, tmp_buf, len);
|
||
via_hdr->via_string[len] = '\0';
|
||
|
||
pps_ctx_ul_add(dst_ctx, via_hdr);
|
||
}
|
||
|
||
/***********************************************************************\
|
||
实用函数: 复制消息中的Record-Route
|
||
\***********************************************************************/
|
||
void sip_save_rx_rr(HSIP_MSG * rx_msg, PPSN_CTX * dst_ctx)
|
||
{
|
||
if (rx_msg == NULL || dst_ctx == NULL)
|
||
{
|
||
return;
|
||
}
|
||
|
||
HDRV * src_rr_hdr = (HDRV *)pps_lookup_start(&(rx_msg->sip_ctx));
|
||
|
||
while (src_rr_hdr != NULL)
|
||
{
|
||
if (strcasecmp(src_rr_hdr->header, "Record-Route") != 0)
|
||
{
|
||
src_rr_hdr = (HDRV *)pps_lookup_next(&(rx_msg->sip_ctx), src_rr_hdr);
|
||
continue;
|
||
}
|
||
|
||
HDRV * dst_rr_hdr = hdrv_buf_get_idle();
|
||
if (dst_rr_hdr == NULL)
|
||
{
|
||
pps_lookup_end(&(rx_msg->sip_ctx));
|
||
return;
|
||
}
|
||
|
||
memcpy(dst_rr_hdr, src_rr_hdr, sizeof(HDRV));
|
||
|
||
if (src_rr_hdr->value_string != NULL)
|
||
{
|
||
int slen = strlen(src_rr_hdr->value_string);
|
||
dst_rr_hdr->value_string = (char *)malloc(slen+1);
|
||
if (dst_rr_hdr->value_string == NULL)
|
||
{
|
||
log_print(HT_LOG_ERR, "%s, memory error!!!\r\n", __FUNCTION__);
|
||
pps_lookup_end(&(rx_msg->sip_ctx));
|
||
hdrv_buf_free(dst_rr_hdr);
|
||
return;
|
||
}
|
||
|
||
memcpy(dst_rr_hdr->value_string, src_rr_hdr->value_string, slen);
|
||
dst_rr_hdr->value_string[slen] = '\0';
|
||
}
|
||
|
||
pps_ctx_ul_add(dst_ctx, dst_rr_hdr);
|
||
|
||
src_rr_hdr = (HDRV *)pps_lookup_next(&(rx_msg->sip_ctx), src_rr_hdr);
|
||
}
|
||
|
||
pps_lookup_end(&(rx_msg->sip_ctx));
|
||
}
|
||
|
||
/***********************************************************************\
|
||
实用函数: 复制消息中的某一行,注意:不要试图复制第一行
|
||
\***********************************************************************/
|
||
void sip_copy_msg_line(HSIP_MSG * src_msg, HSIP_MSG * dst_msg, const char * msg_hdr)
|
||
{
|
||
HDRV * src_line = sip_find_headline(src_msg, msg_hdr);
|
||
if (src_line == NULL)
|
||
{
|
||
return;
|
||
}
|
||
|
||
HDRV * dst_line = hdrv_buf_get_idle();
|
||
if (dst_line == NULL)
|
||
{
|
||
return;
|
||
}
|
||
|
||
strcpy(dst_line->header, src_line->header);
|
||
|
||
dst_line->value_string = dst_msg->msg_buf + dst_msg->buf_offset;
|
||
if (dst_line->value_string == NULL)
|
||
{
|
||
hdrv_buf_free(dst_line);
|
||
return;
|
||
}
|
||
|
||
strcpy(dst_line->value_string, src_line->value_string);
|
||
dst_msg->buf_offset += strlen(src_line->value_string) + 1;
|
||
|
||
pps_ctx_ul_add(&(dst_msg->sip_ctx), dst_line);
|
||
}
|
||
|
||
/***********************************************************************\
|
||
实用函数: 释放消息
|
||
\***********************************************************************/
|
||
void sip_free_msg(HSIP_MSG * msg)
|
||
{
|
||
if (msg == NULL)
|
||
{
|
||
return;
|
||
}
|
||
|
||
sip_free_msg_content(msg);
|
||
sip_free_msg_buf(msg);
|
||
}
|
||
|
||
void sip_free_msg_content(HSIP_MSG * msg)
|
||
{
|
||
if (msg == NULL)
|
||
{
|
||
return;
|
||
}
|
||
|
||
sip_free_msg_ctx(msg, 0); // 释放SIP描述链表
|
||
sip_free_msg_ctx(msg, 1); // 释放SDP描述链表
|
||
sip_free_msg_via_ctx(msg); // 释放VIA描述链表
|
||
|
||
net_buf_free(msg->msg_buf); // 释放消息缓冲区
|
||
}
|
||
|
||
// 0:sip list; 1:sdp list;
|
||
void sip_free_msg_ctx(HSIP_MSG * msg, int type)
|
||
{
|
||
PPSN_CTX * p_free_ctx = NULL;
|
||
|
||
switch (type)
|
||
{
|
||
case 0:
|
||
p_free_ctx = &(msg->sip_ctx);
|
||
break;
|
||
|
||
case 1:
|
||
p_free_ctx = &(msg->sdp_ctx);
|
||
break;
|
||
}
|
||
|
||
if (p_free_ctx == NULL)
|
||
{
|
||
return;
|
||
}
|
||
|
||
hdrv_ctx_free(p_free_ctx);
|
||
}
|
||
|
||
void sip_free_msg_via_ctx(HSIP_MSG * msg)
|
||
{
|
||
if (msg == NULL)
|
||
{
|
||
return;
|
||
}
|
||
|
||
PPSN_CTX * p_via_ctx = &(msg->via_ctx);
|
||
|
||
HSIP_VIAH * p_free = (HSIP_VIAH *)pps_lookup_start(p_via_ctx);
|
||
while (p_free != NULL)
|
||
{
|
||
HSIP_VIAH * p_next = (HSIP_VIAH *)pps_lookup_next(p_via_ctx, p_free);
|
||
pps_ctx_ul_del(p_via_ctx, p_free);
|
||
sip_free_via_buf(p_free);
|
||
|
||
p_free = p_next;
|
||
}
|
||
pps_lookup_end(p_via_ctx);
|
||
}
|
||
|
||
void sip_free_ua_via_ctx(PPSN_CTX * p_via_ctx)
|
||
{
|
||
if (p_via_ctx == NULL)
|
||
{
|
||
return;
|
||
}
|
||
|
||
HSIP_VIAH * p_free = (HSIP_VIAH *)pps_lookup_start(p_via_ctx);
|
||
while (p_free != NULL)
|
||
{
|
||
HSIP_VIAH * p_next = (HSIP_VIAH *)pps_lookup_next(p_via_ctx, p_free);
|
||
|
||
if (p_free->via_string != NULL)
|
||
{
|
||
free(p_free->via_string);
|
||
p_free->via_string = NULL;
|
||
}
|
||
|
||
pps_ctx_ul_del(p_via_ctx, p_free);
|
||
sip_free_via_buf(p_free);
|
||
|
||
p_free = p_next;
|
||
}
|
||
pps_lookup_end(p_via_ctx);
|
||
}
|
||
|
||
void sip_free_ua_rr_ctx(PPSN_CTX * p_rr_ctx)
|
||
{
|
||
if (p_rr_ctx == NULL)
|
||
{
|
||
return;
|
||
}
|
||
|
||
HDRV * p_free = (HDRV *)pps_lookup_start(p_rr_ctx);
|
||
while (p_free != NULL)
|
||
{
|
||
HDRV * p_next = (HDRV *)pps_lookup_next(p_rr_ctx, p_free);
|
||
|
||
if (p_free->value_string != NULL)
|
||
{
|
||
free(p_free->value_string);
|
||
p_free->value_string = NULL;
|
||
}
|
||
|
||
pps_ctx_ul_del(p_rr_ctx, p_free);
|
||
hdrv_buf_free(p_free);
|
||
|
||
p_free = p_next;
|
||
}
|
||
pps_lookup_end(p_rr_ctx);
|
||
}
|
||
|
||
/***********************************************************************\
|
||
实用函数: 消息到事件的转换
|
||
\***********************************************************************/
|
||
CSEVT sip_get_msg_event(HSIP_MSG * rx_msg)
|
||
{
|
||
CSEVT event = (CSEVT)0;
|
||
|
||
if (rx_msg->msg_type == 0)
|
||
{
|
||
switch (rx_msg->msg_sub_type)
|
||
{
|
||
case SIP_MT_INV:
|
||
event = CSE_Call_Recv;
|
||
break;
|
||
|
||
case SIP_MT_ACK:
|
||
event = CSE_ACK_Recv;
|
||
break;
|
||
|
||
case SIP_MT_BYE:
|
||
event = CSE_Hang_Recv;
|
||
break;
|
||
|
||
case SIP_MT_CAN:
|
||
event = CSE_Cancel_Recv;
|
||
break;
|
||
|
||
case SIP_MT_OPT:
|
||
break;
|
||
|
||
case SIP_MT_MSG:
|
||
event = CSE_Message_Recv;
|
||
break;
|
||
|
||
case SIP_MT_PRACK:
|
||
event = CSE_PRACK_Recv;
|
||
break;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (rx_msg->msg_sub_type >= 600)
|
||
event = CSE_6xx_Recv;
|
||
else if (rx_msg->msg_sub_type >= 500)
|
||
event = CSE_5xx_Recv;
|
||
else if (rx_msg->msg_sub_type >= 400)
|
||
event = CSE_4xx_Recv;
|
||
else if (rx_msg->msg_sub_type >= 300)
|
||
event = CSE_3xx_Recv;
|
||
else if (rx_msg->msg_sub_type == 202)
|
||
event = CSE_202_Recv;
|
||
else if (rx_msg->msg_sub_type == 200)
|
||
{
|
||
char type_buf[64];
|
||
sip_get_msg_cseq_type(rx_msg, type_buf, sizeof(type_buf));
|
||
|
||
if (strcasecmp(type_buf,"INVITE") == 0)
|
||
event = CSE_IOK_Recv;
|
||
else if (strcasecmp(type_buf,"BYE") == 0)
|
||
event = CSE_BOK_Recv;
|
||
else if (strcasecmp(type_buf,"MESSAGE") == 0)
|
||
event = CSE_MOK_Recv;
|
||
else if (strcasecmp(type_buf,"CANCEL") == 0)
|
||
event = CSE_COK_Recv;
|
||
else
|
||
event = (CSEVT)0;
|
||
}
|
||
else if (rx_msg->msg_sub_type == 180 || rx_msg->msg_sub_type == 183)
|
||
event = CSE_180_Recv;
|
||
else if (rx_msg->msg_sub_type == 100)
|
||
event = CSE_100_Recv;
|
||
else
|
||
event = (CSEVT)0;
|
||
}
|
||
|
||
return event;
|
||
}
|
||
|
||
/***********************************************************************\
|
||
实用函数: 获取接收消息中的连接地址
|
||
返回值:
|
||
\***********************************************************************/
|
||
BOOL sip_get_remote_media_ip(HSIP_MSG * rx_msg, uint32 * media_ip)
|
||
{
|
||
HDRV * pHdr = sip_find_sdp_headline(rx_msg, "c");
|
||
if ((pHdr != NULL) && (pHdr->value_string != NULL) && (strlen(pHdr->value_string) > 0))
|
||
{
|
||
int next_offset;
|
||
char tmp_buf[128];
|
||
|
||
GetLineWord(pHdr->value_string, 0, strlen(pHdr->value_string),
|
||
tmp_buf, sizeof(tmp_buf), &next_offset, WORD_TYPE_STRING);
|
||
if (strcasecmp(tmp_buf, "IN") != 0)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
GetLineWord(pHdr->value_string, next_offset, strlen(pHdr->value_string),
|
||
tmp_buf, sizeof(tmp_buf), &next_offset, WORD_TYPE_STRING);
|
||
if (strcasecmp(tmp_buf,"IP4") != 0)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
GetLineWord(pHdr->value_string, next_offset, strlen(pHdr->value_string),
|
||
tmp_buf, sizeof(tmp_buf), &next_offset, WORD_TYPE_STRING);
|
||
|
||
if (is_ip_address(tmp_buf))
|
||
{
|
||
*media_ip = inet_addr(tmp_buf);
|
||
return TRUE;
|
||
}
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
BOOL sip_get_remote_rtp_mux_info(HSIP_MSG * rx_msg, uint32 * mux_id)
|
||
{
|
||
int mux_flag = 0, next_offset;
|
||
uint32 mid = 0;
|
||
|
||
HDRV * pHdr = (HDRV *)pps_lookup_start(&(rx_msg->sdp_ctx));
|
||
while (pHdr != NULL)
|
||
{
|
||
if (strcasecmp(pHdr->header, "m") == 0)
|
||
{
|
||
// 这里应该是已经到具体媒体描述了
|
||
break;
|
||
}
|
||
|
||
char * ptr = pHdr->value_string;
|
||
if (memcmp(ptr, "rtpport-mux", strlen("rtpport-mux")) == 0)
|
||
{
|
||
mux_flag = 1;
|
||
}
|
||
else if (memcmp(ptr, "muxid:", strlen("muxid:")) == 0)
|
||
{
|
||
ptr += strlen("muxid:");
|
||
|
||
char id_buf[64];
|
||
GetLineWord(ptr, 0, strlen(ptr), id_buf, sizeof(id_buf), &next_offset, WORD_TYPE_NUM);
|
||
if (id_buf[0] == '\0')
|
||
{
|
||
pps_lookup_end(&(rx_msg->sdp_ctx));
|
||
return FALSE;
|
||
}
|
||
|
||
mid = atoi(id_buf);
|
||
}
|
||
|
||
pHdr = (HDRV *)pps_lookup_next(&(rx_msg->sdp_ctx), pHdr);
|
||
}
|
||
pps_lookup_end(&(rx_msg->sdp_ctx));
|
||
|
||
if (mux_flag == 1 && mid > 0)
|
||
{
|
||
*mux_id = mid;
|
||
return TRUE;
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
/***********************************************************************\
|
||
实用函数: 获取接收消息中的sdp a=setup:active|passive
|
||
\***********************************************************************/
|
||
BOOL sip_get_sdp_setup_mode(HSIP_MSG * rx_msg, const char * cap_name, int * mode)
|
||
{
|
||
*mode = 0; // default to passive mode
|
||
|
||
int cap_match = 0;
|
||
|
||
HDRV * pHdr = (HDRV *)pps_lookup_start(&(rx_msg->sdp_ctx));
|
||
while (pHdr != NULL)
|
||
{
|
||
if (0 == cap_match)
|
||
{
|
||
if (strcasecmp(pHdr->header, "m") != 0)
|
||
{
|
||
pHdr = (HDRV *)pps_lookup_next(&(rx_msg->sdp_ctx), pHdr);
|
||
continue;
|
||
}
|
||
|
||
int next_offset;
|
||
char media_type[128];
|
||
|
||
GetLineWord(pHdr->value_string, 0, strlen(pHdr->value_string),
|
||
media_type, sizeof(media_type), &next_offset, WORD_TYPE_STRING);
|
||
|
||
if (strcasecmp(media_type, cap_name) != 0)
|
||
{
|
||
pHdr = (HDRV *)pps_lookup_next(&(rx_msg->sdp_ctx), pHdr);
|
||
continue;
|
||
}
|
||
|
||
cap_match = 1;
|
||
}
|
||
else if (strcasecmp(pHdr->header, "m") == 0)
|
||
{
|
||
int next_offset;
|
||
char media_type[128];
|
||
|
||
GetLineWord(pHdr->value_string, 0, strlen(pHdr->value_string),
|
||
media_type, sizeof(media_type), &next_offset, WORD_TYPE_STRING);
|
||
|
||
if (strcasecmp(media_type, cap_name) != 0)
|
||
{
|
||
cap_match = 0;
|
||
pHdr = (HDRV *)pps_lookup_next(&(rx_msg->sdp_ctx), pHdr);
|
||
continue;
|
||
}
|
||
}
|
||
|
||
if (strcasecmp(pHdr->header, "a") == 0)
|
||
{
|
||
if (strcasecmp(pHdr->value_string, "setup:active") == 0)
|
||
{
|
||
*mode = 1;
|
||
break;
|
||
}
|
||
else if (strcasecmp(pHdr->value_string, "setup:passive") == 0)
|
||
{
|
||
*mode = 0;
|
||
break;
|
||
}
|
||
}
|
||
|
||
pHdr = (HDRV *)pps_lookup_next(&(rx_msg->sdp_ctx), pHdr);
|
||
}
|
||
pps_lookup_end(&(rx_msg->sdp_ctx));
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
/***********************************************************************\
|
||
实用函数: 获取接收消息中的sdp s=session Play Playback voice music
|
||
\***********************************************************************/
|
||
BOOL sip_get_sdp_session_name(HSIP_MSG * rx_msg, char * sbuf, int mlen)
|
||
{
|
||
HDRV * pHdr = sip_find_sdp_headline(rx_msg, "s");
|
||
if ((pHdr != NULL) && (pHdr->value_string != NULL) && (strlen(pHdr->value_string) > 0))
|
||
{
|
||
strncpy(sbuf, pHdr->value_string, mlen);
|
||
return TRUE;
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
/***********************************************************************\
|
||
实用函数: 获取接收消息中的sdp u=xxxxx
|
||
\***********************************************************************/
|
||
BOOL sip_get_sdp_uname(HSIP_MSG * rx_msg, char * uname, int ulen)
|
||
{
|
||
HDRV * pHdr = sip_find_sdp_headline(rx_msg, "u");
|
||
if ((pHdr != NULL) && (pHdr->value_string != NULL) && (strlen(pHdr->value_string) > 0))
|
||
{
|
||
strncpy(uname, pHdr->value_string, ulen);
|
||
return TRUE;
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
/***********************************************************************\
|
||
实用函数: 获取接收消息中的sdp t=xxxxx xxxxx
|
||
\***********************************************************************/
|
||
BOOL sip_get_sdp_ttime(HSIP_MSG * rx_msg, uint32 * p_st, uint32 * p_et)
|
||
{
|
||
HDRV * pHdr = sip_find_sdp_headline(rx_msg, "t");
|
||
if ((pHdr != NULL) && (pHdr->value_string != NULL) && (strlen(pHdr->value_string) > 0))
|
||
{
|
||
char * p_t1;
|
||
char * p_t2;
|
||
char sbuf[128];
|
||
|
||
strncpy(sbuf, pHdr->value_string, sizeof(sbuf));
|
||
|
||
p_t1 = sbuf;
|
||
while (*p_t1 == ' ')
|
||
{
|
||
p_t1++;
|
||
}
|
||
|
||
p_t2 = strchr(p_t1, ' ');
|
||
if (p_t2 == NULL)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
*p_t2 = '\0';
|
||
p_t2++;
|
||
|
||
while(*p_t2 == ' ')
|
||
{
|
||
p_t2++;
|
||
}
|
||
|
||
*p_st = (uint32)strtoul(p_t1, NULL, 0);
|
||
*p_et = (uint32)strtoul(p_t2, NULL, 0);
|
||
}
|
||
else
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
/***********************************************************************\
|
||
实用函数: 获取接收消息中的sdp y=xxxxx
|
||
\***********************************************************************/
|
||
BOOL sip_get_sdp_yname(HSIP_MSG * rx_msg, char * yname, int ylen)
|
||
{
|
||
HDRV * pHdr = sip_find_sdp_headline(rx_msg, "y");
|
||
if ((pHdr != NULL) && (pHdr->value_string != NULL) && (strlen(pHdr->value_string) > 0))
|
||
{
|
||
strncpy(yname, pHdr->value_string, ylen);
|
||
return TRUE;
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
/***********************************************************************\
|
||
实用函数: 获取接收消息中音频或视频能力集描述开始位置
|
||
\***********************************************************************/
|
||
HDRV * sip_find_mdesc_point(HSIP_MSG * rx_msg, HDRV * pStartHdr, const char * cap_name, int * next_offset)
|
||
{
|
||
HDRV * pHdr = pStartHdr;
|
||
char media_type[16];
|
||
|
||
for (; pHdr != NULL; pHdr = (HDRV *)pps_lookup_next(&(rx_msg->sdp_ctx), pHdr))
|
||
{
|
||
if (strcasecmp(pHdr->header, "m") != 0)
|
||
{
|
||
continue;
|
||
}
|
||
|
||
GetLineWord(pHdr->value_string, 0, strlen(pHdr->value_string),
|
||
media_type, sizeof(media_type), next_offset, WORD_TYPE_STRING);
|
||
|
||
if (strcasecmp(media_type, cap_name) == 0)
|
||
{
|
||
return pHdr;
|
||
}
|
||
}
|
||
|
||
return NULL;
|
||
}
|
||
|
||
/***********************************************************************\
|
||
实用函数: 获取接收消息中的音频或视频能力集
|
||
返回值:
|
||
*cap_count 能力个数
|
||
cap_array[] 能力集数组,最大 MAX_AVN 个
|
||
\***********************************************************************/
|
||
BOOL sip_get_remote_cap(HSIP_MSG * rx_msg, int m_index, const char * cap_name, int * cap_count, uint8 * cap_array, uint16 * rtp_port, int * is_tcp)
|
||
{
|
||
int i;
|
||
int next_offset = 0;
|
||
char media_port[16], tmp_buf[64];
|
||
|
||
*cap_count = 0;
|
||
|
||
HDRV * pHdr = (HDRV *)pps_lookup_start(&(rx_msg->sdp_ctx));
|
||
|
||
for (i=-1; i<m_index; i++) // 获取第index个对应的audio/video描述
|
||
{
|
||
pHdr = (HDRV *)pps_lookup_next(&(rx_msg->sdp_ctx), pHdr);
|
||
pHdr = sip_find_mdesc_point(rx_msg, pHdr, cap_name, &next_offset); // 查找对应的媒体描述
|
||
if (pHdr == NULL)
|
||
{
|
||
pps_lookup_end(&(rx_msg->sdp_ctx));
|
||
return FALSE;
|
||
}
|
||
}
|
||
|
||
GetLineWord(pHdr->value_string,next_offset,strlen(pHdr->value_string),
|
||
media_port,sizeof(media_port),&next_offset,WORD_TYPE_NUM);
|
||
|
||
GetLineWord(pHdr->value_string,next_offset,strlen(pHdr->value_string),
|
||
tmp_buf,sizeof(tmp_buf),&next_offset,WORD_TYPE_STRING);
|
||
|
||
if (strcasecmp(tmp_buf, "RTP/AVP") == 0)
|
||
{
|
||
*is_tcp = 0;
|
||
}
|
||
else if (strcasecmp(tmp_buf, "TCP/RTP/AVP") == 0)
|
||
{
|
||
*is_tcp = 1;
|
||
}
|
||
else
|
||
{
|
||
pps_lookup_end(&(rx_msg->sdp_ctx));
|
||
return FALSE;
|
||
}
|
||
|
||
int count = 0;
|
||
BOOL cap_next_flag = TRUE;
|
||
|
||
do {
|
||
cap_next_flag = GetLineWord(pHdr->value_string,next_offset,strlen(pHdr->value_string),
|
||
tmp_buf,sizeof(tmp_buf),&next_offset,WORD_TYPE_NUM);
|
||
if (tmp_buf[0] != '\0')
|
||
{
|
||
if (count >= MAX_AVN)
|
||
{
|
||
pps_lookup_end(&(rx_msg->sdp_ctx));
|
||
return FALSE; // 能力太强了!!!
|
||
}
|
||
|
||
cap_array[count++] = (uint8)atol(tmp_buf);
|
||
*cap_count = count;
|
||
}
|
||
} while(cap_next_flag);
|
||
|
||
if (count > 0)
|
||
{
|
||
*rtp_port = (uint16)atol(media_port);
|
||
pps_lookup_end(&(rx_msg->sdp_ctx));
|
||
return TRUE;
|
||
}
|
||
|
||
pps_lookup_end(&(rx_msg->sdp_ctx));
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
/***********************************************************************\
|
||
实用函数: 获取接收消息中的连接地址
|
||
+ UDP端口复用信息:
|
||
a=rtpport-mux
|
||
a=muxid:11722
|
||
\***********************************************************************/
|
||
BOOL sip_sdp_connect_ipv4_parse(char * p_desc, uint32 * ipv4)
|
||
{
|
||
char tmp_buf[128];
|
||
int next_offset;
|
||
|
||
GetLineWord(p_desc, 0, strlen(p_desc), tmp_buf, sizeof(tmp_buf), &next_offset, WORD_TYPE_STRING);
|
||
|
||
if (strcasecmp(tmp_buf, "IN") != 0)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
GetLineWord(p_desc, next_offset, strlen(p_desc), tmp_buf, sizeof(tmp_buf), &next_offset, WORD_TYPE_STRING);
|
||
|
||
if (strcasecmp(tmp_buf, "IP4") != 0)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
GetLineWord(p_desc, next_offset, strlen(p_desc), tmp_buf, sizeof(tmp_buf), &next_offset, WORD_TYPE_STRING);
|
||
|
||
log_print(HT_LOG_INFO, "%s, media_ip=%s\r\n", __FUNCTION__, tmp_buf);
|
||
|
||
char * ptr = tmp_buf;
|
||
while (*ptr != '/' && *ptr != '\0')
|
||
{
|
||
ptr++;
|
||
}
|
||
|
||
if (*ptr == '/')
|
||
{
|
||
*ptr = '\0';
|
||
}
|
||
|
||
if (is_ip_address(tmp_buf))
|
||
{
|
||
*ipv4 = inet_addr(tmp_buf);
|
||
log_print(HT_LOG_INFO, "%s, media_ip=0x%08x\r\n", __FUNCTION__, *ipv4);
|
||
return TRUE;
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
/***********************************************************************\
|
||
实用函数: 获取接收消息中的音频或视频能力描述
|
||
输入值:
|
||
cap_count 能力个数
|
||
输出值:
|
||
char * cap_desc[] 能力描述串,最大 MAX_AVN 个
|
||
\***********************************************************************/
|
||
BOOL sip_get_remote_cap_desc(HSIP_MSG * rx_msg, const char * cap_name, char cap_desc[][MAX_AVDESCLEN])
|
||
{
|
||
int next_offset = 0;
|
||
int index = 0;
|
||
|
||
HDRV * pHdr = (HDRV *)pps_lookup_start(&(rx_msg->sdp_ctx));
|
||
|
||
pHdr = sip_find_mdesc_point(rx_msg, pHdr, cap_name, &next_offset); // 查找对应的媒体描述
|
||
if (pHdr == NULL)
|
||
{
|
||
pps_lookup_end(&(rx_msg->sdp_ctx));
|
||
return FALSE;
|
||
}
|
||
|
||
// 清空描述数组
|
||
for (index=0; index<MAX_AVN; index++)
|
||
{
|
||
cap_desc[index][0] = '\0';
|
||
}
|
||
|
||
// 查找媒体描述 a=rtpmap:4 G723/8000 ...
|
||
index = 0;
|
||
pHdr = (HDRV *)pps_lookup_next(&(rx_msg->sdp_ctx), pHdr);
|
||
while (pHdr != NULL)
|
||
{
|
||
if (strcasecmp(pHdr->header, "m") == 0)
|
||
{
|
||
// 这里应该是已经到下一个描述了
|
||
break;
|
||
}
|
||
|
||
if (index >= MAX_AVN)
|
||
{
|
||
break;
|
||
}
|
||
|
||
#if __LINUX_OS__
|
||
snprintf(cap_desc[index], MAX_AVDESCLEN, "%s=%s", pHdr->header, pHdr->value_string);
|
||
#else
|
||
sprintf(cap_desc[index], "%s=%s", pHdr->header, pHdr->value_string);
|
||
#endif
|
||
index++;
|
||
pHdr = (HDRV *)pps_lookup_next(&(rx_msg->sdp_ctx), pHdr);
|
||
}
|
||
|
||
pps_lookup_end(&(rx_msg->sdp_ctx));
|
||
|
||
return (index != 0);
|
||
}
|
||
|
||
/***********************************************************************\
|
||
SDP描述解析
|
||
m=video 0 RTP/AVP 96
|
||
a=rtpmap:96 H264/90000
|
||
a=fmtp:96 packetization-mode=1; profile-level-id=4D001F; sprop-parameter-sets=Z00AH5WoFAFuQA==,aO48gA==
|
||
a=recvonly
|
||
m=audio 6000 RTP/AVP 8 101
|
||
a=rtpmap:8 PCMA/8000
|
||
a=rtpmap:101 telephone-event/8000
|
||
a=fmtp:101 0-15
|
||
a=ptime:20
|
||
a=sendrecv
|
||
\***********************************************************************/
|
||
SDPINFO * sip_sdp_codec_find_pt(SDPINFO * p_ary, int ary_cnt, const char * codec_name)
|
||
{
|
||
int i;
|
||
|
||
for (i=0; i<ary_cnt; i++)
|
||
{
|
||
// 该单元已经无效,后面都应该是无效的
|
||
if (p_ary[i].is_valid == 0)
|
||
{
|
||
break;
|
||
}
|
||
|
||
if (strcasecmp(p_ary[i].encoder, codec_name) == 0)
|
||
{
|
||
return &(p_ary[i]);
|
||
}
|
||
}
|
||
|
||
return NULL;
|
||
}
|
||
|
||
SDPINFO * sip_sdp_pt_find(SDPINFO * p_ary, int ary_cnt, int pt)
|
||
{
|
||
int i;
|
||
|
||
for (i=0; i<ary_cnt; i++)
|
||
{
|
||
// 该单元已经无效,后面都应该是无效的
|
||
if (p_ary[i].is_valid == 0)
|
||
{
|
||
break;
|
||
}
|
||
|
||
if (p_ary[i].pt == pt)
|
||
{
|
||
return &(p_ary[i]);
|
||
}
|
||
}
|
||
|
||
return NULL;
|
||
}
|
||
|
||
BOOL sip_single_sdp_desc_parse(HSIP_MSG * rx_msg, HDRV * p_start, const char * cap_name, int cap_pt, SDPINFO * p_sdp, uint32 * ipv4)
|
||
{
|
||
char pt_buf[16];
|
||
char code_buf[64];
|
||
char * ptr = NULL;
|
||
int pt, next_offset = 0;
|
||
|
||
p_sdp->is_valid = 1;
|
||
p_sdp->pt = cap_pt;
|
||
|
||
if (strcasecmp(cap_name, "audio") == 0)
|
||
{
|
||
p_sdp->mtype = SDP_MEDIA_AUDIO;
|
||
p_sdp->hz = 8000; // 先设置缺省采样
|
||
p_sdp->chn = 1;
|
||
}
|
||
else if (strcasecmp(cap_name, "video") == 0)
|
||
{
|
||
p_sdp->mtype = SDP_MEDIA_VIDEO;
|
||
p_sdp->hz = 90000; // 先设置缺省采样
|
||
}
|
||
else
|
||
{
|
||
p_sdp->mtype = SDP_MEDIA_DATA;
|
||
}
|
||
|
||
HDRV * pHdr = (HDRV *)pps_lookup_next(&(rx_msg->sdp_ctx), p_start);
|
||
while (pHdr != NULL)
|
||
{
|
||
if (strcasecmp(pHdr->header, "m") == 0)
|
||
{
|
||
// 这里应该是已经到下一个描述了
|
||
break;
|
||
}
|
||
|
||
ptr = pHdr->value_string;
|
||
|
||
if (memcmp(ptr, "rtpmap:", strlen("rtpmap:")) == 0)
|
||
{
|
||
next_offset = 0;
|
||
ptr += strlen("rtpmap:");
|
||
|
||
if (GetLineWord(ptr, 0, strlen(ptr), pt_buf, sizeof(pt_buf), &next_offset, WORD_TYPE_NUM) == FALSE)
|
||
{
|
||
// 这个后面必须还要有描述
|
||
pps_lookup_end(&(rx_msg->sdp_ctx));
|
||
return FALSE;
|
||
}
|
||
|
||
pt = atoi(pt_buf);
|
||
if (pt != cap_pt)
|
||
{
|
||
pHdr = (HDRV *)pps_lookup_next(&(rx_msg->sdp_ctx), pHdr);
|
||
continue;
|
||
}
|
||
|
||
strncpy(p_sdp->rtpmap, ptr, sizeof(p_sdp->rtpmap) - 1);
|
||
|
||
// H264/90000 || PS/90000 || JPEG/90000
|
||
// AMR/8000/1
|
||
GetLineWord(ptr, next_offset, strlen(ptr) - next_offset, code_buf, sizeof(code_buf), &next_offset, WORD_TYPE_STRING);
|
||
ptr = strchr(code_buf, '/');
|
||
if (ptr)
|
||
{
|
||
*ptr = '\0'; ptr++;
|
||
}
|
||
|
||
strncpy(p_sdp->encoder, code_buf, sizeof(p_sdp->encoder) - 1);
|
||
|
||
if (ptr)
|
||
{
|
||
char * ptr_e = strchr(ptr, '/');
|
||
if (ptr_e)
|
||
{
|
||
*ptr_e = '\0';
|
||
}
|
||
|
||
p_sdp->hz = atoi(ptr);
|
||
|
||
if (ptr_e)
|
||
{
|
||
ptr_e++;
|
||
p_sdp->chn = atoi(ptr_e);
|
||
}
|
||
else
|
||
{
|
||
p_sdp->chn = 1;
|
||
}
|
||
}
|
||
}
|
||
else if (memcmp(ptr, "fmtp:", strlen("fmtp:")) == 0)
|
||
{
|
||
ptr += strlen("fmtp:");
|
||
|
||
if (GetLineWord(ptr, 0, strlen(ptr), pt_buf, sizeof(pt_buf), &next_offset, WORD_TYPE_NUM) == FALSE)
|
||
{
|
||
// 这个后面必须还要有描述
|
||
pps_lookup_end(&(rx_msg->sdp_ctx));
|
||
return FALSE;
|
||
}
|
||
|
||
pt = atoi(pt_buf);
|
||
if (pt != cap_pt)
|
||
{
|
||
pHdr = (HDRV *)pps_lookup_next(&(rx_msg->sdp_ctx), pHdr);
|
||
continue;
|
||
}
|
||
|
||
strncpy(p_sdp->desc, ptr, sizeof(p_sdp->desc) - 1);
|
||
}
|
||
else if (memcmp(ptr, "ptime:", strlen("ptime:")) == 0)
|
||
{
|
||
ptr += strlen("ptime:");
|
||
|
||
char ptime_buf[64];
|
||
GetLineWord(ptr, 0, strlen(ptr), ptime_buf, sizeof(ptime_buf), &next_offset, WORD_TYPE_NUM);
|
||
int ptime = atoi(ptime_buf);
|
||
if (ptime < 0)
|
||
{
|
||
pps_lookup_end(&(rx_msg->sdp_ctx));
|
||
return FALSE;
|
||
}
|
||
|
||
p_sdp->ptime = ptime;
|
||
}
|
||
else if (strcasecmp(pHdr->header, "b") == 0)
|
||
{
|
||
char bws[16];
|
||
if (memcmp(ptr, "TIAS:", strlen("TIAS:")) == 0)
|
||
{
|
||
strcpy(bws, "TIAS:"); // bps
|
||
}
|
||
else if (memcmp(ptr, "AS:", strlen("AS:")) == 0)
|
||
{
|
||
strcpy(bws, "AS:"); // kbps
|
||
}
|
||
else
|
||
{
|
||
pHdr = (HDRV *)pps_lookup_next(&(rx_msg->sdp_ctx), pHdr);
|
||
continue;
|
||
}
|
||
|
||
// bps
|
||
ptr += strlen(bws);
|
||
GetLineWord(ptr, 0, strlen(ptr), pt_buf, sizeof(pt_buf), &next_offset, WORD_TYPE_NUM);
|
||
int bw = atoi(pt_buf);
|
||
if (bw < 0)
|
||
{
|
||
pps_lookup_end(&(rx_msg->sdp_ctx));
|
||
return FALSE;
|
||
}
|
||
|
||
p_sdp->bps = bw;
|
||
|
||
if (bws[0] == 'A') // AS
|
||
{
|
||
p_sdp->bps *= 1000;
|
||
}
|
||
}
|
||
else if (strcasecmp(pHdr->header, "c") == 0) // 单独的媒体地址
|
||
{
|
||
sip_sdp_connect_ipv4_parse(pHdr->value_string, ipv4);
|
||
}
|
||
else if (memcmp(ptr, "sendonly", strlen("sendonly")) == 0)
|
||
{
|
||
p_sdp->sendrecv = SDP_SENDRECV_TXONLY;
|
||
}
|
||
else if (memcmp(ptr, "recvonly", strlen("recvonly")) == 0)
|
||
{
|
||
p_sdp->sendrecv = SDP_SENDRECV_RXONLY;
|
||
}
|
||
else if (memcmp(ptr, "sendrecv", strlen("sendrecv")) == 0)
|
||
{
|
||
p_sdp->sendrecv = SDP_SENDRECV_TXRX;
|
||
}
|
||
else
|
||
{
|
||
}
|
||
|
||
pHdr = (HDRV *)pps_lookup_next(&(rx_msg->sdp_ctx), pHdr);
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
BOOL sip_sdp_media_desc_parse(HSIP_MSG * rx_msg, int m_index, const char * cap_name, int cap_cnt, uint8 * cap_array, SDPINFO * p_ary, uint32 * ipv4)
|
||
{
|
||
int i, next_offset = 0;
|
||
|
||
HDRV * pHdr = (HDRV *)pps_lookup_start(&(rx_msg->sdp_ctx));
|
||
|
||
for (i=-1; i<m_index; i++) // 获取第index个对应的audio/video描述
|
||
{
|
||
pHdr = (HDRV *)pps_lookup_next(&(rx_msg->sdp_ctx), pHdr);
|
||
pHdr = sip_find_mdesc_point(rx_msg, pHdr, cap_name, &next_offset); // 查找对应的媒体描述
|
||
if (pHdr == NULL)
|
||
{
|
||
pps_lookup_end(&(rx_msg->sdp_ctx));
|
||
return FALSE;
|
||
}
|
||
}
|
||
|
||
for (i = 0; i < cap_cnt; i++)
|
||
{
|
||
sip_single_sdp_desc_parse(rx_msg, pHdr, cap_name, cap_array[i], p_ary + i, ipv4);
|
||
}
|
||
pps_lookup_end(&(rx_msg->sdp_ctx));
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
/***********************************************************************\
|
||
加密解析:
|
||
\***********************************************************************/
|
||
|
||
/***********************************************************************\
|
||
潮流网关CBCOM 模式:
|
||
msg ^= 'GS'
|
||
\***********************************************************************/
|
||
REQMTV gs_req_mtvs[] =
|
||
{
|
||
{SIP_MT_REG, "REGISTER"},
|
||
{SIP_MT_INV, "INVITE"},
|
||
{SIP_MT_ACK, "ACK"},
|
||
{SIP_MT_BYE, "BYE"},
|
||
{SIP_MT_CAN, "CANCEL"},
|
||
{SIP_MT_OPT, "OPTIONS"},
|
||
{SIP_MT_MSG, "MESSAGE"},
|
||
{SIP_MT_SUB, "SUBSCRIBE"},
|
||
{SIP_MT_NTF, "NOTIFY"},
|
||
{SIP_MT_REF, "REFER"},
|
||
{SIP_MT_PRACK, "PRACK"},
|
||
{SIP_MT_NULL, "SIP/2.0"}
|
||
};
|
||
|
||
int gs_crypt_init = 0;
|
||
|
||
void sip_gs_msg_crypt(char * buf, int len)
|
||
{
|
||
int i;
|
||
|
||
for (i=0; i<(len+1); i+=2)
|
||
{
|
||
buf[i] ^= 'K';
|
||
buf[i+1] ^= 'X';
|
||
}
|
||
|
||
buf[len] = '\0';
|
||
}
|
||
|
||
void sip_gs_msg_crypt_all(char * buf, int len)
|
||
{
|
||
int i;
|
||
|
||
for (i=0; i<(len>>1); i++)
|
||
{
|
||
buf[i<<1] ^= 'K';
|
||
buf[(i<<1)+1] ^= 'X';
|
||
}
|
||
|
||
if (len & 1)
|
||
{
|
||
buf[len -1] ^= 'X';
|
||
}
|
||
|
||
buf[len] = '\0';
|
||
}
|
||
|
||
void sip_gs_cbcom_init()
|
||
{
|
||
uint32 i;
|
||
|
||
if (gs_crypt_init)
|
||
{
|
||
return;
|
||
}
|
||
|
||
gs_crypt_init = 1;
|
||
|
||
for (i=0; i<sizeof(gs_req_mtvs)/sizeof(REQMTV); i++)
|
||
{
|
||
gs_req_mtvs[i].msg_len = strlen(gs_req_mtvs[i].msg_str);
|
||
sip_gs_msg_crypt(gs_req_mtvs[i].msg_str, gs_req_mtvs[i].msg_len);
|
||
}
|
||
}
|
||
|
||
BOOL sip_gs_is_cbcom(char * msg_buf, int len)
|
||
{
|
||
uint32 i;
|
||
|
||
for (i=0; i<sizeof(gs_req_mtvs)/sizeof(REQMTV); i++)
|
||
{
|
||
if (memcmp(msg_buf, gs_req_mtvs[i].msg_str, gs_req_mtvs[i].msg_len) == 0)
|
||
{
|
||
return TRUE;
|
||
}
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
/***********************************************************************\
|
||
HSP软电话加密模式处理
|
||
msg ^= 'SECR'
|
||
\***********************************************************************/
|
||
REQMTV hsp_req_mtvs[] =
|
||
{
|
||
{SIP_MT_REG, "REGISTER"},
|
||
{SIP_MT_INV, "INVITE"},
|
||
{SIP_MT_ACK, "ACK"},
|
||
{SIP_MT_BYE, "BYE"},
|
||
{SIP_MT_CAN, "CANCEL"},
|
||
{SIP_MT_OPT, "OPTIONS"},
|
||
{SIP_MT_MSG, "MESSAGE"},
|
||
{SIP_MT_SUB, "SUBSCRIBE"},
|
||
{SIP_MT_NTF, "NOTIFY"},
|
||
{SIP_MT_REF, "REFER"},
|
||
{SIP_MT_PRACK, "PRACK"},
|
||
{SIP_MT_NULL, "SIP/2.0"}
|
||
};
|
||
|
||
int hsp_crypt_init = 0;
|
||
|
||
void sip_hsp_msg_crypt(char * buf, int len)
|
||
{
|
||
int i;
|
||
|
||
for (i=0; i<(len+3); i+=4)
|
||
{
|
||
buf[i+0] ^= 'S';
|
||
buf[i+1] ^= 'E';
|
||
buf[i+2] ^= 'C';
|
||
buf[i+3] ^= 'R';
|
||
}
|
||
|
||
buf[len] = '\0';
|
||
}
|
||
|
||
void sip_hsp_msg_crypt_all(char * buf, int len)
|
||
{
|
||
int i, j;
|
||
|
||
for (i=0; i<(len>>2); i++)
|
||
{
|
||
buf[(i<<2)+0] ^= 'S';
|
||
buf[(i<<2)+1] ^= 'E';
|
||
buf[(i<<2)+2] ^= 'C';
|
||
buf[(i<<2)+3] ^= 'R';
|
||
}
|
||
|
||
char crypt_str[] = "SECR";
|
||
|
||
for (j=0; j<(len & 3); j++)
|
||
{
|
||
buf[i+j] ^= crypt_str[j];
|
||
}
|
||
|
||
buf[len] = '\0';
|
||
}
|
||
|
||
void sip_hsp_crypt_init()
|
||
{
|
||
uint32 i;
|
||
|
||
if (hsp_crypt_init)
|
||
{
|
||
return;
|
||
}
|
||
|
||
hsp_crypt_init = 1;
|
||
|
||
for (i=0; i<sizeof(hsp_req_mtvs)/sizeof(REQMTV); i++)
|
||
{
|
||
hsp_req_mtvs[i].msg_len = strlen(hsp_req_mtvs[i].msg_str);
|
||
sip_hsp_msg_crypt(hsp_req_mtvs[i].msg_str, hsp_req_mtvs[i].msg_len);
|
||
}
|
||
}
|
||
|
||
BOOL sip_hsp_is_crypt(char * msg_buf, int len)
|
||
{
|
||
uint32 i;
|
||
|
||
for (i=0; i<sizeof(hsp_req_mtvs)/sizeof(REQMTV); i++)
|
||
{
|
||
if (memcmp(msg_buf, hsp_req_mtvs[i].msg_str, hsp_req_mtvs[i].msg_len) == 0)
|
||
{
|
||
return TRUE;
|
||
}
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
/***********************************************************************\
|
||
加密/解密预处理:
|
||
\***********************************************************************/
|
||
void sip_msg_crpty(char * msg_buf, int msg_buf_len, HSIP_MSG * msg)
|
||
{
|
||
if (sip_gs_is_cbcom(msg_buf, msg_buf_len))
|
||
{
|
||
msg->msg_crpty_mode = HCRPTY_GS;
|
||
sip_gs_msg_crypt_all(msg_buf, msg_buf_len);
|
||
}
|
||
else if (sip_hsp_is_crypt(msg_buf, msg_buf_len))
|
||
{
|
||
msg->msg_crpty_mode = HCRPTY_HSP;
|
||
sip_hsp_msg_crypt_all(msg_buf, msg_buf_len);
|
||
}
|
||
else
|
||
{
|
||
msg->msg_crpty_mode = HCRPTY_NULL;
|
||
}
|
||
}
|
||
|
||
/***********************************************************************\
|
||
消息描述符缓冲区管理:
|
||
\***********************************************************************/
|
||
PPSN_CTX * via_buf_fl = NULL;
|
||
PPSN_CTX * msg_buf_fl = NULL;
|
||
|
||
/***********************************************************************/
|
||
BOOL sip_via_buf_fl_init(int num)
|
||
{
|
||
via_buf_fl = pps_ctx_fl_init(num, sizeof(HSIP_VIAH), TRUE);
|
||
if (via_buf_fl == NULL)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
void sip_via_buf_fl_deinit()
|
||
{
|
||
if (via_buf_fl)
|
||
{
|
||
pps_fl_free(via_buf_fl);
|
||
via_buf_fl = NULL;
|
||
}
|
||
}
|
||
|
||
HSIP_VIAH * sip_get_via_buf()
|
||
{
|
||
HSIP_VIAH * p_ret = (HSIP_VIAH *)pps_fl_pop(via_buf_fl);
|
||
if (p_ret == NULL)
|
||
{
|
||
log_print(HT_LOG_ERR, "%s, pop null!!!\r\n", __FUNCTION__);
|
||
}
|
||
|
||
return p_ret;
|
||
}
|
||
|
||
void sip_free_via_buf(HSIP_VIAH * pVia)
|
||
{
|
||
// 加入到空闲链表中
|
||
pps_fl_push(via_buf_fl, pVia);
|
||
}
|
||
|
||
void sip_init_ul_via_ctx(PPSN_CTX * ul_ctx)
|
||
{
|
||
pps_ctx_ul_init_nm(via_buf_fl, ul_ctx);
|
||
}
|
||
|
||
/***********************************************************************/
|
||
BOOL sip_msg_buf_fl_init(int num)
|
||
{
|
||
msg_buf_fl = pps_ctx_fl_init(num, sizeof(HSIP_MSG), TRUE);
|
||
if (msg_buf_fl == NULL)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
void sip_msg_buf_fl_deinit()
|
||
{
|
||
if (msg_buf_fl)
|
||
{
|
||
pps_fl_free(msg_buf_fl);
|
||
msg_buf_fl = NULL;
|
||
}
|
||
}
|
||
|
||
HSIP_MSG * sip_get_msg_buf()
|
||
{
|
||
HSIP_MSG * tx_msg = (HSIP_MSG *)pps_fl_pop(msg_buf_fl);
|
||
if (tx_msg == NULL)
|
||
{
|
||
log_print(HT_LOG_ERR, "%s, pop null!!!\r\n", __FUNCTION__);
|
||
return NULL;
|
||
}
|
||
|
||
memset(tx_msg, 0, sizeof(HSIP_MSG));
|
||
tx_msg->msg_buf = net_buf_get_idle();
|
||
if (tx_msg->msg_buf == NULL)
|
||
{
|
||
sip_free_msg_buf(tx_msg);
|
||
return NULL;
|
||
}
|
||
|
||
tx_msg->buf_mlen = net_buf_get_size();
|
||
|
||
sip_msg_ctx_init(tx_msg);
|
||
|
||
return tx_msg;
|
||
}
|
||
|
||
void sip_msg_ctx_init(HSIP_MSG * msg)
|
||
{
|
||
pps_ctx_ul_init_nm(hdrv_buf_fl, &(msg->sip_ctx));
|
||
pps_ctx_ul_init_nm(hdrv_buf_fl, &(msg->sdp_ctx));
|
||
pps_ctx_ul_init_nm(via_buf_fl, &(msg->via_ctx));
|
||
}
|
||
|
||
void sip_free_msg_buf(HSIP_MSG * msg)
|
||
{
|
||
// 加入到空闲链表中
|
||
pps_fl_push(msg_buf_fl, msg);
|
||
}
|
||
|
||
HSIP_MSG * sip_get_msg_large_buf(int size)
|
||
{
|
||
HSIP_MSG * tx_msg = (HSIP_MSG *)pps_fl_pop(msg_buf_fl);
|
||
if (tx_msg == NULL)
|
||
{
|
||
log_print(HT_LOG_ERR, "%s, pop null!!!\r\n", __FUNCTION__);
|
||
return NULL;
|
||
}
|
||
|
||
memset(tx_msg, 0, sizeof(HSIP_MSG));
|
||
|
||
if (size < (int)net_buf_get_size())
|
||
{
|
||
tx_msg->msg_buf = net_buf_get_idle();
|
||
tx_msg->buf_mlen = net_buf_get_size();
|
||
}
|
||
else
|
||
{
|
||
tx_msg->msg_buf = (char *)malloc(size);
|
||
tx_msg->buf_mlen = size;
|
||
}
|
||
|
||
if (tx_msg->msg_buf == NULL)
|
||
{
|
||
sip_free_msg_buf(tx_msg);
|
||
return NULL;
|
||
}
|
||
|
||
sip_msg_ctx_init(tx_msg);
|
||
|
||
return tx_msg;
|
||
}
|
||
|
||
/***********************************************************************/
|
||
BOOL sip_parse_buf_init(int nums)
|
||
{
|
||
BOOL ret = TRUE;
|
||
|
||
ret &= sip_msg_buf_fl_init(nums);
|
||
ret &= sip_via_buf_fl_init(nums * 16);
|
||
|
||
return ret;
|
||
}
|
||
|
||
void sip_parse_buf_deinit()
|
||
{
|
||
sip_via_buf_fl_deinit();
|
||
sip_msg_buf_fl_deinit();
|
||
}
|
||
|
||
|
||
|
||
|