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