#include "StdAfx.h" #include "NetworkCti.h" #include "LineHolder.h" #include "IvrFlowHolder.h" #include "Logger.h" #include "MsgCenter.h" #include "Config.h" #include "CtiDataDef.h" #include "TaskMgr.h" SINGLETON_IMPLEMENT(CNetworkCti) CNetworkCti::CNetworkCti(void) : m_IsAcdConnected(FALSE), m_IsIvrConnected(FALSE) { } CNetworkCti::~CNetworkCti(void) { } /***************************************************************** **【函数名称】 __procRegMsg **【函数功能】 处理注册命令 **【参数】 a_PduEntity:注册命令 **【返回值】 ****************************************************************/ void CNetworkCti::__procRegMsg( CPduEntity& a_PduEntity ) { bool RegResult = false; switch(a_PduEntity.GetLocalDevType()) { case PDU_DEV_TYPE_ACD: RegResult = m_DevAcd.DevId == -1 ? true : false; break; case PDU_DEV_TYPE_IVR: RegResult = m_DevIvr.DevId == -1 ? true : false; break; default: ASSERT(FALSE); break; } // 发送注册结果 a_PduEntity.SetToExecReturn(); a_PduEntity.SetDataBool(0, RegResult); CInterfaceWindow::getIocpCommInstance()->Send(&a_PduEntity, a_PduEntity.GetLocalDevType(), a_PduEntity.GetLocalDevId()); } /***************************************************************** **【函数名称】 __onRegSuccess **【函数功能】 设备注册成功处理函数 **【参数】 linkContent:注册段信息 **【返回值】 ****************************************************************/ void CNetworkCti::__onRegSuccess( const PduLinkContent& linkContent ) { switch(linkContent.nFarType) { case PDU_DEV_TYPE_ACD: { // 保存设备信息 m_DevAcd.DevId = linkContent.nLocalId; lstrcpy(m_DevAcd.szIpAddress, linkContent.szFarIp); m_DevAcd.Port = linkContent.nFarPort; m_IsAcdConnected = TRUE; // 通知线路类Acd连接成功 CLineHolder::GetInstance().onAcdConnected(); } break; case PDU_DEV_TYPE_IVR: { // 保存设备信息 m_DevIvr.DevId = linkContent.nLocalId; lstrcpy(m_DevIvr.szIpAddress, linkContent.szFarIp); m_DevIvr.Port = linkContent.nFarPort; m_IsIvrConnected = TRUE; } break; default: ASSERT(FALSE); break; } } /***************************************************************** **【函数名称】 __onDisconnect **【函数功能】 设备连接断开处理函数 **【参数】 linkContent:连接断开端信息 **【返回值】 ****************************************************************/ void CNetworkCti::__onDisconnect( const PduLinkContent& linkContent ) { switch(linkContent.nFarType) { case PDU_DEV_TYPE_ACD: { if(m_DevAcd.DevId != linkContent.nLocalId) return; if(strcmp(m_DevAcd.szIpAddress, linkContent.szFarIp) != 0) return; if(m_DevAcd.Port != linkContent.nFarPort) return; memset(&m_DevAcd, 0, sizeof(m_DevAcd)); m_DevAcd.DevId = -1; m_IsAcdConnected = FALSE; } break; case PDU_DEV_TYPE_IVR: { if(m_DevIvr.DevId != linkContent.nLocalId) return; if(strcmp(m_DevIvr.szIpAddress, linkContent.szFarIp) != 0) return; if(m_DevIvr.Port != linkContent.nFarPort) return; memset(&m_DevIvr, 0, sizeof(m_DevIvr)); m_DevIvr.DevId = -1; // 通知IvrFlow IVR连接断开 CIvrFlowHolder::GetInstance().onIvrDisconnect(); m_IsIvrConnected = FALSE; } break; default: break; } } /***************************************************************** **【函数名称】 OnLinkStateChanged **【函数功能】 连接状态信息变化 **【参数】 **【返回值】 ****************************************************************/ void CNetworkCti::OnLinkStateChanged( const PduLinkContent& linkContent ) { // 连接信息日志显示 LOG_LEVEL nLogLevel = LOG_LEVEL_WARNING; CString Msg; switch(linkContent.nLinkState) { case PDU_LINK_STATE_ACCEPTED: { Msg = _T("{Net}: Far End Accepted, "); nLogLevel = LOG_LEVEL_NORMAL; } break; case PDU_LINK_STATE_DISCONNECTED: { Msg = _T("{Net}: Far End Disconnected, "); nLogLevel = LOG_LEVEL_WARNING; __onDisconnect(linkContent); } break; case PDU_LINK_STATE_REG_OK: { Msg = _T("{Net}: Far End Reg OK, "); nLogLevel = LOG_LEVEL_NORMAL; __onRegSuccess(linkContent); } break; case PDU_LINK_STATE_REG_FAILED: { Msg = _T("{Net}: Far End Reg Failed, "); nLogLevel = LOG_LEVEL_WARNING; } break; default: { ASSERT(FALSE); Msg = _T("{Net}: Unknown Netlink State, "); nLogLevel = LOG_LEVEL_WARNING; } break; } // 判断设备类型 switch(linkContent.nFarType) { case PDU_DEV_TYPE_ACD: { CString Temp; Temp.Format(_T(" Far End[Type = ACD, Id = %d, Addr = %s:%d]"), linkContent.nFarId, linkContent.szFarIp, linkContent.nFarPort); Msg += Temp; } break; case PDU_DEV_TYPE_IVR: { CString Temp; Temp.Format(_T(" Far End[Type = IVR, Id = %d, Addr = %s:%d]"), linkContent.nFarId, linkContent.szFarIp, linkContent.nFarPort); Msg += Temp; } break; default: CString Temp; Temp.Format(_T(" Far End[Type = UnKnown, Id = %d, Addr = %s:%d]"), linkContent.nFarId, linkContent.szFarIp, linkContent.nFarPort); Msg += Temp; break; } // 通知日志 ILogger::getInstance().log(LOG_CLASS_SOCKET, nLogLevel, _T("%s"), Msg); } /***************************************************************** **【函数名称】 OnRecvCommand **【函数功能】 Pdu命令处理接口 **【参数】 a_pPduEntity:消息实体 **【返回值】 ****************************************************************/ void CNetworkCti::OnRecvCommand( CPduEntity* a_pPduEntity ) { ASSERT(a_pPduEntity != NULL); switch(a_pPduEntity->GetCmdType()) { case PDU_CMD_REG: // 注册命令 __procRegMsg(*a_pPduEntity); break; case PDU_CMD_CTI_IVR_CALLIN: // CallIn返回命令 case PDU_CMD_CTI_IVR_TURNIVR: // 转IVR返回命令 case PDU_CMD_IVR_HANGUP: // IVR通知CTI挂机 case PDU_CMD_IVR_END: // IVR通知CTI流程结束 case PDU_CMD_IVR_WANT_AGENT: // IVR通知CTI请求排队(包括ACD返回) case PDU_CMD_IVR_QUEUE_CONTINUE: // IVR通知CTI继续排队(包括ACD返回) case PDU_CMD_IVR_QUEUE_CANCEL: // IVR通知CTI取消排队 case PDU_CMD_IVR_TURN_AGENT: // IVR通知CTI转坐席 case PDU_CMD_IVR_PLAY_DTMF: // IVR通知CTI放音收按键 case PDU_CMD_IVR_CALL_OUT: // IVR通知CTI自动呼叫某个号码 case PDU_CMD_IVR_TURN_OUTLINE: // IVR呼叫转移 case PDU_CMD_IVR_FAX: // IVR通知收发传真 case PDU_CMD_IVR_LEAVE_WORD: // IVR通知留言 CIvrFlowHolder::GetInstance().onPduMessage(*a_pPduEntity); break; case PDU_CMD_LISTEN: return; default: CTaskMgr::GetInstance().onPduMessage(*a_pPduEntity); break; } } /***************************************************************** **【函数名称】 init **【函数功能】 初始化 **【参数】 **【返回值】 成功TRUE,失败FALSE ****************************************************************/ BOOL CNetworkCti::init() { // 初始化客户端设备信息 memset(&m_DevAcd, 0, sizeof(m_DevAcd)); memset(&m_DevIvr, 0, sizeof(m_DevIvr)); m_DevAcd.DevId = -1; m_DevIvr.DevId = -1; // 初始化命令配置 CPduDataFormat::getInstance()->UnLoad(); #ifdef _DEBUG CPduDataFormat::getInstance()->Load("../NetLib/PDUFormat.ini"); //../NetLib/PDUFormat.ini #else CPduDataFormat::getInstance()->Load("./PDUFormat.ini"); #endif CInterfaceWindow::getIocpLinkInstance()->RegistPduLinkProc(this, FALSE); CInterfaceWindow::getIocpCommInstance()->RegistPduCommProc(this, FALSE); // 注册Pdu消息接口 CInterfaceWindow::getIocpLinkInstance()->RegistPduLinkProc(this, TRUE); CInterfaceWindow::getIocpCommInstance()->RegistPduCommProc(this, TRUE); //创建Socket服务器端 UINT ListenPort = CConfig::GetInstance().listenPort(); if (CInterfaceWindow::getIocpLinkInstance()->CreatePduServer(ListenPort, PDU_DEV_TYPE_CTI, 0)) { ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_NORMAL, "{Net}: 创建网络服务端成功,ListenPort = %d", ListenPort); return TRUE; } else { ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_ERROR, "{Net}: 创建网络服务端失败,ListenPort = %d", ListenPort); return FALSE; } } /***************************************************************** **【函数名称】 release **【函数功能】 释放资源 **【参数】 **【返回值】 成功TRUE,失败FALSE ****************************************************************/ void CNetworkCti::release( void ) { CInterfaceWindow::getIocpLinkInstance()->StopAll(); } /***************************************************************** **【函数名称】 send2ACD **【函数功能】 发送PDU到ACD **【参数】 a_PduEntity:待发送的PDU **【返回值】 ****************************************************************/ BOOL CNetworkCti::send2ACD( CPduEntity& a_PduEntity ) { return CInterfaceWindow::getIocpCommInstance()->Send(&a_PduEntity, PDU_DEV_TYPE_ACD, m_DevAcd.DevId); } /***************************************************************** **【函数名称】 send2IVR **【函数功能】 发送PDU到IVR **【参数】 a_PduEntity:待发送的PDU **【返回值】 ****************************************************************/ BOOL CNetworkCti::send2IVR( CPduEntity& a_PduEntity ) { return CInterfaceWindow::getIocpCommInstance()->Send(&a_PduEntity, PDU_DEV_TYPE_IVR, m_DevIvr.DevId); }