1082 lines
25 KiB
C++
1082 lines
25 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_tx.h"
|
||
#include "sip_reg.h"
|
||
#include "sip_pstate.h"
|
||
#include "sip_util.h"
|
||
|
||
/***********************************************************************/
|
||
extern HSIP_CLASS hsip;
|
||
|
||
/***********************************************************************\
|
||
代理服务器状态处理 - UAS/UAC
|
||
\***********************************************************************/
|
||
void sua_call_state(SUA * p_sua, CSEVT event, HSIP_MSG * rx_msg)
|
||
{
|
||
if (rx_msg)
|
||
{
|
||
event = sip_get_msg_event(rx_msg);
|
||
}
|
||
|
||
log_print(HT_LOG_DBG, "%s, [%s]::%s %s\r\n", __FUNCTION__,
|
||
p_sua->remote_sip_address,
|
||
sua_get_call_state_name(p_sua->call_state),
|
||
sip_get_event_string(event));
|
||
|
||
switch (p_sua->call_state)
|
||
{
|
||
case SUA_CS_IDLE:
|
||
sua_cs_idle(p_sua, event, rx_msg);
|
||
break;
|
||
|
||
case SUAS_CS_TRYING:
|
||
suas_cs_trying(p_sua, event, rx_msg);
|
||
break;
|
||
|
||
case SUAS_CS_1XX_SENT:
|
||
suas_cs_1xx_sent(p_sua, event, rx_msg);
|
||
break;
|
||
|
||
case SUAS_CS_4XX_SENT:
|
||
suas_cs_4xx_sent(p_sua, event, rx_msg);
|
||
break;
|
||
|
||
case SUAS_CS_2XX_SENT:
|
||
suas_cs_2xx_sent(p_sua, event, rx_msg);
|
||
break;
|
||
|
||
case SUAC_CS_INVITE_SENT:
|
||
suac_cs_invite_sent(p_sua, event, rx_msg);
|
||
break;
|
||
|
||
case SUAC_CS_1XX_RECV:
|
||
suac_cs_1xx_recv(p_sua, event, rx_msg);
|
||
break;
|
||
|
||
case SUA_CS_ESTABLISHED: // 通话阶段
|
||
sua_cs_established(p_sua, event, rx_msg);
|
||
break;
|
||
|
||
case SUA_CS_BYE_SENT: // 在该状态应该停留几秒钟,或者收到BYE 200 OK
|
||
sua_cs_bye_sent(p_sua, event, rx_msg);
|
||
break;
|
||
|
||
case SUA_CS_ERR_EXIT: // 错误正在退出
|
||
break;
|
||
}
|
||
}
|
||
|
||
/***********************************************************************\
|
||
SUA呼叫状态机补充部分: 会话控制消息处理
|
||
\***********************************************************************/
|
||
void sua_emsg_recv(PUACMD ua_cmd, SUA * p_sua)
|
||
{
|
||
HSIP_MSG * tx_msg = NULL;
|
||
|
||
if (p_sua == NULL)
|
||
{
|
||
log_print(HT_LOG_ERR, "%s, p_sua[%08X] is NULL\r\n", __FUNCTION__, p_sua);
|
||
return;
|
||
}
|
||
|
||
log_print(HT_LOG_INFO, "%s, [%s]::%s %s\r\n", __FUNCTION__,
|
||
p_sua->remote_sip_address,
|
||
sua_get_call_state_name(p_sua->call_state),
|
||
sip_get_puacmd_name(ua_cmd));
|
||
|
||
// 进行会话层命令和协议层事件的转换
|
||
switch (ua_cmd)
|
||
{
|
||
case PUCMD_NOUSER:
|
||
if (p_sua->call_state == SUAS_CS_TRYING || p_sua->call_state == SUAS_CS_1XX_SENT)
|
||
{
|
||
tx_msg = sua_build_invite_response(p_sua, "404 Not Found");
|
||
sua_tx_free_msg(p_sua, tx_msg);
|
||
sua_timer_set(p_sua, 2, 5, SUA_CS_IDLE);
|
||
p_sua->call_state = SUAS_CS_4XX_SENT;
|
||
}
|
||
break;
|
||
|
||
case PUCMD_CONNECT:
|
||
if (p_sua->uaf_uas == 0)
|
||
{
|
||
return;
|
||
}
|
||
|
||
if (p_sua->l_a_cap_cnt == 0 && p_sua->l_v_cap_cnt == 0)
|
||
{
|
||
tx_msg = sua_build_invite_response(p_sua, "500 Server Internal Error");
|
||
sua_tx_free_msg(p_sua, tx_msg);
|
||
sua_timer_set(p_sua, 1, 5, SUA_CS_IDLE);
|
||
p_sua->call_state = SUAS_CS_4XX_SENT;
|
||
|
||
sip_notify_emsg(p_sua, PUEVT_ERROR);
|
||
|
||
return;
|
||
}
|
||
|
||
// 匹配音视频能力,动态类型以主叫送过来的pt值为准
|
||
if (sua_adjust_l_sdp_set(p_sua) < 0)
|
||
{
|
||
tx_msg = sua_build_invite_response(p_sua, "500 Server Internal Error");
|
||
sua_tx_free_msg(p_sua, tx_msg);
|
||
sua_timer_set(p_sua, 1, 5, SUA_CS_IDLE);
|
||
p_sua->call_state = SUAS_CS_4XX_SENT;
|
||
|
||
sip_notify_emsg(p_sua, PUEVT_ERROR);
|
||
|
||
return;
|
||
}
|
||
|
||
if (p_sua->call_state == SUAS_CS_TRYING || p_sua->call_state == SUAS_CS_1XX_SENT)
|
||
{
|
||
tx_msg = sua_build_iok_msg(p_sua);
|
||
sua_tx_free_msg(p_sua, tx_msg);
|
||
sua_timer_set(p_sua, 2, 7, SUA_CS_IDLE);
|
||
p_sua->call_state = SUAS_CS_2XX_SENT;
|
||
}
|
||
break;
|
||
|
||
case PUCMD_REINVITE:
|
||
{
|
||
// 更改会话参数
|
||
if (p_sua->call_state != SUA_CS_ESTABLISHED)
|
||
{
|
||
return;
|
||
}
|
||
|
||
p_sua->call_cseq++;
|
||
tx_msg = sua_build_invite_msg(p_sua);
|
||
sua_tx_free_msg(p_sua, tx_msg);
|
||
p_sua->uaf_reinvite_s = 1;
|
||
}
|
||
break;
|
||
|
||
case PUCMD_REJECT:
|
||
// 匹配音视频能力,动态类型以主叫送过来的pt值为准
|
||
if (p_sua->call_state == SUA_CS_ESTABLISHED)
|
||
{
|
||
tx_msg = sua_build_invite_response(p_sua, "488 Not Acceptable Here");
|
||
sua_tx_free_msg(p_sua, tx_msg);
|
||
}
|
||
break;
|
||
|
||
case PUCMD_ACCEPT:
|
||
// 匹配音视频能力,动态类型以主叫送过来的pt值为准
|
||
if (p_sua->call_state == SUA_CS_ESTABLISHED)
|
||
{
|
||
tx_msg = sua_build_iok_msg(p_sua);
|
||
sua_tx_free_msg(p_sua, tx_msg);
|
||
}
|
||
break;
|
||
|
||
case PUCMD_ALERTING:
|
||
if (p_sua->uaf_uas == 0)
|
||
{
|
||
return;
|
||
}
|
||
|
||
if (p_sua->call_state == SUAS_CS_TRYING || p_sua->call_state == SUAS_CS_1XX_SENT)
|
||
{
|
||
if (p_sua->l_a_cap_cnt > 0) // 判断是否带媒体信息,如果有发送回铃音
|
||
{
|
||
tx_msg = sua_build_18xsdp_msg(p_sua, "183 Session Progress");
|
||
}
|
||
else
|
||
{
|
||
tx_msg = sua_build_invite_response(p_sua, "180 Ringing");
|
||
}
|
||
|
||
sua_tx_free_msg(p_sua, tx_msg);
|
||
|
||
p_sua->call_state = SUAS_CS_1XX_SENT;
|
||
}
|
||
break;
|
||
|
||
case PUCMD_DISCONNECT:
|
||
if (p_sua->call_state == SUAS_CS_TRYING || p_sua->call_state == SUAS_CS_1XX_SENT)
|
||
{
|
||
tx_msg = sua_build_invite_response(p_sua, "480 Temporarily Unavailable");
|
||
sua_tx_free_msg(p_sua, tx_msg);
|
||
sua_timer_set(p_sua, 1, 5, SUA_CS_IDLE);
|
||
p_sua->call_state = SUAS_CS_4XX_SENT;
|
||
}
|
||
else if (p_sua->call_state == SUAC_CS_INVITE_SENT || p_sua->call_state == SUAC_CS_1XX_RECV)
|
||
{
|
||
// 发送Cancel消息
|
||
tx_msg = sua_build_cancel_msg(p_sua);
|
||
sua_tx_free_msg(p_sua, tx_msg);
|
||
p_sua->uaf_cancel_sent = 1;
|
||
|
||
// 设置TIMER标志,在对方没有响应的情况下超时重发
|
||
sua_timer_set(p_sua, 1, 5, SUA_CS_ERR_EXIT);
|
||
}
|
||
else if (p_sua->call_state == SUA_CS_ESTABLISHED)
|
||
{
|
||
p_sua->call_cseq++;
|
||
|
||
tx_msg = sua_build_bye_msg(p_sua);
|
||
sua_tx_free_msg(p_sua, tx_msg);
|
||
sua_timer_set(p_sua, 1, 5, SUA_CS_IDLE);
|
||
p_sua->call_state = SUA_CS_BYE_SENT;
|
||
|
||
sua_stop_media(p_sua);
|
||
}
|
||
else if(p_sua->call_state == SUA_CS_IDLE)
|
||
{
|
||
}
|
||
else
|
||
{
|
||
}
|
||
break;
|
||
|
||
case PUCMD_FORBID:
|
||
if (p_sua->call_state == SUAS_CS_TRYING || p_sua->call_state == SUAS_CS_1XX_SENT)
|
||
{
|
||
tx_msg = sua_build_invite_response(p_sua, "403 Forbidden");
|
||
sua_tx_free_msg(p_sua, tx_msg);
|
||
sua_timer_set(p_sua, 2, 3, SUA_CS_IDLE);
|
||
p_sua->call_state = SUAS_CS_4XX_SENT;
|
||
}
|
||
else if (p_sua->call_state == SUAC_CS_INVITE_SENT || p_sua->call_state == SUAC_CS_1XX_RECV)
|
||
{
|
||
// 发送Cancel消息
|
||
tx_msg = sua_build_cancel_msg(p_sua);
|
||
sua_tx_free_msg(p_sua, tx_msg);
|
||
p_sua->uaf_cancel_sent = 1;
|
||
|
||
// 设置TIMER标志,在对方没有响应的情况下超时重发
|
||
sua_timer_set(p_sua, 1, 5, SUA_CS_ERR_EXIT);
|
||
}
|
||
else if (p_sua->call_state == SUA_CS_ESTABLISHED)
|
||
{
|
||
p_sua->call_cseq++;
|
||
|
||
tx_msg = sua_build_bye_msg(p_sua);
|
||
sua_tx_free_msg(p_sua, tx_msg);
|
||
sua_timer_set(p_sua, 1, 5, SUA_CS_IDLE);
|
||
p_sua->call_state = SUA_CS_BYE_SENT;
|
||
}
|
||
else if (p_sua->call_state == SUA_CS_IDLE)
|
||
{
|
||
}
|
||
else
|
||
{
|
||
}
|
||
break;
|
||
|
||
case PUCMD_BUSY:
|
||
if (p_sua->call_state == SUAS_CS_TRYING || p_sua->call_state == SUAS_CS_1XX_SENT)
|
||
{
|
||
tx_msg = sua_build_invite_response(p_sua, "486 Busy Here");
|
||
sua_tx_free_msg(p_sua, tx_msg);
|
||
sua_timer_set(p_sua, 2, 3, SUA_CS_IDLE);
|
||
p_sua->call_state = SUAS_CS_4XX_SENT;
|
||
}
|
||
else if (p_sua->call_state == SUA_CS_IDLE)
|
||
{
|
||
sip_notify_emsg(p_sua, PUEVT_LINE_FREE);
|
||
sua_stop_used_sua(p_sua);
|
||
}
|
||
else
|
||
{
|
||
}
|
||
break;
|
||
|
||
case PUCMD_UPLOAD_JPG:
|
||
case PUCMD_CALL:
|
||
if(p_sua->call_state == SUA_CS_IDLE)
|
||
{
|
||
sua_cs_idle(p_sua, CSE_Call_Send, NULL);
|
||
}
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
/***********************************************************************\
|
||
SUA呼叫状态机:空闲状态消息处理
|
||
\***********************************************************************/
|
||
void sua_cs_idle(SUA * p_sua, CSEVT event, HSIP_MSG * rx_msg)
|
||
{
|
||
HSIP_MSG * tx_msg = NULL;
|
||
|
||
if (event == CSE_Call_Recv)
|
||
{
|
||
p_sua->uaf_uas = 1;
|
||
|
||
sua_timer_clear(p_sua); // 清除前面可能遗留的TIMER标志
|
||
|
||
// 保存呼叫信令路径
|
||
sip_free_ua_via_ctx(&(p_sua->via_ctx)); // 清除以前可能存在的
|
||
sip_save_rx_via(rx_msg,&(p_sua->via_ctx));
|
||
|
||
if (p_sua->sua_sip_tag[0] == '\0')
|
||
{
|
||
sprintf(p_sua->sua_sip_tag, "tag=%x%x", rand(), rand());
|
||
}
|
||
|
||
// 记录回应报文中的Record-Route
|
||
sip_free_ua_rr_ctx(&(p_sua->rr_ctx));
|
||
sip_save_rx_rr(rx_msg, &(p_sua->rr_ctx));
|
||
|
||
sip_get_req_name(rx_msg, p_sua->req_name, sizeof(p_sua->req_name));
|
||
sip_get_user_contact_uri(rx_msg, p_sua->remote_contact_uri, sizeof(p_sua->remote_contact_uri));
|
||
|
||
// 发送100 Trying
|
||
tx_msg = sua_build_invite_response(p_sua,"100 Trying");
|
||
sua_tx_free_msg(p_sua,tx_msg);
|
||
|
||
// 这里需要判断是什么类型呼叫: 语音呼叫、视频呼叫、混合呼叫、音频广播呼叫; 28181呼叫
|
||
// 根据不同类型设置回应参数
|
||
if (sua_call_in_sdp_parse(p_sua, rx_msg) < 0)
|
||
{
|
||
tx_msg = sua_build_invite_response(p_sua, "480 Temporarily Unavailable");
|
||
sua_tx_free_msg(p_sua,tx_msg);
|
||
|
||
sip_notify_emsg(p_sua, PUEVT_LINE_FREE);
|
||
sua_stop_used_sua(p_sua);
|
||
return;
|
||
}
|
||
|
||
// SessionTimer解析
|
||
sua_get_session_timer_info(p_sua, rx_msg);
|
||
|
||
sua_state_set(p_sua, SUAS_CS_TRYING);
|
||
sip_remote_callin_emsg(p_sua, PUEVT_CALL_IN); // 向上通知呼叫进入
|
||
// sip_isw_cmd(PUCMD_CONNECT, p_sua); // 自动接通
|
||
|
||
log_print(HT_LOG_INFO, "sip new call recv, caller[%s]\r\n", p_sua->remote_sip_address);
|
||
}
|
||
else if (event == CSE_Call_Send)
|
||
{
|
||
p_sua->uaf_uac = 1;
|
||
|
||
log_print(HT_LOG_INFO, "SUA state idle receive CSE_Invite_Send message\r\n");
|
||
|
||
p_sua->call_cseq = 1;
|
||
|
||
sprintf(p_sua->sua_sip_tag, "tag=%x%x", rand(), rand());
|
||
|
||
sprintf(p_sua->call_id_str, "%X%X%X-%s", rand(), rand(), sys_os_get_uptime(), p_sua->sua_ipstr);
|
||
|
||
sua_start_media(p_sua);
|
||
sua_start_media_rx(p_sua);
|
||
|
||
tx_msg = sua_build_invite_msg(p_sua);
|
||
sua_tx_free_msg(p_sua, tx_msg);
|
||
|
||
// 设置TIMER标志,在对方没有响应的情况下超时重发
|
||
sua_timer_set(p_sua, 3, 5, SUA_CS_IDLE);
|
||
|
||
// 改变呼叫状态
|
||
sua_state_set(p_sua, SUAC_CS_INVITE_SENT);
|
||
|
||
// 向上通知呼叫发出
|
||
sip_notify_emsg(p_sua, PUEVT_CALL_OUT);
|
||
}
|
||
else
|
||
{
|
||
sip_notify_emsg(p_sua, PUEVT_LINE_FREE);
|
||
sua_stop_used_sua(p_sua);
|
||
}
|
||
}
|
||
|
||
void suas_cs_trying(SUA * p_sua, CSEVT event, HSIP_MSG * rx_msg)
|
||
{
|
||
HSIP_MSG * tx_msg = NULL;
|
||
|
||
switch(event)
|
||
{
|
||
case CSE_TIMEOUT:
|
||
{
|
||
log_print(HT_LOG_INFO, "%s, timeout!!!\r\n", __FUNCTION__);
|
||
|
||
tx_msg = sua_build_invite_response(p_sua, "500 Server Internal Error");
|
||
sua_tx_free_msg(p_sua, tx_msg);
|
||
sua_timer_set(p_sua, 2, 7, SUA_CS_IDLE);
|
||
sua_state_set(p_sua, SUAS_CS_4XX_SENT);
|
||
}
|
||
break;
|
||
|
||
case CSE_Cancel_Recv:
|
||
{
|
||
sua_timer_clear(p_sua);
|
||
|
||
tx_msg = sua_build_response_msg(rx_msg, "200 OK");
|
||
sua_tx_free_msg(p_sua, tx_msg);
|
||
|
||
tx_msg = sua_build_invite_response(p_sua, "487 Request Cancelled");
|
||
sua_tx_free_msg(p_sua, tx_msg);
|
||
sua_timer_set(p_sua, 2, 7, SUA_CS_IDLE);
|
||
|
||
// 向上通知用户取消呼叫
|
||
sip_notify_emsg(p_sua, PUEVT_HANGUP);
|
||
|
||
sua_state_set(p_sua, SUAS_CS_4XX_SENT);
|
||
}
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
void suas_cs_1xx_sent(SUA * p_sua, CSEVT event, HSIP_MSG * rx_msg)
|
||
{
|
||
HSIP_MSG * tx_msg = NULL;
|
||
|
||
switch (event)
|
||
{
|
||
case CSE_TIMEOUT:
|
||
{
|
||
tx_msg = sua_build_invite_response(p_sua, "480 Temporarily Unavailable");
|
||
sua_tx_free_msg(p_sua, tx_msg);
|
||
sua_state_set(p_sua, SUAS_CS_4XX_SENT);
|
||
|
||
// 等待超时
|
||
sip_notify_emsg(p_sua, PUEVT_TIMEOUT);
|
||
|
||
sua_timer_set(p_sua, 2, 7, SUA_CS_IDLE);
|
||
}
|
||
break;
|
||
|
||
case CSE_Cancel_Recv:
|
||
{
|
||
sua_timer_clear(p_sua);
|
||
|
||
// 发送200 OK
|
||
tx_msg = sua_build_response_msg(rx_msg, "200 OK");
|
||
sua_tx_free_msg(p_sua, tx_msg);
|
||
|
||
tx_msg = sua_build_invite_response(p_sua, "487 Request Cancelled");
|
||
sua_tx_free_msg(p_sua, tx_msg);
|
||
sua_state_set(p_sua, SUAS_CS_4XX_SENT);
|
||
sua_timer_set(p_sua, 2, 7, SUA_CS_IDLE);
|
||
|
||
// 向上通知用户取消呼叫
|
||
sip_notify_emsg(p_sua, PUEVT_HANGUP);
|
||
}
|
||
break;
|
||
|
||
case CSE_Call_Recv:
|
||
{
|
||
tx_msg = sua_build_invite_response(p_sua, "100 Trying");
|
||
sua_tx_free_msg(p_sua, tx_msg);
|
||
}
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
void suas_cs_2xx_sent(SUA * p_sua, CSEVT event, HSIP_MSG * rx_msg)
|
||
{
|
||
HSIP_MSG * tx_msg = NULL;
|
||
|
||
switch (event)
|
||
{
|
||
case CSE_TIMEOUT:
|
||
// 向上通知链路超时断开
|
||
sip_notify_emsg(p_sua, PUEVT_TIMEOUT);
|
||
sip_notify_emsg(p_sua, PUEVT_LINE_FREE);
|
||
sua_stop_used_sua(p_sua);
|
||
break;
|
||
|
||
case CSE_Cancel_Recv:
|
||
{
|
||
tx_msg = sua_build_response_msg(rx_msg, "200 OK");
|
||
sua_tx_free_msg(p_sua, tx_msg);
|
||
|
||
// 向上通知用户取消呼叫
|
||
sip_notify_emsg(p_sua, PUEVT_HANGUP);
|
||
|
||
tx_msg = sua_build_invite_response(p_sua, "487 Request Cancelled");
|
||
sua_tx_free_msg(p_sua, tx_msg);
|
||
sua_state_set(p_sua, SUAS_CS_4XX_SENT);
|
||
sua_timer_set(p_sua, 2, 7, SUA_CS_IDLE);
|
||
}
|
||
break;
|
||
|
||
case CSE_ACK_Recv:
|
||
{
|
||
sua_timer_clear(p_sua);
|
||
|
||
p_sua->last_rx_refresh = sys_os_get_uptime();
|
||
|
||
// 进入通话状态
|
||
sua_state_set(p_sua, SUA_CS_ESTABLISHED);
|
||
|
||
// 打开媒体通道
|
||
sua_start_media(p_sua);
|
||
sua_start_media_rx(p_sua);
|
||
|
||
sua_set_media_rtp(p_sua);
|
||
|
||
// 向上通知用户进入通话状态
|
||
sip_notify_emsg(p_sua, PUEVT_CONNECT);
|
||
|
||
// 开始发送音视频流
|
||
sua_start_media_tx(p_sua);
|
||
|
||
log_print(HT_LOG_INFO, "sip new call connect, caller[%s]\r\n", p_sua->remote_sip_address);
|
||
}
|
||
break;
|
||
|
||
default:
|
||
return;
|
||
}
|
||
}
|
||
|
||
void suas_cs_4xx_sent(SUA * p_sua,CSEVT event,HSIP_MSG * rx_msg)
|
||
{
|
||
switch (event)
|
||
{
|
||
case CSE_ACK_Recv:
|
||
case CSE_TIMEOUT:
|
||
log_print(HT_LOG_INFO, "sip new call 4xx free, caller[%s]\r\n", p_sua->remote_sip_address);
|
||
|
||
// 向上通知该链路已经断开
|
||
sip_notify_emsg(p_sua, PUEVT_LINE_FREE);
|
||
sua_stop_used_sua(p_sua);
|
||
return;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
void suac_cs_invite_sent(SUA * p_sua,CSEVT event,HSIP_MSG * rx_msg)
|
||
{
|
||
HSIP_MSG * tx_msg;
|
||
|
||
switch (event)
|
||
{
|
||
case CSE_TIMEOUT:
|
||
// 向上通知落地网关超时无应答
|
||
sip_notify_emsg(p_sua, PUEVT_TIMEOUT);
|
||
sip_notify_emsg(p_sua, PUEVT_LINE_FREE);
|
||
sua_stop_used_sua(p_sua);
|
||
break;
|
||
|
||
case CSE_100_Recv:
|
||
// 设置久叫不应呼叫转移的定时器
|
||
sua_timer_set(p_sua, 60, 1, SUA_CS_ERR_EXIT);
|
||
sip_get_user_tag(rx_msg, "To", p_sua->remote_sip_tag, sizeof(p_sua->remote_sip_tag));
|
||
sua_state_set(p_sua, SUAC_CS_1XX_RECV);
|
||
break;
|
||
|
||
case CSE_Call_Recv:
|
||
{
|
||
// 发送 486 Busy Here 给对方
|
||
tx_msg = sua_build_response_msg(rx_msg, "486 Busy Here");
|
||
sua_tx_free_msg(p_sua, tx_msg);
|
||
}
|
||
break;
|
||
|
||
default:
|
||
suac_cs_1xx_recv(p_sua, event, rx_msg);
|
||
break;
|
||
}
|
||
}
|
||
|
||
void suac_cs_1xx_recv(SUA * p_sua, CSEVT event, HSIP_MSG * rx_msg)
|
||
{
|
||
HSIP_MSG * tx_msg = NULL;
|
||
|
||
switch (event)
|
||
{
|
||
case CSE_TIMEOUT:
|
||
if (p_sua->uaf_cancel_sent == 1)
|
||
{
|
||
sip_notify_emsg(p_sua, PUEVT_LINE_FREE);
|
||
sua_stop_used_sua(p_sua);
|
||
}
|
||
else
|
||
{
|
||
tx_msg = sua_build_cancel_msg(p_sua); // 发送Cancel消息
|
||
sua_tx_free_msg(p_sua, tx_msg);
|
||
p_sua->uaf_cancel_sent = 1;
|
||
|
||
// 向上通知落地网关超时无应答
|
||
sip_notify_emsg(p_sua, PUEVT_TIMEOUT);
|
||
}
|
||
break;
|
||
|
||
case CSE_180_Recv:
|
||
if (p_sua->uaf_cancel_sent == 1)
|
||
{
|
||
// 在已经发送Cancel消息的情况下不再处理1xx消息,只等待487消息和超时重传
|
||
}
|
||
else
|
||
{
|
||
// 设置久叫不应呼叫转移的定时器
|
||
sua_timer_set(p_sua, 60, 1, SUA_CS_ERR_EXIT);
|
||
sip_get_user_tag(rx_msg, "To", p_sua->remote_sip_tag, sizeof(p_sua->remote_sip_tag));
|
||
sua_state_set(p_sua, SUAC_CS_1XX_RECV);
|
||
|
||
if (sip_msg_with_sdp(rx_msg))
|
||
{
|
||
if (sua_get_msg_media_info(p_sua, rx_msg))
|
||
{
|
||
// 打开远端回铃音媒体通道
|
||
sua_start_media(p_sua);
|
||
|
||
// 向上通知回铃音消息,带媒体信息
|
||
sip_notify_emsg(p_sua, PUEVT_ALERT);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (p_sua->uaf_183_recv == 0)
|
||
{
|
||
// 向上通知回铃音消息,不带媒体信息
|
||
// sip_notify_emsg(p_sua, PUEVT_ALERT);
|
||
// return CSE_180_Send;
|
||
}
|
||
}
|
||
}
|
||
|
||
sua_state_set(p_sua, SUAC_CS_1XX_RECV);
|
||
break;
|
||
|
||
case CSE_4xx_Recv:
|
||
{
|
||
sua_timer_clear(p_sua); // 取消Invite定时器
|
||
sip_get_user_tag(rx_msg, "To", p_sua->remote_sip_tag, sizeof(p_sua->remote_sip_tag));
|
||
|
||
tx_msg = sua_build_ack_msg(p_sua); // 回应ACK
|
||
sua_tx_free_msg(p_sua, tx_msg);
|
||
|
||
p_sua->remote_sip_tag[0] = '\0';
|
||
|
||
switch (rx_msg->msg_sub_type)
|
||
{
|
||
case 401:
|
||
case 407: // 呼叫消息带认证功能
|
||
if (sip_get_digest_info(rx_msg,&(p_sua->user_auth_info))) // 获取WWW-Authentication/Proxy-Authenticate信息
|
||
{
|
||
strcpy(p_sua->user_auth_info.auth_uri, p_sua->remote_sip_address);
|
||
strcpy(p_sua->user_auth_info.auth_name, p_sua->p_user->user_auth_info.auth_name);
|
||
|
||
sip_sua_digest_calc("INVITE", p_sua); // 计算出Authorization部分信息
|
||
|
||
p_sua->call_cseq++;
|
||
|
||
tx_msg = sua_build_invite_auth_msg(p_sua, rx_msg);
|
||
sua_tx_free_msg(p_sua, tx_msg);
|
||
|
||
// 设置TIMER标志,在对方没有响应的情况下超时重发
|
||
sua_timer_set(p_sua, 10, 3, SUA_CS_IDLE);
|
||
|
||
sua_state_set(p_sua, SUAC_CS_INVITE_SENT);
|
||
}
|
||
else
|
||
{
|
||
sip_notify_emsg(p_sua, PUEVT_AUTH_FAIL);
|
||
sip_notify_emsg(p_sua, PUEVT_LINE_FREE);
|
||
sua_stop_used_sua(p_sua);
|
||
}
|
||
break;
|
||
|
||
case 486:
|
||
sua_state_set(p_sua, SUA_CS_ERR_EXIT);
|
||
sip_notify_emsg(p_sua, PUEVT_BUSY); // 线路忙
|
||
sip_notify_emsg(p_sua, PUEVT_LINE_FREE);
|
||
sua_stop_used_sua(p_sua);
|
||
break;
|
||
|
||
case 480:
|
||
sua_state_set(p_sua, SUA_CS_ERR_EXIT);
|
||
sip_notify_emsg(p_sua, PUEVT_TMEP_UNAVAILABLE);
|
||
sip_notify_emsg(p_sua, PUEVT_LINE_FREE);
|
||
sua_stop_used_sua(p_sua);
|
||
break;
|
||
|
||
case 487:
|
||
sua_state_set(p_sua, SUA_CS_ERR_EXIT);
|
||
|
||
if (p_sua->uaf_cancel_sent == 1)
|
||
{
|
||
sip_notify_emsg(p_sua, PUEVT_CANCEL_FINISH); // 呼叫取消完成
|
||
}
|
||
else
|
||
{
|
||
sip_notify_emsg(p_sua,PUEVT_CALL_TERMINATE); // 呼叫终止
|
||
}
|
||
|
||
sip_notify_emsg(p_sua, PUEVT_LINE_FREE);
|
||
sua_stop_used_sua(p_sua);
|
||
break;
|
||
|
||
case 403:
|
||
sua_state_set(p_sua, SUA_CS_ERR_EXIT);
|
||
sip_notify_emsg(p_sua, PUEVT_CALL_FORBIDDEN);
|
||
sip_notify_emsg(p_sua, PUEVT_LINE_FREE);
|
||
sua_stop_used_sua(p_sua);
|
||
break;
|
||
|
||
default:
|
||
sua_state_set(p_sua, SUA_CS_ERR_EXIT);
|
||
sip_notify_emsg(p_sua, PUEVT_ERROR); // 向上通知线路出错消息
|
||
sip_notify_emsg(p_sua, PUEVT_LINE_FREE);
|
||
sua_stop_used_sua(p_sua);
|
||
break;
|
||
}
|
||
}
|
||
break;
|
||
|
||
case CSE_6xx_Recv:
|
||
case CSE_5xx_Recv:
|
||
{
|
||
sua_timer_clear(p_sua); // 取消Invite定时器
|
||
sip_get_user_tag(rx_msg, "To", p_sua->remote_sip_tag, sizeof(p_sua->remote_sip_tag));
|
||
|
||
tx_msg = sua_build_ack_msg(p_sua); // 回应ACK
|
||
sua_tx_free_msg(p_sua, tx_msg);
|
||
|
||
// 向上通知对端内部错误消息
|
||
sip_notify_emsg(p_sua, PUEVT_ERROR);
|
||
sip_notify_emsg(p_sua, PUEVT_LINE_FREE);
|
||
sua_stop_used_sua(p_sua);
|
||
}
|
||
break;
|
||
|
||
case CSE_IOK_Recv:
|
||
{
|
||
sua_timer_clear(p_sua); // 取消Invite定时器
|
||
|
||
// 记录回应报文中的Record-Route
|
||
sip_free_ua_rr_ctx(&(p_sua->rr_ctx));
|
||
sip_save_rx_rr(rx_msg, &(p_sua->rr_ctx));
|
||
|
||
sip_get_user_contact_uri(rx_msg, p_sua->remote_contact_uri, sizeof(p_sua->remote_contact_uri));
|
||
|
||
// 记录对方可能加上的TAG
|
||
sip_get_user_tag(rx_msg, "To", p_sua->remote_sip_tag, sizeof(p_sua->remote_sip_tag));
|
||
|
||
if (sua_get_msg_media_info(p_sua, rx_msg) && sua_check_same_cap(p_sua) > 0)
|
||
{
|
||
sua_r_map_update(p_sua);
|
||
|
||
// 发送ACK消息,进入通话阶段
|
||
tx_msg = sua_build_ack_msg(p_sua);
|
||
sua_tx_free_msg(p_sua, tx_msg);
|
||
|
||
if (p_sua->r_v_cap_cnt >= 1)
|
||
{
|
||
// 先清除原先设置的标识位(之前标识本地媒体,现在是远端媒体)
|
||
p_sua->uaf_v_h264 = 0;
|
||
p_sua->uaf_v_ps = 0;
|
||
p_sua->uaf_v_jpeg = 0;
|
||
|
||
if (strcasecmp(p_sua->r_v_sdp[0].encoder, "H265") == 0)
|
||
{
|
||
p_sua->uaf_v_h265 = 1;
|
||
}
|
||
else if (strcasecmp(p_sua->r_v_sdp[0].encoder, "H264") == 0)
|
||
{
|
||
p_sua->uaf_v_h264 = 1;
|
||
}
|
||
else if (strcasecmp(p_sua->r_v_sdp[0].encoder, "PS") == 0)
|
||
{
|
||
p_sua->uaf_v_ps = 1;
|
||
}
|
||
}
|
||
|
||
// 打开媒体通道
|
||
sua_start_media(p_sua);
|
||
sua_start_media_rx(p_sua);
|
||
|
||
// 向上通知呼叫接通消息,带媒体信息
|
||
sip_notify_emsg(p_sua, PUEVT_CONNECT);
|
||
p_sua->last_rx_refresh = sys_os_get_uptime();
|
||
sua_state_set(p_sua, SUA_CS_ESTABLISHED);
|
||
}
|
||
else
|
||
{
|
||
p_sua->call_cseq++;
|
||
|
||
tx_msg = sua_build_bye_msg(p_sua);
|
||
sua_tx_free_msg(p_sua, tx_msg);
|
||
|
||
sua_state_set(p_sua, SUA_CS_BYE_SENT);
|
||
sua_timer_set(p_sua, 1, 5, SUA_CS_IDLE);
|
||
|
||
// 向上通知对端媒体错误,链路已经挂断消息
|
||
sip_notify_emsg(p_sua, PUEVT_ERROR);
|
||
}
|
||
}
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
void sua_cs_established(SUA * p_sua, CSEVT event, HSIP_MSG * rx_msg)
|
||
{
|
||
HSIP_MSG * tx_msg = NULL;
|
||
|
||
switch (event)
|
||
{
|
||
case CSE_Call_Recv: // reInvite处理,修改带宽
|
||
// 解析更改的媒体SDP
|
||
if (sua_call_in_sdp_parse(p_sua, rx_msg) < 0)
|
||
{
|
||
return;
|
||
}
|
||
|
||
if ((p_sua->r_a_cap_cnt <= 0) && (p_sua->r_v_cap_cnt <= 0))
|
||
{
|
||
}
|
||
else
|
||
{
|
||
tx_msg = sua_build_response_msg(rx_msg, "491 Request Pending");
|
||
sua_tx_free_msg(p_sua, tx_msg);
|
||
|
||
tx_msg = sua_build_iok_msg(p_sua);
|
||
sua_tx_free_msg(p_sua, tx_msg);
|
||
|
||
sip_notify_emsg(p_sua, PUEVT_REINVITE);
|
||
}
|
||
break;
|
||
|
||
case CSE_Update_Recv:
|
||
tx_msg = sua_build_update_response_msg(rx_msg, "200 OK");
|
||
sua_tx_free_msg(p_sua, tx_msg);
|
||
|
||
case CSE_UOK_Recv:
|
||
{
|
||
int expires = 0, min_se = 0, refresher = 0;
|
||
|
||
if (sip_get_session_timer_info(rx_msg, &expires, &min_se, &refresher))
|
||
{
|
||
p_sua->last_rx_refresh = sys_os_get_uptime();
|
||
}
|
||
}
|
||
break;
|
||
|
||
case CSE_Hang_Recv:
|
||
{
|
||
log_print(HT_LOG_INFO, "sip call hang, caller[%s]\r\n", p_sua->remote_sip_address);
|
||
|
||
tx_msg = sua_build_response_msg(rx_msg, "200 OK");
|
||
sua_tx_free_msg(p_sua, tx_msg);
|
||
|
||
// sua_stop_media(p_sua);
|
||
|
||
// 向上通知本端挂断
|
||
sip_notify_emsg(p_sua, PUEVT_HANGUP);
|
||
sip_notify_emsg(p_sua, PUEVT_LINE_FREE);
|
||
|
||
sua_stop_stream_tx(p_sua);
|
||
|
||
sua_stop_used_sua(p_sua);
|
||
}
|
||
break;
|
||
|
||
case CSE_IOK_Recv: // 可能是重传消息,可能是更改媒体的回应
|
||
{
|
||
if (p_sua->uaf_reinvite_s == 1)
|
||
{
|
||
tx_msg = sua_build_ack_msg(p_sua);
|
||
sua_tx_free_msg(p_sua, tx_msg);
|
||
|
||
p_sua->uaf_reinvite_s = 0; // 清除标识,禁止重传
|
||
}
|
||
|
||
if (p_sua->uaf_uas == 1)
|
||
{
|
||
break; // 只有主叫方式才应该有该消息出现
|
||
}
|
||
|
||
// 记录对方可能加上的TAG
|
||
sip_get_user_tag(rx_msg, "To", p_sua->remote_sip_tag, sizeof(p_sua->remote_sip_tag));
|
||
|
||
// 发送ACK消息,进入通话阶段
|
||
tx_msg = sua_build_ack_msg(p_sua);
|
||
sua_tx_free_msg(p_sua, tx_msg);
|
||
|
||
sua_state_set(p_sua, SUA_CS_ESTABLISHED);
|
||
}
|
||
break;
|
||
|
||
case CSE_TIMEOUT:
|
||
case CSE_RTP_ECHO_TIMEOUT:
|
||
{
|
||
log_print(HT_LOG_INFO, "sip call timeout, caller[%s]\r\n", p_sua->remote_sip_address);
|
||
|
||
p_sua->call_cseq++;
|
||
|
||
tx_msg = sua_build_bye_msg(p_sua);
|
||
sua_tx_free_msg(p_sua, tx_msg);
|
||
|
||
sua_state_set(p_sua, SUA_CS_BYE_SENT);
|
||
sua_timer_set(p_sua, 1, 5, SUA_CS_IDLE);
|
||
|
||
sua_stop_media(p_sua);
|
||
}
|
||
break;
|
||
|
||
default:
|
||
return;
|
||
}
|
||
}
|
||
|
||
void sua_cs_bye_sent(SUA * p_sua, CSEVT event, HSIP_MSG * rx_msg)
|
||
{
|
||
switch (event)
|
||
{
|
||
case CSE_Hang_Recv:
|
||
{
|
||
// 发送200 OK
|
||
HSIP_MSG * tx_msg = sua_build_response_msg(rx_msg, "200 OK");
|
||
sua_tx_free_msg(p_sua, tx_msg);
|
||
|
||
// 关闭媒体通道
|
||
sua_stop_media(p_sua);
|
||
|
||
// 向上通知该链路已经结束
|
||
sip_notify_emsg(p_sua, PUEVT_HANGUP);
|
||
sip_notify_emsg(p_sua, PUEVT_LINE_FREE);
|
||
sua_stop_used_sua(p_sua);
|
||
}
|
||
break;
|
||
|
||
case CSE_BOK_Recv:
|
||
case CSE_TIMEOUT:
|
||
// 向上通知该链路已经结束
|
||
sip_notify_emsg(p_sua, PUEVT_HANGUP);
|
||
sip_notify_emsg(p_sua, PUEVT_LINE_FREE);
|
||
sua_stop_used_sua(p_sua);
|
||
break;
|
||
default:
|
||
return;
|
||
}
|
||
}
|
||
|
||
/***********************************************************************\
|
||
消息事件上报到管理任务
|
||
\***********************************************************************/
|
||
BOOL sip_notify_emsg(SUA * p_sua, PUAEVT evt)
|
||
{
|
||
if (p_sua == NULL)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
sys_os_mutex_enter(hsip.mutex_cb);
|
||
if (p_sua->call_state_cb)
|
||
{
|
||
(*(p_sua->call_state_cb))(p_sua, evt, p_sua->user_data);
|
||
}
|
||
sys_os_mutex_leave(hsip.mutex_cb);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
BOOL rmsg_notify_emsg(char * pFrom, int type, char * pText, int len)
|
||
{
|
||
int rlen = sizeof(RMSGCTX) + len;
|
||
RMSGCTX * rm_ctx = (RMSGCTX *)malloc(rlen);
|
||
if (rm_ctx == NULL)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
memset(rm_ctx, 0, rlen);
|
||
strncpy(rm_ctx->from, pFrom, sizeof(rm_ctx->from));
|
||
rm_ctx->type = type;
|
||
rm_ctx->dlen = len;
|
||
memcpy(rm_ctx->p_data, pText, len);
|
||
|
||
sys_os_mutex_enter(hsip.mutex_cb);
|
||
if (hsip.ext_ntf_func)
|
||
{
|
||
(*hsip.ext_ntf_func)(0, PUEVT_R_MSG, rm_ctx, rlen, hsip.user_data);
|
||
}
|
||
sys_os_mutex_leave(hsip.mutex_cb);
|
||
|
||
free(rm_ctx);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
BOOL user_notify_emsg(char * pFrom, PUAEVT evt)
|
||
{
|
||
sys_os_mutex_enter(hsip.mutex_cb);
|
||
if (hsip.ext_ntf_func)
|
||
{
|
||
(*hsip.ext_ntf_func)(0, evt, pFrom, 0, hsip.user_data);
|
||
}
|
||
sys_os_mutex_leave(hsip.mutex_cb);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
BOOL sip_isw_cmd(PUACMD ua_cmd, SUA * p_sua)
|
||
{
|
||
SIPTM stm;
|
||
|
||
memset(&stm, 0, sizeof(stm));
|
||
|
||
stm.msg_src = SUA_CMD_SRC;
|
||
stm.msg_param = (uint32)ua_cmd;
|
||
stm.dst_port = sua_get_index(p_sua);
|
||
|
||
if (hqBufPut(hsip.msg_queue, (char *)&stm) == FALSE)
|
||
{
|
||
log_print(HT_LOG_ERR, "%s, hqBufPut return FALSE!!!\r\n", __FUNCTION__);
|
||
return FALSE;
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
BOOL sip_remote_callin_emsg(SUA * p_sua, PUAEVT evt)
|
||
{
|
||
if (p_sua == NULL)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
uint32 index = sua_get_index(p_sua);
|
||
|
||
sys_os_mutex_enter(hsip.mutex_cb);
|
||
if (hsip.ext_ntf_func)
|
||
{
|
||
(*hsip.ext_ntf_func)(index, evt, NULL, 0, hsip.user_data);
|
||
}
|
||
sys_os_mutex_leave(hsip.mutex_cb);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
|