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

1082 lines
25 KiB
C++
Raw Permalink 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 "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;
}