#include "StdAfx.h" #include "MakeCallReq.h" #include "ProxyExten.h" #include "MC.h" #include "SessionShell.h" #include "ProxyShell.h" CMakeCallReq::CMakeCallReq(CProxyShell* pParent, CPduEntity& ReqPdu) : CReqBase(pParent, ReqPdu), m_pAssoLine(NULL), m_PendingCallId(0), m_PeerLineType(DEV_RES_TYPE_EXT), m_Step(0), m_SipAccountId(INVALID_ID_SIP_ACCOUNT) { } CMakeCallReq::~CMakeCallReq(void) { } /***************************************************************** **【函数名称】 request **【函数功能】 发出请求(命令方式) **【参数】 **【返回值】 ****************************************************************/ bool CMakeCallReq::request( void ) { // 校验状态 if(m_pHostLine->state() != VIRTUAL_LINE_STATE_FREE) return false; CString ExtenProxyNum; ExtenProxyNum.Format(_T("%lu"), m_pHostLine->lineId()); // 保存主被叫信息 m_CallerNum = m_ReqPdu.GetDataString(4); m_CalleeNum = m_ReqPdu.GetDataString(3); // 不能呼叫自己 if(ExtenProxyNum == m_CalleeNum) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{MakeCallReq}: 分机[%lu]呼叫请求执行失败, 禁止分机自呼"), m_pHostLine->lineId()); return false; } // 根据被叫号码查找对端线路且修正被叫号码 m_pAssoLine = m_pParent->setEnv4Calling(m_CallerNum, m_CalleeNum, m_PeerLineType, m_SipAccountId); if(m_pAssoLine == NULL) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{MakeCallReq}: 分机[%lu]呼叫请求执行失败, 无法找到对端线路, Caller=%s,Callee=%s"), m_pHostLine->lineId(), m_CallerNum, m_CalleeNum); return false; } // end if if(m_pAssoLine->type() == DEV_RES_TYPE_EXT) m_CallerNum = ExtenProxyNum; // 通知启动日志 LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, _T("{MakeCallReq}: 分机[%lu]执行呼叫请求,ExtenProxyNum=%s,Caller=%s,Callee=%s,PduCaller=%s,PduCallee=%s"), m_pHostLine->lineId(), ExtenProxyNum, m_CallerNum, m_CalleeNum, m_ReqPdu.GetDataString(4), m_ReqPdu.GetDataString(3)); // 启动分机外呼 return CMC::GetInstance().offHook(m_pHostLine->devId(), false, ExtenProxyNum); } /***************************************************************** **【函数名称】 request **【函数功能】 操作启动(话机方式) **【参数】 lpContent 被叫号码 **【返回值】 ****************************************************************/ bool CMakeCallReq::request( LPCTSTR lpContent ) { CString ExtenProxyNum; ExtenProxyNum.Format(_T("%lu"), m_pHostLine->lineId()); // 保存主被叫信息 m_CalleeNum.Format(_T("%s"), lpContent); // 如果呼叫自己 if(ExtenProxyNum == m_CalleeNum) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{MakeCallReq}: 分机[%lu]电话呼叫失败, 禁止分机自呼"), m_pHostLine->lineId()); return false; } // 根据被叫号码查找对端线路且修正被叫号码 m_pAssoLine = m_pParent->setEnv4Calling(m_CallerNum, m_CalleeNum, m_PeerLineType, m_SipAccountId); if(m_pAssoLine == NULL) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{MakeCallReq}: 分机[%lu]电话呼叫失败, 无法找到对端线路, DestNum = %s"), m_pHostLine->lineId(), m_CalleeNum); return false; } // end if if(m_pAssoLine->type() == DEV_RES_TYPE_EXT) { if(!m_pAssoLine->isIdle()) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{MakeCallReq}: 分机[%lu]电话呼叫失败, 对端线路非空闲, DestNum = %s"), m_pHostLine->lineId(), m_CalleeNum); return false; } m_CallerNum = ExtenProxyNum; } // 通知手动外呼启动事件 m_pParent->notifyLineOpEvent(m_pHostLine->lineId(), DEV_OP_CALL_OUT, m_CallerNum, m_CalleeNum); m_pHostLine->onLineStateChanged(0, 0, VIRTUAL_LINE_STATE_DIALING, m_CallerNum, m_CalleeNum); LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, _T("{MakeCallReq}: 分机[%lu]执行电话呼叫, DestNum = %s"), m_pHostLine->lineId(), m_CalleeNum); // 内线已摘机 m_Step = 1; // 开始呼叫 PendingCallInfo info; memset(&info, 0, sizeof(PendingCallInfo)); info.nCall = m_pHostLine->activeCallId(); info.nHostLine = m_pHostLine->devId(); info.nAssoLine = m_pAssoLine->devId(); lstrcpy(info.szCallerNum, m_CallerNum); lstrcpy(info.szCalleeNum, m_CalleeNum); info.nCallType = (m_PeerLineType == DEV_RES_TYPE_EXT) ? PENDING_CALL_DIRECT : PENDING_CALL_TRUNK; info.nHostLineStatus = VIRTUAL_LINE_STATE_FREE; info.nSipAccountId = m_SipAccountId; // 如果启动呼叫失败 if(!CSessionShell::GetInstance().procReqDialSetup(m_PendingCallId, &info)) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{MakeCallReq}: 分机[%lu]电话呼叫失败, 呼叫建立出错, DestNum = %s"), m_pHostLine->lineId(), m_CalleeNum); return false; } // end if return true; } /***************************************************************** **【函数名称】 hangUp **【函数功能】 操作中挂机(命令方式) **【参数】 **【返回值】 ****************************************************************/ bool CMakeCallReq::hangUp( long InstanceHangUp ) { // 外呼取消日志 LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, _T("{MakeCallReq}: 分机[%lu]呼叫因挂机而取消, DestNum = %s"), m_pHostLine->lineId(), m_CalleeNum); m_InstanceCancel = InstanceHangUp; DEV_RES_ID LineDrop = (m_Step == 0) ? m_pHostLine->devId() : m_pAssoLine->devId(); return CMC::GetInstance().dropCall(LineDrop, false); } /***************************************************************** **【函数名称】 end **【函数功能】 操作完成 **【参数】 IsSucceed 操作是否成功 lpData 随路数据 **【返回值】 ****************************************************************/ void CMakeCallReq::end( bool IsSucceed, LPCTSTR lpData ) { if(IsSucceed) { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, _T("{MakeCallReq}: 分机[%lu]呼叫成功, DestNum = %s"), m_pHostLine->lineId(), m_CalleeNum); } else { LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{MakeCallReq}: 分机[%lu]呼叫失败, DestNum = %s"), m_pHostLine->lineId(), m_CalleeNum); } // end if // 返回执行结果 if(m_InstanceCancel != 0) { m_pParent->notifyReqResult(m_ReqPdu, m_InstanceCancel, !IsSucceed, lpData); } // end if m_pParent->onLineReqEnd(this, IsSucceed, lpData); } /***************************************************************** **【函数名称】 setAssoInfo **【函数功能】 设置关联信息 **【参数】 nInfo 要关联的数据 **【返回值】 *****************************************************************/ void CMakeCallReq::setAssoInfo( CPduEntity& a_Req ) { m_InstanceCall = a_Req.GetDataLong(0); m_ReqPdu.SetLocalDevInfo(a_Req.GetLocalDevType(), a_Req.GetLocalDevId()); TRACE(_T("@CMakeCallReq::setAssoInfo\r\n")); } /***************************************************************** **【函数名称】 onDevChEvent **【函数功能】 线路向上层发送的设备主动事件 **【参数】 pEventLine 触发事件的线路 EvtType 事件类型 lpContent 事件内容 **【返回值】 *****************************************************************/ void CMakeCallReq::onDevChEvent( CVirtualProxy* pEventLine, DEV_CH_EVT_TYPE EvtType, LPCTSTR lpContent ) { } /***************************************************************** **【函数名称】 onLineStateChanged **【函数功能】 线路状态变化事件响应接口 **【参数】 pEventLine 状态变化的线路实体指针 LineState 线路当前状态 Call 主呼叫ID SubCall 子呼叫ID lpCallerNum 主叫号码 lpCalleeNum 被叫号码 **【返回值】 ****************************************************************/ void CMakeCallReq::onLineStateChanged( CVirtualProxy* pEventLine, VIRTUAL_LINE_STATE LineState, long Call, long SubCall, LPCTSTR lpCallerNum, LPCTSTR lpCalleeNum ) { // 可以开始呼叫 if(SubCall == SESSION_INVALID_SUB_CALL && LineState == VIRTUAL_LINE_STATE_INIT) { // 开始呼叫 PendingCallInfo info; memset(&info, 0, sizeof(PendingCallInfo)); info.nCall = m_pHostLine->activeCallId(); info.nHostLine = m_pHostLine->devId(); info.nAssoLine = m_pAssoLine->devId(); lstrcpy(info.szCallerNum, m_CallerNum); lstrcpy(info.szCalleeNum, m_CalleeNum); info.nCallType = (m_PeerLineType == DEV_RES_TYPE_EXT) ? PENDING_CALL_DIRECT : PENDING_CALL_TRUNK; info.nHostLineStatus = VIRTUAL_LINE_STATE_FREE; info.nSipAccountId = m_SipAccountId; // 启动外呼 if(CSessionShell::GetInstance().procReqDialSetup(m_PendingCallId, &info)) { m_Step = 1; } else { CMC::GetInstance().dropCall(m_pHostLine->devId(), false); return; } } // end if // 主叫方挂机 if(SubCall == SESSION_INVALID_SUB_CALL && LineState == VIRTUAL_LINE_STATE_FREE) { CMC::GetInstance().dropCall(m_pAssoLine->devId(), false); end(false, NULL); return; } // end if // 只处理子会话事件 if(SubCall != m_PendingCallId) return; // 根据子会话状态进行分类处理 switch(LineState) { case VIRTUAL_LINE_STATE_RING_BACK: // 呼叫进展 { _notifyOpProcess(m_pHostLine->lineId(), m_pAssoLine->lineId(), m_PeerLineType, lpCallerNum, lpCalleeNum); } break; case VIRTUAL_LINE_STATE_FREE: // 呼叫失败 { // 调用此操作将线路退出会话 CMC::GetInstance().dropCall(m_pHostLine->devId(), false); // 执行结果返回 end(false, NULL); } break; case VIRTUAL_LINE_STATE_TALKING: // 呼叫成功 { end(true, NULL); } break; } // end switch }