Files
gb28181/GB28181Device/sip/sip_parse.cpp
2024-12-15 20:42:32 +08:00

2981 lines
64 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/***************************************************************************************
*
* 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();
}