#include "stdafx.h" #include "ConnectorFSM.h" #include "../include/ModuleMix.h" #include "../include/EventCode.h" #include "json/json.h" #define RELEASEING_TIMER_INTERVAL 1200 #define RELEASEING_SIP_TIMER 20000 #define SIP_CALL_TIMER 70000 //sip呼叫超时时间,20170314,增加超时时间解决坐席忽闪问题 #define RELEASEING_SIP_TIMEOUT 30000 #define SIP_CONNECT_FAIL_TIMES 10 #define LIVEDETECT_CONNECT_INTERVAL 5000 //live detection实体检测间隔5s #define LIVEDETECTION_TIMEOUT 60000 //活体检测超时时间60s #define CALLROUTE_MAX_TRY_COUNT 3 #ifndef MAX_PATH #define MAX_PATH 260 #endif #ifndef RVC_CALLROUTE_HTTP_API #define RVC_CALLROUTE_HTTP_API "/api/route/query" #endif // !RVC_CALLROUTE_HTTP_API static const char* connect_failed_case_table[] = { "", "[RTA3401] 连线失败,请检查网络", "[RTA3402] 坐席忙,请稍后再试", "[RTA3403] 声卡故障,请使用话筒重新办理", "[RTA3404] 声卡故障,请使用免提重新办理", "[RTA3405] 连线失败,系统忙,请稍后再试", "[RTA3406] 连接坐席失败,系统忙,请稍后再试", "[RTA3407] 连线失败,服务端异常,请稍后再试", "[RTA3408] 连线失败,检测到机器有多张网卡,请禁用无效网卡后再试" }; #ifdef RVC_OS_LINUX unsigned long GetTickCount() { struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); return (ts.tv_sec * 1000 + ts.tv_nsec / 1000000); } #endif class SyncServiceClient:public SyncService_ClientBase { public: SyncServiceClient(CEntityBase *pEntity, ACMCallFSM* fsm) : SyncService_ClientBase(pEntity), m_fsm(fsm) {} ACMCallFSM *m_fsm; }; class MyPhoneClient : public PhoneService_ClientBase { public: MyPhoneClient(CEntityBase *pEntity, ACMCallFSM* fsm) : PhoneService_ClientBase(pEntity), m_fsm(fsm) {m_bSipConnected = false;} virtual void OnMessage(ErrorCodeEnum Error, PhoneService_PhoneState_Info &Msg, CSmartPointer pData) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("rx sip phone state = %d, status = %s", Msg.state, (LPCSTR)Msg.status); //LOG_TRACE("rx sip phone state = %d", Msg.state); if (Error == Error_Succeed) { switch (Msg.state) { case ePhone_Init: case ePhone_Terminated: { FSMEvent *e = new FSMEvent(USER_EVT_SIP_STATE_IDLE); m_fsm->PostEventFIFO(e); } break; case ePhone_Ready: { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("sip channel connected"); FSMEvent *e = new FSMEvent(USER_EVT_SIP_STATE_CONNECTED); m_fsm->PostEventFIFO(e); m_bSipConnected = true; } break; case ePhone_Calling: { m_bSipConnected = false; } break; default: break; } if (ePhone_Terminated == Msg.state){ if (!m_bSipConnected){ char strmsg[MAX_PATH] = { 0 }; snprintf(strmsg, MAX_PATH, "sip connect failed for %s.", Msg.status.GetData()); LogWarn(Severity_Low, Error_Debug, LOG_WARN_COUNTERCONNECT_SIP_CONNECT_FAILED,strmsg); } } } } public: ACMCallFSM *m_fsm; int m_bSipConnected; }; class MyChannelClient : public ChannelService_ClientBase { public: MyChannelClient(CEntityBase *pEntity, ACMCallFSM* fsm) : ChannelService_ClientBase(pEntity), m_fsm(fsm) {} virtual void OnMessage(ErrorCodeEnum Error, ChannelService_State_Info &Msg, CSmartPointer pData) { if (Error == Error_Succeed) { switch (Msg.state) { case eChannelState_Idle: { FSMEvent *e = new FSMEvent(USER_EVT_CHAN_STATE_IDLE); m_fsm->PostEventFIFO(e); } break; case eChannelState_Connected: { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("CHAN_STATE_CONNECTED.param = %s", (LPCSTR)Msg.param); FSMEvent *e = new ChanStateConnectedEvent(Msg.param); m_fsm->PostEventFIFO(e); } break; default: break; } } } ACMCallFSM *m_fsm; }; ACMCallFSM::ACMCallFSM() : m_pPhoneClient(NULL), m_pChannelClient(NULL), m_bRing(FALSE),m_iFailedLastState(0) { m_nCurSipServer = CurServerNum::MAIN_SERVER; m_nCurChanServer = CurServerNum::MAIN_SERVER; m_pSyncServiceClient = NULL; m_bConAssist = FALSE; m_bConSipphone = FALSE; memset(m_strSIPProxyIP, 0, sizeof(m_strSIPProxyIP)); memset(m_strSIPCallNum, 0, sizeof(m_strSIPCallNum)); memset(m_iSIPProxyPort, 0, sizeof(m_iSIPProxyPort)); memset(m_strChanCallNum, 0, sizeof(m_strChanCallNum)); memset(m_strChanProxyIP, 0, sizeof(m_strChanProxyIP)); memset(m_iChanProxyPort, 0, sizeof(m_iChanProxyPort)); m_strCallRouteIP = NULL; m_iCallRoutePort = 0; m_strCallRouteBranchNo = NULL; m_strCallRouteAccessNo = NULL; m_pCallRouteList = NULL; m_strDefaultServer = NULL; m_strHttpCallRouteAddr = NULL; m_strHttpServerAPI = RVC_CALLROUTE_HTTP_API; m_strQueueName = NULL; m_strAddClientLevel = NULL; m_iCallRouteType = 0; m_LastSipError = Error_Succeed; m_LastAssistError = Error_Succeed; m_bNeedQueueName = FALSE; } ACMCallFSM::~ACMCallFSM() { } ErrorCodeEnum ACMCallFSM::OnInit() { ErrorCodeEnum Error = LoadConfig(); if (Error != Error_Succeed) { goto on_error; } DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("LoadConfig success"); GetEntityBase()->GetFunction()->SetSysVar("CallState", "O"); // set to offline state Error = LoadTerminalId(); if (Error != Error_Succeed) { goto on_error; } DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("sip proxy ip1:%s,num1:%s,port1:%d;ip2:%s,num2:%s,port2:%d", (LPCSTR)m_strSIPProxyIP[0],(LPCSTR)m_strSIPCallNum[0], m_iSIPProxyPort[0],(LPCSTR)m_strSIPProxyIP[1],(LPCSTR)m_strSIPCallNum[1], m_iSIPProxyPort[1]); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("chan proxy ip1:%s,num1:%s,port1:%d;ip2:%s,num2:%s,port2:%d", (LPCSTR)m_strChanProxyIP[0],(LPCSTR)m_strChanCallNum[0], m_iChanProxyPort[0],(LPCSTR)m_strChanProxyIP[1],(LPCSTR)m_strChanCallNum[1], m_iChanProxyPort[1]); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("CallRouteIP:%s,port:%d", (LPCSTR)m_strCallRouteIP,m_iCallRoutePort); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("TerminalId: %s", (LPCSTR)m_strTerminalId); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("default_voip_server: %s", m_strDefaultServer.GetData()); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("HttpCallRouteAddr: %s", m_strHttpCallRouteAddr.GetData()); if(m_strDefaultServer.GetLength() > 0){ ParseDefaultServer(m_strDefaultServer.GetData()); } m_bHangup = FALSE; m_bHandFree = TRUE; m_bAgentHandFree = TRUE; m_bIsAgentControl = FALSE; m_nSipErrorNum = 0; m_nLiveDetctionTime = 0; memset(&m_CallingParam,0,sizeof(m_CallingParam)); m_nSysCallType = 0; DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("fsm init ok!"); AddStateHooker(this); return Error; on_error: DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("on_error"); FSMEvent *e = new FSMEvent(USER_EVT_ERROR); PostEventFIFO(e); // jump to error state return Error; } BOOL ACMCallFSM::ReConnectionAssistchan() { if (m_pChannelClient != NULL){ m_pChannelClient->GetFunction()->CloseSession(); m_pChannelClient = NULL; DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Close AssistChannel Session "); } if (m_pChannelClient == NULL){ DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("ReConnection AssistChannel Session"); m_pChannelClient = new MyChannelClient(m_pEntity, this); ErrorCodeEnum Error = m_pChannelClient->Connect(); if (Error != Error_Succeed) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("m_channelClient connect fail!"); m_pChannelClient = NULL; return FALSE; } else { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("m_channelClient connect success!"); } if (Error == Error_Succeed){ ChannelService_BeginState_Sub ChannelSub; Error = (*m_pChannelClient)(EntityResource::getLink().upgradeLink())->BeginState(ChannelSub); if (Error != Error_Succeed){ DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("BeginState biz channel failed!"); m_pChannelClient->GetFunction()->CloseSession(); m_pChannelClient = NULL; return FALSE; } else { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("BeginState biz channel success!"); } } } return TRUE; } BOOL ACMCallFSM::ReConnectionSipphone() { if (m_pPhoneClient != NULL){ m_pPhoneClient->GetFunction()->CloseSession(); m_pPhoneClient = NULL; DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Close sip Session"); } if (m_pPhoneClient == NULL){ DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("ReConnection sip Session"); m_pPhoneClient = new MyPhoneClient(m_pEntity, this); ErrorCodeEnum Error = m_pPhoneClient->Connect(); if (Error != Error_Succeed) { LogWarn(Severity_Low, Error_Debug, EVENT_MOD_CONNECT_SIPPHONE_ERROR, "connect sip phone error"); m_pPhoneClient = NULL; DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("m_phoneClient connect fail!"); return FALSE; } else { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("m_phoneClient connect success!"); } if (Error == Error_Succeed) { PhoneService_BeginState_Sub PhoneSub; Error = (*m_pPhoneClient)(EntityResource::getLink().upgradeLink())->BeginState(PhoneSub); if (Error != Error_Succeed) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("BeginState sip failed!"); m_pPhoneClient->GetFunction()->CloseSession(); m_pPhoneClient = NULL; return FALSE; } else { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("BeginState sip success!"); } } } return TRUE; } BOOL ACMCallFSM::ReConnectionSyncService() { if (NULL != m_pSyncServiceClient){ m_pSyncServiceClient->GetFunction()->CloseSession(); m_pSyncServiceClient = NULL; DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Close SyncService Session."); } m_pSyncServiceClient = new SyncServiceClient(m_pEntity, this); ErrorCodeEnum Error = m_pSyncServiceClient->Connect(); if (Error_Succeed != Error){ DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("Connect SyncService Fail!"); m_pSyncServiceClient = NULL; return FALSE; } else { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Connect SyncService Success!"); } return TRUE; } int ACMCallFSM::GetCallRouteList() { int iret = -1; if (0 == m_iCallRouteType) { if (m_strCallRouteIP.GetLength() != 0) { int icount = 0; call_info_t call_info; call_info.callroute_server_ip = m_strCallRouteIP; call_info.callroute_server_port = m_iCallRoutePort; call_info.szbranchno = m_strCallRouteBranchNo; call_info.szcaller_num = m_strTerminalId; call_info.szdest_num = m_strCallRouteAccessNo; do { m_pCallRouteList = get_callroute_list(&call_info); icount++; } while (!m_pCallRouteList && icount < CALLROUTE_MAX_TRY_COUNT); if (icount > 1) { char strmsg[MAX_PATH] = { 0 }; snprintf(strmsg, MAX_PATH, "request call route {%s:%d} %d times.", m_strCallRouteIP.GetData(), m_iCallRoutePort, icount); LogWarn(Severity_Low, Error_Debug, LOG_WARN_COUNTERCONNECT_CALLROUTE_TIMES, strmsg); } } } else{ if (m_strHttpCallRouteAddr.GetLength() != 0) { int ihttpcount = 0; http_call_info_t http_callinfo; http_callinfo.strServerURL = m_strHttpCallRouteAddr; http_callinfo.strAPI = m_strHttpServerAPI; if (m_bNeedQueueName) { http_callinfo.strQueueName = m_strQueueName; http_callinfo.strAddClientLevel = m_strAddClientLevel; } else { http_callinfo.strQueueName = NULL; http_callinfo.strAddClientLevel = NULL; } char strmsg[MAX_PATH] = { 0 }; snprintf(strmsg, MAX_PATH, "call type is %d, http call route queue name is %s, and client level is %s.", m_CallingParam.nCallType, http_callinfo.strQueueName.GetData(), http_callinfo.strAddClientLevel.GetData()); LogWarn(Severity_Low, Error_Debug, LOG_WARN_COUNTERCONNECT_CALL_QUEUE_INFO, strmsg); http_callinfo.strTerminalNo = m_strTerminalId; do { m_pCallRouteList = get_http_callroute_list(&http_callinfo); ihttpcount++; } while (!m_pCallRouteList && ihttpcount < CALLROUTE_MAX_TRY_COUNT); if (ihttpcount > 1) { char strmsg[MAX_PATH] = { 0 }; snprintf(strmsg, MAX_PATH, "request http call route address{%s} %d times.", m_strHttpCallRouteAddr.GetData(), ihttpcount); LogWarn(Severity_Low, Error_Debug, LOG_WARN_COUNTERCONNECT_CALLROUTE_TIMES, strmsg); } } } if (NULL != m_pCallRouteList) { iret = 0; } else { LogWarn(Severity_Middle, Error_Debug, LOG_WARN_COUNTERCONNECT_CALLROUTE_FAILED, "call route request failed!"); } return iret; } int ACMCallFSM::GetDelayTime() { ErrorCodeEnum error= Error_Unexpect; SyncService_GetMachineData_Req req; req.key = "DelayTime"; SyncService_GetMachineData_Ans ans; DWORD Timeout = 500; if (m_pSyncServiceClient) { error = (*m_pSyncServiceClient)(EntityResource::getLink().upgradeLink())->GetMachineData(req,ans,Timeout); } if (error == Error_Succeed) { int delaytime = atoi(ans.value); return delaytime; } else { return -1; } } void ACMCallFSM::SetDelayTime() { if (m_pSyncServiceClient) { SyncService_SetMachineData_Info info; info.key = "DelayTime"; info.data = "0"; (*m_pSyncServiceClient)(EntityResource::getLink().upgradeLink())->SetMachineData(info); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("set delay time to 0"); } } static int CStringSplit(char* str, char** result, size_t ucount, const char* del) { char* ptr = NULL; size_t unum = ucount; char* p = strtok_r(str, del, &ptr); while (p != NULL && unum > 0){ *result++ = p; p = strtok_r(NULL, del, &ptr); unum--; } return ucount - unum; } static int GetCallInfoFromConfig(char* strcallurl, size_t ucalllen, char* strassist, size_t assitlen, size_t *uport, const char* psrc) { int iRet = -1; if (NULL == psrc || NULL == strcallurl || NULL == strassist){ return iRet; } char *result[MAX_VOIP_SERVER_NUM] = {0}; int icount = CStringSplit((char*)psrc, result, MAX_VOIP_SERVER_NUM, ","); if(2 == icount){ snprintf(strcallurl, ucalllen, "%s", result[0]); char *assitresult[MAX_VOIP_SERVER_NUM] = {0}; icount = CStringSplit(result[1], assitresult, MAX_VOIP_SERVER_NUM, " "); if(2 == icount){ snprintf(strassist, assitlen, "%s", assitresult[0]); *uport = atoi(assitresult[1]); iRet = 0; } } return iRet; } /*无符号长整形转字符型*/ static char* _ultoa(unsigned long value, char* pstring, int radix) { char tmp[33] = { 0 }; char* tp = tmp; long i; unsigned long v = value; char* sp; if (radix > 36 || radix <= 1 || NULL == pstring) { return 0; } while (v || tp == tmp) { i = v % radix; v = v / radix; if (i < 10) * tp++ = i + '0'; else *tp++ = i + 'a' - 10; } sp = pstring; while (tp > tmp) * sp++ = *--tp; *sp = 0; return pstring; } static int get_interger_netaddr(char *strbuf, size_t ubufszie, const char* szip) { int ret = -1; unsigned long ulip = 0; if (NULL == strbuf || NULL == szip){ return ret; } ulip = inet_addr(szip); _ultoa(ulip, strbuf, 10); ret = 0; return ret; } int ACMCallFSM::ParseDefaultServer(const char* strServer) { int iRet = 0; if(NULL == strServer){ return iRet; } char *result[MAX_VOIP_SERVER_NUM] = {0}; int icount = CStringSplit((char*)strServer, result, MAX_VOIP_SERVER_NUM, "|"); int index = 0; while(index < icount && result[index]){ m_voipserver.push_back(result[index]); index++; } iRet = m_voipserver.size(); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("default voip server number is %d.", iRet); for (int i = 0; i < iRet; i++){ DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("default voip server address is %s", m_voipserver[i].c_str()); } return iRet; } ErrorCodeEnum ACMCallFSM::OnExit() { return Error_Succeed; } int ACMCallFSM::GetFailedErrorCode(int iSrcState) { int iState = 0; if (s20 != iSrcState){ switch (m_iFailedLastState) { case s11: if(Error_Succeed != m_LastSipError){ iState = 5; } else{ iState = 1; } break; case s12: if (Error_Succeed != m_LastAssistError){ iState = 5; } else{ iState = 2; } break; default: break; } } return iState; } int ACMCallFSM::LogFailedWarns(int iFailedCode, const char* strmsg) { int iRet = 0; if (m_bHangup){ LogWarn(Severity_Low, Error_Debug, LOG_WARN_COUNTERCONNECT_FAILED_USER_HANGUP, strmsg); } else{ switch (iFailedCode) { case 1: LogWarn(Severity_Middle, Error_Debug, LOG_WARN_COUNTERCONNECT_FAILED_NETWORK_FAILURE, strmsg); break; case 2: LogWarn(Severity_Middle, Error_Debug, LOG_WARN_COUNTERCONNECT_FAILED_AGENT_BUSY, strmsg); break; case 5: if (s11 == m_iFailedLastState){ LogWarn(Severity_Middle, Error_Debug, LOG_WARN_COUNTERCONNECT_FAILED_SIPPHONE_LOST, strmsg); } else if(s12 == m_iFailedLastState){ LogWarn(Severity_Middle, Error_Debug, LOG_WARN_COUNTERCONNECT_FAILED_ASSISTCHANNEL_LOST, strmsg); } break; default: break; } } return iRet; } void ACMCallFSM::OnStateTrans(int iSrcState, int iDstState) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("FSM state from state %s to %s", GetStateName(iSrcState), GetStateName(iDstState)); if (CheckBeginRing(iSrcState, iDstState)) { StartRing(); } else { if (CheckEndRing(iSrcState, iDstState)) StopRing(); } if (iSrcState != FSM_STATE_INIT && iDstState != FSM_STATE_EXIT) { int st1 = TranslateState(iSrcState); int st2 = TranslateState(iDstState); if (eState_Fail == st2){ m_iFailedLastState = iSrcState; } if (st1 != st2) { PhoneState evt; evt.state = st2; evt.status = CSimpleStringA::Format("OnStateTrans from state %d to %d", st1, st2); evt.errinfo = ""; LogWarn(Severity_Low, Error_Debug, LOG_WARN_COUNTERCONNECT_CALL_STATE_TRANS, evt.status.GetData()); //LOG_TRACE(evt.status); if (!((st2 == eState_Fail)&&(m_nCurChanServer != CurServerNum::Error_Server)&&(m_nCurSipServer != CurServerNum::Error_Server))||m_bHangup) { if (eState_Fail != st1 || eState_Connecting != st2){ char strmsg[MAX_PATH] = {0}; snprintf(strmsg, MAX_PATH,"Broadcast state from %d to %d", st1, st2); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)(strmsg); if (eState_Fail == st2){ int ierrcode = GetFailedErrorCode(iSrcState); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("connect_failed_case_table size is %d, and ierrcode = %d.", sizeof(connect_failed_case_table)/ sizeof(char*), ierrcode); if (ierrcode >= 0 && ierrcode < sizeof(connect_failed_case_table)/ sizeof(char*)){ evt.errinfo = CSimpleStringA2W(connect_failed_case_table[ierrcode]); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("connect failed for %s.", CSimpleStringW2A(evt.errinfo).GetData()); } char strerrmsg[MAX_PATH] = {0}; if (m_bHangup){ snprintf(strerrmsg, MAX_PATH, "connect failed for %s and last state is %d, and current src state is %d.","接通前客户主动挂机", m_iFailedLastState, iSrcState); } else{ snprintf(strerrmsg, MAX_PATH, "connect failed for %s and last state is %d, and current src state is %d.",CSimpleStringW2A(evt.errinfo).GetData(), m_iFailedLastState, iSrcState); } LogWarn(Severity_Middle, Error_Debug, LOG_WARN_COUNTERCONNECT_CONNECT_FAILED, strerrmsg); LogFailedWarns(ierrcode, strerrmsg); } SpSendBroadcast(GetEntityBase()->GetFunction(), SP_MSG_OF(PhoneState), SP_MSG_SIG_OF(PhoneState), evt); //LogWarn(Severity_Low, Error_Debug, LOG_WARN_COUNTERCONNECT_BROADCAST_CALL_STATE, strmsg); } else{ char strinfo[MAX_PATH] = {0}; snprintf(strinfo, MAX_PATH,"state from %d to %d, auto reconnect, not broadcast state to ui.", st1, st2); LogWarn(Severity_Low, Error_Debug, LOG_WARN_COUNTERCONNECT_AUTO_RECONNECT,strinfo); } if (eState_HandFree == st2 || eState_Pickup == st2){ if (eState_Connecting == st1){ LogWarn(Severity_Low, Error_Debug, LOG_WARN_COUNTERCONNECT_CONNECT_SUCCESS, "connect success!"); } } } SetCallState(st2); GetEntityBase()->GetFunction()->SetUserDefineState(st2+USER_SIP_OFFLINE); } } } ErrorCodeEnum ACMCallFSM::SetCallState(int state) { char *sts[] = { "O", // Offline "C", // Connecting "H", // HandFree "P", // Pickup "B", // Broken "F", // Fail "R", // Releasing "L", // LiveDetect "V" // Recording }; char* strCallState = "O"; if (0 <= state && state < sizeof(sts)/sizeof(char*)){ strCallState = sts[state]; } DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("set call state to [%s].", strCallState); return GetEntityBase()->GetFunction()->SetSysVar("CallState", strCallState); } void ACMCallFSM::s0_on_entry() { m_strHintCallNum.Clear(); m_nCurChanServer = CurServerNum::MAIN_SERVER; m_nCurSipServer = CurServerNum::MAIN_SERVER; memset(&m_CallingParam,0,sizeof(m_CallingParam)); GetEntityBase()->GetFunction()->SetSysVar("CallType", "N"); //进入初始状态时设置呼叫模式为常规呼叫 m_nSysCallType = 0; if(m_pCallRouteList != NULL){ free_node_list(m_pCallRouteList); m_pCallRouteList = NULL; } m_iFailedLastState = 0; } void ACMCallFSM::s0_on_exit() { m_bHangup = FALSE; m_nStarttime = GetTickCount(); } unsigned int ACMCallFSM::s0_on_event(FSMEvent* event) { if (event->iEvt == USER_EVT_PICKUP_CALL) { memset(&m_CallingParam,0,sizeof(m_CallingParam)); //正常呼叫 GetEntityBase()->GetFunction()->SetSysVar(SYSVAR_CALLTYPE, CALLTYPE_NORMAL); // 设置呼叫模式为常规呼叫 m_nSysCallType = 0; LogWarn(Severity_Low, Error_Debug, LOG_WARN_COUNTERCONNECT_PICKUPCALL,"begin pickup call"); } else if (event->iEvt == USER_EVT_HANDFREE_CALL) { GetEntityBase()->GetFunction()->SetSysVar(SYSVAR_CALLTYPE,CALLTYPE_NORMAL); // 设置呼叫模式为常规呼叫 m_nSysCallType = 0; memset(&m_CallingParam,0,sizeof(m_CallingParam)); // 正常呼叫 LogWarn(Severity_Low, Error_Debug, LOG_WARN_COUNTERCONNECT_HANDFREECALL,"begin hand free call"); } else if (event->iEvt == USER_EVT_COMMAND_CALL) { //由指令模块触发呼叫 GetEntityBase()->GetFunction()->SetSysVar(SYSVAR_CALLTYPE, CALLTYPE_MOBILE); // 设置呼叫模式为手机呼叫 m_nSysCallType = 1; DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("start command call!"); } else if (event->iEvt == USER_EVT_ASSISTCHAN_IDEL) { if (ReConnectionAssistchan()) { m_bConAssist = TRUE; } } else if (event->iEvt == USER_EVT_SIPPHONE_IDEL) { if (ReConnectionSipphone()) { m_bConSipphone = TRUE; } } else if (event->iEvt == USER_EVT_STARTVIDEODISPLAY) { StartVideoDisplayEvent *e = static_cast(event); StartVideoRender((LPCSTR)e->m_param); } else if (event->iEvt == USER_EVT_SHOWLOACALVIDEO) { ShowLocalVideoEvent *e = static_cast(event); SetCallingType(NORMAL_CALLTYPE); StartVideoRender((LPCSTR)e->m_param); } else if (event->iEvt == USER_EVT_SHOWLOACALREMOTEVIDEO) { ShowLocalAndRemoteVideoEvent *e = static_cast(event); SetCallingType(NORMAL_CALLTYPE); StartVideoRender((LPCSTR)e->m_param); } else if (event->iEvt == USER_EVT_DOUBLE_RECORD_CALL) { m_CallingParam.nCallType = DOUBLERECORD_CALLTYPE; //GetEntityBase()->GetFunction()->SetSysVar(SYSVAR_CALLTYPE,CALLTYPE_RECORD); // 设置呼叫模式为双录呼叫 m_nSysCallType = 0; DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("start double record call,call type is %d.", m_CallingParam.nCallType); LogWarn(Severity_Low, Error_Debug, LOG_WARN_COUNTERCONNECT_DOUBLERECORDCALL,"begin double record call"); } else if (event->iEvt == USER_EVT_STOPLOACALREMOTEVIDEO) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("%s:%d, stop show local and remote video.", __FUNCTION__, __LINE__); } return 0; } void ACMCallFSM::s7_on_entry() { } void ACMCallFSM::s7_on_exit() { } unsigned int ACMCallFSM::s7_on_event(FSMEvent* event) { if (event->iEvt == USER_EVT_STOPLOCALVIDEO) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("stop show local video"); StopVideo(); } else if (event->iEvt == USER_EVT_SIPPHONE_IDEL) { if (ReConnectionSipphone()) { m_bConSipphone = TRUE; } } return 0; } void ACMCallFSM::s9_on_entry() { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("start liveness detection."); m_nLiveDetctionTime = 0; ScheduleTimer(9, 2*LIVEDETECT_CONNECT_INTERVAL); } void ACMCallFSM::s9_on_exit() { CancelTimer(9); m_nLiveDetctionTime = 0; } unsigned int ACMCallFSM::s9_on_event(FSMEvent* event) { if (event->iEvt == USER_EVT_STOPVIDEODISPLAY) { //ScheduleTimer(9,3000); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("stop live detection display"); StopVideo(); LogEvent(Severity_Middle,LOG_EVT_RELEASELIVEDETECTION,"release live detection"); } else if (event->iEvt == EVT_TIMER) { m_nLiveDetctionTime += LIVEDETECT_CONNECT_INTERVAL; } else if (event->iEvt == USER_EVT_SIPPHONE_IDEL) { if (ReConnectionSipphone()) { m_bConSipphone = TRUE; } } return 0; } void ACMCallFSM::s8_on_entry() { //get call route,采用直接总行方式 if(FALSE == m_bIsPadDevice){ //大机 if (0 == GetCallRouteList()) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("get call route list success."); } else { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("get call route list failed."); } } int time = GetDelayTime(); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("get Delay time = %d",time); if (time > 0){ ScheduleTimer(8,time*1000); } else{ PostEventFIFO(new FSMEvent(EVT_TIMER)); } } void ACMCallFSM::s8_on_exit() { CancelTimer(8); } unsigned int ACMCallFSM::s8_on_event(FSMEvent* event) { return 0; } void ACMCallFSM::s10_on_entry() { //LOG_FUNCTION(); ErrorCodeEnum Error = Error_Succeed; if (m_nCurSipServer == CurServerNum::Error_Server) { Error = Error_NetBroken; } if (Error != Error_Succeed) { PostEventFIFO(new FSMEvent(USER_EVT_JMP_FAIL)); } } void ACMCallFSM::s10_on_exit() {} unsigned int ACMCallFSM::s10_on_event(FSMEvent* event) { if (event->iEvt == USER_EVT_ASSISTCHAN_IDEL) { if (ReConnectionAssistchan()) { m_bConAssist = TRUE; } } else if (event->iEvt == USER_EVT_SIPPHONE_IDEL) { if (ReConnectionSipphone()) { m_bConSipphone = TRUE; } } else if (event->iEvt == USER_EVT_STOPLOACALREMOTEVIDEO) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("%s:%d, hang up call and stop show local and remote video.", __FUNCTION__, __LINE__); PostEventFIFO(new FSMEvent(USER_EVT_HANGUP)); m_bHangup=TRUE; StopVideo(); } return 0; } void ACMCallFSM::s11_on_entry() { m_LastSipError = Error_Succeed; LogWarn(Severity_Low, Error_Debug, LOG_WARN_COUNTERCONNECT_MAKECALL,"begin make call"); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_USER).setLogCode("QLR0402304Z80101")("begin remote video call"); if (m_nCurSipServer == CurServerNum::Error_Server){ m_LastSipError = Error_NetBroken; } if (m_LastSipError == Error_Succeed){ char ipstr[MAX_PATH] = {0}; GetLocalIP(ipstr, MAX_PATH); if (FALSE == m_bIsPadDevice) { //get call route,采用直接总行方式 callurl_node_t *node = get_no_used_node(m_pCallRouteList); char callid_str[64] = { 0 }; get_format_uuid(callid_str, 64); if (node != NULL){ DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Begin Head Office Make Call!"); m_LastSipError = MakeCall(node->strcallurl, CSimpleStringA::Format("sip:%s@%s;transport=UDP", node->strnewcallernum, ipstr), callid_str, m_CallingParam); m_iChanProxyPort[0] = node->uassistport; m_iChanProxyPort[1] = node->uassistport; m_strChanProxyIP[0] = node->strassistip; m_strChanProxyIP[1] = node->strassistip; node->bused = TRUE; } else{ int icount = m_voipserver.size(); if (icount > 0){ int index = GetTickCount()%icount; char strcallurl[MAX_PATH] = {0}; char strassistip[32] = {0}; size_t uport = 0; char strserver[MAX_PATH] = { 0 }; snprintf(strserver, MAX_PATH, "%s", m_voipserver[index].c_str()); if (0 == GetCallInfoFromConfig(strcallurl, MAX_PATH, strassistip, 32, &uport, strserver)){ char strassitinter[32] = {0}; get_interger_netaddr(strassitinter, 32, strassistip); m_LastSipError = MakeCall(strcallurl, CSimpleStringA::Format("sip:%s#%s@%s;transport=UDP", m_strTerminalId.GetData(), strassitinter, ipstr), callid_str, m_CallingParam); m_iChanProxyPort[0] = uport; m_iChanProxyPort[1] = uport; m_strChanProxyIP[0] = strassistip; m_strChanProxyIP[1] = strassistip; char strmsg[MAX_PATH] = {0}; snprintf(strmsg, MAX_PATH, "head office mode no more call router, use default config(call url is %s, assistip is %s).", strcallurl, strassistip); LogWarn(Severity_Low, Error_Debug, LOG_WARN_COUNTERCONNECT_CALLROUTE_CONFIG, strmsg); } else { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("GetCallInfoFromConfig failed!"); m_LastSipError = Error_Param; } } else { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("no default voip server config!"); m_LastSipError = Error_Param; } } if (m_LastSipError!=Error_Succeed){ (bool)m_nCurSipServer?(m_nCurSipServer= CurServerNum::Error_Server):(m_nCurSipServer= CurServerNum::BACK_SERVER); } m_nCurChanServer = CurServerNum::BACK_SERVER; DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("head office make call result:0x%08x", m_LastSipError); } else { if (NORMAL_CALLTYPE == m_CallingParam.nCallType){ DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Begin Branch Make Normal Call!"); } else{ DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Begin Branch Make Record Call!"); } m_LastSipError = MakeCall(m_strHintCallNum.GetLength() > 0 ? (LPCSTR)m_strHintCallNum : (LPCSTR)m_strSIPCallNum[(int)m_nCurSipServer], (int)m_nCurSipServer); if (m_LastSipError != Error_Succeed) { (bool)m_nCurSipServer ? (m_nCurSipServer = CurServerNum::Error_Server) : (m_nCurSipServer = CurServerNum::BACK_SERVER); } DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("branch make call result:0x%08x", m_LastSipError); } } if (m_LastSipError != Error_Succeed) { PostEventFIFO(new FSMEvent(USER_EVT_JMP_FAIL)); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_USER).setLogCode("QLR0402304Z80201").setResultCode("RTA3421")("send sip failed!"); } else { ScheduleTimer(11,SIP_CALL_TIMER); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_USER).setLogCode("QLR0402304Z80201")("send sip success!"); } } void ACMCallFSM::s11_on_exit() { CancelTimer(11); } unsigned int ACMCallFSM::s11_on_event(FSMEvent* event) { if (event->iEvt == USER_EVT_HANGUP) { m_bHangup = TRUE; DWORD now = GetTickCount(); int interval = now - m_nStarttime; char msg[128] = {0}; snprintf(msg, 128, "sip connecting, customer active hangup after %d ms.", interval); LogWarn(Severity_Low, Error_Unexpect, LOG_WARN_COUNTERCONNECT_SIPCONNECT_HANGUP, msg); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_USER).setLogCode("QLR0402304Z80301").setResultCode("RTA3431")("sip connect failed!"); } else if (event->iEvt == USER_EVT_SIP_STATE_IDLE) { if (m_nCurSipServer == CurServerNum::MAIN_SERVER){ LogWarn(Severity_Low, Error_Unexpect, LOG_WARN_COUNTERCONNECT_MAIN_SIPCONNECT_SIPSTATE_IDLE,"sipphone connect main server failed"); }else if (m_nCurSipServer == CurServerNum::BACK_SERVER){ LogWarn(Severity_Low, Error_Unexpect, LOG_WARN_COUNTERCONNECT_BAK_SIPCONNECT_SIPSTATE_IDLE,"sipphone connect bak server failed"); }else{ LogWarn(Severity_Low, Error_Unexpect, LOG_WARN_COUNTERCONNECT_SIPCONNECT_SIPSTATE_IDLE,"sipphone connect error server failed"); } (bool)m_nCurSipServer?(m_nCurSipServer= CurServerNum::Error_Server):(m_nCurSipServer= CurServerNum::BACK_SERVER); m_nSipErrorNum++; //StopChannel(); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_USER).setLogCode("QLR0402304Z80301").setResultCode("RTA3432")("sip connect failed!"); } else if (event->iEvt == USER_EVT_ASSISTCHAN_IDEL) { if (m_nCurSipServer == CurServerNum::MAIN_SERVER){ LogWarn(Severity_Middle, Error_Unexpect, LOG_WARN_COUNTERCONNECT_MAIN_SIPCONNECT_CHANSTATE_IDLE,"chan mod idle, main server"); }else if (m_nCurSipServer == CurServerNum::BACK_SERVER){ LogWarn(Severity_Middle, Error_Unexpect, LOG_WARN_COUNTERCONNECT_BAK_SIPCONNECT_CHANSTATE_IDLE,"chan mod idle, bak server"); }else{ LogWarn(Severity_Middle, Error_Unexpect, LOG_WARN_COUNTERCONNECT_SIPCONNECT_CHANSTATE_IDLE,"chan mod idle, error server"); } if (ReConnectionAssistchan()) { m_bConAssist = TRUE; } DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_USER).setLogCode("QLR0402304Z80301").setResultCode("RTA3433")("sip connect failed!"); } else if (event->iEvt == USER_EVT_SIPPHONE_IDEL) { if (m_nCurSipServer == CurServerNum::MAIN_SERVER){ LogWarn(Severity_Middle, Error_Unexpect, LOG_WARN_COUNTERCONNECT_MAIN_SIPCONNECT_SIPENTITY_RESTART,"sipphone mod idle, main server"); }else if (m_nCurSipServer == CurServerNum::BACK_SERVER){ LogWarn(Severity_Middle, Error_Unexpect, LOG_WARN_COUNTERCONNECT_BAK_SIPCONNECT_SIPENTITY_RESTART,"sipphone mod idle, bak server"); }else{ LogWarn(Severity_Middle, Error_Unexpect, LOG_WARN_COUNTERCONNECT_SIPCONNECT_SIPENTITY_RESTART,"sipphone mod idle, error server"); } if (ReConnectionSipphone()) { m_bConSipphone = TRUE; } DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_USER).setLogCode("QLR0402304Z80301").setResultCode("RTA3434")("sip connect failed!"); } else if (event->iEvt == EVT_TIMER) { if (m_nCurSipServer == CurServerNum::MAIN_SERVER){ LogWarn(Severity_Low, Error_Unexpect, LOG_WARN_COUNTERCONNECT_MAIN_SIPCONNECT_TIMEOUT,"sipphone connect timeout, main server"); }else if (m_nCurSipServer == CurServerNum::BACK_SERVER){ LogWarn(Severity_Low, Error_Unexpect, LOG_WARN_COUNTERCONNECT_BAK_SIPCONNECT_TIMEOUT,"sipphone connect timeout, bak server"); }else{ LogWarn(Severity_Low, Error_Unexpect, LOG_WARN_COUNTERCONNECT_SIPCONNECT_TIMEOUT,"sipphone connect timeout, error server"); } DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("sip call timeout,release call"); m_nSipErrorNum++; DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_USER).setLogCode("QLR0402304Z80301").setResultCode("RTA3435")("sip connect failed!"); } else if (event->iEvt == USER_EVT_JMP_FAIL) { if (m_nCurSipServer == CurServerNum::MAIN_SERVER){ LogWarn(Severity_Low, Error_Unexpect, LOG_WARN_COUNTERCONNECT_MAIN_SIPCONNECT_FUNC_FAILED,"sipphone connect func failed, main server"); }else if (m_nCurSipServer == CurServerNum::BACK_SERVER){ LogWarn(Severity_Low, Error_Unexpect, LOG_WARN_COUNTERCONNECT_BAK_SIPCONNECT_FUNC_FAILED,"sipphone connect func failed, bak server"); }else{ LogWarn(Severity_Low, Error_Unexpect, LOG_WARN_COUNTERCONNECT_SIPCONNECT_FUNC_FAILED,"sipphone connect func failed, error server"); } m_nSipErrorNum++; DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_USER).setLogCode("QLR0402304Z80301").setResultCode("RTA3436")("sip connect failed!"); } else if (event->iEvt == USER_EVT_STOPLOACALREMOTEVIDEO) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("%s:%d, hang up call and stop show local and remote video.", __FUNCTION__, __LINE__); PostEventFIFO(new FSMEvent(USER_EVT_HANGUP)); m_bHangup=TRUE; StopVideo(); } return 0; } void ACMCallFSM::s12_on_entry() { //ErrorCodeEnum Error = Error_Succeed; DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_USER).setLogCode("QLR0402304Z80301")("sip connect success!"); m_LastAssistError = Error_Succeed; if (m_nCurChanServer == CurServerNum::Error_Server) { m_LastAssistError = Error_NetBroken; } m_nSipErrorNum = 0; Sleep(200); if (m_LastAssistError == Error_Succeed) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("begin start channel,m_nCurChanServer=%d",m_nCurChanServer); if (m_CallingParam.nCallType == NORMAL_CALLTYPE && m_CallingParam.nCallType != DOUBLERECORD_CALLTYPE) { m_LastAssistError = StartChannel((int)m_nCurChanServer); } else { m_LastAssistError = StartChannel((int)m_nCurChanServer,m_CallingParam); //if (DOUBLERECORD_CALLTYPE == m_CallingParam.nCallType){ // if (FALSE == m_bHandFree){ // StopSpeakerAudioCapture(); // DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("double record call type, current is pick up mode, stop speaker audio capture."); // } //} } DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("start channel result:0x%08x", m_LastAssistError); if (m_LastAssistError != Error_Succeed) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("start channel failed:0x%08x,start hangup", m_LastAssistError); HangupCall(); (bool)m_nCurChanServer?(m_nCurChanServer= CurServerNum::Error_Server):(m_nCurChanServer= CurServerNum::BACK_SERVER); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("hangup call result:0x%08x", m_LastAssistError); } } if (m_LastAssistError != Error_Succeed) { PostEventFIFO(new FSMEvent(USER_EVT_JMP_FAIL)); if (Error_NetBroken == m_LastAssistError) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_USER).setLogCode("QLR0402304Z80401").setResultCode("RTA3441")("assistant channel connect failed!"); } else if (Error_Param == m_LastAssistError) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_USER).setLogCode("QLR0402304Z80401").setResultCode("RTA3442")("assistant channel connect failed!"); } else { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_USER).setLogCode("QLR0402304Z80401").setResultCode("RTA3443")("assistant channel connect failed!"); } } else { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_USER).setLogCode("QLR0402304Z80401")("assistant channel connect success!"); } } void ACMCallFSM::s12_on_exit() {} unsigned int ACMCallFSM::s12_on_event(FSMEvent* event) { if (event->iEvt == USER_EVT_HANGUP) { m_bHangup = TRUE; DWORD now = GetTickCount(); int interval = now - m_nStarttime; char msg[128] = {0}; snprintf(msg, 128, "chan connecting, customer active hangup after %d ms.", interval); LogWarn(Severity_Low, Error_Unexpect, LOG_WARN_COUNTERCONNECT_CHANCONNECT_HANGUP, msg); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_USER).setLogCode("QLR0402304Z80501").setResultCode("RTA3451")("assistant channel bridge failed!"); } else if (event->iEvt == USER_EVT_SIP_STATE_IDLE) { if (m_nCurChanServer == CurServerNum::MAIN_SERVER){ LogWarn(Severity_Low, Error_Unexpect, LOG_WARN_COUNTERCONNECT_MAIN_CHANCONNECT_SIPSTATE_IDLE,"sipphone connect server failed at channel connect, main server"); }else if (m_nCurChanServer == CurServerNum::BACK_SERVER){ LogWarn(Severity_Low, Error_Unexpect, LOG_WARN_COUNTERCONNECT_BAK_CHANCONNECT_SIPSTATE_IDLE,"sipphone connect server failed at channel connect, bak server"); }else{ LogWarn(Severity_Low, Error_Unexpect, LOG_WARN_COUNTERCONNECT_CHANCONNECT_SIPSTATE_IDLE,"sipphone connect server failed at channel connect, error server"); } (bool)m_nCurSipServer?(m_nCurSipServer= CurServerNum::Error_Server):(m_nCurSipServer= CurServerNum::BACK_SERVER); StopChannel(); } else if (event->iEvt == USER_EVT_CHAN_STATE_IDLE) { if (!m_bHangup) { if (m_nCurChanServer == CurServerNum::MAIN_SERVER){ LogWarn(Severity_Low, Error_Unexpect, LOG_WARN_COUNTERCONNECT_MAIN_CHANCONNECT_CHANSTATE_IDLE,"chan connect server failed, main server"); }else if (m_nCurChanServer == CurServerNum::BACK_SERVER){ LogWarn(Severity_Low, Error_Unexpect, LOG_WARN_COUNTERCONNECT_BAK_CHANCONNECT_CHANSTATE_IDLE,"chan connect server failed, bak server"); }else{ LogWarn(Severity_Low, Error_Unexpect, LOG_WARN_COUNTERCONNECT_CHANCONNECT_CHANSTATE_IDLE,"chan connect server failed, error server"); } (bool)m_nCurChanServer?(m_nCurChanServer= CurServerNum::Error_Server):(m_nCurChanServer= CurServerNum::BACK_SERVER); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_USER).setLogCode("QLR0402304Z80501").setResultCode("RTA3452")("assistant channel bridge failed!"); } HangupCall(); //StopVideo(); } else if (event->iEvt == USER_EVT_CHAN_STATE_CONNECTED) { ChanStateConnectedEvent *e = static_cast(event); StartVideo((LPCSTR)e->m_param); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_USER).setLogCode("QLR0402304Z80501")("assistant channel bridge success!"); } else if (event->iEvt == USER_EVT_ASSISTCHAN_IDEL) { if (m_nCurChanServer == CurServerNum::MAIN_SERVER){ LogWarn(Severity_Low, Error_Unexpect, LOG_WARN_COUNTERCONNECT_MAIN_CHANCONNECT_CHANENTITY_RESTART,"chan mod idle, main server"); }else if (m_nCurChanServer == CurServerNum::BACK_SERVER){ LogWarn(Severity_Low, Error_Unexpect, LOG_WARN_COUNTERCONNECT_BAK_CHANCONNECT_CHANENTITY_RESTART,"chan mod idle, bak server"); }else{ LogWarn(Severity_Low, Error_Unexpect, LOG_WARN_COUNTERCONNECT_CHANCONNECT_CHANENTITY_RESTART,"chan mod idle, error server"); } if (ReConnectionAssistchan()) { m_bConAssist = TRUE; } } else if (event->iEvt == USER_EVT_SIPPHONE_IDEL) { if (m_nCurChanServer == CurServerNum::MAIN_SERVER){ LogWarn(Severity_Low, Error_Unexpect, LOG_WARN_COUNTERCONNECT_MAIN_CHANCONNECT_SIPENTITY_RESTART,"sipphone mod idle, main server"); }else if (m_nCurChanServer == CurServerNum::BACK_SERVER){ LogWarn(Severity_Low, Error_Unexpect, LOG_WARN_COUNTERCONNECT_BAK_CHANCONNECT_SIPENTITY_RESTART,"sipphone mod idle, bak server"); }else{ LogWarn(Severity_Low, Error_Unexpect, LOG_WARN_COUNTERCONNECT_CHANCONNECT_SIPENTITY_RESTART,"sipphone mod idle, error server"); } if (ReConnectionSipphone()) { m_bConSipphone = TRUE; } } else if (event->iEvt == USER_EVT_STOPLOACALREMOTEVIDEO) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("%s:%d, hang up call and stop show local and remote video.", __FUNCTION__, __LINE__); PostEventFIFO(new FSMEvent(USER_EVT_HANGUP)); m_bHangup=TRUE; StopVideo(); } else if (event->iEvt == USER_EVT_JMP_FAIL) { if (m_nCurChanServer == CurServerNum::MAIN_SERVER){ LogWarn(Severity_Low, Error_Unexpect, LOG_WARN_COUNTERCONNECT_MAIN_CHANCONNECT_FUNC_FAILED,"chan connect func failed, main server"); }else if (m_nCurChanServer == CurServerNum::BACK_SERVER){ LogWarn(Severity_Low, Error_Unexpect, LOG_WARN_COUNTERCONNECT_BAK_CHANCONNECT_FUNC_FAILED,"chan connect func failed, bak server"); }else{ LogWarn(Severity_Low, Error_Unexpect, LOG_WARN_COUNTERCONNECT_CHANCONNECT_FUNC_FAILED,"chan connect func failed, error server"); } } return 0; } void ACMCallFSM::s13_on_entry() { if (m_bHandFree) { PostEventLIFO(new FSMEvent(USER_EVT_JMP_HANDFREE)); } else { PostEventLIFO(new FSMEvent(USER_EVT_JMP_PICKUP)); } } void ACMCallFSM::s13_on_exit() {} unsigned int ACMCallFSM::s13_on_event(FSMEvent* event) { if (event->iEvt == USER_EVT_ASSISTCHAN_IDEL) { if (ReConnectionAssistchan()) { m_bConAssist = TRUE; } } else if (event->iEvt == USER_EVT_SIPPHONE_IDEL) { if (ReConnectionSipphone()) { m_bConSipphone = TRUE; } } return 0; } void ACMCallFSM::s14_on_entry() { } void ACMCallFSM::s14_on_exit() { } unsigned int ACMCallFSM::s14_on_event(FSMEvent* event) { if (event->iEvt == USER_EVT_STOPLOACALREMOTEVIDEO) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("%s:%d, stop show local and remote video.", __FUNCTION__, __LINE__); StopVideoRender(); } else if (event->iEvt == USER_EVT_STOP_RECORD_BROADCAST) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("stop double record broadcast."); } else if (event->iEvt == USER_EVT_SIPPHONE_IDEL) { if (ReConnectionSipphone()) { m_bConSipphone = TRUE; } } return 0; } void ACMCallFSM::s20_on_entry() { StopChannel(); } void ACMCallFSM::s20_on_exit() {} unsigned int ACMCallFSM::s20_on_event(FSMEvent* event) { if (event->iEvt == USER_EVT_CHAN_STATE_IDLE) { StopVideo(); } else if (event->iEvt == USER_EVT_ASSISTCHAN_IDEL) { if (ReConnectionAssistchan()) { m_bConAssist = TRUE; } } else if (event->iEvt == USER_EVT_SIPPHONE_IDEL) { if (ReConnectionSipphone()) { m_bConSipphone = TRUE; } } return 0; } void ACMCallFSM::s21_on_entry() { ScheduleTimer(21,RELEASEING_SIP_TIMER); HangupCall(); } void ACMCallFSM::s21_on_exit() { CancelTimer(21); CancelTimer(210); } unsigned int ACMCallFSM::s21_on_event(FSMEvent* event) { if (event->iEvt == USER_EVT_ASSISTCHAN_IDEL) { if (ReConnectionAssistchan()) { m_bConAssist = TRUE; } } else if (event->iEvt == USER_EVT_SIPPHONE_IDEL) { if (ReConnectionSipphone()) { m_bConSipphone = TRUE; } } else if (event->iEvt == EVT_TIMER) { if(event->param1 == 21) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("hangupcall timeout,release call"); ScheduleTimer(210,RELEASEING_SIP_TIMEOUT); ReleaseCall(0); } else if (event->param1 == 210) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("release call timeout,restart sipphone"); PostEventFIFO(new FSMEvent(USER_EVT_JMP_FAIL)); //RealSipErrorCheck(); LogEvent(Severity_Middle, EVENT_MOD_RELEASESIP_TIMEOUT,"restart sipphone"); LogWarn(Severity_Middle, Error_Unexpect, LOG_WARN_COUNTERCONNECT_RESTART_SIPPHONE,"restart sipphone"); } } return 0; } void ACMCallFSM::s22_on_entry() { StopChannel(); } void ACMCallFSM::s22_on_exit() {} unsigned int ACMCallFSM::s22_on_event(FSMEvent* event) { if (event->iEvt == USER_EVT_CHAN_STATE_IDLE) { StopVideo(); } else if (event->iEvt == USER_EVT_ASSISTCHAN_IDEL) { if (ReConnectionAssistchan()) { m_bConAssist = TRUE; } } else if (event->iEvt == USER_EVT_SIPPHONE_IDEL) { if (ReConnectionSipphone()) { m_bConSipphone = TRUE; } } return 0; } void ACMCallFSM::s23_on_entry() { if((!m_bHangup)&&(((m_nCurSipServer== CurServerNum::BACK_SERVER)&&(m_nCurChanServer!= CurServerNum::Error_Server))||((m_nCurChanServer== CurServerNum::BACK_SERVER)&&(m_nCurSipServer!= CurServerNum::Error_Server)))) { PostEventLIFO(new FSMEvent(USER_EVT_RECONNECT)); } else { ScheduleTimer(23, RELEASEING_TIMER_INTERVAL); } } void ACMCallFSM::s23_on_exit() { CancelTimer(23); } unsigned int ACMCallFSM::s23_on_event(FSMEvent* event) { if (event->iEvt == USER_EVT_ASSISTCHAN_IDEL) { if (ReConnectionAssistchan()) { m_bConAssist = TRUE; } } else if (event->iEvt == USER_EVT_SIPPHONE_IDEL) { if (ReConnectionSipphone()) { m_bConSipphone = TRUE; } } else if (event->iEvt == EVT_TIMER) { if (m_nSipErrorNum >= SIP_CONNECT_FAIL_TIMES) { m_nSipErrorNum = 0; LogEvent(Severity_Middle, EVENT_MOD_RELEASESIP_TIMEOUT,"restart sipphone "); LogWarn(Severity_Middle, Error_Unexpect, LOG_WARN_COUNTERCONNECT_RESTART_SIPPHONE,"FAIL TIMES, restart sipphone "); } } return 0; } void ACMCallFSM::s24_on_entry() { ScheduleTimer(24, RELEASEING_TIMER_INTERVAL); } void ACMCallFSM::s24_on_exit() { CancelTimer(24); } unsigned int ACMCallFSM::s24_on_event(FSMEvent* event) { if (event->iEvt == USER_EVT_ASSISTCHAN_IDEL) { if (ReConnectionAssistchan()) { m_bConAssist = TRUE; } } else if (event->iEvt == USER_EVT_SIPPHONE_IDEL) { if (ReConnectionSipphone()) { m_bConSipphone = TRUE; } } return 0; } void ACMCallFSM::s3_on_entry() {} void ACMCallFSM::s3_on_exit() {} unsigned int ACMCallFSM::s3_on_event(FSMEvent* event) { //LOG_TRACE("ACMCallFSM::s3_on_event, id = %d", event->iEvt); if (event->iEvt == USER_EVT_TO_HANDFREE) { //m_bHandFree = TRUE; } else if (event->iEvt == USER_EVT_TO_PICKUP) { //m_bHandFree = FALSE; } else if (event->iEvt == USER_EVT_SIP_STATE_IDLE) { StopChannel(); } else if (event->iEvt == USER_EVT_CHAN_STATE_IDLE) { HangupCall(); StopVideo(); } else if (event->iEvt == USER_EVT_AGENT_WRITABLE) { AllowAgentWrite(); } else if (event->iEvt == USER_EVT_ASSISTCHAN_IDEL) { if (ReConnectionAssistchan()) { m_bConAssist = TRUE; } } else if (event->iEvt == USER_EVT_SIPPHONE_IDEL) { if (ReConnectionSipphone()) { m_bConSipphone = TRUE; } } return 0; } void ACMCallFSM::s4_on_entry() {} void ACMCallFSM::s4_on_exit() {} unsigned int ACMCallFSM::s4_on_event(FSMEvent* event) { if (event->iEvt == USER_EVT_TO_HANDFREE) { //m_bHandFree = TRUE; } else if (event->iEvt == USER_EVT_TO_PICKUP) { //m_bHandFree = FALSE; } else if (event->iEvt == USER_EVT_SIP_STATE_IDLE) { StopChannel(); } else if (event->iEvt == USER_EVT_CHAN_STATE_IDLE) { HangupCall(); StopVideo(); } else if (event->iEvt == USER_EVT_AGENT_WRITABLE) { AllowAgentWrite(); } else if (event->iEvt == USER_EVT_ASSISTCHAN_IDEL) { if (ReConnectionAssistchan()) { m_bConAssist = TRUE; } } else if (event->iEvt == USER_EVT_SIPPHONE_IDEL) { if (ReConnectionSipphone()) { m_bConSipphone = TRUE; } } return 0; } void ACMCallFSM::s50_on_entry() {} void ACMCallFSM::s50_on_exit() {} unsigned int ACMCallFSM::s50_on_event(FSMEvent* event) { if (event->iEvt == USER_EVT_CHAN_STATE_IDLE) { StopVideo(); } else if (event->iEvt == USER_EVT_ASSISTCHAN_IDEL) { if (ReConnectionAssistchan()) { m_bConAssist = TRUE; } } else if (event->iEvt == USER_EVT_SIPPHONE_IDEL) { if (ReConnectionSipphone()) { m_bConSipphone = TRUE; } } return 0; } void ACMCallFSM::s51_on_entry() {} void ACMCallFSM::s51_on_exit() {} unsigned int ACMCallFSM::s51_on_event(FSMEvent* event) { if (event->iEvt == USER_EVT_CHAN_STATE_IDLE) { StopVideo(); } return 0; } void ACMCallFSM::s52_on_entry() { ScheduleTimer(52,RELEASEING_SIP_TIMER); } void ACMCallFSM::s52_on_exit() { CancelTimer(52); CancelTimer(520); } unsigned int ACMCallFSM::s52_on_event(FSMEvent* event) { if (event->iEvt == USER_EVT_ASSISTCHAN_IDEL) { if (ReConnectionAssistchan()) { m_bConAssist = TRUE; } } else if (event->iEvt == USER_EVT_SIPPHONE_IDEL) { if (ReConnectionSipphone()) { m_bConSipphone = TRUE; } } else if (event->iEvt == EVT_TIMER) { if (event->param1 == 52) { ScheduleTimer(520,RELEASEING_SIP_TIMEOUT); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("sip finished timeout,release call"); ReleaseCall(0); } else if (event->param1 == 520) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("release call timeout,restart sipphone"); PostEventFIFO(new FSMEvent(USER_EVT_JMP_FAIL)); LogEvent(Severity_Middle, EVENT_MOD_RELEASESIP_TIMEOUT,"restart sipphone "); LogWarn(Severity_Middle, Error_Unexpect, LOG_WARN_COUNTERCONNECT_RESTART_SIPPHONE,"restart sipphone "); } } return 0; } void ACMCallFSM::s53_on_entry() { ScheduleTimer(53, RELEASEING_TIMER_INTERVAL); } void ACMCallFSM::s53_on_exit() { CancelTimer(53); } unsigned int ACMCallFSM::s53_on_event(FSMEvent* event) { if (event->iEvt == USER_EVT_ASSISTCHAN_IDEL) { if (ReConnectionAssistchan()) { m_bConAssist = TRUE; } } else if (event->iEvt == USER_EVT_SIPPHONE_IDEL) { if (ReConnectionSipphone()) { m_bConSipphone = TRUE; } } else if (event->iEvt == EVT_TIMER) { if (m_nSipErrorNum >= SIP_CONNECT_FAIL_TIMES) { m_nSipErrorNum = 0; LogEvent(Severity_Middle, EVENT_MOD_RELEASESIP_TIMEOUT,"restart sipphone "); LogWarn(Severity_Middle, Error_Unexpect, LOG_WARN_COUNTERCONNECT_RESTART_SIPPHONE,"FAIL TIMES, restart sipphone "); } } return 0; } void ACMCallFSM::s60_on_entry() { StopChannel(); HangupCall(); } void ACMCallFSM::s60_on_exit() {} unsigned int ACMCallFSM::s60_on_event(FSMEvent* event) { if (event->iEvt == USER_EVT_CHAN_STATE_IDLE) { StopVideo(); } else if (event->iEvt == USER_EVT_ASSISTCHAN_IDEL) { if (ReConnectionAssistchan()) { m_bConAssist = TRUE; } } else if (event->iEvt == USER_EVT_SIPPHONE_IDEL) { if (ReConnectionSipphone()) { m_bConSipphone = TRUE; } } return 0; } void ACMCallFSM::s61_on_entry() {} void ACMCallFSM::s61_on_exit() {} unsigned int ACMCallFSM::s61_on_event(FSMEvent* event) { if (event->iEvt == USER_EVT_CHAN_STATE_IDLE) { StopVideo(); } else if (event->iEvt == USER_EVT_ASSISTCHAN_IDEL) { if (ReConnectionAssistchan()) { m_bConAssist = TRUE; } } else if (event->iEvt == USER_EVT_SIPPHONE_IDEL) { if (ReConnectionSipphone()) { m_bConSipphone = TRUE; } } return 0; } void ACMCallFSM::s62_on_entry() { ScheduleTimer(62,RELEASEING_SIP_TIMER); } void ACMCallFSM::s62_on_exit() { CancelTimer(62); CancelTimer(620); } unsigned int ACMCallFSM::s62_on_event(FSMEvent* event) { if (event->iEvt == USER_EVT_ASSISTCHAN_IDEL) { if (ReConnectionAssistchan()) { m_bConAssist = TRUE; } } else if (event->iEvt == USER_EVT_SIPPHONE_IDEL) { if (ReConnectionSipphone()) { m_bConSipphone = TRUE; } } else if (event->iEvt == EVT_TIMER) { if (event->param1 == 62) { ScheduleTimer(620,RELEASEING_SIP_TIMEOUT); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("sip hangup timeout,release call"); ReleaseCall(0); } else if (event->param1 == 620) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("release call timeout,restart sipphone"); PostEventFIFO(new FSMEvent(USER_EVT_JMP_FAIL)); LogEvent(Severity_Middle, EVENT_MOD_RELEASESIP_TIMEOUT,"restart sipphone "); LogWarn(Severity_Middle, Error_Unexpect, LOG_WARN_COUNTERCONNECT_RESTART_SIPPHONE,"restart sipphone "); } } return 0; } void ACMCallFSM::s63_on_entry() { ScheduleTimer(63, RELEASEING_TIMER_INTERVAL); } void ACMCallFSM::s63_on_exit() { CancelTimer(63); } unsigned int ACMCallFSM::s63_on_event(FSMEvent* event) { if (event->iEvt == USER_EVT_ASSISTCHAN_IDEL) { if (ReConnectionAssistchan()) { m_bConAssist = TRUE; } } else if (event->iEvt == USER_EVT_SIPPHONE_IDEL) { if (ReConnectionSipphone()) { m_bConSipphone = TRUE; } } else if (event->iEvt == EVT_TIMER) { if (m_nSipErrorNum >= SIP_CONNECT_FAIL_TIMES) { m_nSipErrorNum = 0; //RealSipErrorCheck(); LogEvent(Severity_Middle, EVENT_MOD_RELEASESIP_TIMEOUT,"restart sipphone"); LogWarn(Severity_Middle, Error_Unexpect, LOG_WARN_COUNTERCONNECT_RESTART_SIPPHONE,"FAIL TIMES, restart sipphone"); } } return 0; } int ACMCallFSM::TranslateState( int innerState ) { switch (innerState) { case s0: return eState_Offline; case s8: case s10: case s11: case s12: case s13: return eState_Connecting; case s20: case s21: case s22: case s23: case s24: return eState_Fail; case s3: return eState_HandFree; case s4: return eState_Pickup; case s50: case s51: case s52: case s53: return eState_Broken; case s60: case s61: case s62: case s63: return eState_Releasing; case s9: return eState_LiveDetect; case s7: case s14: return eState_Recording; default: assert(0); return 0; } }