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

785 lines
18 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_timer.h"
#include "sip_reg.h"
#include "sip_pstate.h"
#include "gb28181_cfg.h"
/***********************************************************************/
HSIP_CLASS hsip;
HSIP_USER g_user;
/***********************************************************************/
BOOL is_local_if_ip(uint32 dst_ip)
{
return (dst_ip == hsip.local_ip);
}
/***********************************************************************\
检查域名或者ip地址是否是自己
1.如果是ip,检查是否是本机地址,或者是对外映射的ip地址
2.如果是名称,检查是否是本域名,或者是本机主机名
\***********************************************************************/
BOOL is_local_domain(char * domain)
{
if (is_ip_address(domain) && is_local_if_ip(inet_addr(domain)))
{
return TRUE;
}
if (strcasecmp(hsip.host_name, domain) == 0)
{
return TRUE;
}
if (is_local_if_ip(get_address_by_name(domain)))
{
return TRUE;
}
return FALSE;
}
BOOL init_local_net()
{
if (gethostname(hsip.host_name, sizeof(hsip.host_name)-1) == 0)
{
log_print(HT_LOG_INFO, "%s, %s\r\n", __FUNCTION__, hsip.host_name);
struct in_addr addr;
addr.s_addr = get_default_if_ip();
strcpy(hsip.local_ipstr, inet_ntoa(addr));
log_print(HT_LOG_INFO, "%s, hsip.local_ipstr = %s\r\n", __FUNCTION__, hsip.local_ipstr);
}
hsip.local_ip = inet_addr(hsip.local_ipstr);
return TRUE;
}
/***********************************************************************\
系统数据结构初始化,必要的任务初始化
\***********************************************************************/
BOOL sip_init_bufs()
{
if (sys_buf_init(MAX_NUM_SUA * 4) == FALSE)
{
log_print(HT_LOG_ERR, "%s, sys_buf_init failed!!!\r\n", __FUNCTION__);
return FALSE;
}
if (sip_parse_buf_init(MAX_NUM_SUA * 4) == FALSE)
{
log_print(HT_LOG_ERR, "%s, sip_parse_buf_init failed!!!\r\n", __FUNCTION__);
return FALSE;
}
hsip.msg_queue = hqCreate(MAX_NUM_SUA * 4, sizeof(SIPTM), HQ_GET_WAIT);
if (hsip.msg_queue == NULL)
{
log_print(HT_LOG_ERR, "%s, create sip task queue failed!!!\r\n", __FUNCTION__);
return FALSE;
}
sua_proxy_init();
return TRUE;
}
/***********************************************************************\
用户网络初始化
\***********************************************************************/
BOOL sip_user_socket_init(HSIP_USER * p_user)
{
if (p_user->sip_fd > 0)
{
return TRUE;
}
// 清空接收缓冲区
p_user->rcv_dlen = 0;
p_user->sip_len = 0;
p_user->sdp_len = 0;
if (p_user->dyn_recv_buf)
{
free(p_user->dyn_recv_buf);
p_user->dyn_recv_buf = NULL;
}
p_user->p_rbuf = NULL;
if (p_user->usrf_tcp_sip == 1)
{
p_user->sip_fd = socket(AF_INET, SOCK_STREAM, 0);
if (p_user->sip_fd <= 0)
{
log_print(HT_LOG_ERR, "%s, socket init fail\r\n", __FUNCTION__);
return FALSE;
}
struct sockaddr_in addr;
int addr_len = sizeof(addr);
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = hsip.local_ip;
addr.sin_port = htons(g_gb28181_cfg.local_port);
if (bind(p_user->sip_fd, (struct sockaddr *)&addr, addr_len) != 0)
{
log_print(HT_LOG_ERR, "%s, Bind tcp socket fail,error = %s\r\n",
__FUNCTION__, sys_os_get_socket_error());
closesocket(p_user->sip_fd);
return FALSE;
}
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(p_user->server_ipstr);
addr.sin_port = htons(p_user->server_port);
if (connect(p_user->sip_fd, (struct sockaddr *)&addr, addr_len) != 0)
{
log_print(HT_LOG_ERR, "%s, connect srv[%s,%u] fail,error = %s\r\n", __FUNCTION__,
p_user->server_ipstr, p_user->server_port, sys_os_get_socket_error());
closesocket(p_user->sip_fd);
return FALSE;
}
if (getsockname(p_user->sip_fd, (struct sockaddr *)&addr, (socklen_t*)&addr_len) == 0)
{
p_user->user_port = p_user->sip_port = ntohs(addr.sin_port);
log_print(HT_LOG_INFO, "%s, sip local port %u\r\n", __FUNCTION__, p_user->sip_port);
}
else
{
return FALSE;
}
}
else
{
p_user->sip_fd = socket(AF_INET, SOCK_DGRAM, 0);
if (p_user->sip_fd <= 0)
{
log_print(HT_LOG_ERR, "%s, socket init fail\r\n", __FUNCTION__);
return FALSE;
}
struct sockaddr_in addr;
int addr_len = sizeof(addr);
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = hsip.local_ip;
addr.sin_port = htons(g_gb28181_cfg.local_port);
if (bind(p_user->sip_fd, (struct sockaddr *)&addr, addr_len) != 0)
{
log_print(HT_LOG_ERR, "%s, Bind udp socket fail,error = %s\r\n",
__FUNCTION__, sys_os_get_socket_error());
closesocket(p_user->sip_fd);
return FALSE;
}
if (getsockname(p_user->sip_fd, (struct sockaddr *)&addr, (socklen_t*)&addr_len) == 0)
{
p_user->user_port = p_user->sip_port = ntohs(addr.sin_port);
log_print(HT_LOG_INFO, "%s, sip local port %u\r\n", __FUNCTION__, p_user->sip_port);
}
else
{
return FALSE;
}
}
return TRUE;
}
int sip_pkt_find_end(char * p_buf)
{
int end_off = 0;
int sip_pkt_finish = 0; // SIP包是否完整(不包括SDP)标识
while (p_buf[end_off] != '\0')
{
if ((p_buf[end_off+0] == '\r' && p_buf[end_off+1] == '\n') &&
(p_buf[end_off+2] == '\r' && p_buf[end_off+3] == '\n'))
{
sip_pkt_finish = 1;
break;
}
end_off++;
}
if (sip_pkt_finish)
{
return(end_off + 4);
}
return 0;
}
void sip_commit_rx_msg(HSIP_USER * p_user, HSIP_MSG * rx_msg)
{
// 下面三行是为兼容UDP模式处理代码
rx_msg->local_port = p_user->sip_port;
rx_msg->remote_ip = inet_addr(p_user->server_ipstr);
rx_msg->remote_port = htons(p_user->server_port);
// 将信令消息打包,发送到状态机处理任务
SIPTM stm;
memset(&stm, 0, sizeof(SIPTM));
stm.msg_len = (rx_msg ? rx_msg->buf_mlen : 0);
stm.msg_src = SIP_PMSG_SRC;
stm.msg_buf = (char *)rx_msg;
if (hqBufPut(hsip.msg_queue, (char *)&stm) == FALSE)
{
sip_free_msg(rx_msg);
log_print(HT_LOG_ERR, "%s, hqBufPut return fail!!!\r\n", __FUNCTION__);
}
}
BOOL sip_tcp_rx(HSIP_USER * p_user)
{
if (p_user->p_rbuf == NULL) // 接收缓冲初始化
{
p_user->p_rbuf = p_user->rcv_buf;
p_user->mlen = sizeof(p_user->rcv_buf)-1;
p_user->rcv_dlen = 0;
p_user->sdp_len = 0;
p_user->sip_len = 0;
}
int rlen = recv(p_user->sip_fd, p_user->p_rbuf+p_user->rcv_dlen, p_user->mlen-p_user->rcv_dlen, 0);
if (rlen <= 0)
{
// 接收出错,可能是连接断开了
log_print(HT_LOG_ERR, "%s, recv return = %d, dlen[%d], mlen[%d]\r\n",
__FUNCTION__, rlen, p_user->rcv_dlen, p_user->mlen);
closesocket(p_user->sip_fd);
p_user->sip_fd = 0;
return FALSE;
}
p_user->rcv_dlen += rlen;
p_user->p_rbuf[p_user->rcv_dlen] = '\0';
//if(memcmp(p_user->p_rbuf, "MESSAGE", strlen("MESSAGE")) == 0)
//{
// log_print(HT_LOG_DBG, "rcv tcp message, rlen=%d\r\n", rlen);
// log_print(HT_LOG_DBG, "%s\r\n", p_user->p_rbuf+(p_user->rcv_dlen-rlen));
//}
rx_analyse_point:
if (p_user->rcv_dlen < 16)
{
return TRUE;
}
if (sip_is_sip_msg(p_user->p_rbuf) == FALSE) // 判断是否是SIP包
{
return FALSE;
}
HSIP_MSG * rx_msg = NULL;
if (p_user->sip_len == 0)
{
int sip_pkt_len = sip_pkt_find_end(p_user->p_rbuf);
if (sip_pkt_len == 0)
{
// 没有接收全, 等下次接收
return TRUE;
}
p_user->sip_len = sip_pkt_len;
rx_msg = sip_get_msg_buf();
if (rx_msg == NULL)
{
log_print(HT_LOG_ERR, "%s, sip_get_msg_buf ret null!!!\r\n", __FUNCTION__);
return FALSE;
}
memcpy(rx_msg->msg_buf, p_user->p_rbuf, sip_pkt_len);
rx_msg->msg_buf[sip_pkt_len] = '\0';
log_print(HT_LOG_DBG, "%s\r\n", rx_msg->msg_buf);
int parse_len = sip_msg_parse_part1(rx_msg->msg_buf, sip_pkt_len, rx_msg);
if (parse_len != sip_pkt_len)
{
// 解析出错
log_print(HT_LOG_ERR, "%s, sip_msg_parse_part1=%d, sip_pkt_len=%d!!!\r\n", __FUNCTION__, parse_len, sip_pkt_len);
sip_free_msg(rx_msg);
return FALSE;
}
p_user->sdp_len = rx_msg->ctx_len;
}
if ((p_user->sdp_len + p_user->sip_len) > p_user->mlen)
{
if (p_user->dyn_recv_buf)
{
// 不应该出现这种情况
log_print(HT_LOG_WARN, "%s, dyn_recv_buf=%p, mlen=%d!!!\r\n", __FUNCTION__, p_user->dyn_recv_buf, p_user->mlen);
free(p_user->dyn_recv_buf);
}
p_user->dyn_recv_buf = (char *)malloc(p_user->sdp_len + p_user->sip_len + 1);
if (p_user->dyn_recv_buf)
{
memcpy(p_user->dyn_recv_buf, p_user->rcv_buf, p_user->rcv_dlen);
p_user->p_rbuf = p_user->dyn_recv_buf;
p_user->mlen = p_user->sdp_len + p_user->sip_len;
}
if (rx_msg)
{
sip_free_msg(rx_msg);
}
return TRUE;
}
if (p_user->rcv_dlen >= (p_user->sdp_len + p_user->sip_len))
{
if (rx_msg == NULL)
{
// 属于第二次进入接收
int nlen = p_user->sdp_len + p_user->sip_len;
rx_msg = sip_get_msg_large_buf(nlen+1);
if (NULL == rx_msg)
{
log_print(HT_LOG_ERR, "%s, get message buffer failed\r\n", __FUNCTION__);
return FALSE;
}
memcpy(rx_msg->msg_buf, p_user->p_rbuf, p_user->sip_len);
rx_msg->msg_buf[p_user->sip_len] = '\0';
log_print(HT_LOG_DBG, "%s\r\n", rx_msg->msg_buf);
int parse_len = sip_msg_parse_part1(rx_msg->msg_buf, p_user->sip_len, rx_msg);
if (parse_len != p_user->sip_len)
{
// 解析出错
log_print(HT_LOG_ERR, "%s, sip_msg_parse_part1=%d, sip_pkt_len=%d!!!\r\n", __FUNCTION__, parse_len, p_user->sip_len);
sip_free_msg(rx_msg);
return FALSE;
}
}
if (p_user->sdp_len > 0)
{
memcpy(rx_msg->msg_buf+p_user->sip_len, p_user->p_rbuf+p_user->sip_len, p_user->sdp_len);
rx_msg->msg_buf[p_user->sip_len + p_user->sdp_len] = '\0';
log_print(HT_LOG_DBG, "%s\r\n", rx_msg->msg_buf+p_user->sip_len);
int parse_len = sip_msg_parse_part2(rx_msg->msg_buf+p_user->sip_len, p_user->sdp_len, rx_msg);
if (parse_len != p_user->sdp_len)
{
log_print(HT_LOG_ERR, "%s, sip_msg_parse_part2=%d, sdp_pkt_len=%d!!!\r\n", __FUNCTION__, parse_len, p_user->sdp_len);
sip_free_msg(rx_msg);
return FALSE;
}
}
// 整个消息接收完成, 提交 rx_msg 到主任务
sip_commit_rx_msg(p_user, rx_msg);
p_user->rcv_dlen -= p_user->sip_len + p_user->sdp_len;
if (p_user->dyn_recv_buf == NULL)
{
if (p_user->rcv_dlen > 0)
{
memmove(p_user->rcv_buf, p_user->rcv_buf+p_user->sip_len + p_user->sdp_len, p_user->rcv_dlen);
p_user->rcv_buf[p_user->rcv_dlen] = '\0';
}
p_user->p_rbuf = p_user->rcv_buf;
p_user->mlen = sizeof(p_user->rcv_buf)-1;
p_user->sip_len = 0;
p_user->sdp_len = 0;
if (p_user->rcv_dlen > 16)
{
goto rx_analyse_point;
}
}
else
{
free(p_user->dyn_recv_buf);
p_user->dyn_recv_buf = NULL;
p_user->sip_len = 0;
p_user->sdp_len = 0;
p_user->p_rbuf = 0;
p_user->rcv_dlen = 0;
}
}
return TRUE;
}
/***********************************************************************\
SIP系统任务
\***********************************************************************/
void * sip_task(void * argv)
{
SIPTM stm;
while (hsip.net_rx_flag == 1)
{
if (hqBufGet(hsip.msg_queue, (char *)&stm))
{
switch (stm.msg_src)
{
case SIP_MSG_SRC:
sip_msg_rx(stm.msg_buf, stm.msg_len, stm.src_ip, stm.src_port, stm.dst_port);
break;
case SIP_PMSG_SRC:
sip_pmsg_rx((HSIP_MSG *)stm.msg_buf, &g_user);
sip_free_msg((HSIP_MSG *)stm.msg_buf);
break;
case SIP_TIMER_SRC:
sip_timer();
break;
case SUA_DEL_SRC:
sua_del_native(stm.msg_param, stm.dst_port);
break;
case SUA_CMD_SRC:
sua_emsg_recv((PUACMD)stm.msg_param, sua_get_by_index(stm.dst_port));
if (stm.msg_lock)
{
sys_os_mutex_leave(stm.msg_lock);
}
break;
case MEDIA_VIDEO_SRC:
sip_notify_emsg(NULL, (PUAEVT)stm.msg_param);
break;
case SIP_MSG_EXIT:
goto sip_task_exit;
break;
case SIP_RETCP_SRC:
sip_user_socket_init(&g_user);
g_user.user_state = HSIP_AUTH_IDLE;
break;
}
}
}
sip_task_exit:
hsip.sip_task_tid = 0;
return 0;
}
void * sip_net_rx(void * argv)
{
HSIP_USER * p_user = &g_user;
struct sockaddr_in addr;
int addr_len = sizeof(struct sockaddr_in);
while (hsip.net_rx_flag == 1)
{
fd_set fdr;
FD_ZERO(&fdr);
if (p_user->sip_fd > 0)
{
FD_SET(p_user->sip_fd, &fdr);
}
else
{
usleep(100*1000);
continue;
}
struct timeval tv;
tv.tv_sec = 1;
tv.tv_usec = 0;
select(p_user->sip_fd+1, &fdr, NULL, NULL, &tv);
if (FD_ISSET(p_user->sip_fd, &fdr))
{
if (p_user->usrf_tcp_sip == 1)
{
sip_tcp_rx(p_user);
}
else
{
char buff[SIP_MAX_BUFF];
int rlen = recvfrom(p_user->sip_fd, buff, sizeof(buff), 0, (struct sockaddr *)&addr, (socklen_t*)&addr_len);
if (rlen < 16)
{
continue;
}
int retry_cnt = 0;
SIPTM stm;
memset(&stm, 0, sizeof(SIPTM));
while (stm.msg_buf == NULL)
{
if (rlen >= (int)net_buf_get_size())
{
stm.msg_buf = (char *)malloc(rlen+8);
}
else
{
stm.msg_buf = net_buf_get_idle();
}
if (stm.msg_buf == NULL)
{
if (retry_cnt++ > 3)
{
log_print(HT_LOG_ERR, "%s, get idle net buf retry times > 3 !!!\r\n", __FUNCTION__);
goto net_rx_exit;
}
}
else
{
break;
}
}
memcpy(stm.msg_buf, buff, rlen);
stm.msg_len = rlen;
stm.msg_src = SIP_MSG_SRC;
stm.src_ip = addr.sin_addr.s_addr;
stm.src_port = addr.sin_port;
stm.dst_port = p_user->sip_port;
stm.msg_buf[stm.msg_len] = '\0';
if (hqBufPut(hsip.msg_queue, (char *)&stm) == FALSE)
{
net_buf_free(stm.msg_buf);
log_print(HT_LOG_ERR, "%s, hqBufPut return fail!!!\r\n", __FUNCTION__);
}
}
}
}
net_rx_exit:
hsip.net_rx_tid = 0;
return NULL;
}
BOOL sip_tcp_reconnect_commit()
{
SIPTM stm;
memset(&stm, 0, sizeof(SIPTM));
stm.msg_src = SIP_RETCP_SRC;
if (hqBufPut(hsip.msg_queue, (char *)&stm) == FALSE)
{
log_print(HT_LOG_ERR, "%s, hqBufPut fail\r\n", __FUNCTION__);
return FALSE;
}
return TRUE;
}
/***********************************************************************\
系统入口
\***********************************************************************/
BOOL sip_init()
{
strcpy(hsip.ver, "IP Camera");
hsip.user_expires_sec = 3600;
if (init_local_net() == FALSE)
{
log_print(HT_LOG_ERR, "%s, init_local_net fail\r\n", __FUNCTION__);
return FALSE;
}
hsip.user_expires_sec = g_gb28181_cfg.reg_expires;
srand((unsigned)time(NULL));
hsip.crypt_mode = HCRPTY_NULL;
sip_gs_cbcom_init();
sip_hsp_crypt_init();
return sip_init_bufs();
}
BOOL sip_start()
{
// 缺省rtp类型定义
sua_default_rtp_map_init();
memset(&hsip, 0, sizeof(HSIP_CLASS));
memset(&g_user, 0, sizeof(HSIP_USER));
if (sip_init() == FALSE)
{
return FALSE;
}
// 初始化事务管理器
sip_trans_init(&(hsip.sip_trans), 100);
hsip.mutex_cb = sys_os_create_mutex();
hsip.net_rx_flag = 1;
hsip.net_rx_tid = sys_os_create_thread((void *)sip_net_rx, NULL);
if (hsip.net_rx_tid == 0)
{
log_print(HT_LOG_ERR, "%s, sys_os_create_thread sip_net_rx\r\n", __FUNCTION__);
return FALSE;
}
log_print(HT_LOG_INFO, "%s, create net rx thread sucessful\r\n", __FUNCTION__);
hsip.sip_task_tid = sys_os_create_thread((void *)sip_task, NULL);
if (hsip.sip_task_tid == 0)
{
log_print(HT_LOG_ERR, "%s, sys_os_create_thread sip_task\r\n", __FUNCTION__);
return FALSE;
}
log_print(HT_LOG_INFO, "%s, create sip main thread sucessful\r\n", __FUNCTION__);
sip_timer_init();
hsip.sys_init_flag = 1;
return TRUE;
}
void sip_stop()
{
HSIP_USER * p_user = &g_user;
if (p_user->usrf_tcp_sip == 0)
{
// tcp模式不发注销包
p_user->expires_time = 0;
HSIP_MSG * tx_msg = sip_build_register_normal_msg(&g_user, inet_addr(p_user->server_ipstr), htons(p_user->server_port));
user_tx_free_msg(p_user,tx_msg);
}
hsip.sys_init_flag = 0;
// 停止sip timer
log_print(HT_LOG_INFO, "%s, sip_timer_deinit.\r\n", __FUNCTION__);
sip_timer_deinit();
// 停止网络接收任务
hsip.net_rx_flag = 0;
log_print(HT_LOG_INFO, "%s, stop net rx.\r\n", __FUNCTION__);
while (hsip.net_rx_tid != 0)
{
usleep(100*1000);
}
// 停止sip_task
log_print(HT_LOG_INFO, "%s, stop sip task.\r\n", __FUNCTION__);
SIPTM stm;
memset(&stm, 0, sizeof(SIPTM));
stm.msg_src = SIP_MSG_EXIT;
log_print(HT_LOG_INFO, "%s, send exit message to sip task.\r\n", __FUNCTION__);
hqBufPut(hsip.msg_queue, (char *)&stm);
usleep(100*1000);
while (hsip.sip_task_tid != 0)
{
usleep(100*1000);
}
log_print(HT_LOG_INFO, "%s, closesocket.\r\n", __FUNCTION__);
if (g_user.sip_fd > 0)
{
closesocket(g_user.sip_fd);
g_user.sip_fd = -1;
}
log_print(HT_LOG_INFO, "%s, sua_proxy_deinit.\r\n", __FUNCTION__);
sua_proxy_deinit();
// 停止消息队列
log_print(HT_LOG_INFO, "%s, sip msg queue delete.\r\n", __FUNCTION__);
if (hsip.msg_queue)
{
hqDelete(hsip.msg_queue);
hsip.msg_queue = NULL;
}
sip_trans_uninit(&(hsip.sip_trans));
sys_os_destroy_sig_mutex(hsip.mutex_cb);
// 释放缓冲区
log_print(HT_LOG_INFO, "%s, sip_parse_buf_deinit.\r\n", __FUNCTION__);
sip_parse_buf_deinit();
sys_buf_deinit();
log_print(HT_LOG_INFO, "%s, sip stop finish.\r\n", __FUNCTION__);
}