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

451 lines
11 KiB
C++
Raw Permalink 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 "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);
}