/*************************************************************************************** * * 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 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; imsg_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) // 空行, 分析结束 { 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: ;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, "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, "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 ;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, "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" ;tag=12fddc2f8060842f To: Contact: \***********************************************************************/ 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, "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, "= 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, "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; isdp_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; indexsdp_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; iis_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; isdp_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>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; imsg_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(); }