/*************************************************************************************** * * 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); }