451 lines
11 KiB
C++
451 lines
11 KiB
C++
/***************************************************************************************
|
||
*
|
||
* IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||
*
|
||
* By downloading, copying, installing or using the software you agree to this license.
|
||
* If you do not agree to this license, do not download, install,
|
||
* copy or use the software.
|
||
*
|
||
* Copyright (C) 2014-2022, Happytimesoft Corporation, all rights reserved.
|
||
*
|
||
* Redistribution and use in binary forms, with or without modification, are permitted.
|
||
*
|
||
* Unless required by applicable law or agreed to in writing, software distributed
|
||
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||
* CONDITIONS OF ANY KIND, either express or implied. See the License for the specific
|
||
* language governing permissions and limitations under the License.
|
||
*
|
||
****************************************************************************************/
|
||
|
||
#include "sys_inc.h"
|
||
#include "hsip.h"
|
||
#include "sua.h"
|
||
#include "sip_parse.h"
|
||
#include "sip_rx.h"
|
||
#include "sip_tx.h"
|
||
#include "sip_msg.h"
|
||
#include "sua.h"
|
||
#include "sip_reg.h"
|
||
#include "sip_pstate.h"
|
||
#include "mansrtsp.h"
|
||
#include "gb28181_msg.h"
|
||
#include "gb28181_subscribe.h"
|
||
|
||
|
||
/*******************************************************/
|
||
extern HSIP_CLASS hsip;
|
||
extern HSIP_USER g_user;
|
||
|
||
/*******************************************************\
|
||
消息接收处理
|
||
\*******************************************************/
|
||
void sip_msg_rx(char * sip_msg, int len, uint32 rx_ip, uint16 rx_port, uint16 dst_port)
|
||
{
|
||
HSIP_MSG msg;
|
||
memset(&msg, 0, sizeof(HSIP_MSG));
|
||
|
||
log_print(HT_LOG_DBG, "%s, server-->client : \r\n%s\r\n", __FUNCTION__, sip_msg);
|
||
|
||
msg.remote_ip = rx_ip;
|
||
msg.remote_port = rx_port;
|
||
msg.local_port = dst_port;
|
||
|
||
msg.msg_buf = sip_msg;
|
||
msg.buf_offset = 0;
|
||
|
||
sip_msg_crpty(sip_msg, len, &msg);
|
||
|
||
if (sip_is_sip_msg(sip_msg) == FALSE)
|
||
{
|
||
net_buf_free(sip_msg); // 释放接收缓冲区
|
||
log_print(HT_LOG_ERR, "%s, sip_is_sip_msg failed!!!\r\n", __FUNCTION__);
|
||
return;
|
||
}
|
||
|
||
sip_msg_ctx_init(&msg);
|
||
|
||
// 第一步:分析消息,得到消息类型
|
||
|
||
int ret = sip_msg_parse(sip_msg, len, &msg);
|
||
if (ret <= 0)
|
||
{
|
||
log_print(HT_LOG_ERR, "%s, sip_msg_parse return %d!!!\r\n", __FUNCTION__, ret);
|
||
sip_free_msg_content(&msg);
|
||
return;
|
||
}
|
||
|
||
// 第二步:根据消息类型,调用相应的消息接收函数
|
||
// 在相应的消息接收函数中根据用户状态和消息内容进行处理
|
||
|
||
if (msg.msg_type == 0)
|
||
{
|
||
if (sip_check_request_via(&msg))
|
||
{
|
||
sip_request_rx(&msg);
|
||
}
|
||
else
|
||
{
|
||
log_print(HT_LOG_ERR, "%s, sip_check_request_via error!!!\r\n", __FUNCTION__);
|
||
}
|
||
}
|
||
else if (msg.msg_type == 1)
|
||
{
|
||
if (sip_check_response_via(&msg))
|
||
{
|
||
sip_response_rx(&msg);
|
||
}
|
||
else
|
||
{
|
||
log_print(HT_LOG_ERR, "%s, sip_check_response_via error!!!\r\n", __FUNCTION__);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
log_print(HT_LOG_ERR, "%s, msg type error!!!\r\n", __FUNCTION__);
|
||
}
|
||
|
||
sip_free_msg_content(&msg);
|
||
}
|
||
|
||
void sip_pmsg_rx(HSIP_MSG * rx_msg, HSIP_USER * p_user)
|
||
{
|
||
if (rx_msg->msg_type == 0)
|
||
{
|
||
if (sip_check_request_via(rx_msg))
|
||
{
|
||
sip_request_rx(rx_msg);
|
||
}
|
||
else
|
||
{
|
||
log_print(HT_LOG_ERR, "%s, sip_check_request_via error!!!\r\n", __FUNCTION__);
|
||
}
|
||
}
|
||
else if (rx_msg->msg_type == 1)
|
||
{
|
||
if (sip_check_response_via(rx_msg))
|
||
{
|
||
sip_response_rx(rx_msg);
|
||
}
|
||
else
|
||
{
|
||
log_print(HT_LOG_ERR, "%s, sip_check_response_via error!!!\r\n", __FUNCTION__);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
log_print(HT_LOG_ERR, "%s, msg type error!!!\r\n", __FUNCTION__);
|
||
}
|
||
}
|
||
|
||
/*******************************************************\
|
||
检查Via,防止路由环回
|
||
\*******************************************************/
|
||
BOOL sip_check_request_via(HSIP_MSG * rx_msg)
|
||
{
|
||
// 某些服务器在请求消息VIA带的居然是设备的本地IP地址!!!
|
||
#if 0
|
||
HSIP_VIAH * via_hdr = (HSIP_VIAH *)pps_lookup_start(&(rx_msg->via_ctx));
|
||
while (via_hdr != NULL)
|
||
{
|
||
if ((is_local_if_ip(via_hdr->ip)) && (via_hdr->port == rx_msg->local_port)) // 碰到与自己地址相同的VIA
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
via_hdr = (HSIP_VIAH *)pps_lookup_next(&(rx_msg->via_ctx), via_hdr);
|
||
}
|
||
pps_lookup_end(&(rx_msg->via_ctx));
|
||
#endif
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
BOOL sip_check_response_via(HSIP_MSG * rx_msg)
|
||
{
|
||
if (rx_msg->via_ctx.node_num == 0)
|
||
{
|
||
log_print(HT_LOG_ERR, "%s, rx_msg->via_ctx.node_num == 0\r\n", __FUNCTION__);
|
||
return FALSE;
|
||
}
|
||
|
||
HSIP_VIAH * via_hdr = (HSIP_VIAH *)pps_lookup_start(&(rx_msg->via_ctx));
|
||
pps_lookup_end(&(rx_msg->via_ctx));
|
||
|
||
if (via_hdr == NULL)
|
||
{
|
||
log_print(HT_LOG_ERR, "%s, via_hdr == NULL\r\n", __FUNCTION__);
|
||
return FALSE;
|
||
}
|
||
|
||
if (via_hdr->port != rx_msg->local_port)
|
||
{
|
||
log_print(HT_LOG_ERR, "%s, via_hdr->port[%u] != rx_msg->local_port[%u]\r\n", __FUNCTION__, via_hdr->port, rx_msg->local_port);
|
||
return FALSE;
|
||
}
|
||
|
||
if (is_local_if_ip(via_hdr->ip))
|
||
{
|
||
//去掉这个VIA
|
||
pps_ctx_ul_del(&(rx_msg->via_ctx), via_hdr);
|
||
sip_free_via_buf(via_hdr);
|
||
|
||
return TRUE;
|
||
}
|
||
else
|
||
{
|
||
log_print(HT_LOG_ERR, "%s, is_local_if_ip return FALSE via_hdr->ip=0x%08x\r\n", __FUNCTION__, via_hdr->ip);
|
||
}
|
||
|
||
if (is_local_if_ip(via_hdr->ip) || is_local_domain(via_hdr->domain))
|
||
{
|
||
// 去掉这个VIA
|
||
pps_ctx_ul_del(&(rx_msg->via_ctx), via_hdr);
|
||
sip_free_via_buf(via_hdr);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
/*******************************************************\
|
||
响应消息接收处理,需要先判断是哪一个呼叫会话的SESSION
|
||
\*******************************************************/
|
||
void sip_response_rx(HSIP_MSG * rx_msg)
|
||
{
|
||
char callid_buf[256];
|
||
char user_buf[256];
|
||
char type_buf[64];
|
||
|
||
HSIP_USER * p_user = &g_user;
|
||
|
||
p_user->last_rx_time = sys_os_get_uptime();
|
||
|
||
// 查找对应的会话
|
||
sip_get_msg_call_id(rx_msg, callid_buf, sizeof(callid_buf));
|
||
sip_get_user_name(rx_msg, "To", user_buf, sizeof(user_buf));
|
||
sip_get_msg_cseq_type(rx_msg, type_buf, sizeof(type_buf));
|
||
|
||
if (strcmp(type_buf, "REGISTER") == 0)
|
||
{
|
||
if (strcmp(callid_buf, p_user->auth_call_id) == 0)
|
||
{
|
||
sip_register_response_rx(rx_msg, p_user);
|
||
return;
|
||
}
|
||
}
|
||
else if (strcmp(type_buf, "MESSAGE") == 0)
|
||
{
|
||
sip_message_rly_rx(rx_msg);
|
||
}
|
||
else if (strcmp(type_buf, "NOTIFY") == 0)
|
||
{
|
||
p_user->hb_tm_count = 0;
|
||
}
|
||
else
|
||
{
|
||
SUA * p_sua = sua_lookup_by_callid(callid_buf);
|
||
if (p_sua == NULL) // 没有找到对应SUA
|
||
{
|
||
return;
|
||
}
|
||
|
||
char cseq_buf[32];
|
||
sip_get_msg_cseq(rx_msg, cseq_buf, sizeof(cseq_buf));
|
||
p_sua->call_cseq = atol(cseq_buf);
|
||
|
||
sua_call_state(p_sua, (CSEVT)0, rx_msg);
|
||
}
|
||
}
|
||
|
||
/*******************************************************\
|
||
请求消息接收处理
|
||
\*******************************************************/
|
||
void sip_request_rx(HSIP_MSG * rx_msg)
|
||
{
|
||
char call_id[128];
|
||
char f_domain[64];
|
||
char f_user_name[MAX_USRL];
|
||
|
||
HSIP_USER * p_user = &g_user;
|
||
|
||
if (sip_get_msg_call_id(rx_msg, call_id, sizeof(call_id)) == FALSE)
|
||
{
|
||
return;
|
||
}
|
||
|
||
if (sip_get_user_domain(rx_msg, "From", f_domain, sizeof(f_domain)) == FALSE)
|
||
{
|
||
return;
|
||
}
|
||
|
||
if (sip_get_user_name(rx_msg, "From", f_user_name, sizeof(f_user_name)) == FALSE)
|
||
{
|
||
return;
|
||
}
|
||
|
||
p_user->last_rx_time = sys_os_get_uptime();
|
||
|
||
log_print(HT_LOG_INFO, "%s, from user [%s]@[%s]\r\n", __FUNCTION__, f_user_name, f_domain);
|
||
|
||
if (rx_msg->msg_sub_type == SIP_MT_INFO)
|
||
{
|
||
HSIP_MSG * tx_msg = sip_build_call_response(rx_msg, "200 OK");
|
||
user_tx_free_msg(p_user, tx_msg);
|
||
|
||
SUA * p_sua = sua_lookup_by_callid(call_id);
|
||
if (p_sua)
|
||
{
|
||
if (rx_msg->ctx_type == SIP_CTX_MANSRTSP)
|
||
{
|
||
HDRV * pHdr = sip_find_sdp_headline(rx_msg, "");
|
||
if (pHdr)
|
||
{
|
||
mansrtsp_msg_handler(p_sua, pHdr->value_string, rx_msg->sdp_len);
|
||
}
|
||
}
|
||
}
|
||
|
||
return;
|
||
}
|
||
else if (rx_msg->msg_sub_type == SIP_MT_OPT)
|
||
{
|
||
HSIP_MSG * tx_msg = sip_build_call_response(rx_msg, "200 OK");
|
||
user_tx_free_msg(p_user, tx_msg);
|
||
return;
|
||
}
|
||
else if (rx_msg->msg_sub_type == SIP_MT_SUB)
|
||
{
|
||
gb28181_subscribe_rx(rx_msg);
|
||
}
|
||
else if (rx_msg->msg_sub_type == SIP_MT_NTF)
|
||
{
|
||
HSIP_MSG * tx_msg = sip_build_call_response(rx_msg, "200 OK");
|
||
user_tx_free_msg(p_user, tx_msg);
|
||
}
|
||
else if (rx_msg->msg_sub_type == SIP_MT_MSG)
|
||
{
|
||
HSIP_MSG * tx_msg = sip_build_call_response(rx_msg, "200 OK");
|
||
user_tx_free_msg(p_user, tx_msg);
|
||
|
||
if (rx_msg->ctx_type == SIP_CTX_XML)
|
||
{
|
||
gb28181_msg_rx(rx_msg);
|
||
}
|
||
else
|
||
{
|
||
// 非事务消息, 获取消息类型和内容, 提交给上层回调函数
|
||
HDRV * pHdr = (HDRV *)pps_lookup_start(&(rx_msg->sdp_ctx));
|
||
if (pHdr && pHdr->value_string)
|
||
{
|
||
rmsg_notify_emsg(f_user_name, rx_msg->ctx_type, pHdr->value_string, strlen(pHdr->value_string));
|
||
}
|
||
pps_lookup_end(&(rx_msg->sdp_ctx));
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// 找到对应的已经存在的呼叫表项和用户
|
||
SUA * p_sua = sua_lookup_by_callid(call_id);
|
||
if (p_sua == NULL)
|
||
{
|
||
switch (rx_msg->msg_sub_type)
|
||
{
|
||
case SIP_MT_BYE:
|
||
case SIP_MT_CAN: // 对于没有找到SESSION的BYE和CANCEL应该是被叫已经回应,而主叫没有收到转发的回应消息(网络丢包)
|
||
{
|
||
HSIP_MSG * tx_msg = sip_build_call_response(rx_msg, "200 OK"); // 让曾经的主叫闭嘴
|
||
user_tx_free_msg(p_user, tx_msg);
|
||
return;
|
||
}
|
||
break;
|
||
|
||
case SIP_MT_INV:
|
||
{
|
||
p_sua = sua_get_idle_sua(p_user);
|
||
if (p_sua == NULL)
|
||
{
|
||
HSIP_MSG * tx_msg = sip_build_call_response(rx_msg, "486 Busy Here");
|
||
user_tx_free_msg(p_user, tx_msg);
|
||
return;
|
||
}
|
||
|
||
p_sua->p_user = p_user;
|
||
|
||
strcpy(p_sua->call_id_str, call_id);
|
||
|
||
p_sua->remote_real_ip = rx_msg->remote_ip;
|
||
p_sua->remote_real_port = rx_msg->remote_port;
|
||
strcpy(p_sua->sua_ipstr, hsip.local_ipstr);
|
||
p_sua->sua_port = rx_msg->local_port;
|
||
p_sua->user_crpty_mode = p_user->user_crpty_mode;
|
||
}
|
||
break;
|
||
|
||
case SIP_MT_ACK: // 没有记录状态的ACK直接丢弃
|
||
log_print(HT_LOG_INFO, "%s, SIP ACK rx, but not found call id[%s]!!!\r\n", __FUNCTION__, call_id);
|
||
|
||
case SIP_MT_OPT:
|
||
case SIP_MT_REF:
|
||
case SIP_MT_NTF: // 通知消息,这里需要再确定
|
||
default:
|
||
return;
|
||
}
|
||
|
||
}
|
||
|
||
switch (rx_msg->msg_sub_type)
|
||
{
|
||
case SIP_MT_CAN:
|
||
case SIP_MT_BYE:
|
||
case SIP_MT_INV:
|
||
sip_call_request_rx(rx_msg, p_sua);
|
||
break;
|
||
|
||
case SIP_MT_ACK:
|
||
sip_call_request_rx(rx_msg, p_sua);
|
||
break;
|
||
|
||
case SIP_MT_OPT:
|
||
case SIP_MT_REF:
|
||
default:
|
||
sip_call_request_rx(rx_msg, p_sua);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
/*******************************************************\
|
||
呼叫请求消息接收处理
|
||
\*******************************************************/
|
||
void sip_call_request_rx(HSIP_MSG * rx_msg, SUA * f_sua)
|
||
{
|
||
if (rx_msg->msg_sub_type != SIP_MT_INV)
|
||
{
|
||
// 此处应该检查该sua中的From,To是否匹配
|
||
sua_call_state(f_sua, CSE_NULL, rx_msg);
|
||
return;
|
||
}
|
||
|
||
sip_get_user_name(rx_msg, "From", f_sua->remote_name, sizeof(f_sua->remote_name));
|
||
sip_get_user_domain(rx_msg, "From", f_sua->remote_domain, sizeof(f_sua->remote_domain));
|
||
sip_get_user_tag(rx_msg, "From", f_sua->remote_sip_tag, sizeof(f_sua->remote_sip_tag));
|
||
sip_get_disp_name(rx_msg, "From", f_sua->remote_disp_name, sizeof(f_sua->remote_disp_name));
|
||
sip_get_sip_address(rx_msg, "From", f_sua->remote_sip_address, sizeof(f_sua->remote_sip_address));
|
||
|
||
sip_get_user_name(rx_msg, "To", f_sua->sua_name, sizeof(f_sua->sua_name));
|
||
sip_get_user_domain(rx_msg, "To", f_sua->sua_domain, sizeof(f_sua->sua_domain));
|
||
sip_get_user_tag(rx_msg, "To", f_sua->sua_sip_tag, sizeof(f_sua->sua_sip_tag));
|
||
sip_get_disp_name(rx_msg, "To", f_sua->sua_disp_name, sizeof(f_sua->sua_disp_name));
|
||
sip_get_sip_address(rx_msg, "To", f_sua->sua_sip_address, sizeof(f_sua->sua_sip_address));
|
||
|
||
char cseq_buf[32];
|
||
sip_get_msg_cseq(rx_msg, cseq_buf, sizeof(cseq_buf));
|
||
f_sua->call_cseq = atol(cseq_buf);
|
||
|
||
sua_call_state(f_sua, CSE_NULL, rx_msg);
|
||
}
|
||
|
||
|
||
|