1366 lines
35 KiB
C++
1366 lines
35 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 "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;
|
||
}
|
||
|
||
|
||
|