#include "StdAfx.h" #include "ProxyShell.h" #include "MC.h" #include "MsgCenter.h" #include "ProxyDti.h" #include "ProxyVoip.h" #include "ProxyExten.h" #include "NetLinkMgr.h" #include "ReqBase.h" #include "Config.h" #include "SessionShell.h" #include "ControlShell.h" #include "PlaySoundReq.h" #include "MakeCallReq.h" #include "TrunkTurnReq.h" #include "TurnAgentReq.h" #include "AnswerCallReq.h" #include "PredictionCallReq.h" #include "TransferReq.h" #include "MeetingReq.h" #include "InsteadReq.h" #include "InterceptReq.h" #include "InsertReq.h" #include "ListenReq.h" #include "FaxReq.h" #include "LeaveWordReq.h" #include "MuteReq.h" #include "ConsultCallReq.h" #include "OneLeg.h" #include "ChannelResource.h" #include "VoipChannel.h" #include "TrunkAidedAllocator.h" SINGLETON_IMPLEMENT(CProxyShell) CProxyShell::CProxyShell(void) { } CProxyShell::~CProxyShell(void) { __free(); } /***************************************************************** **【函数名称】 __free **【函数功能】 释放资源 **【参数】 **【返回值】 ****************************************************************/ void CProxyShell::__free( void ) { UINT LineId; CProxyExten* pExten; POSITION Pos = m_ExtenMap.GetStartPosition(); while(Pos != NULL) { m_ExtenMap.GetNextAssoc(Pos, LineId, pExten); ASSERT(pExten != NULL); delete pExten; } m_ExtenMap.RemoveAll(); CProxyVoip* pVoip; Pos = m_VoipMap.GetStartPosition(); while(Pos != NULL) { m_VoipMap.GetNextAssoc(Pos, LineId, pVoip); ASSERT(pVoip != NULL); delete pVoip; } m_VoipMap.RemoveAll(); CProxyDti* pDti; Pos = m_DtiMap.GetStartPosition(); while(Pos != NULL) { m_DtiMap.GetNextAssoc(Pos, LineId, pDti); ASSERT(pDti != NULL); delete pDti; } m_DtiMap.RemoveAll(); } /***************************************************************** **【函数名称】 __getProxyExten **【函数功能】 根据分机号查找内线代理并绑定VOIP线路 **【参数】 ExtnNum 内线分机号 **【返回值】 ****************************************************************/ CProxyExten* CProxyShell::__getProxyExten( UINT ExtnNum ) { CProxyExten* pExten = NULL; m_ExtenMap.Lookup(ExtnNum, pExten); return pExten; } /***************************************************************** **【函数名称】 __getProxyVoip **【函数功能】 根据VOIP号查找VOIP线路 **【参数】 VoipId 线路ID **【返回值】 ****************************************************************/ CProxyVoip* CProxyShell::__getProxyVoip( UINT VoipId ) { CProxyVoip* pVoip = NULL; m_VoipMap.Lookup(VoipId, pVoip); return pVoip; } /***************************************************************** **【函数名称】 __getProxyTrunk **【函数功能】 根据外线ID查找外线代理 **【参数】 TrunkId 外线ID **【返回值】 ****************************************************************/ CVirtualProxy* CProxyShell::__getProxyTrunk( UINT TrunkId ) { CProxyDti* pDti = NULL; if(m_DtiMap.Lookup(TrunkId, pDti)) return pDti; CProxyVoip* pVoip = NULL; m_VoipMap.Lookup(TrunkId, pVoip); return pVoip; } /***************************************************************** **【函数名称】 onNetworkClientConnect **【函数功能】 网络客户端连接的处理函数 **【参数】 **【返回值】 ****************************************************************/ void CProxyShell::onNetworkClientReg( PDU_DEV_TYPE DestType, int DestId ) { UINT LineId; CProxyExten* pExten; POSITION Pos = m_ExtenMap.GetStartPosition(); while(Pos != NULL) { m_ExtenMap.GetNextAssoc(Pos, LineId, pExten); ASSERT(pExten != NULL); if(!pExten->invalidFlag()) pExten->notifyLineInfo(DestType, DestId); } CProxyVoip* pVoip; Pos = m_VoipMap.GetStartPosition(); while(Pos != NULL) { m_VoipMap.GetNextAssoc(Pos, LineId, pVoip); ASSERT(pVoip != NULL); if(!pVoip->invalidFlag()) pVoip->notifyLineInfo(DestType, DestId); } CProxyDti* pDti; Pos = m_DtiMap.GetStartPosition(); while(Pos != NULL) { m_DtiMap.GetNextAssoc(Pos, LineId, pDti); ASSERT(pDti != NULL); if(!pDti->invalidFlag()) pDti->notifyLineInfo(DestType, DestId); } if(CMC::GetInstance().isPbxOK(0)) notifyDevResourceState(DEV_RES_TYPE_MB, 0, DEVICE_STATE_ENABLE); } /***************************************************************** **【函数名称】 onNetworkClientReq **【函数功能】 网络客户端请求的处理函数 **【参数】 **【返回值】 ****************************************************************/ void CProxyShell::onNetworkClientReq( CPduEntity* pReq ) { ASSERT(pReq != NULL); LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, _T("{ClientProxy}: 网络客户端请求, Req = %d"), pReq->GetCmdType()); bool Res = false; // 根据操作类型进行分类处理 switch(pReq->GetCmdType()) { case PDU_CMD_SC_REQ_MAKECALL: // 座席外呼 Res = __procReqMakeCall(*pReq); break; case PDU_CMD_SC_REQ_ANSWER: // 应答呼叫 Res = __procReqAnswerCall(*pReq); break; case PDU_CMD_SC_REQ_PCALL: // 预测外呼 Res = __procReqPCall(*pReq); break; case PDU_CMD_SC_REQ_HANGUP: // 挂机 Res = __procReqHangUp(*pReq); break; case PDU_CMD_SC_REQ_TRANSFER: // 呼叫转移 Res = __procReqTransfer(*pReq); break; case PDU_CMD_SC_REQ_TRUNKTURN: // 转外线 Res = __procReqTrunkTurn(*pReq); break; case PDU_CMD_SC_REQ_TURNAGENT: // 转坐席 Res = __procReqTurnAgent(*pReq); break; case PDU_CMD_SC_REQ_TURNIVR: // 转IVR Res = __procReqTurnIvr(*pReq); break; case PDU_CMD_SC_REQ_MEETING: // 单步会议 Res = __procReqMeeting(*pReq); break; case PDU_CMD_SC_REQ_LISTEN: // 监听 Res = __procReqListen(*pReq); break; case PDU_CMD_SC_REQ_INSERT: // 强插 Res = __procReqInsert(*pReq); break; case PDU_CMD_SC_REQ_RESET: // 重置 Res = __procReqReset(*pReq); break; case PDU_CMD_SC_REQ_INSTEAD: // 代接 Res = __procReqInstead(*pReq); break; case PDU_CMD_SC_REQ_INTERCEPT: // 强截 Res = __procReqIntercept(*pReq); break; case PDU_CMD_SC_REQ_INFOTRANSFER: // 信息交互 Res = __procReqInfoTransfer(*pReq); break; case PDU_CMD_SC_REQ_PLAY: // 放音收号 Res = __procReqPlaySound(*pReq); break; case PDU_CMD_SC_REQ_FAX: // 传真 Res = __procReqFax(*pReq); break; case PDU_CMD_SC_REQ_RECORD: // 录音 Res = __procReqRecord(*pReq); break; case PDU_CMD_SC_REQ_LEAVEWORD: // 留言 Res = __procReqLeaveWord(*pReq); break; case PDU_CMD_SC_REQ_MUTE: { if(pReq->GetDataUInt(3) == CLIENT_REQ_MUTE_ON) Res = __procReqMuteOn(*pReq); // 静音开始 else Res = __procReqMuteOff(*pReq); // 静音结束 } break; case PDU_CMD_SC_REQ_LINECHECK: // 线路自检 Res = __procReqLineCheck(*pReq); break; case PDU_CMD_SC_REQ_CONSULTCALL: // 协商呼叫启动 Res = __procReqConsultCall(*pReq); break; case PDU_CMD_SC_REQ_CONSULTCONFIRM: // 协商呼叫确认 Res = __procReqConsultCallConfirm(*pReq); break; default: ASSERT(FALSE); } // end switch pReq->SetDataBool(1, Res); CNetLinkMgr::GetInstance().send(pReq, pReq->GetLocalDevType(), pReq->GetLocalDevId()); } /***************************************************************** **【函数名称】 __beginLineReq **【函数功能】 启动线路操作 **【参数】 pLineReq 线路操作实体 **【返回值】 ****************************************************************/ bool CProxyShell::__beginLineReq( CReqBase* pLineReq ) { if(!pLineReq->request()) { pLineReq->detachHostLine(); delete pLineReq; return false; } // end if return true; } /***************************************************************** **【函数名称】 __procReqInfoTransfer **【函数功能】 数据交互 **【参数】 **【返回值】 启动操作是否成功 ****************************************************************/ bool CProxyShell::__procReqInfoTransfer( CPduEntity& a_Req ) { // 通过设备资源查找主控线路 CVirtualProxy* pHostLine = getProxyExtenWrapped(a_Req.GetDataUInt(2)); if(pHostLine == NULL) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行数据交换请求失败, 未找到线路[%lu], Instance = %d"), a_Req.GetDataUInt(2), a_Req.GetDataLong(0)); return false; } // 查找线路关联的操作 CReqBase* pCurrReq = pHostLine->currLineReq(); if(pCurrReq == NULL) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行数据交换请求失败, 线路[%lu]当前空闲, Instance = %d"), a_Req.GetDataUInt(2), a_Req.GetDataLong(0)); return false; } // 执行信息交互 pCurrReq->setAssoInfo(a_Req); return true; } /***************************************************************** **【函数名称】 __procReqPlayVoice **【函数功能】 线路放音收号 **【参数】 **【返回值】 ****************************************************************/ bool CProxyShell::__procReqPlaySound( CPduEntity& a_Req ) { // 通过设备资源查找主控线路 CVirtualProxy* pLine = getProxy(a_Req.GetDataUInt(2)); if(pLine == NULL) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行放音请求失败, 未找到线路[%lu], mode = %d, AudioFile = %s"), a_Req.GetDataUInt(2), a_Req.GetDataInt(3), a_Req.GetDataString(12)); return false; } CReqBase* pCurrReq = pLine->currLineReq(); if(a_Req.GetDataInt(3) == PVM_STOP_PLAY) // 停止放音 { // 如果线路未在执行放音操作 if(pCurrReq == NULL || dynamic_cast(pCurrReq) == NULL) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行停止放音请求失败, 线路[%lu]未执行放音操作"), a_Req.GetDataUInt(2)); return false; } else return pCurrReq->cancel(a_Req.GetDataLong(0)); // 执行取消操作 } else // 启动放音 { // 如果线路正在执行其它操作 if(pCurrReq != NULL) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行放音请求失败, 线路[%lu]忙, mode = %d, AudioFile = %s"), a_Req.GetDataUInt(2), a_Req.GetDataInt(3), a_Req.GetDataString(12)); return false; } // 生成放音操作类 CReqBase* pLineReq = new CPlaySoundReq(this, a_Req); pLineReq->attachHostLine(pLine); // 启动操作 return __beginLineReq(pLineReq); } // end if } /***************************************************************** **【函数名称】 __procReqMakeCall **【函数功能】 坐席外呼处理 **【参数】 **【返回值】 ****************************************************************/ bool CProxyShell::__procReqMakeCall( CPduEntity& a_Req ) { // 通过设备资源查找主控线路 CProxyExten* pLine = getProxyExtenWrapped(a_Req.GetDataUInt(2)); if(pLine == NULL) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行呼叫请求失败, 未找到线路[%lu], DestNum = %s"), a_Req.GetDataUInt(2), a_Req.GetDataString(3)); return false; } // 如果线路正在执行其它操作 if(pLine->currLineReq() != NULL) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行呼叫请求失败, 线路[%lu]忙, DestNum = %s"), a_Req.GetDataUInt(2), a_Req.GetDataString(3)); return false; } // 生成外呼操作类 CReqBase* pLineReq = new CMakeCallReq(this, a_Req); pLineReq->attachHostLine(pLine); // 启动操作 return __beginLineReq(pLineReq); } /***************************************************************** **【函数名称】 __procReqHangUp **【函数功能】 挂机操作处理 **【参数】 **【返回值】 ****************************************************************/ bool CProxyShell::__procReqHangUp( CPduEntity& a_Req ) { long InstanceCall = a_Req.GetDataLong(0); // 查找要挂机的线路 CVirtualProxy* pLine = getProxy(a_Req.GetDataUInt(2)); if(pLine == NULL) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行挂机请求失败, 未找到线路[%lu], Instance = %d"), a_Req.GetDataUInt(2), InstanceCall); return false; } // end if // 如果线路正在执行其它操作 if(pLine->currLineReq() != NULL) return pLine->currLineReq()->hangUp(InstanceCall); // 执行挂机操作 if(CMC::GetInstance().dropCall(pLine->devId(), false)) { notifyReqResult(a_Req, InstanceCall, true); return true; } // end if return false; } /***************************************************************** **【函数名称】 __procReqTrunkTurn **【函数功能】 外线呼叫跳转 **【参数】 **【返回值】 ****************************************************************/ bool CProxyShell::__procReqTrunkTurn( CPduEntity& a_Req ) { // 通过设备资源查找主控线路 CVirtualProxy* pLine = __getProxyTrunk(a_Req.GetDataUInt(2)); if(pLine == NULL) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行中继呼叫跳转失败, 未找到中继线路[%lu], DestNum = %s"), a_Req.GetDataUInt(2), a_Req.GetDataString(3)); return false; } // 当前线路是否正在进行其它操作 if(pLine->currLineReq() != NULL) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行中继呼叫跳转失败, 中继线路[%lu]忙, DestNum = %s"), a_Req.GetDataUInt(2), a_Req.GetDataString(3)); return false; } // 生成外线呼叫转移操作类 CReqBase* pLineReq = new CTrunkTurnReq(this, a_Req); pLineReq->attachHostLine(pLine); // 启动操作 return __beginLineReq(pLineReq); } /***************************************************************** **【函数名称】 __procReqTurnAgent **【函数功能】 外线转坐席 **【参数】 **【返回值】 ****************************************************************/ bool CProxyShell::__procReqTurnAgent( CPduEntity& a_Req ) { // 通过设备资源查找主控线路 CVirtualProxy* pLine = __getProxyTrunk(a_Req.GetDataUInt(2)); if(pLine == NULL) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行中继转座席失败, 未找到中继线路[%lu], ExtenNum = %s"), a_Req.GetDataUInt(2), a_Req.GetDataString(3)); return false; } // 当前线路是否正在进行其它操作 if(pLine->currLineReq() != NULL) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行中继转座席失败, 中继线路[%lu]忙, ExtenNum = %s"), a_Req.GetDataUInt(2), a_Req.GetDataString(3)); return false; } // 生成外线呼叫转移操作类 CReqBase* pLineReq = new CTurnAgentReq(this, a_Req); pLineReq->attachHostLine(pLine); // 启动操作 return __beginLineReq(pLineReq); } /***************************************************************** **【函数名称】 __procReqAnswerCall **【函数功能】 应答呼叫 **【参数】 **【返回值】 ****************************************************************/ bool CProxyShell::__procReqAnswerCall( CPduEntity& a_Req ) { // 查找要应答呼叫的线路 CVirtualProxy* pLine = getProxyExtenWrapped(a_Req.GetDataUInt(2)); if(pLine == NULL) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行应答请求失败, 未找到线路[%lu], Instance = %d"), a_Req.GetDataUInt(2), a_Req.GetDataLong(0)); return false; } // end if // 如果线路正在执行其它操作 if(pLine->currLineReq() != NULL) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行应答请求失败, 线路[%lu]忙, Instance = %d"), a_Req.GetDataUInt(2), a_Req.GetDataLong(0)); return false; } // 生成应答呼叫操作类 CReqBase* pLineReq = new CAnswerCallReq(this, a_Req); pLineReq->attachHostLine(pLine); // 启动操作 return __beginLineReq(pLineReq); } /***************************************************************** **【函数名称】 __procReqPCall **【函数功能】 预测外呼 **【参数】 **【返回值】 ****************************************************************/ bool CProxyShell::__procReqPCall( CPduEntity& a_Req ) { // 生成自动呼叫操作类 CReqBase* pLineReq = new CPredictionCallReq(this, a_Req); // 启动操作 return __beginLineReq(pLineReq); } /***************************************************************** **【函数名称】 __procReqTransfer **【函数功能】 座席呼叫转移 **【参数】 **【返回值】 ****************************************************************/ bool CProxyShell::__procReqTransfer( CPduEntity& a_Req ) { // 通过设备资源查找主控线路 CProxyExten* pLine = getProxyExtenWrapped(a_Req.GetDataUInt(2)); if(pLine == NULL) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行呼叫转移请求失败, 未找到线路[%lu], DestNum = %s"), a_Req.GetDataUInt(2), a_Req.GetDataString(3)); return false; } // 如果线路正在执行其它操作 if(pLine->currLineReq() != NULL) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行呼叫转移请求失败, 线路[%lu]忙, DestNum = %s"), a_Req.GetDataUInt(2), a_Req.GetDataString(3)); return false; } CReqBase* pLineReq = new CTransferReq(this, a_Req); pLineReq->attachHostLine(pLine); // 启动操作 return __beginLineReq(pLineReq); } /***************************************************************** **【函数名称】 __procReqMeeting **【函数功能】 单步会议 **【参数】 **【返回值】 ****************************************************************/ bool CProxyShell::__procReqMeeting( CPduEntity& a_Req ) { // 通过设备资源查找主控线路 CProxyExten* pLine = getProxyExtenWrapped(a_Req.GetDataUInt(2)); if(pLine == NULL) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行会议请求失败, 未找到线路[%lu], DestNum = %s"), a_Req.GetDataUInt(2), a_Req.GetDataString(3)); return false; } // 如果线路正在执行其它操作 if(pLine->currLineReq() != NULL) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行会议请求失败, 线路[%lu]忙, DestNum = %s"), a_Req.GetDataUInt(2), a_Req.GetDataString(3)); return false; } CReqBase* pLineReq = new CMeetingReq(this, a_Req); pLineReq->attachHostLine(pLine); // 启动操作 return __beginLineReq(pLineReq); } /***************************************************************** **【函数名称】 __procReqTurnIvr **【函数功能】 转IVR **【参数】 **【返回值】 ****************************************************************/ bool CProxyShell::__procReqTurnIvr( CPduEntity& a_Req ) { // 查找要转IVR的线路 CVirtualProxy* pLine = getProxyExtenWrapped(a_Req.GetDataUInt(2)); if(pLine == NULL) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行跳转IVR请求失败, 未找到线路[%lu], Instance = %d"), a_Req.GetDataUInt(2), a_Req.GetDataLong(0)); return false; } // end if // 条件过滤 if(pLine->currLineReq() != NULL || pLine->state() != VIRTUAL_LINE_STATE_TALKING) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行跳转IVR请求失败, 线路[%lu]忙, Instance = %d"), a_Req.GetDataUInt(2), a_Req.GetDataLong(0)); return false; } // end if // 执行转IVR操作 if(CSessionShell::GetInstance().procReqLeave(pLine->activeCallId(), pLine->devId())) { notifyReqResult(a_Req, a_Req.GetDataLong(0), true); return true; } // end if return false; } /***************************************************************** **【函数名称】 __procReqInstead **【函数功能】 代接 **【参数】 **【返回值】 ****************************************************************/ bool CProxyShell::__procReqInstead( CPduEntity& a_Req ) { // 通过设备资源查找主控线路 CProxyExten* pLine = getProxyExtenWrapped(a_Req.GetDataUInt(2)); if(pLine == NULL) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行代接请求失败, 未找到线路[%lu], DestNum = %lu"), a_Req.GetDataUInt(2), a_Req.GetDataUInt(3)); return false; } // 如果线路正在执行其它操作 if(pLine->currLineReq() != NULL) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行代接请求失败, 线路[%lu]忙, DestNum = %lu"), a_Req.GetDataUInt(2), a_Req.GetDataUInt(3)); return false; } CReqBase* pLineReq = new CInsteadReq(this, a_Req); pLineReq->attachHostLine(pLine); // 启动操作 return __beginLineReq(pLineReq); } /***************************************************************** **【函数名称】 __procReqIntercept **【函数功能】 强截 **【参数】 **【返回值】 ****************************************************************/ bool CProxyShell::__procReqIntercept( CPduEntity& a_Req ) { // 通过设备资源查找主控线路 CProxyExten* pLine = getProxyExtenWrapped(a_Req.GetDataUInt(2)); if(pLine == NULL) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行强截请求失败, 未找到线路[%lu], DestNum = %lu"), a_Req.GetDataUInt(2), a_Req.GetDataUInt(3)); return false; } // 如果线路正在执行其它操作 if(pLine->currLineReq() != NULL) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行强截请求失败, 线路[%lu]忙, DestNum = %lu"), a_Req.GetDataUInt(2), a_Req.GetDataUInt(3)); return false; } CReqBase* pLineReq = new CInterceptReq(this, a_Req); pLineReq->attachHostLine(pLine); // 启动操作 return __beginLineReq(pLineReq); } /***************************************************************** **【函数名称】 __procReqInsert **【函数功能】 强插 **【参数】 **【返回值】 ****************************************************************/ bool CProxyShell::__procReqInsert( CPduEntity& a_Req ) { // 通过设备资源查找主控线路 CProxyExten* pLine = getProxyExtenWrapped(a_Req.GetDataUInt(2)); if(pLine == NULL) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行强插请求失败, 未找到线路[%lu], DestNum = %lu"), a_Req.GetDataUInt(2), a_Req.GetDataUInt(3)); return false; } // 如果线路正在执行其它操作 if(pLine->currLineReq() != NULL) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行强插请求失败, 线路[%lu]忙, DestNum = %lu"), a_Req.GetDataUInt(2), a_Req.GetDataUInt(3)); return false; } // 生成强插操作类 CReqBase* pLineReq = new CInsertReq(this, a_Req); pLineReq->attachHostLine(pLine); // 启动操作 return __beginLineReq(pLineReq); } /***************************************************************** **【函数名称】 __procReqListen **【函数功能】 监听 **【参数】 **【返回值】 ****************************************************************/ bool CProxyShell::__procReqListen( CPduEntity& a_Req ) { // 通过设备资源查找主控线路 CProxyExten* pLine = getProxyExtenWrapped(a_Req.GetDataUInt(2)); if(pLine == NULL) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行监听请求失败, 未找到线路[%lu], DestNum = %lu"), a_Req.GetDataUInt(2), a_Req.GetDataUInt(3)); return false; } // 如果线路正在执行其它操作 if(pLine->currLineReq() != NULL) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行监听请求失败, 线路[%lu]忙, DestNum = %lu"), a_Req.GetDataUInt(2), a_Req.GetDataUInt(3)); return false; } // 生成强插操作类 CReqBase* pLineReq = new CListenReq(this, a_Req); pLineReq->attachHostLine(pLine); // 启动操作 return __beginLineReq(pLineReq); } /***************************************************************** **【函数名称】 __procReqReset **【函数功能】 重置 **【参数】 **【返回值】 ****************************************************************/ bool CProxyShell::__procReqReset( CPduEntity& a_Req ) { // 通过设备资源查找主控线路 CProxyExten* pLine = getProxyExtenWrapped(a_Req.GetDataUInt(2)); if(pLine == NULL) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行线路重置请求失败, 未找到线路[%lu]"), a_Req.GetDataUInt(2)); return false; } LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, _T("{ClientProxy}: 执行线路重置请求, Line = %lu"), a_Req.GetDataUInt(2)); // 清除关联操作 CReqBase* pLineOp = pLine->currLineReq(); if(pLineOp != NULL) { pLineOp->hangUp(0); pLineOp->detachHostLine(); delete pLineOp; } else { CMC::GetInstance().dropCall(pLine->devId(), false); } // end if return true; } /***************************************************************** **【函数名称】 __procReqFax **【函数功能】 传真 **【参数】 **【返回值】 ****************************************************************/ bool CProxyShell::__procReqFax( CPduEntity& a_Req ) { // 通过设备资源查找主控线路 CVirtualProxy* pProxy = __getProxyTrunk(a_Req.GetDataUInt(2)); if(pProxy == NULL) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行传真请求失败, 未找到线路[%lu], FaxFile = %s"), a_Req.GetDataUInt(2), a_Req.GetDataString(4)); return false; } // 如果线路正在执行其它操作 if(pProxy->currLineReq() != NULL) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行传真请求失败, 线路[%lu]忙, FaxFile = %s"), a_Req.GetDataUInt(2), a_Req.GetDataString(4)); return false; } // 生成强插操作类 CReqBase* pLineReq = new CFaxReq(this, a_Req); pLineReq->attachHostLine(pProxy); // 启动操作 return __beginLineReq(pLineReq); } /***************************************************************** **【函数名称】 __procReqRecord **【函数功能】 线路录音 **【参数】 **【返回值】 ****************************************************************/ bool CProxyShell::__procReqRecord( CPduEntity& a_Req ) { // 查找要录音的线路 CVirtualProxy* pLine = getProxy(a_Req.GetDataUInt(2)); if(pLine == NULL) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行线路录音请求失败, 未找到线路[%lu]"), a_Req.GetDataUInt(2)); return false; } // end if // 如果线路正在执行其它操作 if(pLine->currLineReq() != NULL) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行线路录音请求失败, 线路[%lu]忙"), a_Req.GetDataUInt(2)); return false; } // 查找线路所属的活动呼叫 long Call = pLine->activeCallId(); if(Call == SESSION_INVALID_CALL) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行线路录音请求失败, 线路[%lu]未在通话中"), a_Req.GetDataUInt(2)); return false; } // end if // 执行录音操作 return CSessionShell::GetInstance().procReqRecord(Call, pLine->devId(), a_Req.GetDataString(3)); } /***************************************************************** **【函数名称】 __procReqLeaveWord **【函数功能】 留言录音 **【参数】 **【返回值】 ****************************************************************/ bool CProxyShell::__procReqLeaveWord( CPduEntity& a_Req ) { // 查找要留言的线路 CVirtualProxy* pLine = __getProxyTrunk(a_Req.GetDataUInt(2)); // 外线 if(pLine == NULL) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行留言请求失败, 未找到线路[%lu], SaveFile = %s"), a_Req.GetDataUInt(2), a_Req.GetDataString(5)); return false; } // end if // 如果线路正在执行其它操作 if(pLine->currLineReq() != NULL) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行留言请求失败, 线路[%lu]忙, SaveFile = %s"), a_Req.GetDataUInt(2), a_Req.GetDataString(5)); return false; } // 生成留言操作类 CReqBase* pLineReq = new CLeaveWordReq(this, a_Req); pLineReq->attachHostLine(pLine); // 启动操作 return __beginLineReq(pLineReq); } /***************************************************************** **【函数名称】 __procReqMuteBegin **【函数功能】 静音启动 **【参数】 **【返回值】 ****************************************************************/ bool CProxyShell::__procReqMuteOn( CPduEntity& a_Req ) { // 通过设备资源查找主控线路 CProxyExten* pLine = getProxyExtenWrapped(a_Req.GetDataUInt(2)); if(pLine == NULL) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行静音请求失败, 未找到线路[%lu], Instance = %d"), a_Req.GetDataUInt(2), a_Req.GetDataLong(0)); return false; } // 如果线路正在执行其它操作 if(pLine->currLineReq() != NULL) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行静音请求失败, 线路[%lu]忙, Instance = %d"), a_Req.GetDataUInt(2), a_Req.GetDataLong(0)); return false; } // 生成静音操作类 CReqBase* pLineReq = new CMuteReq(this, a_Req); pLineReq->attachHostLine(pLine); // 启动操作 return __beginLineReq(pLineReq); } /***************************************************************** **【函数名称】 __procReqMuteEnd **【函数功能】 静音结束 **【参数】 **【返回值】 ****************************************************************/ bool CProxyShell::__procReqMuteOff( CPduEntity& a_Req ) { // 通过设备资源查找主控线路 CProxyExten* pLine = getProxyExtenWrapped(a_Req.GetDataUInt(2)); if(pLine == NULL) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行取消静音请求失败, 未找到线路[%lu], Instance = %d"), a_Req.GetDataUInt(2), a_Req.GetDataLong(0)); return false; } // 如果线路正在执行其它操作 CReqBase* pCurrReq = pLine->currLineReq(); if(pCurrReq == NULL || dynamic_cast(pCurrReq) == NULL) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行取消静音请求失败, 线路[%lu]忙, Instance = %d"), a_Req.GetDataUInt(2), a_Req.GetDataLong(0)); return false; } // 执行取消静音操作 return pCurrReq->cancel(a_Req.GetDataLong(0)); } /***************************************************************** **【函数名称】 __procReqSelfCheck **【函数功能】 线路自检(当前只对模拟外线有效) **【参数】 **【返回值】 ****************************************************************/ bool CProxyShell::__procReqLineCheck( CPduEntity& a_Req ) { return false; } /***************************************************************** **【函数名称】 __procReqConsultCall **【函数功能】 协商呼叫启动 **【参数】 **【返回值】 ****************************************************************/ bool CProxyShell::__procReqConsultCall( CPduEntity& a_Req ) { // 通过设备资源查找主控线路 CProxyExten* pLine = getProxyExtenWrapped(a_Req.GetDataUInt(2)); if(pLine == NULL) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行协商呼叫请求失败, 未找到线路[%lu], DestNum = %s"), a_Req.GetDataUInt(2), a_Req.GetDataString(3)); return false; } // 如果线路正在执行其它操作 if(pLine->currLineReq() != NULL) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行协商呼叫请求失败, 线路[%lu]忙, DestNum = %s"), a_Req.GetDataUInt(2), a_Req.GetDataString(3)); return false; } // 生成协商呼叫操作类 CReqBase* pCurrReq = new CConsultCallReq(this, a_Req); pCurrReq->attachHostLine(pLine); // 启动操作 return __beginLineReq(pCurrReq); } /***************************************************************** **【函数名称】 __procReqConsultCallConfirm **【函数功能】 协商呼叫确认 **【参数】 **【返回值】 ****************************************************************/ bool CProxyShell::__procReqConsultCallConfirm( CPduEntity& a_Req ) { // 通过设备资源查找主控线路 CProxyExten* pLine = getProxyExtenWrapped(a_Req.GetDataUInt(2)); if(pLine == NULL) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行协商确认失败, 未找到线路[%lu], Instance = %d"), a_Req.GetDataUInt(2), a_Req.GetDataLong(0)); return false; } // 如果线路未执行协商呼叫操作 CReqBase* pCurrReq = pLine->currLineReq(); if(pCurrReq == NULL || dynamic_cast(pCurrReq) == NULL) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行协商确认失败, 线路[%lu]忙, Instance = %d"), a_Req.GetDataUInt(2), a_Req.GetDataLong(0)); return false; } // 执行操作确认 if(!pCurrReq->resume(a_Req.GetDataLong(0), a_Req.GetDataInt(3))) { pCurrReq->detachHostLine(); delete pCurrReq; return false; } // end if return true; } /***************************************************************** **【函数名称】 __procFunCodeDevEvent **【函数功能】 收取功能键事件处理函数 **【参数】 **【返回值】 ****************************************************************/ bool CProxyShell::__procFunCodeDevEvent( CVirtualProxy* pLine, LPCTSTR lpContent, UINT ExtenId ) { CProxyExten* pExten = __getProxyExten(ExtenId); ASSERT(pExten != NULL); if(pExten == NULL) return false; ASSERT(pLine->state() == VIRTUAL_LINE_STATE_FREE); // 如果线路正在执行其它操作 if(pLine->currLineReq() != NULL || pExten->currLineReq() != NULL) return false; pLine->wrap(pExten); pExten->wrap(pLine); // 生成外呼操作类 CPduEntity CallPdu(PDU_CMD_SC_REQ_MAKECALL); CReqBase* pLineReq = new CMakeCallReq(this, CallPdu); pLineReq->attachHostLine(pExten); if(!pLineReq->request(lpContent)) { pLineReq->detachHostLine(); delete pLineReq; return false; } // end if return true; } /***************************************************************** **【函数名称】 __procHoldOnDevEvent **【函数功能】 分机保持事件处理函数 **【参数】 **【返回值】 ****************************************************************/ bool CProxyShell::__procHoldOnDevEvent( CVirtualProxy* pLine, UINT ExtenId ) { CProxyExten* pExten = __getProxyExten(ExtenId); ASSERT(pExten != NULL); if(pExten == NULL) return false; ASSERT(pLine->state() == VIRTUAL_LINE_STATE_TALKING); // 如果线路正在执行其它操作 if(pLine->currLineReq() != NULL || pExten->currLineReq() != NULL) return false; return pExten->holdOn(); } /***************************************************************** **【函数名称】 __procTakeBackDevEvent **【函数功能】 分机接回事件处理函数 **【参数】 **【返回值】 ****************************************************************/ bool CProxyShell::__procTakeBackDevEvent( CVirtualProxy* pLine, UINT ExtenId ) { CProxyExten* pExten = __getProxyExten(ExtenId); ASSERT(pExten != NULL); if(pExten == NULL) return false; ASSERT(pLine->state() == VIRTUAL_LINE_STATE_TALKING); // 如果线路正在执行其它操作 if(pLine->currLineReq() != NULL || pExten->currLineReq() != NULL) return false; return pExten->takeBack(); } /***************************************************************** **【函数名称】 getProxyExten **【函数功能】 根据分机号查找内线代理 **【参数】 ExtnNum 内线分机号 **【返回值】 ****************************************************************/ CProxyExten* CProxyShell::getProxyExtenWrapped( UINT ExtnNum ) { CProxyExten* pExten = NULL; if(m_ExtenMap.Lookup(ExtnNum, pExten)) { ASSERT(pExten != NULL); if(pExten->isVoipExten() && pExten->isNull()) { // 向底层申请VOIP通道 CVoipChannel* pVoipChan = CMC::GetInstance().allocVoipCh4Exten(DEVICE_NODE_NO_ANY); ASSERT(pVoipChan != NULL); if(pVoipChan == NULL) return NULL; // 查找通道对应代理 CVirtualProxy* pVoipProxy = __getProxyVoip(pVoipChan->id().toIntId()); ASSERT(pVoipProxy != NULL); if(pVoipProxy == NULL) // 代理为空则创建 pVoipProxy = onLineNew(pVoipChan->id()); ASSERT(pVoipProxy != NULL); pExten->wrap(pVoipProxy); pVoipProxy->wrap(pExten); } } return pExten; } /***************************************************************** **【函数名称】 getProxy **【函数功能】 根据ID查找线路代理 **【参数】 LineDevId 线路设备ID **【返回值】 ****************************************************************/ CVirtualProxy* CProxyShell::getProxy( UINT ResId ) { CVirtualProxy* pProxy = __getProxyExten(ResId); if(pProxy == NULL) pProxy = __getProxyTrunk(ResId); return pProxy; } /***************************************************************** **【函数名称】 setEnv4Calling **【函数功能】 设置呼叫环境 **【参数】 **【返回值】 ****************************************************************/ CVirtualProxy* CProxyShell::setEnv4Calling(CString& CallerNum, CString& CalleeNum, DEV_RES_TYPE& LineType, int& SipAccountId) { TRUNK_ITEM* pItem = NULL; COneLeg* pLeg = CTrunkAidedAllocator::GetInstance().aidedAlloc(CallerNum, CalleeNum, &pItem); if(pLeg != NULL) // 被叫是外线 { ASSERT(pItem != NULL); SipAccountId = pItem->SipAccountId; LineType = DEV_RES_TYPE_TRUNK; return __getProxyTrunk(pLeg->resourceAttribute()->id().toIntId()); } else // 被叫是内线 { SipAccountId = INVALID_ID_SIP_ACCOUNT; LineType = DEV_RES_TYPE_EXT; UINT ExtNum = 0; sscanf_s(CalleeNum, "%lu", &ExtNum); return getProxyExtenWrapped(ExtNum); } } /***************************************************************** **【函数名称】 setEnv4PredictionCall **【函数功能】 设置预测外呼环境 **【参数】 **【返回值】 ****************************************************************/ CVirtualProxy* CProxyShell::setEnv4PredictionCall( CString& CallerNum, CString& CalleeNum, int& SipAccountId ) { TRUNK_ITEM* pItem = NULL; COneLeg* pLeg = CTrunkAidedAllocator::GetInstance().aidedAllocWithDefault(CallerNum, CalleeNum, &pItem); if(pLeg != NULL) { ASSERT(pItem != NULL); SipAccountId = pItem->SipAccountId; return __getProxyTrunk(pLeg->resourceAttribute()->id().toIntId()); } else return NULL; } /***************************************************************** **【函数名称】 notifyResourceDetail **【函数功能】 向客户端发送设备资源明细 **【参数】 **【返回值】 ****************************************************************/ void CProxyShell::notifyResourceDetail( DEV_RES_TYPE ResType, UINT ResID ) { CPduEntity ResPdu(PDU_CMD_SC_RES_DETAIL); ResPdu.SetDataUInt(0, ResType); ResPdu.SetDataUInt(1, ResID); CNetLinkMgr::GetInstance().send(&ResPdu); } /***************************************************************** **【函数名称】 notifyResourceDetail **【函数功能】 向客户端发送设备资源明细 **【参数】 **【返回值】 ****************************************************************/ void CProxyShell::notifyResourceDetail( PDU_DEV_TYPE DestType, int DestId, DEV_RES_TYPE ResType, UINT ResID ) { CPduEntity ResPdu(PDU_CMD_SC_RES_DETAIL); ResPdu.SetDataUInt(0, ResType); ResPdu.SetDataUInt(1, ResID); CNetLinkMgr::GetInstance().send(&ResPdu, DestType, DestId); } /***************************************************************** **【函数名称】 __notifyDevResourceState **【函数功能】 向客户端发送设备资源状态信息 **【参数】 **【返回值】 ****************************************************************/ void CProxyShell::notifyDevResourceState( DEV_RES_TYPE ResType, UINT ResID, UINT State, LPCTSTR CallerNum /*= NULL*/, LPCTSTR CalleeNum /*= NULL*/ ) { CPduEntity ResStatePdu(PDU_CMD_SC_RES_STATE); ResStatePdu.SetDataUInt(0, ResType); ResStatePdu.SetDataUInt(1, ResID); ResStatePdu.SetDataUInt(2, State); if(CallerNum != NULL) ResStatePdu.SetDataString(3, CallerNum); if(CalleeNum != NULL) ResStatePdu.SetDataString(4, CalleeNum); CNetLinkMgr::GetInstance().send(&ResStatePdu); } /***************************************************************** **【函数名称】 __notifyDevResourceState **【函数功能】 向客户端发送设备资源状态信息 **【参数】 **【返回值】 ****************************************************************/ void CProxyShell::notifyDevResourceState( PDU_DEV_TYPE DestType, int DestId, DEV_RES_TYPE ResType, UINT ResID, UINT State, LPCTSTR CallerNum /*= NULL*/, LPCTSTR CalleeNum /*= NULL*/ ) { CPduEntity ResStatePdu(PDU_CMD_SC_RES_STATE); ResStatePdu.SetDataUInt(0, ResType); ResStatePdu.SetDataUInt(1, ResID); ResStatePdu.SetDataUInt(2, State); if(CallerNum != NULL) ResStatePdu.SetDataString(3, CallerNum); if(CalleeNum != NULL) ResStatePdu.SetDataString(4, CalleeNum); CNetLinkMgr::GetInstance().send(&ResStatePdu, DestType, DestId); } /***************************************************************** **【函数名称】 notifyLineEvent **【函数功能】 通知设备主动操作事件 **【参数】 LineID 线路ID EvtTp 事件类型 CallerNum 主叫号码 CalleeNum 被叫号码 **【返回值】 ****************************************************************/ void CProxyShell::notifyLineOpEvent( UINT ResID, DEV_OP OpTp, const CString& CallerNum, const CString& CalleeNum ) { CPduEntity EvtPdu(PDU_CMD_SC_ACTIVE_EVENT); EvtPdu.SetDataUInt(0, ResID); EvtPdu.SetDataUInt(1, OpTp); EvtPdu.SetDataString(2, CallerNum); EvtPdu.SetDataString(3, CalleeNum); CNetLinkMgr::GetInstance().send(&EvtPdu); } /***************************************************************** **【函数名称】 notifyOpProcess **【函数功能】 通知请求进展 **【参数】 LineReq 线路请求 HostLine 主控线路ID AssoLine 关联线路ID AssoLineType 关联线路类型 lpCallerNum 主叫号码 lpCalleeNum 被叫号码 **【返回值】 ****************************************************************/ void CProxyShell::notifyReqProcess( CReqBase& LineReq, UINT HostLine, UINT AssoLine, DEV_RES_TYPE AssoLineType, LPCTSTR lpCallerNum, LPCTSTR lpCalleeNum ) { CPduEntity ProcessPdu(PDU_CMD_SC_REQ_PROCESS); ProcessPdu.SetDataLong(0, LineReq.callInstance()); ProcessPdu.SetDataUInt(1, HostLine); ProcessPdu.SetDataUInt(2, AssoLine); ProcessPdu.SetDataUInt(3, AssoLineType); ProcessPdu.SetDataString(4, lpCallerNum); ProcessPdu.SetDataString(5, lpCalleeNum); CNetLinkMgr::GetInstance().send(&ProcessPdu, LineReq.comeFrom().GetLocalDevType(), LineReq.comeFrom().GetLocalDevId()); } /***************************************************************** **【函数名称】 notifyReqResult **【函数功能】 通知请求执行结果 **【参数】 Instance 调用实例 ToWhere 发往哪里 IsSucceed 是否成功 lpData 执行结果返回的随路数据 **【返回值】 ****************************************************************/ void CProxyShell::notifyReqResult( CPduEntity& SrcReq, long Instance, bool IsSucceed, LPCTSTR lpData /*= NULL*/ ) { CPduEntity ResultPdu(PDU_CMD_SC_REQ_RESULT); ResultPdu.SetDataLong(0, Instance); ResultPdu.SetDataBool(1, IsSucceed); if(lpData != NULL) ResultPdu.SetDataString(2, lpData); CNetLinkMgr::GetInstance().send(&ResultPdu, SrcReq.GetLocalDevType(), SrcReq.GetLocalDevId()); } /***************************************************************** **【函数名称】 onLineReqEnd **【函数功能】 线路请求结束的处理函数 **【参数】 LineReq 线路请求实例 IsSucceed 是否成功 lpData 执行结果返回的随路数据 **【返回值】 ****************************************************************/ void CProxyShell::onLineReqEnd( CReqBase* pLineReq, bool IsSucceed, LPCTSTR lpData /*= NULL*/ ) { ASSERT(pLineReq != NULL); // 关闭线路关联 pLineReq->detachHostLine(); // 返回执行结果 notifyReqResult(pLineReq->comeFrom(), pLineReq->callInstance(), IsSucceed, lpData); // 关闭操作 delete pLineReq; } /***************************************************************** **【函数名称】 onLineNew **【函数功能】 线路初始信息事件通知 **【参数】 LineDevId 线路的设备ID **【返回值】 ****************************************************************/ CVirtualProxy* CProxyShell::onLineNew( CRDRID LineDevId ) { switch(LineDevId.ResType) { case DEV_RES_TYPE_EXT: { CProxyExten* pExtn = NULL; if(!m_ExtenMap.Lookup(LineDevId.ChanNo, pExtn)) { // 生成分机实体类 pExtn = new CProxyExten(this, LineDevId); ASSERT(pExtn != NULL); m_ExtenMap.SetAt(LineDevId.ChanNo, pExtn); // 通知业务逻辑分机信息 pExtn->notifyLineInfo(); } else { if(pExtn->invalidFlag()) pExtn->invalidFlag() = false; } return pExtn; } break; case DEV_RES_TYPE_TRUNK: { CProxyDti* pDti = NULL; if(!m_DtiMap.Lookup(LineDevId.toIntId(), pDti)) { // 生成外线实体类 pDti = new CProxyDti(this, LineDevId); ASSERT(pDti != NULL); m_DtiMap.SetAt(LineDevId.toIntId(), pDti); // 通知业务逻辑外线信息 pDti->notifyLineInfo(); } else { if(pDti->invalidFlag()) pDti->invalidFlag() = false; } return pDti; } break; case DEV_RES_TYPE_VOIP: { CProxyVoip* pVoip = NULL; if(!m_VoipMap.Lookup(LineDevId.toIntId(), pVoip)) { // 生成外线实体类 pVoip = new CProxyVoip(this, LineDevId); ASSERT(pVoip != NULL); m_VoipMap.SetAt(LineDevId.toIntId(), pVoip); // 通知业务逻辑外线信息 pVoip->notifyLineInfo(); } else { if(pVoip->invalidFlag()) pVoip->invalidFlag() = false; } return pVoip; } break; default: return NULL; } } /***************************************************************** **【函数名称】 onLineDelete **【函数功能】 线路删除 **【参数】 LineDevId 线路的设备ID **【返回值】 ****************************************************************/ void CProxyShell::onLineDelete( CRDRID LineDevId ) { switch(LineDevId.ResType) { case DEV_RES_TYPE_EXT: { // 删除分机代理类 CProxyExten* pExtn = NULL; m_ExtenMap.Lookup(LineDevId.ChanNo, pExtn); if (pExtn != NULL) { if(pExtn->isFree()) { m_ExtenMap.RemoveKey(LineDevId.ChanNo); delete pExtn; } else pExtn->invalidFlag() = true; } } break; case DEV_RES_TYPE_TRUNK: { // 删除分机代理类 CProxyDti* pDti = NULL; m_DtiMap.Lookup(LineDevId.toIntId(), pDti); if (pDti != NULL) { if(pDti->isFree()) { m_DtiMap.RemoveKey(LineDevId.toIntId()); delete pDti; } else pDti->invalidFlag() = true; } } break; case DEV_RES_TYPE_VOIP: { // 删除分机代理类 CProxyVoip* pVoip = NULL; m_VoipMap.Lookup(LineDevId.toIntId(), pVoip); if (pVoip != NULL) { if(pVoip->isFree()) { m_VoipMap.RemoveKey(LineDevId.toIntId()); delete pVoip; } else pVoip->invalidFlag() = true; } } break; default: ASSERT(FALSE); } } /***************************************************************** **【函数名称】 onNewCall **【函数功能】 线路进入会话事件 **【参数】 LineDevId 线路设备ID Call 线路当前所属的主会话ID SubCall 线路当前所属的子会话ID **【返回值】 ****************************************************************/ void CProxyShell::onNewCall( CRDRID LineDevId, long Call, long SubCall ) { CVirtualProxy* pLine = getProxy(LineDevId.toIntId()); ASSERT(pLine != NULL); if(pLine != NULL) pLine->onNewCall(Call, SubCall); } /***************************************************************** **【函数名称】 onLineStateUpdated **【函数功能】 线路状态变化事件通知 **【参数】 LineDevId 线路设备ID Call 线路当前所属的主会话ID SubCall 线路当前所属的子会话ID Status 线路当前状态 lpCallerNum 主叫号码 lpCalleeNum 被叫号码 **【返回值】 ****************************************************************/ void CProxyShell::onLineStateUpdated( CRDRID LineDevId, long Call, long SubCall, VIRTUAL_LINE_STATE State, LPCTSTR lpCallerNum/* = NULL*/, LPCTSTR lpCalleeNum /*= NULL*/ ) { CVirtualProxy* pLine = getProxy(LineDevId.toIntId()); ASSERT(pLine != NULL); if(pLine != NULL) { pLine->onLineStateChanged(Call, SubCall, State, lpCallerNum, lpCalleeNum); if(pLine->invalidFlag() && pLine->isFree()) onLineDelete(pLine->devId()); } } /***************************************************************** **【函数名称】 onDevChannelEvent **【函数功能】 设备通道向上层发送的设备主动事件 **【参数】 LineDevId 触发事件的线路ID EvtType 事件类型 lpContent 事件内容 **【返回值】 *****************************************************************/ bool CProxyShell::onDevChannelEvent( CRDRID LineDevId, DEV_CH_EVT_TYPE EvtType, LPCTSTR lpContent, UINT ExtenId ) { // 获取触发事件的线路 CVirtualProxy* pLine = getProxy(LineDevId.toIntId()); ASSERT(pLine != NULL); if(pLine == NULL) return false; // 进行分类处理 switch(EvtType) { case DEV_CH_EVT_PLAY_END: // 放音结束 case DEV_CH_EVT_OFF_HOOK: // 内线已摘机 case DEV_CH_EVT_FAX_OK: // 传真成功 case DEV_CH_EVT_FAX_FAILED: // 传真失败 case DEV_CH_EVT_REC_END: // 录音结束 case DEV_CH_EVT_MEETING_RESULT: // 会议结果 case DEV_CH_EVT_CALL_FAILD_CAUSE: // 呼叫失败原因 { pLine->onDevChEvent(EvtType, lpContent); } break; case DEV_CH_EVT_FUN_CODE: // 收取功能键 return __procFunCodeDevEvent(pLine, lpContent, ExtenId); case DEV_CH_EVT_HOLD_ON: return __procHoldOnDevEvent(pLine, ExtenId); case DEV_CH_EVT_TAKE_BACK: return __procTakeBackDevEvent(pLine, ExtenId); } return true; }