#include "StdAfx.h" #include "CallSession.h" #include "LogicLine.h" #include "Record.h" #include "TaskMgr.h" #include "IvrFlow.h" #include "IvrFlowHolder.h" #include "StatisticsMgr.h" #include "LineHolder.h" #include "CtiCore.h" CCallSession::CCallSession(ULONG CallId) : m_CallId(CallId), m_RecFile(_T("")), m_Data(_T("")) { } CCallSession::~CCallSession(void) { } /***************************************************************** **【函数名称】 __procLineRecord **【函数功能】 处理线路录音 **【参数】 pRecLine: 录音线路 RecFile:录音文件 **【返回值】 ****************************************************************/ void CCallSession::__procLineRecord( CLogicLine* pRecLine, CString& RecFile ) { // 设置会话中录音文件名 m_RecFile = RecFile; // 设置录音线路的录音文件名 pRecLine->setRecordFile(RecFile); // 设置关联线路的录音文件名 CLogicLine* pLine = NULL; CLineHolder& LineHolder = CLineHolder::GetInstance(); POSITION pos = m_LineList.GetHeadPosition(); while(pos != NULL) { pLine = LineHolder.getLogicLine(m_LineList.GetNext(pos)); ASSERT(pLine != NULL); if(pLine != NULL && pRecLine->type() != pLine->type() && pLine->recordFile() == _T("")) pLine->setRecordFile(RecFile); } } /***************************************************************** **【函数名称】 __onLineTalking **【函数功能】 开始通话后的处理函数 **【参数】 pLine:通话线路 **【返回值】 ****************************************************************/ void CCallSession::__onLineTalking( CLogicLine* pLine ) { ASSERT(pLine != NULL); //如果是监听 不再产生录音文件文件路径 if (pLine->opType() == PDU_CMD_AGENT_MONI_LISTEN) return; // 对该线路进行录音处理 CString RecFile = ""; if(CRecord::GetInstance().record(pLine, RecFile)) __procLineRecord(pLine, RecFile); else pLine->setRecordFile(m_RecFile); } /***************************************************************** **【函数名称】 __onLineHangUp **【函数功能】 处理线路挂机(离开会话) **【参数】 pLine:通话线路 **【返回值】 ****************************************************************/ void CCallSession::__onLineHangUp( CLogicLine* pLine ) { // 通知IVR线路挂机 if (pLine->type() == DEV_RES_TYPE_TRUNK || pLine->type() == DEV_RES_TYPE_VOIP) { // 显示日志 ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, _T("{CallSession}: [外线挂机], Trunk = %d,CallId = %d,caller=%s,callee=%s"), pLine->lineId(), m_CallId, pLine->callerNum(), pLine->calleeNum()); // 通知IVR外线挂机 CIvrFlow* pIvrFlow = CIvrFlowHolder::GetInstance().getFlowByLineId(pLine->lineId()); if (pIvrFlow != NULL) { ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, _T("{CallSession}: [外线挂机], Trunk = %d,IvrFlow_assoLineId=%d"), pLine->lineId(), pIvrFlow->assoLineId()); pIvrFlow->procLineHangUp(); } if (pLine->opType() != PDU_CMD_AGENT_FAX && pLine->opType() != PDU_CMD_IVR_FAX) { // 通知外线关联Task销毁,不在向IVR发返回消息 CTaskMgr::GetInstance().removeTask(pLine->taskIdBinded()); } } // 统计挂机 T_EvtHangUp repInfo; memset(&repInfo, 0, sizeof(repInfo)); repInfo.nHangUpFlag = (m_LineList.GetCount() > 1 ? 0:1); // 0本端先挂机 1对端先挂机 CStatisticsMgr::GetInstance().onCallDetail(m_CallId, REP_EVENT_HANG_UP, pLine->lineId(), &repInfo); // 移除线路 POSITION pos = m_LineList.Find(pLine->lineId()); if(pos != NULL) m_LineList.RemoveAt(pos); // 任务(协商转移)失败时,不重置发起方的逻辑线路信息 if (pLine->opResult() == FALSE && pLine->opType() == PDU_CMD_AGENT_CONSULTATION_CALL) pLine->opType() = PDU_CMD_UNKNOWN; else pLine->resetLine(); // 重置线路信息 } void CCallSession::__onLineTrunkTransfer(CLogicLine* pHostLine) { // 统计外线连通的时间,需要保证外线转分机的时候有内线接通状态的相关数据值 by ; } // 更新相对应的外线记录表中的数据 by void CCallSession::__onLineTrunkTransferCrd() { ; } /***************************************************************** **【函数名称】 getAssoLineExt **【函数功能】 获取指定线路的关联线路 **【参数】 pHostLine:指定线路 **【返回值】 关联线路对象 ****************************************************************/ CLogicLine* CCallSession::getAssoLine( CLogicLine* pHostLine ) { if(m_LineList.GetCount() < 2) return NULL; CLineHolder& LineHolder = CLineHolder::GetInstance(); POSITION pos = m_LineList.GetHeadPosition(); while(pos != NULL) { CLogicLine* pLine = LineHolder.getLogicLine(m_LineList.GetNext(pos)); ASSERT(pLine != NULL); if(pLine != NULL && pLine != pHostLine) return pLine; } return NULL; } /***************************************************************** **【函数名称】 addLine **【函数功能】 会话中添加线路 **【参数】 pLine: 待添加线路 **【返回值】 ****************************************************************/ void CCallSession::addLine( CLogicLine *pLine ) { ASSERT(pLine != NULL); if(pLine == NULL) return; if(m_LineList.Find(pLine->lineId()) != NULL) return; m_LineList.AddTail(pLine->lineId()); pLine->callId() = m_CallId; } /***************************************************************** **【函数名称】 onLineStatusUpdated **【函数功能】 处理线路状态改变 **【参数】 pLine: 状态变化的线路 **【返回值】 ****************************************************************/ void CCallSession::onLineStatusUpdated( CLogicLine* pLine ) { // 保持状态过滤 UINT Status = (HELD_STATE_FILTER_MASK & pLine->status()); ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, _T("{CallSession}:onLineStatusUpdated, Trunk = %d,CallId = %d,Status=%d"), pLine->lineId(), m_CallId, Status); // 通话 if(Status == TRUNK_STATE_TALKING || Status == INNER_STATE_TALKING) { // 有至少两个线路通话时才录音 /*CLogicLine* pTempLine = NULL; CLineHolder& LineHolder = CLineHolder::GetInstance(); POSITION pos = m_LineList.GetHeadPosition(); while(pos)*/ { /*pTempLine = LineHolder.getLogicLine(m_LineList.GetNext(pos)); ASSERT(pTempLine != NULL); if(pTempLine == NULL || pTempLine == pLine) continue; UINT nTempStatus = (HELD_STATE_FILTER_MASK & pTempLine->status()); if(nTempStatus == INNER_STATE_TALKING || nTempStatus == TRUNK_STATE_TALKING) { __onLineTalking(pLine); __onLineTalking(pTempLine); break; }*/ // by 修改分支对应的录音 CLogicLine* pTempLine = NULL; CLineHolder& LineHolder = CLineHolder::GetInstance(); POSITION pos = m_LineList.GetHeadPosition(); while (pos) { pTempLine = LineHolder.getLogicLine(m_LineList.GetNext(pos)); ASSERT(pTempLine != NULL); if (pTempLine == NULL || pTempLine == pLine) continue; UINT nTempStatus = (HELD_STATE_FILTER_MASK & pTempLine->status()); if (nTempStatus == INNER_STATE_TALKING || nTempStatus == TRUNK_STATE_FREE) { __onLineTalking(pLine); __onLineTalking(pTempLine); break; } } } if (Status == INNER_STATE_TALKING) { // 需要修改通话时的操作代码保证分机能够成功 by // 增加相关的cdr的内线通话时的相关字段数据记录 // 获取转分机接通之后的外线线路 CCtiCore::GetInstance().getDevLink().exec((long)-1, LINE_OP_PLAY_VOICE, atoi(pLine->calleeNum()), NULL); } } // 空闲状态当挂机处理 by 屏蔽了挂机操作 /*if (Status == TRUNK_STATE_FREE || Status == INNER_STATE_FREE) __onLineHangUp(pLine); */ } void CCallSession::onRecord(CLogicLine* pLine) { //ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_NORMAL, _T("{CallSession},onRecord")); CLogicLine* pTempLine = NULL; CLineHolder& LineHolder = CLineHolder::GetInstance(); POSITION pos = m_LineList.GetHeadPosition(); while (pos) { pTempLine = LineHolder.getLogicLine(m_LineList.GetNext(pos)); ASSERT(pTempLine != NULL); if (pTempLine == NULL || pTempLine == pLine) continue; UINT nTempStatus = (HELD_STATE_FILTER_MASK & pTempLine->status()); if (nTempStatus == INNER_STATE_TALKING || nTempStatus == TRUNK_STATE_TALKING) { ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_NORMAL, _T("{CallSession},onRecord,%d"), nTempStatus); __onLineTalking(pLine); __onLineTalking(pTempLine); break; } else { ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_NORMAL, _T("{CallSession},onRecord,nTempStatus=%d"), nTempStatus); } } }