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

1366 lines
35 KiB
C++
Raw 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 "gb28181_cfg.h"
/***********************************************************************/
extern HSIP_CLASS hsip;
extern HSIP_USER g_user;
/***********************************************************************/
SUACN sua_state_name[]=
{
{SUA_CS_IDLE, "IDLE"},
{SUAS_CS_TRYING, "UAS_TRYING"},
{SUAS_CS_1XX_SENT, "UAS_1XX_SENT"},
{SUAS_CS_2XX_SENT, "UAS_2XX_SENT"},
{SUAS_CS_4XX_SENT, "UAS_4XX_SENT"},
{SUAC_CS_INVITE_SENT, "UAC_INVITE_SENT"},
{SUAC_CS_1XX_RECV, "UAC_1XX_RECV"},
{SUA_CS_ESTABLISHED, "ESTABLISHED"},
{SUA_CS_BYE_SENT, "BYE_SENT"},
{SUA_CS_ERR_EXIT, "ERR_EXIT"},
};
char * sua_get_call_state_name(SUACS state)
{
uint32 i;
for (i=0; i<sizeof(sua_state_name)/sizeof(SUACN); i++)
{
if (sua_state_name[i].state == state)
{
return sua_state_name[i].state_name;
}
}
return (char *)"Unknow State";
}
/*******************************************************\
建立SUA呼叫消息的各个子函数
\*******************************************************/
void sua_build_from(HSIP_MSG * tx_msg, SUA * p_sua)
{
int offset = 0;
char tmp_buf[512];
if (p_sua->sua_disp_name[0] != '\0')
{
offset += sprintf(tmp_buf+offset, "\"%s\" ", p_sua->sua_disp_name);
}
offset += sprintf(tmp_buf+offset, "<%s>", p_sua->sua_sip_address);
if (p_sua->sua_sip_tag[0] != '\0')
{
offset += sprintf(tmp_buf+offset, ";%s", p_sua->sua_sip_tag);
}
sip_add_tx_msg_line(tx_msg, "From", "%s", tmp_buf);
}
void sua_build_response_from(HSIP_MSG * tx_msg, SUA * p_sua)
{
int offset = 0;
char tmp_buf[512];
if (p_sua->remote_disp_name[0] != '\0')
{
offset += sprintf(tmp_buf+offset, "\"%s\" ", p_sua->remote_disp_name);
}
offset += sprintf(tmp_buf+offset, "<%s>", p_sua->remote_sip_address);
if (p_sua->remote_sip_tag[0] != '\0')
{
offset += sprintf(tmp_buf+offset, ";%s", p_sua->remote_sip_tag);
}
sip_add_tx_msg_line(tx_msg, "From", "%s", tmp_buf);
}
void sua_build_to(HSIP_MSG * tx_msg, SUA * p_sua)
{
int offset = 0;
char tmp_buf[512];
if (p_sua->remote_disp_name[0] != '\0')
{
offset += sprintf(tmp_buf+offset, "\"%s\" ", p_sua->remote_disp_name);
}
offset += sprintf(tmp_buf+offset, "<%s>", p_sua->remote_sip_address);
if (p_sua->remote_sip_tag[0] != '\0')
{
offset += sprintf(tmp_buf+offset, ";%s", p_sua->remote_sip_tag);
}
sip_add_tx_msg_line(tx_msg, "To", "%s", tmp_buf);
}
void sua_build_response_to(HSIP_MSG * tx_msg, SUA * p_sua)
{
int offset = 0;
char tmp_buf[512];
if (p_sua->sua_disp_name[0] != '\0')
{
offset += sprintf(tmp_buf+offset, "\"%s\" ", p_sua->sua_disp_name);
}
offset += sprintf(tmp_buf+offset, "<%s>", p_sua->sua_sip_address);
if (p_sua->sua_sip_tag[0] != '\0')
{
offset += sprintf(tmp_buf+offset, ";%s", p_sua->sua_sip_tag);
}
sip_add_tx_msg_line(tx_msg, "To", "%s", tmp_buf);
}
void sua_build_contact(HSIP_MSG * tx_msg, SUA * p_sua)
{
if (p_sua->sua_disp_name[0] == '\0')
{
sip_add_tx_msg_line(tx_msg, "Contact", "<%s>", p_sua->sua_sip_address);
}
else
{
sip_add_tx_msg_line(tx_msg, "Contact", "\"%s\" <%s>", p_sua->sua_disp_name, p_sua->sua_sip_address);
}
}
void sua_build_route(HSIP_MSG * tx_msg, SUA * p_sua)
{
HDRV * p_rr = (HDRV *)pps_lookback_start(&(p_sua->rr_ctx));
while (p_rr != NULL)
{
sip_add_tx_msg_line(tx_msg, "Route", "%s", p_rr->value_string);
p_rr = (HDRV *)pps_lookback_next(&(p_sua->rr_ctx), p_rr);
}
pps_lookback_end(&(p_sua->rr_ctx));
}
void sua_build_record_route(HSIP_MSG * tx_msg, SUA * p_sua)
{
HDRV * p_rr = (HDRV *)pps_lookup_start(&(p_sua->rr_ctx));
while(p_rr != NULL)
{
sip_add_tx_msg_line(tx_msg, "Record-Route", "%s", p_rr->value_string);
p_rr = (HDRV *)pps_lookup_next(&(p_sua->rr_ctx), p_rr);
}
pps_lookup_end(&(p_sua->rr_ctx));
}
/*******************************************************\
建立SUA呼叫请求[INVITE]消息
type:
0 - 普通呼叫
1 - 上传JPG
2 - 上传VRF
\*******************************************************/
HSIP_MSG * sua_build_invite_msg(SUA * p_sua)
{
if (p_sua == NULL)
{
return NULL;
}
HSIP_MSG * tx_msg = sip_get_msg_buf();
if (NULL == tx_msg)
{
log_print(HT_LOG_ERR, "%s, get message buffer failed\r\n", __FUNCTION__);
return NULL;
}
tx_msg->msg_type = 0;
tx_msg->msg_sub_type = SIP_MT_INV;
tx_msg->msg_crpty_mode = p_sua->user_crpty_mode;
tx_msg->local_port = p_sua->sua_port;
sip_add_tx_msg_fline(tx_msg, "INVITE", "%s SIP/2.0", p_sua->remote_sip_address);
sip_free_ua_via_ctx(&(p_sua->via_ctx)); // 清除以前可能存在的
sip_new_ua_via(&(p_sua->via_ctx), p_sua->sua_ipstr, p_sua->sua_port, p_sua->p_user->usrf_tcp_sip);
sip_copy_via_tx(&(p_sua->via_ctx), tx_msg);
sua_build_from(tx_msg, p_sua);
sua_build_to(tx_msg, p_sua);
sua_build_contact(tx_msg, p_sua);
sip_add_tx_msg_line(tx_msg, "Call-ID", "%s", p_sua->call_id_str);
sip_add_tx_msg_line(tx_msg, "CSeq", "%u INVITE", p_sua->call_cseq);
sip_add_tx_msg_line(tx_msg, "Max-Forwards", "70");
sip_add_tx_msg_line(tx_msg, "Content-Type", "application/sdp");
sua_build_sdp_msg(p_sua, tx_msg);
int sdp_len = sua_calc_sdp_length(tx_msg);
sip_add_tx_msg_line(tx_msg, "Content-Length", "%d", sdp_len);
tx_msg->remote_ip = p_sua->remote_real_ip;
tx_msg->remote_port = p_sua->remote_real_port;
return tx_msg;
}
/*******************************************************\
建立UA呼叫请求[INVITE]消息,带MD5-CHAP认证消息
\*******************************************************/
HSIP_MSG * sua_build_invite_auth_msg(SUA * p_sua, HSIP_MSG * rx_msg)
{
if (p_sua == NULL || rx_msg == NULL)
{
return NULL;
}
HD_AUTH_INFO * auth_info = &(p_sua->user_auth_info);
HSIP_USER * p_user = p_sua->p_user;
if (p_user == NULL)
{
log_print(HT_LOG_ERR, "%s, p_sua->p_user = NULL!!!\r\n", __FUNCTION__);
return NULL;
}
HSIP_MSG * tx_msg = sip_get_msg_buf();
if (NULL == tx_msg)
{
log_print(HT_LOG_ERR, "%s, get message buffer failed\r\n", __FUNCTION__);
return NULL;
}
tx_msg->msg_type = 0;
tx_msg->msg_sub_type = SIP_MT_INV;
tx_msg->msg_crpty_mode = p_sua->user_crpty_mode;
tx_msg->local_port = p_sua->sua_port;
sip_add_tx_msg_fline(tx_msg, "INVITE", "%s SIP/2.0", p_sua->remote_sip_address);
sip_free_ua_via_ctx(&(p_sua->via_ctx)); // 清除以前可能存在的
sip_new_ua_via(&(p_sua->via_ctx), p_sua->sua_ipstr, p_sua->sua_port, p_sua->p_user->usrf_tcp_sip);
sip_copy_via_tx(&(p_sua->via_ctx), tx_msg);
sua_build_from(tx_msg, p_sua);
sua_build_to(tx_msg, p_sua);
sua_build_contact(tx_msg, p_sua);
sip_add_tx_msg_line(tx_msg, "Call-ID", "%s", p_sua->call_id_str);
sip_add_tx_msg_line(tx_msg, "CSeq", "%u INVITE", p_sua->call_cseq);
sip_add_tx_msg_line(tx_msg, "Max-Forwards", "70");
char auth_field_name[64];
if (rx_msg->msg_sub_type == 401)
{
strcpy(auth_field_name,"Authorization");
}
else if(rx_msg->msg_sub_type == 407)
{
strcpy(auth_field_name,"Proxy-Authorization");
}
else
{
auth_field_name[0] = '\0';
}
if (auth_info->auth_qop[0] != '\0')
{
sip_add_tx_msg_line(tx_msg,auth_field_name,"Digest username=\"%s\",realm=\"%s\",nonce=\"%s\",response=\"%s\","
"uri=\"%s\",qop=auth,algorithm=md5,cnonce=\"%s\",nc=%s",
auth_info->auth_name, auth_info->auth_realm, auth_info->auth_nonce,
auth_info->auth_response, auth_info->auth_uri, auth_info->auth_cnonce, auth_info->auth_ncstr);
}
else
{
sip_add_tx_msg_line(tx_msg,auth_field_name,"Digest username=\"%s\",realm=\"%s\",algorithm=MD5,uri=\"%s\",nonce=\"%s\",response=\"%s\"",
auth_info->auth_name, auth_info->auth_realm,
auth_info->auth_uri, auth_info->auth_nonce, auth_info->auth_response);
}
sip_add_tx_msg_line(tx_msg, "Content-Type", "application/sdp");
sua_build_sdp_msg(p_sua, tx_msg);
int sdp_len = sua_calc_sdp_length(tx_msg);
sip_add_tx_msg_line(tx_msg, "Content-Length", "%d", sdp_len);
tx_msg->remote_ip = p_sua->remote_real_ip;
tx_msg->remote_port = p_sua->remote_real_port;
return tx_msg;
}
/*******************************************************\
建立UA呼叫响应[INVITE 200 OK]消息
\*******************************************************/
HSIP_MSG * sua_build_iok_msg(SUA * p_sua)
{
HSIP_MSG * tx_msg = sip_get_msg_buf();
if (NULL == tx_msg)
{
log_print(HT_LOG_ERR, "%s, get message buffer failed\r\n", __FUNCTION__);
return NULL;
}
tx_msg->msg_type = 1;
tx_msg->msg_sub_type = 200;
tx_msg->msg_crpty_mode = p_sua->user_crpty_mode;
tx_msg->local_port = p_sua->sua_port;
sip_add_tx_msg_fline(tx_msg, "SIP/2.0", "200 OK");
sip_copy_via_tx(&(p_sua->via_ctx),tx_msg);
sua_build_response_from(tx_msg, p_sua);
sua_build_response_to(tx_msg, p_sua);
sua_build_contact(tx_msg, p_sua);
sua_build_record_route(tx_msg, p_sua);
sip_add_tx_msg_line(tx_msg, "Call-ID", "%s", p_sua->call_id_str);
sip_add_tx_msg_line(tx_msg, "CSeq", "%u INVITE", p_sua->call_cseq);
sip_add_tx_msg_line(tx_msg, "Max-Forwards", "70");
sip_add_tx_msg_line(tx_msg, "User-Agent", "%s", hsip.ver);
sip_add_tx_msg_line(tx_msg, "Content-Type", "application/sdp");
sua_build_sdp_msg(p_sua, tx_msg);
int sdp_len = sua_calc_sdp_length(tx_msg);
sip_add_tx_msg_line(tx_msg, "Content-Length", "%d", sdp_len);
tx_msg->remote_ip = p_sua->remote_real_ip;
tx_msg->remote_port = p_sua->remote_real_port;
return tx_msg;
}
/*******************************************************\
建立UA呼叫响应[INVITE 180/183 with SDP]消息
"183 Session Progress"
\*******************************************************/
HSIP_MSG * sua_build_18xsdp_msg(SUA * p_sua, const char * response_hdr)
{
HSIP_MSG * tx_msg = sip_get_msg_buf();
if (NULL == tx_msg)
{
log_print(HT_LOG_ERR, "%s, get message buffer failed\r\n", __FUNCTION__);
return NULL;
}
tx_msg->msg_type = 1;
tx_msg->msg_sub_type = 200;
tx_msg->msg_crpty_mode = p_sua->user_crpty_mode;
tx_msg->local_port = p_sua->sua_port;
sip_add_tx_msg_fline(tx_msg, "SIP/2.0", response_hdr);
sip_copy_via_tx(&(p_sua->via_ctx), tx_msg);
sua_build_response_from(tx_msg, p_sua);
sua_build_response_to(tx_msg, p_sua);
sua_build_contact(tx_msg, p_sua);
sua_build_record_route(tx_msg, p_sua);
sip_add_tx_msg_line(tx_msg, "Call-ID", "%s", p_sua->call_id_str);
sip_add_tx_msg_line(tx_msg, "CSeq", "%u INVITE", p_sua->call_cseq);
sip_add_tx_msg_line(tx_msg, "User-Agent", "%s", hsip.ver);
sip_add_tx_msg_line(tx_msg, "Content-Type", "application/sdp");
sua_build_sdp_msg(p_sua,tx_msg);
int sdp_len = sua_calc_sdp_length(tx_msg);
sip_add_tx_msg_line(tx_msg, "Content-Length", "%d", sdp_len);
tx_msg->remote_ip = p_sua->remote_real_ip;
tx_msg->remote_port = p_sua->remote_real_port;
return tx_msg;
}
/*******************************************************\
建立UA呼叫请求[BYE]消息
\*******************************************************/
HSIP_MSG * sua_build_bye_msg(SUA * p_sua)
{
if (p_sua == NULL)
{
return NULL;
}
HSIP_MSG * tx_msg = sip_get_msg_buf();
if (NULL == tx_msg)
{
log_print(HT_LOG_ERR, "%s, get message buffer failed\r\n", __FUNCTION__);
return NULL;
}
tx_msg->msg_type = 0;
tx_msg->msg_sub_type = SIP_MT_BYE;
tx_msg->msg_crpty_mode = p_sua->user_crpty_mode;
tx_msg->local_port = p_sua->sua_port;
if (p_sua->remote_contact_uri[0] == '\0')
{
sip_add_tx_msg_fline(tx_msg, "BYE", "%s SIP/2.0", p_sua->remote_sip_address);
}
else
{
sip_add_tx_msg_fline(tx_msg, "BYE", "%s SIP/2.0", p_sua->remote_contact_uri);
}
sip_free_ua_via_ctx(&(p_sua->via_ctx)); // 清除以前可能存在的
sip_new_ua_via(&(p_sua->via_ctx), p_sua->sua_ipstr, p_sua->sua_port, p_sua->p_user->usrf_tcp_sip);
sip_copy_via_tx(&(p_sua->via_ctx), tx_msg);
sua_build_from(tx_msg, p_sua);
sua_build_to(tx_msg, p_sua);
sua_build_contact(tx_msg, p_sua);
sua_build_route(tx_msg, p_sua);
sip_add_tx_msg_line(tx_msg, "Call-ID", "%s", p_sua->call_id_str);
sip_add_tx_msg_line(tx_msg, "CSeq", "%u BYE", p_sua->call_cseq);
sip_add_tx_msg_line(tx_msg, "Max-Forwards", "70");
sip_add_tx_msg_line(tx_msg, "Content-Length", "0");
tx_msg->remote_ip = p_sua->remote_real_ip;
tx_msg->remote_port = p_sua->remote_real_port;
return tx_msg;
}
/*******************************************************\
建立UA呼叫请求[CANCEL]消息
\*******************************************************/
HSIP_MSG * sua_build_cancel_msg(SUA * p_sua)
{
HSIP_MSG * tx_msg = sip_get_msg_buf();
if (NULL == tx_msg)
{
log_print(HT_LOG_ERR, "%s, get message buffer failed\r\n", __FUNCTION__);
return NULL;
}
tx_msg->msg_type = 0;
tx_msg->msg_sub_type = SIP_MT_BYE;
tx_msg->msg_crpty_mode = p_sua->user_crpty_mode;
tx_msg->local_port = p_sua->sua_port;
sip_add_tx_msg_fline(tx_msg, "CANCEL", "%s SIP/2.0", p_sua->remote_sip_address);
sip_copy_via_tx(&(p_sua->via_ctx), tx_msg);
sua_build_from(tx_msg, p_sua);
p_sua->remote_sip_tag[0] = '\0';
sua_build_to(tx_msg, p_sua);
sua_build_contact(tx_msg, p_sua);
sip_add_tx_msg_line(tx_msg, "Call-ID", "%s", p_sua->call_id_str);
sip_add_tx_msg_line(tx_msg, "CSeq", "%u CANCEL", p_sua->call_cseq);
sip_add_tx_msg_line(tx_msg, "Max-Forwards", "70");
sip_add_tx_msg_line(tx_msg, "Content-Length", "0");
tx_msg->remote_ip = p_sua->remote_real_ip;
tx_msg->remote_port = p_sua->remote_real_port;
return tx_msg;
}
/*******************************************************\
建立UA呼叫请求[ACK]消息
\*******************************************************/
HSIP_MSG * sua_build_ack_msg(SUA * p_sua)
{
HSIP_MSG * tx_msg = sip_get_msg_buf();
if (NULL == tx_msg)
{
log_print(HT_LOG_ERR, "%s, get message buffer failed\r\n", __FUNCTION__);
return NULL;
}
tx_msg->msg_type = 0;
tx_msg->msg_sub_type = SIP_MT_ACK;
tx_msg->msg_crpty_mode = p_sua->user_crpty_mode;
tx_msg->local_port = p_sua->sua_port;
if (p_sua->remote_contact_uri[0] == '\0')
{
sip_add_tx_msg_fline(tx_msg, "ACK", "%s SIP/2.0", p_sua->remote_sip_address);
}
else
{
sip_add_tx_msg_fline(tx_msg, "ACK", "%s SIP/2.0", p_sua->remote_contact_uri);
}
sip_copy_via_tx(&(p_sua->via_ctx), tx_msg);
sua_build_from(tx_msg, p_sua);
sua_build_to(tx_msg, p_sua);
sua_build_contact(tx_msg, p_sua);
sua_build_route(tx_msg, p_sua);
sip_add_tx_msg_line(tx_msg, "Call-ID","%s", p_sua->call_id_str);
sip_add_tx_msg_line(tx_msg, "CSeq","%u ACK", p_sua->call_cseq);
sip_add_tx_msg_line(tx_msg, "Max-Forwards", "70");
sip_add_tx_msg_line(tx_msg, "Content-Length", "0");
tx_msg->remote_ip = p_sua->remote_real_ip;
tx_msg->remote_port = p_sua->remote_real_port;
return tx_msg;
}
/*******************************************************\
建立UA呼叫请求[PRACK]消息
\*******************************************************/
HSIP_MSG * sua_build_prack_msg(SUA * p_sua)
{
HSIP_MSG * tx_msg = sip_get_msg_buf();
if (NULL == tx_msg)
{
log_print(HT_LOG_ERR, "%s, get message buffer failed\r\n", __FUNCTION__);
return NULL;
}
tx_msg->msg_type = 0;
tx_msg->msg_sub_type = SIP_MT_ACK;
tx_msg->msg_crpty_mode = p_sua->user_crpty_mode;
tx_msg->local_port = p_sua->sua_port;
if (p_sua->remote_contact_uri[0] == '\0')
{
sip_add_tx_msg_fline(tx_msg, "PRACK", "%s SIP/2.0", p_sua->remote_sip_address);
}
else
{
sip_add_tx_msg_fline(tx_msg, "PRACK", "%s SIP/2.0", p_sua->remote_contact_uri);
}
sip_free_ua_via_ctx(&(p_sua->via_ctx)); // 清除以前可能存在的
sip_new_ua_via(&(p_sua->via_ctx), p_sua->sua_ipstr, p_sua->sua_port, p_sua->p_user->usrf_tcp_sip);
sip_copy_via_tx(&(p_sua->via_ctx), tx_msg);
sua_build_from(tx_msg, p_sua);
sua_build_to(tx_msg, p_sua);
sip_add_tx_msg_line(tx_msg, "Call-ID","%s", p_sua->call_id_str);
p_sua->call_cseq++;
sip_add_tx_msg_line(tx_msg, "CSeq", "%u PRACK", p_sua->call_cseq);
sip_add_tx_msg_line(tx_msg, "Max-Forwards", "70");
sip_add_tx_msg_line(tx_msg, "Content-Length", "0");
tx_msg->remote_ip = p_sua->remote_real_ip;
tx_msg->remote_port = p_sua->remote_real_port;
return tx_msg;
}
/*******************************************************\
建立UA呼叫响应[100,180,4xx,200]消息
\*******************************************************/
HSIP_MSG * sua_build_update_response_msg(HSIP_MSG * rx_msg, const char * response_hdr)
{
if (rx_msg == NULL || response_hdr == NULL)
{
return NULL;
}
HSIP_MSG * tx_msg = sip_get_msg_buf();
if (NULL == tx_msg)
{
log_print(HT_LOG_ERR, "%s, get message buffer failed\r\n", __FUNCTION__);
return NULL;
}
tx_msg->msg_type = 1;
tx_msg->msg_sub_type = 200;
tx_msg->msg_crpty_mode = rx_msg->msg_crpty_mode;
tx_msg->local_port = rx_msg->local_port;
sip_add_tx_msg_fline(tx_msg, "SIP/2.0", response_hdr);
sip_copy_msg_via(rx_msg, tx_msg);
sip_copy_msg_line(rx_msg, tx_msg, "From");
sip_copy_msg_line(rx_msg, tx_msg, "To");
sip_copy_msg_line(rx_msg, tx_msg, "Call-ID");
sip_copy_msg_line(rx_msg, tx_msg, "CSeq");
sip_copy_msg_line(rx_msg, tx_msg, "Supported");
sip_copy_msg_line(rx_msg, tx_msg, "Require");
sip_copy_msg_line(rx_msg, tx_msg, "Session-Expires");
sip_copy_msg_line(rx_msg, tx_msg, "Min-SE");
sip_add_tx_msg_line(tx_msg, "Content-Length", "0");
tx_msg->remote_ip = rx_msg->remote_ip;
tx_msg->remote_port = rx_msg->remote_port;
return tx_msg;
}
HSIP_MSG * sua_build_response_msg(HSIP_MSG * rx_msg, const char * response_hdr)
{
if (rx_msg == NULL || response_hdr == NULL)
{
return NULL;
}
HSIP_MSG * tx_msg = sip_get_msg_buf();
if (NULL == tx_msg)
{
log_print(HT_LOG_ERR, "%s, get message buffer failed\r\n", __FUNCTION__);
return NULL;
}
tx_msg->msg_type = 1;
tx_msg->msg_sub_type = 200;
tx_msg->msg_crpty_mode = rx_msg->msg_crpty_mode;
tx_msg->local_port = rx_msg->local_port;
sip_add_tx_msg_fline(tx_msg, "SIP/2.0", response_hdr);
sip_copy_msg_via(rx_msg, tx_msg);
// 一些服务器发送的From, To 不带<>, 直接COPY回去不认
#if 1
char f_user_name[64] = {'\0'};
char f_user_domain[64] = {'\0'};
char f_user_tag[64] = {'\0'};
char t_user_name[64] = {'\0'};
char t_user_domain[64] = {'\0'};
char t_user_tag[64] = {'\0'};
sip_get_user_name(rx_msg, "From", f_user_name, sizeof(f_user_name));
sip_get_user_domain(rx_msg, "From", f_user_domain, sizeof(f_user_domain));
sip_get_user_tag(rx_msg, "From", f_user_tag, sizeof(f_user_tag));
sip_get_user_name(rx_msg, "To", t_user_name, sizeof(t_user_name));
sip_get_user_domain(rx_msg, "To", t_user_domain, sizeof(t_user_domain));
sip_get_user_tag(rx_msg, "To", t_user_tag, sizeof(t_user_tag));
if (f_user_tag[0] != '\0')
{
sip_add_tx_msg_line(tx_msg, "From", "<sip:%s@%s>;tag=%s", f_user_name, f_user_domain, f_user_tag);
}
else
{
sip_add_tx_msg_line(tx_msg, "From", "<sip:%s@%s>", f_user_name, f_user_domain);
}
if (f_user_tag[0] != '\0')
{
sip_add_tx_msg_line(tx_msg, "To", "<sip:%s@%s>;tag=%s", t_user_name, t_user_domain, t_user_tag);
}
else
{
sip_add_tx_msg_line(tx_msg, "To", "<sip:%s@%s>", t_user_name, t_user_domain);
}
#else
sip_copy_msg_line(rx_msg, tx_msg, "From");
sip_copy_msg_line(rx_msg, tx_msg, "To");
#endif
sip_copy_msg_line(rx_msg, tx_msg, "Call-ID");
sip_copy_msg_line(rx_msg, tx_msg, "CSeq");
sip_add_tx_msg_line(tx_msg, "User-Agent", "%s", hsip.ver);
sip_add_tx_msg_line(tx_msg, "Content-Length", "0");
tx_msg->remote_ip = rx_msg->remote_ip;
tx_msg->remote_port = rx_msg->remote_port;
return tx_msg;
}
HSIP_MSG * sua_build_invite_response(SUA * p_sua, const char * response_hdr)
{
HSIP_MSG * tx_msg = sip_get_msg_buf();
if (NULL == tx_msg)
{
log_print(HT_LOG_ERR, "%s, get message buffer failed\r\n", __FUNCTION__);
return NULL;
}
tx_msg->msg_type = 1;
tx_msg->msg_sub_type = 200;
tx_msg->msg_crpty_mode = p_sua->user_crpty_mode;
tx_msg->local_port = p_sua->sua_port;
sip_add_tx_msg_fline(tx_msg, "SIP/2.0", response_hdr);
sip_copy_via_tx(&(p_sua->via_ctx), tx_msg);
sua_build_response_from(tx_msg, p_sua);
sua_build_response_to(tx_msg, p_sua);
sua_build_record_route(tx_msg, p_sua);
sip_add_tx_msg_line(tx_msg, "Call-ID", "%s", p_sua->call_id_str);
sip_add_tx_msg_line(tx_msg, "CSeq", "%u INVITE", p_sua->call_cseq);
sip_add_tx_msg_line(tx_msg, "User-Agent", "%s", hsip.ver);
sip_add_tx_msg_line(tx_msg, "Content-Length", "0");
tx_msg->remote_ip = p_sua->remote_real_ip;
tx_msg->remote_port = p_sua->remote_real_port;
return tx_msg;
}
BOOL sua_get_session_timer_info(SUA * p_sua, HSIP_MSG * rx_msg)
{
int expires=0, min_se=0, refresher=0;
if (sip_get_session_timer_info(rx_msg, &expires, &min_se, &refresher))
{
p_sua->uaf_timer = 1;
p_sua->SessionExpires = expires;
if (min_se == 0)
{
min_se = expires / 2;
}
p_sua->MinSE = min_se;
if (refresher == 1 && p_sua->uaf_uac == 1)
{
p_sua->uaf_refresher = 1;
}
else if (refresher == 2 && p_sua->uaf_uas == 1)
{
p_sua->uaf_refresher = 1;
}
return TRUE;
}
return FALSE;
}
void sua_timer_set(SUA * p_sua, uint32 interval, uint32 max_times, SUACS fail_state)
{
p_sua->state_timer_interval = interval;
p_sua->state_retx_count = 0;
p_sua->state_retx_max_times = max_times;
p_sua->state_retx_fail_state = fail_state;
p_sua->uaf_state_timer = 1;
}
void sua_timer_clear(SUA * p_sua)
{
p_sua->uaf_state_timer = 0;
}
/******************************************************************\
回调函数设置
\******************************************************************/
void sua_set_state_cb(SUA * p_sua, SIPCALLCBF state_cb, void * user_data)
{
if (pps_safe_node(hsip.sua_fl, p_sua) == FALSE)
{
log_print(HT_LOG_ERR, "%s, param p_sua[%p] err!!!\r\n", __FUNCTION__, p_sua);
p_sua = NULL;
}
if (p_sua == NULL)
{
return;
}
sys_os_mutex_enter(hsip.mutex_cb);
p_sua->call_state_cb = state_cb;
p_sua->user_data = user_data;
sys_os_mutex_leave(hsip.mutex_cb);
}
void sua_set_audio_cb(SUA * p_sua, RTPRXCBF rtp_cb)
{
if (p_sua == NULL)
{
return;
}
if (pps_safe_node(hsip.sua_fl, p_sua) == FALSE)
{
log_print(HT_LOG_ERR, "%s, param p_sua[%p] err!!!\r\n", __FUNCTION__, p_sua);
return;
}
sys_os_mutex_enter(hsip.mutex_cb);
p_sua->audio_rx_cb = rtp_cb;
sys_os_mutex_leave(hsip.mutex_cb);
}
/******************************************************************\
打开媒体通道
\******************************************************************/
BOOL sua_start_media(SUA * p_sua)
{
if (sua_check_same_cap(p_sua) <= 0)
{
return FALSE;
}
if (p_sua->uaf_rtp_mux == 1)
{
sua_start_mux_media(p_sua);
}
else
{
if (p_sua->l_v_cap_cnt > 0 && p_sua->r_v_cap_cnt > 0)
{
sua_start_video(p_sua);
}
if (p_sua->l_a_cap_cnt > 0 && p_sua->r_a_cap_cnt > 0)
{
sua_start_audio(p_sua);
}
else if (p_sua->uaf_ps_audio_tx && strcasecmp(p_sua->l_v_sdp[0].encoder, "PS") == 0)
{
sua_start_audio(p_sua);
}
}
if (p_sua->l_a_cap_cnt > 0 && p_sua->r_a_cap_cnt > 0)
{
if (p_sua->uaf_multicast == 1)
{
if (p_sua->uaf_uas == 1) // 被叫根据主叫的方向要求确定首发方向在解析主叫SDP的时候已经更改
{
if (p_sua->l_a_sdp[0].sendrecv != SDP_SENDRECV_RXONLY)
{
p_sua->uaf_a_tx_flag = 1;
}
else if (p_sua->l_a_sdp[0].sendrecv != SDP_SENDRECV_TXONLY)
{
p_sua->uaf_a_rx_flag = 1;
}
}
else if (p_sua->uaf_uac == 1) // 主叫确定的方向呢?
{
if (p_sua->l_a_sdp[0].sendrecv != SDP_SENDRECV_TXONLY)
{
p_sua->uaf_a_tx_flag = 1;
}
else if (p_sua->l_a_sdp[0].sendrecv != SDP_SENDRECV_RXONLY)
{
p_sua->uaf_a_rx_flag = 1;
}
}
}
else
{
if (p_sua->r_a_sdp[0].sendrecv != SDP_SENDRECV_TXONLY)
{
p_sua->uaf_a_tx_flag = 1;
}
}
}
else if (p_sua->uaf_ps_audio_tx && strcasecmp(p_sua->l_v_sdp[0].encoder, "PS") == 0)
{
if (p_sua->uaf_multicast == 1)
{
if (p_sua->uaf_uas == 1) // 被叫根据主叫的方向要求确定首发方向在解析主叫SDP的时候已经更改
{
if (p_sua->l_v_sdp[0].sendrecv != SDP_SENDRECV_RXONLY)
{
p_sua->uaf_a_tx_flag = 1;
}
else if (p_sua->l_v_sdp[0].sendrecv != SDP_SENDRECV_TXONLY)
{
p_sua->uaf_a_rx_flag = 1;
}
}
else if (p_sua->uaf_uac == 1) // 主叫确定的方向呢?
{
if (p_sua->l_v_sdp[0].sendrecv != SDP_SENDRECV_TXONLY)
{
p_sua->uaf_a_tx_flag = 1;
}
else if (p_sua->l_v_sdp[0].sendrecv != SDP_SENDRECV_RXONLY)
{
p_sua->uaf_a_rx_flag = 1;
}
}
}
else
{
if (p_sua->r_v_sdp[0].sendrecv != SDP_SENDRECV_TXONLY)
{
p_sua->uaf_a_tx_flag = 1;
}
}
}
if (p_sua->l_v_cap_cnt > 0 && p_sua->r_v_cap_cnt > 0)
{
if (p_sua->uaf_multicast == 1)
{
if (p_sua->uaf_uas == 1) // 被叫根据主叫的方向要求确定首发方向在解析主叫SDP的时候已经更改
{
if (p_sua->l_v_sdp[0].sendrecv != SDP_SENDRECV_RXONLY)
{
p_sua->uaf_v_tx_flag = 1;
}
else if (p_sua->l_v_sdp[0].sendrecv != SDP_SENDRECV_TXONLY)
{
p_sua->uaf_v_rx_flag = 1;
}
}
else if (p_sua->uaf_uac == 1) // 主叫确定的方向呢?
{
if (p_sua->l_v_sdp[0].sendrecv != SDP_SENDRECV_TXONLY)
{
p_sua->uaf_v_tx_flag = 1;
}
else if (p_sua->l_v_sdp[0].sendrecv != SDP_SENDRECV_RXONLY)
{
p_sua->uaf_v_rx_flag = 1;
}
}
}
else
{
if (p_sua->r_v_sdp[0].sendrecv != SDP_SENDRECV_TXONLY)
{
p_sua->uaf_v_tx_flag = 1;
}
}
}
uint32 cur_time = sys_os_get_uptime();
p_sua->audio_rtp_media.last_pkt_time = cur_time;
p_sua->audio_rtcp_media.last_pkt_time = cur_time;
p_sua->video_rtp_media.last_pkt_time = cur_time;
p_sua->video_rtcp_media.last_pkt_time = cur_time;
return TRUE;
}
BOOL sua_start_media_rx(SUA * p_sua)
{
if (p_sua->uaf_rtp_mux == 1)
{
return sua_start_mux_media_rx(p_sua);
}
else
{
BOOL ret1 = sua_start_video_rx(p_sua);
BOOL ret2 = sua_start_audio_rx(p_sua);
return (ret1 && ret2);
}
}
/******************************************************************\
关闭SESSION
\******************************************************************/
void sua_stop_media(SUA * p_sua)
{
uint32 u_index = sua_get_index(p_sua);
p_sua->uaf_rtp_tx = 0;
while (p_sua->tid_media)
{
usleep(10*1000);
}
if (p_sua->uaf_rtp_mux == 1)
{
log_print(HT_LOG_INFO, "%s, sua_stop_mux_rtp sua[%u] start.\r\n", __FUNCTION__, u_index);
sua_stop_mux_rtp(p_sua);
log_print(HT_LOG_INFO, "%s, sua_stop_mux_rtp sua[%u] end.\r\n", __FUNCTION__, u_index);
}
else
{
log_print(HT_LOG_INFO, "%s, sua_stop_video sua[%u] start.\r\n", __FUNCTION__, u_index);
sua_stop_video(p_sua);
log_print(HT_LOG_INFO, "%s, sua_stop_audio sua[%u] start.\r\n", __FUNCTION__, u_index);
sua_stop_audio(p_sua);
log_print(HT_LOG_INFO, "%s, sua_stop_audio sua[%u] end.\r\n", __FUNCTION__, u_index);
}
#ifdef MEDIA_FILE
if (p_sua->media_info.file_demuxer)
{
delete p_sua->media_info.file_demuxer;
p_sua->media_info.file_demuxer = NULL;
}
#endif
#ifdef MEDIA_DEVICE
if (p_sua->media_info.video_capture)
{
p_sua->media_info.video_capture->freeInstance(p_sua->media_info.v_index);
p_sua->media_info.video_capture = NULL;
}
if (p_sua->media_info.audio_capture)
{
p_sua->media_info.audio_capture->freeInstance(p_sua->media_info.a_index);
p_sua->media_info.audio_capture = NULL;
}
#endif
#ifdef MEDIA_LIVE
if (p_sua->media_info.live_video)
{
p_sua->media_info.live_video->freeInstance(p_sua->media_info.v_index);
p_sua->media_info.live_video = NULL;
}
if (p_sua->media_info.live_audio)
{
p_sua->media_info.live_audio->freeInstance(p_sua->media_info.a_index);
p_sua->media_info.live_audio = NULL;
}
#endif
}
void sua_stop_used_sua(SUA * p_sua)
{
log_print(HT_LOG_INFO, "%s, sua[%u] start.\r\n", __FUNCTION__, sua_get_index(p_sua));
if (pps_safe_node(hsip.sua_fl, p_sua) == FALSE)
{
log_print(HT_LOG_ERR, "%s, unit ptr error!!!\r\n", __FUNCTION__);
return;
}
sua_stop_media(p_sua);
sua_state_set(p_sua, SUA_CS_IDLE);
// if (p_sua->uaf_uas == 1) // 这种情况下是协议栈内部分配的, 需要内部自己释放
{
sua_set_idle_sua(p_sua);
}
log_print(HT_LOG_INFO, "%s, sua[%u] finish.\r\n", __FUNCTION__, sua_get_index(p_sua));
}
void sua_free_used_sua(SUA * p_sua)
{
log_print(HT_LOG_INFO, "%s, sua[%u] start.\r\n", __FUNCTION__, sua_get_index(p_sua));
if (pps_safe_node(hsip.sua_fl, p_sua) == FALSE)
{
log_print(HT_LOG_ERR, "%s, unit ptr error!!!\r\n", __FUNCTION__);
return;
}
sua_stop_media(p_sua);
sua_state_set(p_sua, SUA_CS_IDLE);
sua_set_idle_sua(p_sua);
}
/******************************************************************\
SUA管理功能(使用push/pop机制)
1. 取得一个空闲的SUA
2. 释放一个SUA
sua_fl 存储空闲的SUA
sua_ul 存储在用的SUA
\******************************************************************/
static uint32 sua_guid_seq = 100;
void sua_proxy_init()
{
hsip.sua_fl = pps_ctx_fl_init(MAX_NUM_SUA, sizeof(SUA), TRUE);
hsip.sua_ul = pps_ctx_ul_init(hsip.sua_fl, TRUE);
}
void sua_proxy_deinit()
{
int i;
for (i=0; i<MAX_NUM_SUA; i++)
{
SUA * p_sua = sua_get_by_index(i);
sua_stop_media(p_sua);
sua_set_idle_sua(p_sua);
}
if (hsip.sua_ul)
{
pps_ul_free(hsip.sua_ul);
hsip.sua_ul = NULL;
}
if (hsip.sua_fl)
{
pps_fl_free(hsip.sua_fl);
hsip.sua_fl = NULL;
}
}
void sua_user_init(HSIP_USER * p_user, SUA * p_sua)
{
int ua_index = sua_get_index(p_sua);
int ua_offset= ua_index << 2;
p_sua->user_crpty_mode = p_user->user_crpty_mode;
strcpy(p_sua->sua_ipstr, hsip.local_ipstr);
p_sua->sua_port = p_user->sip_port;
p_sua->remote_real_ip = inet_addr(p_user->server_ipstr);
p_sua->remote_real_port = htons(p_user->server_port);
p_sua->audio_rtp_media.local_port = g_gb28181_cfg.media_base_port + ua_offset;
p_sua->audio_rtcp_media.local_port = g_gb28181_cfg.media_base_port + 1 + ua_offset;
p_sua->video_rtp_media.local_port = g_gb28181_cfg.media_base_port + 2 + ua_offset;
p_sua->video_rtcp_media.local_port = g_gb28181_cfg.media_base_port + 3 + ua_offset;
strcpy(p_sua->sua_disp_name, p_user->user_disp_name);
strcpy(p_sua->sua_domain, p_user->user_domain);
strcpy(p_sua->sua_sip_address, p_user->user_sip_addr);
strcpy(p_sua->sua_deviceid, p_user->user_name);
strcpy(p_sua->remote_domain, p_user->user_domain);
p_sua->a_rtp_info.rtp_cnt = rand() & 0xFFFF;
p_sua->v_rtp_info.rtp_cnt = rand() & 0xFFFF;
p_sua->a_rtp_info.rtp_ssrc = rand();
p_sua->v_rtp_info.rtp_ssrc = rand();
p_sua->uaf_v_h264 = 0;
p_sua->uaf_v_jpeg = 0;
p_sua->uaf_v_ps = 1;
p_sua->uaf_multicast = 0;
p_sua->uaf_timer = 1;
p_sua->SessionExpires = 200;
p_sua->MinSE = 90;
p_sua->uaf_refresher = 0;
p_sua->p_user = p_user;
sip_init_ul_via_ctx(&(p_sua->via_ctx));
p_sua->uaf_v_tcp_rtp = p_sua->uaf_a_tcp_rtp = p_user->usrf_tcp_rtp;
sua_r_rtp_map_init(p_sua);
}
SUA * sua_get_idle_sua(HSIP_USER * p_user)
{
SUA * p_sua = (SUA *)pps_fl_pop(hsip.sua_fl);
if (p_sua)
{
memset(p_sua, 0, sizeof(SUA));
p_sua->s_time = sys_os_get_ms();
sua_user_init(p_user, p_sua);
pps_ctx_ul_add(hsip.sua_ul,p_sua);
p_sua->guid = sua_guid_seq++;
}
else
{
// pps_ctx_show(hsip.sua_fl);
}
log_print(HT_LOG_INFO, "%s, p_sua=%p, index[%u]\r\n", __FUNCTION__, p_sua, sua_get_index(p_sua));
return p_sua;
}
void sua_set_idle_sua(SUA * p_sua)
{
log_print(HT_LOG_INFO, "%s, p_sua=%p, index[%u]\r\n", __FUNCTION__, p_sua, sua_get_index(p_sua));
sip_free_ua_via_ctx(&(p_sua->via_ctx));
pps_ctx_ul_del(hsip.sua_ul, p_sua);
memset(p_sua, 0, sizeof(SUA));
pps_fl_push(hsip.sua_fl, p_sua);
}
SUA * sua_lookup_start()
{
return (SUA *)pps_lookup_start(hsip.sua_ul);
}
SUA * sua_lookup_next(SUA * p_sua)
{
return (SUA *)pps_lookup_next(hsip.sua_ul, p_sua);
}
void sua_lookup_stop()
{
pps_lookup_end(hsip.sua_ul);
}
/******************************************************************\
获取对应的RUA会话表项索引值
\******************************************************************/
uint32 sua_get_index(SUA * p_sua)
{
return pps_get_index(hsip.sua_fl, p_sua);
}
SUA * sua_get_by_index(uint32 index)
{
return (SUA *)pps_get_node_by_index(hsip.sua_fl, index);
}
/******************************************************************\
根据CALL-ID字符串查找对应SUA, 在少量情况下用循环, 否则哈希
\******************************************************************/
SUA * sua_lookup_by_callid(char * p_callid)
{
SUA * p_sua = sua_lookup_start();
while (p_sua)
{
if (strcmp(p_sua->call_id_str, p_callid) == 0)
{
break;
}
p_sua = sua_lookup_next(p_sua);
}
sua_lookup_stop();
return p_sua;
}
void sua_del_native(uint32 ua_index, uint32 ua_guid)
{
SUA * p_sua = sua_get_by_index(ua_index);
if (p_sua == NULL)
{
return;
}
if (p_sua->guid != ua_guid)
{
log_print(HT_LOG_ERR, "%s, p_sua[%u]->guid[%u] != ua_guid[%u]!!!\r\n", __FUNCTION__, ua_index, p_sua->guid, ua_guid);
return;
}
sua_free_used_sua(p_sua);
}
/***********************************************************************\
设置呼叫状态, 如果有线程在等待某个状态, 唤醒该线程
等待的状态目前应该只能有: 接通, 挂断
\***********************************************************************/
void sua_state_set(SUA * p_sua, SUACS state)
{
if (p_sua->call_state == state)
{
return;
}
p_sua->call_state = state;
if (p_sua->uaf_state_wait == 1)
{
if (p_sua->call_state == p_sua->wait_state)
{
if (p_sua->wait_sig)
{
sys_os_sig_sign(p_sua->wait_sig);
}
p_sua->uaf_state_wait = 0;
}
else
{
if (p_sua->wait_state == SUA_CS_ESTABLISHED)
{
if (p_sua->call_state > SUA_CS_ESTABLISHED || p_sua->call_state == SUA_CS_IDLE)
{
// 等待接通的呼叫已经进入挂机阶段
if (p_sua->wait_sig)
{
sys_os_sig_sign(p_sua->wait_sig);
}
p_sua->uaf_state_wait = 0;
}
}
}
}
}
/******************************************************************\
SUA分配/释放接口
\******************************************************************/
void * sua_new_handle()
{
SUA * p_sua = sua_get_idle_sua(&g_user);
return p_sua;
}
void * sua_get_handle(uint32 index)
{
return sua_get_by_index(index);
}
int sua_get_handle_index(void * hSua)
{
return sua_get_index((SUA *)hSua);
}
void sua_del_handle(void * hSua)
{
SUA * p_sua = (SUA *)hSua;
sua_post_del_handle(sua_get_index(p_sua), p_sua->guid);
}
BOOL sua_post_del_handle(uint32 ua_index, uint32 ua_guid)
{
SIPTM stm;
memset(&stm, 0, sizeof(stm));
stm.msg_src = SUA_DEL_SRC;
stm.msg_param = ua_index;
stm.dst_port = ua_guid;
if (hqBufPut(hsip.msg_queue, (char *)&stm) == FALSE)
{
log_print(HT_LOG_ERR, "%s, hqBufPut return FALSE!!!\r\n", __FUNCTION__);
return FALSE;
}
return TRUE;
}