| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551 |
- #include "StdAfx.h"
- #include "SessionShell.h"
- #include "CallSession.h"
- #include "MC.h"
- #include "ProxyShell.h"
- SINGLETON_IMPLEMENT(CSessionShell)
- CSessionShell::CSessionShell(void) : m_pThreadObj(NULL), m_Stop(true), m_nBaseCallId(0)
- {
- m_mapCall.InitHashTable(4999);
- }
- CSessionShell::~CSessionShell(void)
- {
- __freeAllLineState();
- __freeAllCall();
- }
- /*****************************************************************
- **【函数名称】 __procLineStatus
- **【函数功能】 将事件队列中的事件进行分发处理
- **【参数】
- **【返回值】 当前队列中结余的事件数
- ****************************************************************/
- UINT CSessionShell::__procLineStatus( void )
- {
- int LeftCount = 0;
- LineState* pInfo = __popLineState(LeftCount);
- if(pInfo == NULL)
- return LeftCount;
- // 开始处理事件
- if(pInfo->nSession == SESSION_INVALID_CALL) // 状态变化的线路未在会话中
- {
- if((pInfo->nState == VIRTUAL_LINE_STATE_FREE ||
- pInfo->nState == VIRTUAL_LINE_STATE_DISABLED ||
- pInfo->nState == VIRTUAL_LINE_STATE_REMOVE))
- {
- // 不需启动会话,直接通知上层逻辑
- CProxyShell::GetInstance().onLineStateUpdated(pInfo->nLineDevId, SESSION_INVALID_CALL, SESSION_INVALID_SUB_CALL,
- pInfo->nState, pInfo->szCallerNum, pInfo->szCalleeNum);
- }
- else
- {
- CCallSession* pNewCall = __createCall(pInfo->nLineDevId); // 创建新会话
- pNewCall->onLineStateChanged(pInfo->nLineDevId, pInfo->nState, pInfo->szCallerNum, pInfo->szCalleeNum);
- } // end if(nDevState)
- }
- else // 线路在会话中
- {
- CCallSession* pCall = __getCall(pInfo->nSession);
- if(pCall != NULL)
- {
- pCall->onLineStateChanged(pInfo->nLineDevId, pInfo->nState, pInfo->szCallerNum, pInfo->szCalleeNum);
- // 是否清除会话
- if(pInfo->nState == VIRTUAL_LINE_STATE_FREE && pCall->lineCount() == 0)
- {
- __delCall(pInfo->nSession);
- pCall = NULL;
- } // end if
- }
- else
- {
- CProxyShell::GetInstance().onLineStateUpdated(pInfo->nLineDevId, SESSION_INVALID_CALL, SESSION_INVALID_SUB_CALL,
- pInfo->nState, pInfo->szCallerNum, pInfo->szCalleeNum);
- }
- } // end if
- // 处理完成
- delete pInfo;
- return LeftCount;
- }
- /*****************************************************************
- **【函数名称】 __wait
- **【函数功能】 置线程于等待信号状态
- **【参数】
- **【返回值】
- ****************************************************************/
- void CSessionShell::__wait( void )
- {
- m_ThreadWaitFlag.Lock();
- }
- /*****************************************************************
- **【函数名称】 __pushLineState
- **【函数功能】 存入一个线路状态事件
- **【参数】
- **【返回值】
- *****************************************************************/
- void CSessionShell::__pushLineState( LineState* pState )
- {
- m_Cs4LineStateEvent.Lock();
- m_listLineStatus.AddTail(pState);
- m_Cs4LineStateEvent.Unlock();
- }
- /*****************************************************************
- **【函数名称】 __popLineState
- **【函数功能】 弹出一个线路状态事件
- **【参数】
- **【返回值】
- *****************************************************************/
- LineState* CSessionShell::__popLineState( int& LeftCount )
- {
- LineState* pState = NULL;
- m_Cs4LineStateEvent.Lock();
- if((LeftCount = m_listLineStatus.GetCount()) > 0)
- {
- --LeftCount;
- pState = m_listLineStatus.RemoveHead();
- }
- m_Cs4LineStateEvent.Unlock();
- return pState;
- }
- /*****************************************************************
- **【函数名称】 __freeAllLineState
- **【函数功能】 释放所有线路状态事件
- **【参数】
- **【返回值】
- *****************************************************************/
- void CSessionShell::__freeAllLineState( void )
- {
- m_Cs4LineStateEvent.Lock();
- while(m_listLineStatus.GetCount() > 0)
- {
- delete m_listLineStatus.RemoveHead();
- }
- m_Cs4LineStateEvent.Unlock();
- }
- /*****************************************************************
- **【函数名称】 __createCall
- **【函数功能】 生成新会话
- **【参数】 HostLineId 会话的主控线路ID
- **【返回值】 新创建的会话实体指针
- *****************************************************************/
- CCallSession* CSessionShell::__createCall(CRDRID HostLineId)
- {
- CCallSession* pNewCall = NULL;
- m_Cs4Session.Lock();
- pNewCall = new CCallSession(++m_nBaseCallId);
- m_mapCall.SetAt(m_nBaseCallId, pNewCall);
- m_Cs4Session.Unlock();
- pNewCall->insertLine(HostLineId, CALL_PARTY_HOST, true); // 添加主控线路到会话
- return pNewCall;
- }
- /*****************************************************************
- **【函数名称】 __delCall
- **【函数功能】 删除会话
- **【参数】 会话ID
- **【返回值】
- *****************************************************************/
- void CSessionShell::__delCall( long CallId )
- {
- CCallSession* pCall = NULL;
- m_Cs4Session.Lock();
- if(m_mapCall.Lookup(CallId, pCall))
- {
- m_mapCall.RemoveKey(CallId);
- delete pCall;
- }
- m_Cs4Session.Unlock();
- }
- /*****************************************************************
- **【函数名称】 __GetCall
- **【函数功能】 查找指定的会话
- **【参数】 会话ID
- **【返回值】 指定ID的会话实体
- *****************************************************************/
- CCallSession* CSessionShell::__getCall(long CallId)
- {
- CCallSession* pCall = NULL;
- m_Cs4Session.Lock();
- m_mapCall.Lookup(CallId, pCall);
- m_Cs4Session.Unlock();
- return pCall;
- }
- /*****************************************************************
- **【函数名称】 __freeAllCall
- **【函数功能】 销毁所有会话
- **【参数】
- **【返回值】
- *****************************************************************/
- void CSessionShell::__freeAllCall( void )
- {
- m_Cs4Session.Lock();
- long CallId;
- CCallSession* pCall = NULL;
- POSITION Pos = m_mapCall.GetStartPosition();
- while(Pos != NULL)
- {
- m_mapCall.GetNextAssoc(Pos, CallId, pCall);
- ASSERT(pCall != NULL);
- delete pCall;
- }
- m_mapCall.RemoveAll();
- m_Cs4Session.Unlock();
- }
- /*****************************************************************
- **【函数名称】 __DispatchLineStatus
- **【函数功能】 分发线路状态事件的线程函数
- **【参数】
- **【返回值】
- ****************************************************************/
- UINT CSessionShell::__dispatchLineState(LPVOID pParam)
- {
- CSessionShell* pSelf = (CSessionShell*)pParam;
- ASSERT(pSelf != NULL);
- // 工作线程开始处理
- while(!pSelf->m_Stop)
- {
- pSelf->__wait();
- while(pSelf->__procLineStatus() > 0);
- } // end while
- return 0;
- }
- /*****************************************************************
- **【函数名称】 procReqDialSetup
- **【函数功能】 线路操作控制[临时呼叫启动]
- **【参数】 SubCall 当前操作关联的子会话ID(回传参数)
- pInfo 呼叫内容
- **【返回值】 操作启动是否成功
- *****************************************************************/
- bool CSessionShell::procReqDialSetup( long &SubCall, PendingCallInfo* pInfo )
- {
- CCallSession* pCall = NULL;
- if(pInfo->nCall == 0)
- pCall = __createCall(pInfo->nHostLine); // 创建新会话
- else
- pCall = __getCall(pInfo->nCall);
- ASSERT(pCall != NULL);
- if(pCall == NULL)
- return false;
- return pCall->setupPendingCall(SubCall, pInfo);
- }
- /*****************************************************************
- **【函数名称】 procReqLeave
- **【函数功能】 线路操作控制[指定线路退出会话且挂机]
- **【参数】 Call 线路要退出的会话
- LineId 线路ID
- **【返回值】 操作启动是否成功
- *****************************************************************/
- bool CSessionShell::procReqLeave( long Call, CRDRID LineId )
- {
- CCallSession* pCall = __getCall(Call);
- if(pCall == NULL)
- return false;
- return pCall->lineLeave(LineId);
- }
- /*****************************************************************
- **【函数名称】 procReqInstead
- **【函数功能】 线路操作控制[代接指定线路]
- **【参数】 Call 目标线路所在的会话
- HostLine 申请代接的线路
- PeerLine 被代接的线路
- ExtNum 申请代接线路的分机号
- **【返回值】 操作启动是否成功
- *****************************************************************/
- bool CSessionShell::procReqInstead( long Call, CRDRID HostLine, CRDRID PeerLine, UINT ExtNum )
- {
- CCallSession* pCall = __getCall(Call);
- if(pCall == NULL)
- return false;
- return pCall->lineInstead(HostLine, PeerLine, ExtNum);
- }
- /*****************************************************************
- **【函数名称】 procReqIntercept
- **【函数功能】 线路操作控制[替换通话中的线路]
- **【参数】 Call 目标线路所在的会话
- HostLine 主控线路
- PeerLine 被替换的线路
- **【返回值】 操作启动是否成功
- *****************************************************************/
- bool CSessionShell::procReqIntercept( long Call, CRDRID HostLine, CRDRID PeerLine )
- {
- CCallSession* pCall = __getCall(Call);
- if(pCall == NULL)
- return false;
- return pCall->lineIntercept(HostLine, PeerLine);
- }
- /*****************************************************************
- **【函数名称】 procReqInsert
- **【函数功能】 线路操作控制[插入通话中的线路]
- **【参数】 Call 线路要进入的会话
- HostLine 要进入会话的线路ID
- PeerLine 被插入线路的线路ID
- **【返回值】 操作启动是否成功
- *****************************************************************/
- bool CSessionShell::procReqInsert( long Call, CRDRID HostLine, CRDRID PeerLine )
- {
- CCallSession* pCall = __getCall(Call);
- if(pCall == NULL)
- return false;
- return pCall->lineInsert(HostLine, PeerLine);
- }
- /*****************************************************************
- **【函数名称】 procReqListen
- **【函数功能】 线路操作控制[监听通话中的线路]
- **【参数】 Call 目标线路所在的会话
- HostLine 主控线路
- PeerLine 被监听的线路
- **【返回值】 操作启动是否成功
- *****************************************************************/
- bool CSessionShell::procReqListen( long Call, CRDRID HostLine, CRDRID PeerLine )
- {
- CCallSession* pCall = __getCall(Call);
- if(pCall == NULL)
- return false;
- return pCall->lineListen(HostLine, PeerLine);
- }
- /*****************************************************************
- **【函数名称】 procReqRecord
- **【函数功能】 线路操作控制[录音启动]
- **【参数】 Call 目标线路所在的会话
- HostLine 主控线路
- lpFileName 录音文件名
- **【返回值】 操作启动是否成功
- *****************************************************************/
- bool CSessionShell::procReqRecord( long Call, CRDRID HostLine, LPCTSTR lpFileName )
- {
- CCallSession* pCall = __getCall(Call);
- if(pCall == NULL)
- return false;
- return pCall->lineRecord(HostLine, lpFileName);
- }
- /*****************************************************************
- **【函数名称】 procReqLeaveWord
- **【函数功能】 线路操作控制[留言启动]
- **【参数】 Call 目标线路所在的会话
- HostLine 主控线路
- pContent 留言参数
- **【返回值】 操作启动是否成功
- *****************************************************************/
- bool CSessionShell::procReqLeaveWord( long Call, CRDRID HostLine, RecordContent* pContent )
- {
- CCallSession* pCall = __getCall(Call);
- if(pCall == NULL)
- return false;
- return pCall->lineLeaveWord(HostLine, pContent);
- }
- /*****************************************************************
- **【函数名称】 procReqMute
- **【函数功能】 线路操作控制[静音控制]
- **【参数】 Call 目标线路所在的会话
- HostLine 主控线路
- **【返回值】 操作启动是否成功
- *****************************************************************/
- bool CSessionShell::procReqMute( long Call, CRDRID HostLine, bool IsOn )
- {
- CCallSession* pCall = __getCall(Call);
- if(pCall == NULL)
- return false;
- return pCall->lineMute(HostLine, IsOn);
- }
- /*****************************************************************
- **【函数名称】 procReqConsultConfirm
- **【函数功能】 线路操作控制[协商呼叫]
- **【参数】 Call 目标线路所在的会话
- HostLine 主控线路
- PeerLine 被叫线路
- Type 会话类型 0 -> 转移,1 -> 会议
- **【返回值】 操作是否成功
- *****************************************************************/
- bool CSessionShell::procReqConsultConfirm( long Call, CRDRID HostLine, CRDRID PeerLine, int Type )
- {
- CCallSession* pCall = __getCall(Call);
- if(pCall == NULL)
- return false;
- return pCall->lineConsultConfirm(PeerLine, Type);
- }
- /*****************************************************************
- **【函数名称】 onDevResourceNew
- **【函数功能】 线路初始化
- **【参数】
- **【返回值】
- *****************************************************************/
- void CSessionShell::onDevResourceNew( CRDRID Id )
- {
- // 转发初始化线路信息至ClientProxy
- CProxyShell::GetInstance().onLineNew(Id);
- }
- /*****************************************************************
- **【函数名称】 onDevResourceDel
- **【函数功能】 线路逆初始化
- **【参数】
- **【返回值】
- *****************************************************************/
- void CSessionShell::onDevResourceDel( CRDRID Id )
- {
- // 转发删除线路信息至ClientProxy
- CProxyShell::GetInstance().onLineDelete(Id);
- }
- /*****************************************************************
- **【函数名称】 OnLineStateChanged
- **【函数功能】 线路状态变化
- **【参数】 Id 线路设备ID
- Session 物理线路关联的主呼叫ID
- State 线路当前状态(ACS_LINE_STATUS)
- Caller 主叫号码
- Callee 被叫号码
- **【返回值】
- *****************************************************************/
- void CSessionShell::onLineStateChanged( CRDRID Id, long Session, VIRTUAL_LINE_STATE State, LPCTSTR Caller, LPCTSTR Callee )
- {
- // 填充事件内容
- LineState* pInfo = new LineState;
- memset(pInfo, 0, sizeof(LineState));
- pInfo->nLineDevId = Id;
- pInfo->nSession = Session;
- pInfo->nState = State;
- if(Caller != NULL)
- lstrcpy(pInfo->szCallerNum, Caller);
- if(Callee != NULL)
- lstrcpy(pInfo->szCalleeNum, Callee);
- __pushLineState(pInfo);
- // 需要唤醒分发线程
- m_ThreadWaitFlag.SetEvent();
- }
- /*****************************************************************
- **【函数名称】 onLineChannelEvent
- **【函数功能】 线路向上层发送的设备主动事件
- **【参数】 Id 触发事件的线路ID
- Session 线路所在的会话
- EvtType 事件类型
- lpContent 事件内容
- **【返回值】
- *****************************************************************/
- bool CSessionShell::onLineChannelEvent( CRDRID Id, long Session, DEV_CH_EVT_TYPE EvtType, LPCTSTR lpContent, UINT ExtenId /*= 0*/ )
- {
- switch(EvtType)
- {
- case DEV_CH_EVT_FUN_CODE: // 收取功能键
- 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_HOLD_ON: // 保持
- case DEV_CH_EVT_TAKE_BACK: // 接回
- case DEV_CH_EVT_CALL_FAILD_CAUSE: // 呼叫失败原因
- {
- return CProxyShell::GetInstance().onDevChannelEvent(Id, EvtType, lpContent, ExtenId);
- }
- break;
- case DEV_CH_EVT_REC_END: // 录音完成
- {
- CCallSession* pSession = __getCall(Session);
- ASSERT(pSession != NULL);
- if(pSession != NULL)
- pSession->onRecordStop(Id, atoi(lpContent));
- }
- break;
- } // end switch
- return true;
- }
- /*****************************************************************
- **【函数名称】 start
- **【函数功能】 启动
- **【参数】
- **【返回值】
- ****************************************************************/
- void CSessionShell::start( void )
- {
- m_Stop = false;
- m_pThreadObj = AfxBeginThread(__dispatchLineState, this); // 启动事件处理线程
- LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, _T("{SessionShell}: 会话管理器启动"));
- }
- /*****************************************************************
- **【函数名称】 stop
- **【函数功能】 停止
- **【参数】
- **【返回值】
- ****************************************************************/
- void CSessionShell::stop( void )
- {
- m_Stop = true;
- if(m_pThreadObj != NULL)
- {
- DWORD ExitCode;
- GetExitCodeThread(m_pThreadObj->m_hThread, &ExitCode);
- if(ExitCode == STILL_ACTIVE)
- {
- m_ThreadWaitFlag.SetEvent();
- WaitForSingleObject(m_pThreadObj->m_hThread, INFINITE);
- }
- m_pThreadObj = NULL;
- }
- __freeAllLineState();
- __freeAllCall();
- }
|