| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169 |
- #include "StdAfx.h"
- #include "FsProxy.h"
- #include "ChanExten.h"
- #include "ChanTrunk.h"
- #include "Session.h"
- #include "OperationReactor.h"
- #include "../../IVR/IvrSysInc.h"
- SINGLETON_IMPLEMENT(CFsProxy)
- CFsProxy::CFsProxy(void) : m_Gateway(this), m_pEventHandler(NULL)
- {
- }
- CFsProxy::~CFsProxy(void)
- {
- }
- /*****************************************************************
- **【函数名称】 __transLogicState2CtiState
- **【函数功能】 将逻辑状态转换为CTI识别的状态
- **【参数】
- **【返回值】
- ****************************************************************/
- UINT CFsProxy::__transLogicState2CtiState( DEV_RES_TYPE ChanType, CHAN_LOGIC_STATE State )
- {
- if(ChanType == DEV_RES_TYPE_EXT)
- {
- UINT HoldMask = State & HELD_STATE_IND_MASK;
- switch(State & HELD_STATE_FILTER_MASK)
- {
- case CHAN_LOGIC_STATE_DISABLED: return INNER_STATE_DISABLED; // 不可用
- case CHAN_LOGIC_STATE_FREE: return INNER_STATE_FREE | HoldMask; // 空闲
- case CHAN_LOGIC_STATE_INIT: return INNER_STATE_INIT | HoldMask; // 摘机等待拨号
- case CHAN_LOGIC_STATE_DIALING: return INNER_STATE_DIALING | HoldMask; // 拨号
- case CHAN_LOGIC_STATE_RING_BACK: return INNER_STATE_RING_BACK | HoldMask; // 呼出振铃
- case CHAN_LOGIC_STATE_ALERTING: return INNER_STATE_ALERTING | HoldMask; // 来电振铃
- case CHAN_LOGIC_STATE_TALKING: return INNER_STATE_TALKING | HoldMask; // 通话中
- default:
- ASSERT(FALSE);
- return INNER_STATE_DISABLED;
- }
- }
- else
- {
- switch(State)
- {
- case CHAN_LOGIC_STATE_DISABLED: return TRUNK_STATE_DISABLED; // 不可用
- case CHAN_LOGIC_STATE_FREE: return TRUNK_STATE_FREE; // 空闲
- case CHAN_LOGIC_STATE_DIALING: return TRUNK_STATE_DIALING; // 拨号
- case CHAN_LOGIC_STATE_RING_BACK: return TRUNK_STATE_RING_BACK; // 呼出振铃
- case CHAN_LOGIC_STATE_ALERTING: return TRUNK_STATE_ALERTING; // 来电振铃
- case CHAN_LOGIC_STATE_STANDBY:
- case CHAN_LOGIC_STATE_TALKING: return TRUNK_STATE_TALKING; // 通话中
- default:
- ASSERT(FALSE);
- return TRUNK_STATE_UNKNOWN;
- }
- }
- }
- /*****************************************************************
- **【函数名称】 __addExten
- **【函数功能】 添加分机
- **【参数】
- **【返回值】
- ****************************************************************/
- void CFsProxy::__addExten( UINT ExtenNo )
- {
- CChanExten* pExten = new CChanExten(this, ExtenNo);
- m_MapChanExt.SetAt(ExtenNo, pExten);
- pExten->regist();
- }
- /*****************************************************************
- **【函数名称】 delExten
- **【函数功能】 删除分机
- **【参数】
- **【返回值】
- ****************************************************************/
- void CFsProxy::__delExten( UINT ExtenNo )
- {
- CChanExten* pExten = NULL;
- if(m_MapChanExt.Lookup(ExtenNo, pExten))
- {
- if(pExten->isFree())
- {
- m_MapChanExt.RemoveKey(ExtenNo);
- FS_LINK_DELETE(pExten);
- }
- else pExten->discard(true);
- }
- }
- /*****************************************************************
- **【函数名称】 __freeExten
- **【函数功能】 清空分机
- **【参数】
- **【返回值】
- ****************************************************************/
- void CFsProxy::__freeExten( void )
- {
- UINT ExtenNo = 0;
- CChanExten* pExten = NULL;
- POSITION Pos = m_MapChanExt.GetStartPosition();
- while(Pos != NULL)
- {
- m_MapChanExt.GetNextAssoc(Pos, ExtenNo, pExten);
- FS_LINK_DELETE(pExten);
- }
- m_MapChanExt.RemoveAll();
- }
- /*****************************************************************
- **【函数名称】 __initTrunkChan
- **【函数功能】 初始化中继通道
- **【参数】
- **【返回值】
- ****************************************************************/
- void CFsProxy::__initTrunkChan( void )
- {
- for(int i = 1; i <= CConfig::trunkCount(); ++i)
- {
- CChanTrunk* pTrunk = new CChanTrunk(this, i);
- m_ArrayTrunk.Add(pTrunk);
- pTrunk->regist();
- }
- }
- /*****************************************************************
- **【函数名称】 __freeTrunkChan
- **【函数功能】 清空中继通道
- **【参数】
- **【返回值】
- ****************************************************************/
- void CFsProxy::__freeTrunkChan( void )
- {
- CChanTrunk* pTrunk = NULL;
- for(int i = 0; i < m_ArrayTrunk.GetCount(); ++i)
- {
- pTrunk = m_ArrayTrunk[i];
- FS_LINK_DELETE(pTrunk);
- }
- m_ArrayTrunk.RemoveAll();
- }
- /*****************************************************************
- **【函数名称】 __getSession
- **【函数功能】 查找会话
- **【参数】
- **【返回值】
- ****************************************************************/
- CSession* CFsProxy::__getSession( PCHAN_EVENT_NOTIFY pNotify, bool NewWhenNull /*= false*/ )
- {
- CSession* pSession = __getSession(pNotify->CallId);
-
- if(pSession == NULL && NewWhenNull)
- {
- pSession = new CSession(this, pNotify->CallId);
- pSession->prepare(pNotify);
- m_MapSession.SetAt(pNotify->CallId, pSession);
- std::cout << "m_MapSession.SetAt" << pNotify->CallId << endl;
- std::cout << "m_MapSession.SetAt" << pSession->id() << endl;
- LOGGER(LOG_LEVEL_NORMAL,_T("{CFsProxy}:Add Session[%s],ChanId[%s],EventId[%d],CallID[%s]"), pSession->id(), pNotify->ChanId, pNotify->EventId,pNotify->CallId);
- }
- return pSession;
- }
- /*****************************************************************
- **【函数名称】 __getSession
- **【函数功能】 查找会话
- **【参数】
- **【返回值】
- ****************************************************************/
- CSession* CFsProxy::__getSession( LPCTSTR SessionId )
- {
- CSession* pSession = NULL;
- m_MapSession.Lookup(SessionId, pSession);
- std::cout << "__getSession" << SessionId << endl;
- return pSession;
- }
- /*****************************************************************
- **【函数名称】 __delSession
- **【函数功能】 删除会话
- **【参数】
- **【返回值】
- ****************************************************************/
- void CFsProxy::__delSession( LPCTSTR SessionId )
- {
- if (SessionId == NULL)
- return;
- CSession* pSession = NULL;
- if(m_MapSession.Lookup(SessionId, pSession))
- {
- m_MapSession.RemoveKey(SessionId);
- LOGGER(LOG_LEVEL_NORMAL, _T("{FsProxy}: Delete Session[%s]"), pSession->id());
- FS_LINK_DELETE(pSession);
- }
- }
- /*****************************************************************
- **【函数名称】 __freeSession
- **【函数功能】 清空会话
- **【参数】
- **【返回值】
- ****************************************************************/
- void CFsProxy::__freeSession( void )
- {
- CString SessionId = 0;
- CSession* pSession = NULL;
- POSITION Pos = m_MapSession.GetStartPosition();
- while(Pos != NULL)
- {
- m_MapSession.GetNextAssoc(Pos, SessionId, pSession);
- FS_LINK_DELETE(pSession);
- }
- m_MapSession.RemoveAll();
- }
- /*****************************************************************
- **【函数名称】 __kill
- **【函数功能】 挂断通道
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CFsProxy::__kill( LONG JobId, LPCTSTR ChanId )
- {
- CString EslCmd;
- if(JobId == FS_LINK_JOBID_INVALID)
- EslCmd.Format(_T("bgapi uuid_kill %s"), ChanId);
- else
- EslCmd.Format(_T("bgapi uuid_kill %s\r\n%s: %ld"), ChanId, ESL_HEADER_JOB_UUID, JobId);
- return m_Gateway.sendCmd(EslCmd);
- }
- /*****************************************************************
- **【函数名称】 init
- **【函数功能】 初始化
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CFsProxy::init( IEslEventHandler* pEventHandler )
- {
- ASSERT(pEventHandler != NULL);
- m_pEventHandler = pEventHandler;
- __initTrunkChan();
- if(m_Gateway.start())
- {
- m_Gateway.hangupAll();
- if(m_Gateway.scanExten())
- {
- LOGGER(LOG_LEVEL_NORMAL, _T("{FsProxy}: FreeSWITCH代理初始化成功"));
- return true;
- }
- else
- {
- LOGGER(LOG_LEVEL_ERROR, _T("{FsProxy}: FreeSWITCH代理初始化失败, 扫描分机资源失败"));
- return false;
- }
- }
- else
- {
- LOGGER(LOG_LEVEL_ERROR, _T("{FsProxy}: FreeSWITCH代理初始化失败, ESL网关启动失败"));
- m_pEventHandler = NULL;
- return false;
- }
- }
- /*****************************************************************
- **【函数名称】 release
- **【函数功能】 释放资源
- **【参数】
- **【返回值】
- ****************************************************************/
- void CFsProxy::release( void )
- {
- // by 临时添加的esl_handle_t句柄
- esl_handle_t m_EslHandle;
- esl_disconnect(&m_EslHandle);
- m_Gateway.stop();
- __freeSession();
- __freeExten();
- __freeTrunkChan();
- }
- /*****************************************************************
- **【函数名称】 onChanRegist
- **【函数功能】 通道注册的处理函数
- **【参数】
- **【返回值】
- ****************************************************************/
- void CFsProxy::onChanRegist( DEV_RES_TYPE ChanType, UINT ChanNo, CHAN_LOGIC_STATE ChanState )
- {
- CDevControl::GetInstance().onEventResDetail(ChanType, ChanNo);
- CDevControl::GetInstance().onEventResState(ChanType, ChanNo, __transLogicState2CtiState(ChanType, ChanState));
- }
- /*****************************************************************
- **【函数名称】 onExtenDestroy
- **【函数功能】 分机销毁的处理函数
- **【参数】
- **【返回值】
- ****************************************************************/
- void CFsProxy::onExtenDestroy( UINT ExtenNo )
- {
- CDevControl::GetInstance().onEventResState(DEV_RES_TYPE_EXT, ExtenNo, INNER_STATE_REMOVE);
- }
- /*****************************************************************
- **【函数名称】 onExtenDirectOp
- **【函数功能】 分机直接操作启动
- **【参数】 OpType 启动的操作类型
- pHostChan 触发事件的通道
- pNotify 触发操作事件内容
- **【返回值】
- ****************************************************************/
- void CFsProxy::onExtenDirectOp( DEV_OP OpType, CVirtualChan* pHostChan, PCHAN_EVENT_NOTIFY pNotify )
- {
- switch(OpType)
- {
- case DEV_OP_CALL_OUT:
- {
- if(!COperationReactor::GetInstance().onExtenCallFromDev(pHostChan, pNotify))
- __kill(FS_LINK_JOBID_INVALID, pHostChan->chanId());
- }
- break;
- } // end switch
- }
- /*****************************************************************
- **【函数名称】 onChanStateUpdate
- **【函数功能】 通道状态更新处理
- **【参数】
- **【返回值】
- *****************************************************************/
- void CFsProxy::onChanStateUpdate( LONG OpInstance, CVirtualChan* pChan )
- {
- if(OpInstance != FS_LINK_INSTANCE_INVALID)
- m_pEventHandler->onEslEvtChanState(OpInstance, pChan);
- CDevControl::GetInstance().onEventResState(pChan->type(), pChan->no(), __transLogicState2CtiState(pChan->type(), pChan->state()), pChan->callerNum(), pChan->calleeNum());
- }
- /*****************************************************************
- **【函数名称】 onChanPoor
- **【函数功能】 空闲通道枯竭处理
- **【参数】
- **【返回值】
- *****************************************************************/
- void CFsProxy::onChanPoor( CSession* pSession, PCHAN_EVENT_NOTIFY pNotify )
- {
- __kill(FS_LINK_JOBID_INVALID, pNotify->ChanId);
- }
- /*****************************************************************
- **【函数名称】 onTrunkCallIn
- **【函数功能】 中继呼入
- **【参数】
- **【返回值】
- *****************************************************************/
- void CFsProxy::onTrunkCallIn( CChanTrunk* pTrunk )
- {
- CDevControl::GetInstance().onEventDevOperation(pTrunk->no(), DEV_OP_CALL_IN, pTrunk->callerNum(), pTrunk->calleeNum());
- }
- /*****************************************************************
- **【函数名称】 onEslDisconnect
- **【函数功能】 ESL连接中断处理
- **【参数】
- **【返回值】
- *****************************************************************/
- void CFsProxy::onEslDisconnect( void )
- {
- CDevControl::GetInstance().onEventDevDown();
- }
- /*****************************************************************
- **【函数名称】 onEslSipReg
- **【函数功能】 分机注册的处理函数
- **【参数】
- **【返回值】
- ****************************************************************/
- void CFsProxy::onEslExtenReg( UINT ExtenNo )
- {
- CChanExten* pExten = getExten(ExtenNo);
- if(pExten == NULL)
- {
- __addExten(ExtenNo);
- }
- else
- {
- if(pExten->isVoid()) // 若被丢弃,则改变丢弃状态
- pExten->discard(false);
- }
- #ifdef _DEBUG
- LOGGER(LOG_LEVEL_NORMAL, _T("{FsProxy}: 分机[%u]注册"), ExtenNo);
- #endif
- }
- /*****************************************************************
- **【函数名称】 onEslExtenUnreg
- **【函数功能】 分机注销的处理函数
- **【参数】
- **【返回值】
- ****************************************************************/
- void CFsProxy::onEslExtenUnreg( UINT ExtenNo )
- {
- __delExten(ExtenNo);
- #ifdef _DEBUG
- LOGGER(LOG_LEVEL_NORMAL, _T("{FsProxy}: 分机[%u]注销"), ExtenNo);
- #endif
- }
- /*****************************************************************
- **【函数名称】 onEslGwExten
- **【函数功能】 网关分机的处理函数
- **【参数】
- **【返回值】
- ****************************************************************/
- void CFsProxy::onEslGwExtenReg(LPCTSTR ExtenNo, LPCTSTR Ip)
- {
- m_MapAddrGwExt.SetAt(ExtenNo, Ip);
- return;
- }
- void CFsProxy::onEslGwExtenUnreg(LPCTSTR ExtenNo)
- {
- CString t_ip;
- if (m_MapAddrGwExt.Lookup(ExtenNo, t_ip))
- {
- t_ip.Empty();
- m_MapAddrGwExt.RemoveKey(ExtenNo);
- }
- }
- /*****************************************************************
- **【函数名称】 onEslEvtBgJobDone
- **【函数功能】 后台任务执行结束事件处理
- **【参数】
- **【返回值】
- *****************************************************************/
- void CFsProxy::onEslEvtBgJobDone( PBG_JOB_NOTIFY pNotify )
- {
- ASSERT(m_pEventHandler != NULL);
- m_pEventHandler->onEslEvtBgJobDone(pNotify);
- }
- /*****************************************************************
- **【函数名称】 onEslEvtChannel
- **【函数功能】 通道事件处理
- **【参数】
- **【返回值】
- *****************************************************************/
- void CFsProxy::onEslEvtChannel( PCHAN_EVENT_NOTIFY pNotify )
- {
- ASSERT(pNotify != NULL);
- if (pNotify == NULL)
- return;
- CSession* pSession = __getSession(pNotify, true);
- ASSERT(pSession != NULL);
- if (pSession == NULL)
- {
- LOGGER(LOG_LEVEL_WARNING, _T("{FsProxy}: 通道事件,没有找到会话,EslEventId=%d,ChanId[%s],CallId[%s],Caller[%s],Callee[%s]"), pNotify->EventId, pNotify->ChanId, pNotify->CallId, pNotify->Caller, pNotify->Callee);
- return;
- }
- else
- {
- std::cout << "m_MapSession.SetAt" << pNotify->CallId << endl;
- std::cout << "m_MapSession.SetAt" << pSession->id() << endl;
- }
- __try {
- pSession->onChanEvent(pNotify);
- if (pSession->isVoid())
- __delSession(pSession->id());
- }
- __except (EXCEPTION_EXECUTE_HANDLER)
- {
- LOGGER(LOG_LEVEL_WARNING, _T("{FsProxy}: 处理通道事件时异常[%u],EslEventId=%d,ChanId[%s],CallId[%s],Caller[%s],Callee[%s]"), GetExceptionCode(), pNotify->EventId, pNotify->ChanId, pNotify->CallId, pNotify->Caller, pNotify->Callee);
- __delSession(pSession->id());
- }
- }
- /*****************************************************************
- **【函数名称】 onEslEvtDtmf
- **【函数功能】 DTMF事件处理
- **【参数】
- **【返回值】
- *****************************************************************/
- void CFsProxy::onEslEvtDtmf( PDTMF_NOTIFY pNotify )
- {
- ASSERT(pNotify != NULL);
- CSession* pSession = __getSession(pNotify->CallId);
- ASSERT(pSession != NULL);
- if(pSession != NULL)
- pSession->onChanDtmf(pNotify);
- }
- /*****************************************************************
- **【函数名称】 onEslEvtHold
- **【函数功能】 保持事件处理
- **【参数】
- **【返回值】
- *****************************************************************/
- void CFsProxy::onEslEvtHold( PHOLD_NOTIFY pNotify )
- {
- ASSERT(pNotify != NULL);
- CSession* pSession = __getSession(pNotify->CallId);
- ASSERT(pSession != NULL);
- if(pSession != NULL)
- pSession->onChanHold(pNotify);
- }
- /*****************************************************************
- **【函数名称】 getExten
- **【函数功能】 查找分机
- **【参数】
- **【返回值】
- ****************************************************************/
- CChanExten* CFsProxy::getExten( UINT ExtenNo )
- {
- CChanExten* pExten = NULL;
- m_MapChanExt.Lookup(ExtenNo, pExten);
- return pExten;
- }
- /*****************************************************************
- **【函数名称】 getTrunk
- **【函数功能】 查找中继
- **【参数】
- **【返回值】
- ****************************************************************/
- CChanTrunk* CFsProxy::getTrunk( UINT TrunkNo )
- {
- if (TrunkNo <= 0 || TrunkNo > (UINT)m_ArrayTrunk.GetCount())
- return NULL;
- --TrunkNo;
- return m_ArrayTrunk[TrunkNo];
- }
- /*****************************************************************
- **【函数名称】 delChan
- **【函数功能】 删除通道
- **【参数】
- **【返回值】
- ****************************************************************/
- void CFsProxy::delChan( CVirtualChan* pChan )
- {
- if(pChan->type() == DEV_RES_TYPE_EXT)
- __delExten(pChan->no());
- }
- /*****************************************************************
- **【函数名称】 getFreeTrunk
- **【函数功能】 查找空闲中继
- **【参数】
- **【返回值】
- ****************************************************************/
- CChanTrunk* CFsProxy::getFreeTrunk( void )
- {
- // 当前轮循到的索引
- static int PosStatic = 0;
- int CurPos = PosStatic;
- int BusyTruckCount = 0;
- // 保证遍历一轮
- for(int i = 0; i < m_ArrayTrunk.GetCount(); ++i)
- {
- // 保证POS是有效的
- if(PosStatic >= m_ArrayTrunk.GetCount())
- PosStatic = 0;
- CChanTrunk* pTrunk = m_ArrayTrunk[PosStatic++];
- ASSERT(pTrunk != NULL);
- // 当前外线是否空闲
- if (pTrunk->isFree())
- {
- return pTrunk;
- }
- else
- {
- BusyTruckCount++;
- }
- }
- LOGGER(LOG_LEVEL_WARNING, _T("{FsProxy}: 没有空闲中继通道,起始索引=%d,当前索引=%d,中继总数量=%d,忙通道数量=%d"), CurPos, PosStatic, m_ArrayTrunk.GetCount(), BusyTruckCount);
- //2019.3.7
- PosStatic = CurPos;
- for (int i = 0; i < m_ArrayTrunk.GetCount(); ++i)
- {
- // 保证POS是有效的
- if (PosStatic >= m_ArrayTrunk.GetCount())
- PosStatic = 0;
- CChanTrunk* pTrunk = m_ArrayTrunk[PosStatic++];
- ASSERT(pTrunk != NULL);
- // 当前外线是否空闲
- if (pTrunk->state() == CHAN_LOGIC_STATE_FREE)
- {
- if (pTrunk->currOp() != NULL) {
- COperationReactor::GetInstance().releaseOpResult(pTrunk->currOp());
- pTrunk->releaseOp(pTrunk->currOp());
- LOGGER(LOG_LEVEL_WARNING, _T("{FsProxy}:没有空闲中继通道,通道[%u],释放操作."), pTrunk->no());
- }
- return pTrunk;
- }
- }
- LOGGER(LOG_LEVEL_WARNING, _T("{FsProxy}: 没有空闲中继通道,起始索引=%d,当前索引=%d"), CurPos, PosStatic);
- return NULL;
- }
- /*****************************************************************
- **【函数名称】 getAssoChanInSession
- **【函数功能】 获取会话中关联通道
- **【参数】
- **【返回值】
- ****************************************************************/
- CVirtualChan* CFsProxy::getAssoChanInSession( CVirtualChan* pChan )
- {
- CSession* pSession = __getSession(pChan->sessionId());
- if(pSession != NULL)
- return pSession->getAssoChan(pChan);
- else
- return NULL;
- }
- /*****************************************************************
- **【函数名称】 getBusyChan
- **【函数功能】 获取忙通道
- **【参数】
- **【返回值】
- *****************************************************************/
- CVirtualChan* CFsProxy::getBusyChan( LPCTSTR ChanId )
- {
- CVirtualChan* pBusyChan = NULL;
- m_MapBusyChan.Lookup(ChanId, pBusyChan);
- return pBusyChan;
- }
- /*****************************************************************
- **【函数名称】 regBusyChan
- **【函数功能】 登记忙通道
- **【参数】
- **【返回值】
- *****************************************************************/
- void CFsProxy::regBusyChan( CVirtualChan* pChan )
- {
- m_MapBusyChan.SetAt(pChan->chanId(), pChan);
- }
- /*****************************************************************
- **【函数名称】 unregBusyChan
- **【函数功能】 取消登记忙通道
- **【参数】
- **【返回值】
- *****************************************************************/
- void CFsProxy::unregBusyChan( CVirtualChan* pChan )
- {
- m_MapBusyChan.RemoveKey(pChan->chanId());
- }
- /*****************************************************************
- **【函数名称】 ExtenCall
- **【函数功能】 分机呼叫
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CFsProxy::ExtenCall( LONG JobId, CVirtualChan* pChan, LPCTSTR CallerNum, LPCTSTR CalleeNum )
- {
- CString EslCmd;
- EslCmd.Format(_T("bgapi originate {origination_caller_id_number=%lu}user/%lu %s XML %s\r\n%s: %ld"),
- pChan->no(), pChan->no(), CalleeNum, CConfig::extContext(), ESL_HEADER_JOB_UUID, JobId);
- return m_Gateway.sendCmd(EslCmd);
- }
- bool CFsProxy::ExtenCall(CVirtualChan* pChan)
- {
- CString EslCmd;
- EslCmd.Format(_T("bgapi originate user/1014 &echo\n\n"));
- return m_Gateway.sendCmd(EslCmd);
- }
- /*****************************************************************
- **【函数名称】 PredictionCall
- **【函数功能】 预测外呼
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CFsProxy::PredictionCall( LONG JobId, CString CallerNum, CString CalleeNum )
- {
- CString CallString;
- if(!m_CallStringMaker.makeCallStringWithDefault(CallerNum, CalleeNum, CallString))
- return false;
- CString EslCmd;
- EslCmd.Format(_T("bgapi originate {origination_caller_id_number=%s,%s=%ld}%s %s XML %s\r\n%s: %ld"),
- CallerNum, ESL_VAR_OP_INSTANCE, JobId, CallString, CalleeNum, CConfig::pCallContext(), ESL_HEADER_JOB_UUID, JobId);
- return m_Gateway.sendCmd(EslCmd);
- }
- /*****************************************************************
- **【函数名称】 answer
- **【函数功能】 应答通道
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CFsProxy::answer( LONG JobId, CVirtualChan* pChan )
- {
- return false;
- }
- /*****************************************************************
- **【函数名称】 kill
- **【函数功能】 挂断通道
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CFsProxy::kill( LONG JobId, CVirtualChan* pChan )
- {
- return __kill(JobId, pChan->chanId());
- }
- /*****************************************************************
- **【函数名称】 consult
- **【函数功能】 协商呼叫
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CFsProxy::consult( LONG JobId, CVirtualChan* pChan, CString DestNum )
- {
- CString CallerNum;
- CString CallString;
- if(!m_CallStringMaker.makeCallString(CallerNum, DestNum, CallString))
- return false;
- CString EslCmd;
- EslCmd.Format(_T("bgapi uuid_broadcast %s att_xfer::%s\r\n%s: %ld"), pChan->chanId(), CallString, ESL_HEADER_JOB_UUID, JobId);
- return m_Gateway.sendCmd(EslCmd);
- }
- /*****************************************************************
- **【函数名称】 insert
- **【函数功能】 强插
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CFsProxy::insert( LONG JobId, CVirtualChan* pChan, LPCTSTR DestSessionId )
- {
- CString EslCmd;
- EslCmd.Format(_T("bgapi originate {origination_caller_id_number=%lu}user/%lu &three_way(%s)\r\n%s: %ld"),
- pChan->no(), pChan->no(), DestSessionId, ESL_HEADER_JOB_UUID, JobId);
- return m_Gateway.sendCmd(EslCmd);
- }
- /*****************************************************************
- **【函数名称】 intercept
- **【函数功能】 强截
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CFsProxy::intercept( LONG JobId, CVirtualChan* pChan, LPCTSTR DestChanId )
- {
- CString EslCmd;
- EslCmd.Format(_T("bgapi originate {origination_caller_id_number=%lu}user/%lu &intercept(%s)\r\n%s: %ld"),
- pChan->no(), pChan->no(), DestChanId, ESL_HEADER_JOB_UUID, JobId);
- return m_Gateway.sendCmd(EslCmd);
- }
- /*****************************************************************
- **【函数名称】 listen
- **【函数功能】 监听
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CFsProxy::listen( LONG JobId, CVirtualChan* pChan, LPCTSTR DestChanId )
- {
- CString EslCmd;
- EslCmd.Format(_T("bgapi originate {origination_caller_id_number=%lu}user/%lu &eavesdrop(%s)\r\n%s: %ld"),
- pChan->no(), pChan->no(), DestChanId, ESL_HEADER_JOB_UUID, JobId);
- return m_Gateway.sendCmd(EslCmd);
- }
- // ych
- std::string CFsProxy::EslCommand(std::string strFsIp, int FsPort, std::string strName, std::string strPsWd, std::string strCommand)
- {
-
- if (!m_EslHandle.connected)
- {
- esl_connect(&m_EslHandle, strFsIp.c_str(), FsPort, strName.c_str(), strPsWd.c_str());
- }
- if (m_EslHandle.connected)
- {
- esl_send_recv_timed(&m_EslHandle, strCommand.c_str(), 2000);
- if (m_EslHandle.last_sr_event && m_EslHandle.last_sr_event->body)
- {
- std::string strRet = m_EslHandle.last_sr_event->body;
- return strRet;
- }
- }
- return "";
- }
- /*****************************************************************
- **【函数名称】 meeting
- **【函数功能】 会议
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CFsProxy::meeting( LONG JobId, CString CallerNum, CString DestNum, LPCTSTR MeetingId )
- {
- bool bMatchPrefix = m_CallStringMaker.isMatchPrefix(DestNum);
- TRUNK_MATCH* pMatch = NULL;
- CString CallString;
- if (!m_CallStringMaker.makeCallString(CallerNum, DestNum, CallString, pMatch))
- return false;
- if (pMatch != NULL)
- {
- SIP_ACCOUNT* pAccount = CConfig::sipAccount().getAccount(pMatch->TrunkItemId);
- if (bMatchPrefix && pAccount != NULL && pAccount->IsDynamicGw) // 外线且动态网关
- {
- std::string strSipAccount = pAccount->Account;
- std::string strGwIp = EslCommand(CConfig::fsAddr(), CConfig::fsPort(), "", CConfig::fsPwd(), "api sofia_contact " + strSipAccount);
- if (!strGwIp.empty())
- {
- size_t Index = strGwIp.find_first_of('@');
- if (Index != std::string::npos)
- {
- strGwIp = strGwIp.substr(Index);
- CallString = "sofia/internal/";
- CallString += DestNum;
- CallString += strGwIp.c_str();
- }
- }
- }
- }
- LOGGER(LOG_LEVEL_NORMAL, _T("{FsProxy}: 三方会议呼叫字符串: %s"), CallString);
- CString EslCmd;
- EslCmd.Format(_T("bgapi originate {origination_caller_id_number=%s,%s=%ld}%s %s XML %s\r\n%s: %ld"),
- CallerNum, ESL_VAR_OP_INSTANCE, JobId, CallString, MeetingId, CConfig::meetingContext(), ESL_HEADER_JOB_UUID, JobId);
- return m_Gateway.sendCmd(EslCmd);
- }
- /*****************************************************************
- **【函数名称】 muteOn
- **【函数功能】 静音
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CFsProxy::muteOn( LONG JobId, CVirtualChan* pChan )
- {
- CString EslCmd;
- EslCmd.Format(_T("bgapi uuid_audio %s start write mute -4\r\n%s: %ld"), pChan->chanId(), ESL_HEADER_JOB_UUID, JobId);
- return m_Gateway.sendCmd(EslCmd);
- }
- /*****************************************************************
- **【函数名称】 muteOff
- **【函数功能】 取消静音
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CFsProxy::muteOff( LONG JobId, CVirtualChan* pChan )
- {
- CString EslCmd;
- EslCmd.Format(_T("bgapi uuid_audio %s stop write mute -4\r\n%s: %ld"), pChan->chanId(), ESL_HEADER_JOB_UUID, JobId);
- return m_Gateway.sendCmd(EslCmd);
- }
- /*****************************************************************
- **【函数名称】 holdon
- **【函数功能】 保持
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CFsProxy::holdon( LONG JobId, CVirtualChan* pChan )
- {
- // by 屏蔽了uuid_hold命令以及sendCmd函数
- CString EslCmd;
- EslCmd.Format(_T("bgapi uuid_hold %s\r\n%s"), pChan->chanId(),ESL_HEADER_JOB_UUID);
- return m_Gateway.sendCmd(EslCmd);
- /*EslCmd.Format(_T("bgapi uuid_hold %s\r\n%s: %ld"), pChan->chanId(), ESL_HEADER_JOB_UUID, JobId);
- return m_Gateway.sendCmd(EslCmd);*/
- }
- /*****************************************************************
- **【函数名称】 takeBack
- **【函数功能】 接回
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CFsProxy::takeBack( LONG JobId, CVirtualChan* pChan )
- {
- CString EslCmd;
- EslCmd.Format(_T("bgapi uuid_hold off %s\r\n%s: %ld"), pChan->chanId(), ESL_HEADER_JOB_UUID, JobId);
- return m_Gateway.sendCmd(EslCmd);
- }
- /*****************************************************************
- **【函数名称】 record
- **【函数功能】 录音
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CFsProxy::record( LONG JobId, CVirtualChan* pChan, LPCTSTR RcdFile )
- {
- CString EslCmd;
- EslCmd.Format(_T("bgapi uuid_record %s start %s\r\n%s: %ld"), pChan->chanId(), RcdFile, ESL_HEADER_JOB_UUID, JobId);
- return m_Gateway.sendCmd(EslCmd);
- }
- /*****************************************************************
- **【函数名称】 transfer
- **【函数功能】 呼叫转移
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CFsProxy::transfer( LONG JobId, CVirtualChan* pChan, LPCTSTR DestNum )
- {
- CString EslCmd;
- EslCmd.Format(_T("bgapi uuid_transfer %s %s xml %s\r\n%s: %ld"), pChan->chanId(), DestNum, CConfig::extContext(), ESL_HEADER_JOB_UUID, JobId);
- return m_Gateway.sendCmd(EslCmd);
- }
- /*****************************************************************
- **【函数名称】 transfer2Context
- **【函数功能】 转移通道至其它Context
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CFsProxy::transfer2Context( LONG JobId, LPCTSTR DestChanId, LPCTSTR Exten, LPCTSTR Context, bool BothSide /*= false*/ )
- {
- CString EslCmd;
- if(BothSide)
- EslCmd.Format(_T("bgapi uuid_transfer %s -both %s xml %s\r\n%s: %ld"), DestChanId, Exten, Context, ESL_HEADER_JOB_UUID, JobId);
- else
- EslCmd.Format(_T("bgapi uuid_transfer %s %s xml %s\r\n%s: %ld"), DestChanId, Exten, Context, ESL_HEADER_JOB_UUID, JobId);
- return m_Gateway.sendCmd(EslCmd);
- }
- /*****************************************************************
- **【函数名称】 cancel
- **【函数功能】 取消当前执行的应用
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CFsProxy::cancel( CChanTrunk* pChan )
- {
- ASSERT(pChan != NULL);
- return m_Gateway.Execte2(ESL_APP_BREAK,NULL,pChan->chanId());
- }
- /*****************************************************************
- **【函数名称】 hangup
- **【函数功能】 挂机
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CFsProxy::hangup( CChanTrunk* pChan )
- {
- ASSERT(pChan != NULL);
- return m_Gateway.execute(pChan->m_pEslHandle,ESL_APP_HANGUP,NULL);
- }
- /*****************************************************************
- **【函数名称】 leaveWord
- **【函数功能】 留言
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CFsProxy::leaveWord( CChanTrunk* pChan, LPCTSTR FileName, UINT LimitTime, TCHAR FinishKey )
- {
- ASSERT(pChan != NULL);
- CString Param;
- Param.Format(_T("playback_terminators=%c"), FinishKey);
- m_Gateway.Execte2(ESL_APP_SET,Param,pChan->chanId());
- Param.Format(_T("%s %lu"), FileName, LimitTime);
- return m_Gateway.Execte2(ESL_APP_LEAVEWORD,Param,pChan->chanId());
- }
- /*****************************************************************
- **【函数名称】 playAndDtmf
- **【函数功能】 放音收按键
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CFsProxy::playAndDtmf( CChanTrunk* pChan, PlayVoiceContent* pPlayContent )
- {
- ASSERT(pChan != NULL);
- ASSERT(pPlayContent != NULL);
- if(pChan==NULL||pPlayContent==NULL) return false;
- TCHAR AudioFile[MAX_PATH] = { 0 };
- // 如果使用了TTS,进行TTS转换
- switch(pPlayContent->nTts)
- {
- default:
- case PLAY_CONTENT_AUDIO: // 不使用TTS
- lstrcpy(AudioFile, pPlayContent->szFileName);
- break;
- case PLAY_CONTENT_TTS_STR: // TTS文本
- {
- ITtsInterface::getInstance().setTTSParam(pPlayContent->nTtsDigitMode, pPlayContent->nTtsSpeed, pPlayContent->nTtsVolume);
- if(!ITtsInterface::getInstance().string2Audio(pPlayContent->szFileName, AudioFile, MAX_PATH))
- {
- LOGGER(LOG_LEVEL_WARNING, _T("{FsProxy}: 中继通道[%lu]放音时TTS文本转换失败"), pChan->no());
- return false;
- }
- }
- break;
- case PLAY_CONTENT_TTS_FILE: // TTS文件
- {
- ITtsInterface::getInstance().setTTSParam(pPlayContent->nTtsDigitMode, pPlayContent->nTtsSpeed, pPlayContent->nTtsVolume);
- if(!ITtsInterface::getInstance().file2Audio(pPlayContent->szFileName, AudioFile, MAX_PATH))
- {
- LOGGER(LOG_LEVEL_WARNING, _T("{FsProxy}: 中继通道[%lu]放音时TTS文件转换失败, File = %s"), pChan->no(), pPlayContent->szFileName);
- return false;
- }
- }
- break;
- }
- CString Param;
- if(pPlayContent->nModel == PVM_PLAY_ONLY && pPlayContent->cDtmfEnd == 0)
- {
- Param.Format(_T("playback_terminators=none"));
- m_Gateway.Execte2(ESL_APP_SET,Param,pChan->chanId());
- //m_Gateway.execute(pChan->m_pEslHandle,ESL_APP_SET,Param);
- Param.Format(_T("%s"), AudioFile);
- //return m_Gateway.Execte2(ESL_APP_PLAY,Param,pChan->chanId());
- return m_Gateway.execute(pChan->m_pEslHandle,ESL_APP_PLAY,Param);
- }
- else
- {
- Param.Format(_T("%lu %lu 1 %lu %c %s slience_stream:0 %s"), pPlayContent->nDtmfCount, pPlayContent->nDtmfCount,
- pPlayContent->nDtmfCount * pPlayContent->nDtmfPeriod * 1000, pPlayContent->cDtmfEnd, AudioFile, ESL_VAR_DTMF_KEY);
-
- return m_Gateway.execute(pChan->m_pEslHandle,ESL_APP_PLAY_DTMF,Param);
- }
- }
- //by 2019-09-11
- bool CFsProxy::ExtenPlayback(LONG JobId, CChanExten* pChan, PlayVoiceContent* pPlayContent)
- {
- CString EslCmd;
- EslCmd.Format(_T("bgapi uuid_playback %s start %s\r\n%s: %ld"), pChan->chanId(), pPlayContent->szFileName, ESL_HEADER_JOB_UUID, JobId);
- return m_Gateway.sendCmd(EslCmd);;
- }
- bool CFsProxy::playAndDtmf(CChanExten* pChanExten, PlayVoiceContent* pPlayContent)
- {
- ASSERT(pChan != NULL);
- ASSERT(pPlayContent != NULL);
- if (pChanExten == NULL || pPlayContent == NULL) return false;
- TCHAR AudioFile[MAX_PATH] = { 0 };
- // 如果使用了TTS,进行TTS转换
- switch (pPlayContent->nTts)
- {
- default:
- case PLAY_CONTENT_AUDIO: // 不使用TTS
- lstrcpy(AudioFile, pPlayContent->szFileName);
- break;
- case PLAY_CONTENT_TTS_STR: // TTS文本
- {
- ITtsInterface::getInstance().setTTSParam(pPlayContent->nTtsDigitMode, pPlayContent->nTtsSpeed, pPlayContent->nTtsVolume);
- if (!ITtsInterface::getInstance().string2Audio(pPlayContent->szFileName, AudioFile, MAX_PATH))
- {
- LOGGER(LOG_LEVEL_WARNING, _T("{FsProxy}: 中继通道[%lu]放音时TTS文本转换失败"), pChanExten->no());
- return false;
- }
- }
- break;
- case PLAY_CONTENT_TTS_FILE: // TTS文件
- {
- ITtsInterface::getInstance().setTTSParam(pPlayContent->nTtsDigitMode, pPlayContent->nTtsSpeed, pPlayContent->nTtsVolume);
- if (!ITtsInterface::getInstance().file2Audio(pPlayContent->szFileName, AudioFile, MAX_PATH))
- {
- LOGGER(LOG_LEVEL_WARNING, _T("{FsProxy}: 中继通道[%lu]放音时TTS文件转换失败, File = %s"), pChanExten->no(), pPlayContent->szFileName);
- return false;
- }
- }
- break;
- }
- CString Param;
- if (pPlayContent->nModel == PVM_PLAY_ONLY && pPlayContent->cDtmfEnd == 0)
- {
- Param.Format(_T("playback_terminators=none"));
- m_Gateway.Execte2(ESL_APP_SET, Param, pChanExten->chanId());
- Param.Format(_T("%s"), AudioFile);
- return m_Gateway.Execte2(ESL_APP_PLAY_DTMF, Param, pChanExten->chanId());
-
- }
- else
- {
- /*Param.Format(_T("playback_terminators=none"));
- m_Gateway.Execte2(ESL_APP_SET, Param, pChanExten->chanId());*/
- Param.Format(_T("%s"), AudioFile);
- return m_Gateway.Execte2(ESL_APP_PLAY_DTMF, Param, pChanExten->chanId());
-
- }
- }
- /*****************************************************************
- **【函数名称】
- **【函数功能】 桥接通道
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CFsProxy::bridge( CChanTrunk* pChan, CString CallerNum, CString CalleeNum )
- {
- CString CallString;
- CallerNum = "0000000000";
- CalleeNum = "1030";
- if(!m_CallStringMaker.makeCallString(CallerNum, CalleeNum, CallString))
- return false;
- CString Param;
- Param.Format(_T("ringback=${us-ring}"));
- m_Gateway.Execte2(ESL_APP_SET,Param,pChan->chanId());
- return m_Gateway.Execte2(ESL_APP_BRIDGE,CallString,pChan->chanId());
- /*CString EslCmd;
- EslCmd.Format(_T("bgapi uuid_transfer %s %s xml"), pChan->chanId(), CalleeNum, "TurnOut.xml");
- return m_Gateway.sendCmd(EslCmd);*/
- }
- bool CFsProxy::origine(CChanExten* pChan,CString CallerNum, CString CalleeNum,LONG JobId)
- {
- CString EslCmd;
- EslCmd.Format(_T("bgapi originate user/%s &echo"),CalleeNum/*,pChan->chanId(), ESL_HEADER_JOB_UUID, JobId*/);
- //EslCmd.Format(_T("originate{ origination_uuid = %s }user /1017"), pChan->chanId());
- return m_Gateway.sendCmd(EslCmd);
- }
- bool CFsProxy::origine(CString ExtenID)
- {
- CString EslCmd;
- EslCmd.Format(_T("bgapi originate user/%s &park"), ExtenID);
- return m_Gateway.sendCmd(EslCmd);
- }
|