华辉中间件项目(代码服务器上没有,用杨成电脑的源代码上传的)

FsProxy.cpp 30KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024
  1. #include "StdAfx.h"
  2. #include "FsProxy.h"
  3. #include "ChanExten.h"
  4. #include "ChanTrunk.h"
  5. #include "Session.h"
  6. #include "OperationReactor.h"
  7. #include "../IVR/IvrSysInc.h"
  8. SINGLETON_IMPLEMENT(CFsProxy)
  9. CFsProxy::CFsProxy(void) : m_Gateway(this), m_pEventHandler(NULL)
  10. {
  11. }
  12. CFsProxy::~CFsProxy(void)
  13. {
  14. }
  15. /*****************************************************************
  16. **【函数名称】 __transLogicState2CtiState
  17. **【函数功能】 将逻辑状态转换为CTI识别的状态
  18. **【参数】
  19. **【返回值】
  20. ****************************************************************/
  21. UINT CFsProxy::__transLogicState2CtiState( DEV_RES_TYPE ChanType, CHAN_LOGIC_STATE State )
  22. {
  23. if(ChanType == DEV_RES_TYPE_EXT)
  24. {
  25. UINT HoldMask = State & HELD_STATE_IND_MASK;
  26. switch(State & HELD_STATE_FILTER_MASK)
  27. {
  28. case CHAN_LOGIC_STATE_DISABLED: return INNER_STATE_DISABLED; // 不可用
  29. case CHAN_LOGIC_STATE_FREE: return INNER_STATE_FREE | HoldMask; // 空闲
  30. case CHAN_LOGIC_STATE_INIT: return INNER_STATE_INIT | HoldMask; // 摘机等待拨号
  31. case CHAN_LOGIC_STATE_DIALING: return INNER_STATE_DIALING | HoldMask; // 拨号
  32. case CHAN_LOGIC_STATE_RING_BACK: return INNER_STATE_RING_BACK | HoldMask; // 呼出振铃
  33. case CHAN_LOGIC_STATE_ALERTING: return INNER_STATE_ALERTING | HoldMask; // 来电振铃
  34. case CHAN_LOGIC_STATE_TALKING: return INNER_STATE_TALKING | HoldMask; // 通话中
  35. default:
  36. ASSERT(FALSE);
  37. return INNER_STATE_DISABLED;
  38. }
  39. }
  40. else
  41. {
  42. switch(State)
  43. {
  44. case CHAN_LOGIC_STATE_DISABLED: return TRUNK_STATE_DISABLED; // 不可用
  45. case CHAN_LOGIC_STATE_FREE: return TRUNK_STATE_FREE; // 空闲
  46. case CHAN_LOGIC_STATE_DIALING: return TRUNK_STATE_DIALING; // 拨号
  47. case CHAN_LOGIC_STATE_RING_BACK: return TRUNK_STATE_RING_BACK; // 呼出振铃
  48. case CHAN_LOGIC_STATE_ALERTING: return TRUNK_STATE_ALERTING; // 来电振铃
  49. case CHAN_LOGIC_STATE_STANDBY:
  50. case CHAN_LOGIC_STATE_TALKING: return TRUNK_STATE_TALKING; // 通话中
  51. default:
  52. ASSERT(FALSE);
  53. return TRUNK_STATE_UNKNOWN;
  54. }
  55. }
  56. }
  57. /*****************************************************************
  58. **【函数名称】 __addExten
  59. **【函数功能】 添加分机
  60. **【参数】
  61. **【返回值】
  62. ****************************************************************/
  63. void CFsProxy::__addExten( UINT ExtenNo )
  64. {
  65. CChanExten* pExten = new CChanExten(this, ExtenNo);
  66. m_MapChanExt.SetAt(ExtenNo, pExten);
  67. pExten->regist();
  68. }
  69. /*****************************************************************
  70. **【函数名称】 delExten
  71. **【函数功能】 删除分机
  72. **【参数】
  73. **【返回值】
  74. ****************************************************************/
  75. void CFsProxy::__delExten( UINT ExtenNo )
  76. {
  77. CChanExten* pExten = NULL;
  78. if(m_MapChanExt.Lookup(ExtenNo, pExten))
  79. {
  80. if(pExten->isFree())
  81. {
  82. m_MapChanExt.RemoveKey(ExtenNo);
  83. FS_LINK_DELETE(pExten);
  84. }
  85. else pExten->discard(true);
  86. }
  87. }
  88. /*****************************************************************
  89. **【函数名称】 __freeExten
  90. **【函数功能】 清空分机
  91. **【参数】
  92. **【返回值】
  93. ****************************************************************/
  94. void CFsProxy::__freeExten( void )
  95. {
  96. UINT ExtenNo = 0;
  97. CChanExten* pExten = NULL;
  98. POSITION Pos = m_MapChanExt.GetStartPosition();
  99. while(Pos != NULL)
  100. {
  101. m_MapChanExt.GetNextAssoc(Pos, ExtenNo, pExten);
  102. FS_LINK_DELETE(pExten);
  103. }
  104. m_MapChanExt.RemoveAll();
  105. }
  106. /*****************************************************************
  107. **【函数名称】 __initTrunkChan
  108. **【函数功能】 初始化中继通道
  109. **【参数】
  110. **【返回值】
  111. ****************************************************************/
  112. void CFsProxy::__initTrunkChan( void )
  113. {
  114. for(int i = 1; i <= CConfig::trunkCount(); ++i)
  115. {
  116. CChanTrunk* pTrunk = new CChanTrunk(this, i);
  117. m_ArrayTrunk.Add(pTrunk);
  118. pTrunk->regist();
  119. }
  120. }
  121. /*****************************************************************
  122. **【函数名称】 __freeTrunkChan
  123. **【函数功能】 清空中继通道
  124. **【参数】
  125. **【返回值】
  126. ****************************************************************/
  127. void CFsProxy::__freeTrunkChan( void )
  128. {
  129. CChanTrunk* pTrunk = NULL;
  130. for(int i = 0; i < m_ArrayTrunk.GetCount(); ++i)
  131. {
  132. pTrunk = m_ArrayTrunk[i];
  133. FS_LINK_DELETE(pTrunk);
  134. }
  135. m_ArrayTrunk.RemoveAll();
  136. }
  137. /*****************************************************************
  138. **【函数名称】 __getSession
  139. **【函数功能】 查找会话
  140. **【参数】
  141. **【返回值】
  142. ****************************************************************/
  143. CSession* CFsProxy::__getSession( PCHAN_EVENT_NOTIFY pNotify, bool NewWhenNull /*= false*/ )
  144. {
  145. CSession* pSession = __getSession(pNotify->CallId);
  146. if(pSession == NULL && NewWhenNull)
  147. {
  148. pSession = new CSession(this, pNotify->CallId);
  149. pSession->prepare(pNotify);
  150. m_MapSession.SetAt(pNotify->CallId, pSession);
  151. LOGGER(LOG_LEVEL_NORMAL,_T("{CFsProxy}:Add Session[%s],ChanId[%s],EventId[%d]"), pSession->id(), pNotify->ChanId, pNotify->EventId);
  152. }
  153. return pSession;
  154. }
  155. /*****************************************************************
  156. **【函数名称】 __getSession
  157. **【函数功能】 查找会话
  158. **【参数】
  159. **【返回值】
  160. ****************************************************************/
  161. CSession* CFsProxy::__getSession( LPCTSTR SessionId )
  162. {
  163. CSession* pSession = NULL;
  164. m_MapSession.Lookup(SessionId, pSession);
  165. return pSession;
  166. }
  167. /*****************************************************************
  168. **【函数名称】 __delSession
  169. **【函数功能】 删除会话
  170. **【参数】
  171. **【返回值】
  172. ****************************************************************/
  173. void CFsProxy::__delSession( LPCTSTR SessionId )
  174. {
  175. if (SessionId == NULL)
  176. return;
  177. CSession* pSession = NULL;
  178. if(m_MapSession.Lookup(SessionId, pSession))
  179. {
  180. m_MapSession.RemoveKey(SessionId);
  181. LOGGER(LOG_LEVEL_NORMAL, _T("{FsProxy}: Delete Session[%s]"), pSession->id());
  182. FS_LINK_DELETE(pSession);
  183. }
  184. }
  185. /*****************************************************************
  186. **【函数名称】 __freeSession
  187. **【函数功能】 清空会话
  188. **【参数】
  189. **【返回值】
  190. ****************************************************************/
  191. void CFsProxy::__freeSession( void )
  192. {
  193. CString SessionId = 0;
  194. CSession* pSession = NULL;
  195. POSITION Pos = m_MapSession.GetStartPosition();
  196. while(Pos != NULL)
  197. {
  198. m_MapSession.GetNextAssoc(Pos, SessionId, pSession);
  199. FS_LINK_DELETE(pSession);
  200. }
  201. m_MapSession.RemoveAll();
  202. }
  203. /*****************************************************************
  204. **【函数名称】 __kill
  205. **【函数功能】 挂断通道
  206. **【参数】
  207. **【返回值】
  208. ****************************************************************/
  209. bool CFsProxy::__kill( LONG JobId, LPCTSTR ChanId )
  210. {
  211. CString EslCmd;
  212. if(JobId == FS_LINK_JOBID_INVALID)
  213. EslCmd.Format(_T("bgapi uuid_kill %s"), ChanId);
  214. else
  215. EslCmd.Format(_T("bgapi uuid_kill %s\r\n%s: %ld"), ChanId, ESL_HEADER_JOB_UUID, JobId);
  216. return m_Gateway.sendCmd(EslCmd);
  217. }
  218. /*****************************************************************
  219. **【函数名称】 init
  220. **【函数功能】 初始化
  221. **【参数】
  222. **【返回值】
  223. ****************************************************************/
  224. bool CFsProxy::init( IEslEventHandler* pEventHandler )
  225. {
  226. ASSERT(pEventHandler != NULL);
  227. m_pEventHandler = pEventHandler;
  228. __initTrunkChan();
  229. if(m_Gateway.start())
  230. {
  231. m_Gateway.hangupAll();
  232. if(m_Gateway.scanExten())
  233. {
  234. LOGGER(LOG_LEVEL_NORMAL, _T("{FsProxy}: FreeSWITCH代理初始化成功"));
  235. return true;
  236. }
  237. else
  238. {
  239. LOGGER(LOG_LEVEL_ERROR, _T("{FsProxy}: FreeSWITCH代理初始化失败, 扫描分机资源失败"));
  240. return false;
  241. }
  242. }
  243. else
  244. {
  245. LOGGER(LOG_LEVEL_ERROR, _T("{FsProxy}: FreeSWITCH代理初始化失败, ESL网关启动失败"));
  246. m_pEventHandler = NULL;
  247. return false;
  248. }
  249. }
  250. /*****************************************************************
  251. **【函数名称】 release
  252. **【函数功能】 释放资源
  253. **【参数】
  254. **【返回值】
  255. ****************************************************************/
  256. void CFsProxy::release( void )
  257. {
  258. esl_disconnect(&m_EslHandle);
  259. m_Gateway.stop();
  260. __freeSession();
  261. __freeExten();
  262. __freeTrunkChan();
  263. }
  264. /*****************************************************************
  265. **【函数名称】 onChanRegist
  266. **【函数功能】 通道注册的处理函数
  267. **【参数】
  268. **【返回值】
  269. ****************************************************************/
  270. void CFsProxy::onChanRegist( DEV_RES_TYPE ChanType, UINT ChanNo, CHAN_LOGIC_STATE ChanState )
  271. {
  272. CDevControl::GetInstance().onEventResDetail(ChanType, ChanNo);
  273. CDevControl::GetInstance().onEventResState(ChanType, ChanNo, __transLogicState2CtiState(ChanType, ChanState));
  274. }
  275. /*****************************************************************
  276. **【函数名称】 onExtenDestroy
  277. **【函数功能】 分机销毁的处理函数
  278. **【参数】
  279. **【返回值】
  280. ****************************************************************/
  281. void CFsProxy::onExtenDestroy( UINT ExtenNo )
  282. {
  283. CDevControl::GetInstance().onEventResState(DEV_RES_TYPE_EXT, ExtenNo, INNER_STATE_REMOVE);
  284. }
  285. /*****************************************************************
  286. **【函数名称】 onExtenDirectOp
  287. **【函数功能】 分机直接操作启动
  288. **【参数】 OpType 启动的操作类型
  289. pHostChan 触发事件的通道
  290. pNotify 触发操作事件内容
  291. **【返回值】
  292. ****************************************************************/
  293. void CFsProxy::onExtenDirectOp( DEV_OP OpType, CVirtualChan* pHostChan, PCHAN_EVENT_NOTIFY pNotify )
  294. {
  295. switch(OpType)
  296. {
  297. case DEV_OP_CALL_OUT:
  298. {
  299. if(!COperationReactor::GetInstance().onExtenCallFromDev(pHostChan, pNotify))
  300. __kill(FS_LINK_JOBID_INVALID, pHostChan->chanId());
  301. }
  302. break;
  303. } // end switch
  304. }
  305. /*****************************************************************
  306. **【函数名称】 onChanStateUpdate
  307. **【函数功能】 通道状态更新处理
  308. **【参数】
  309. **【返回值】
  310. *****************************************************************/
  311. void CFsProxy::onChanStateUpdate( LONG OpInstance, CVirtualChan* pChan )
  312. {
  313. if(OpInstance != FS_LINK_INSTANCE_INVALID)
  314. m_pEventHandler->onEslEvtChanState(OpInstance, pChan);
  315. CDevControl::GetInstance().onEventResState(pChan->type(), pChan->no(), __transLogicState2CtiState(pChan->type(), pChan->state()), pChan->callerNum(), pChan->calleeNum());
  316. }
  317. /*****************************************************************
  318. **【函数名称】 onChanPoor
  319. **【函数功能】 空闲通道枯竭处理
  320. **【参数】
  321. **【返回值】
  322. *****************************************************************/
  323. void CFsProxy::onChanPoor( CSession* pSession, PCHAN_EVENT_NOTIFY pNotify )
  324. {
  325. __kill(FS_LINK_JOBID_INVALID, pNotify->ChanId);
  326. }
  327. /*****************************************************************
  328. **【函数名称】 onTrunkCallIn
  329. **【函数功能】 中继呼入
  330. **【参数】
  331. **【返回值】
  332. *****************************************************************/
  333. void CFsProxy::onTrunkCallIn( CChanTrunk* pTrunk )
  334. {
  335. CDevControl::GetInstance().onEventDevOperation(pTrunk->no(), DEV_OP_CALL_IN, pTrunk->callerNum(), pTrunk->calleeNum());
  336. }
  337. /*****************************************************************
  338. **【函数名称】 onEslDisconnect
  339. **【函数功能】 ESL连接中断处理
  340. **【参数】
  341. **【返回值】
  342. *****************************************************************/
  343. void CFsProxy::onEslDisconnect( void )
  344. {
  345. CDevControl::GetInstance().onEventDevDown();
  346. }
  347. /*****************************************************************
  348. **【函数名称】 onEslSipReg
  349. **【函数功能】 分机注册的处理函数
  350. **【参数】
  351. **【返回值】
  352. ****************************************************************/
  353. void CFsProxy::onEslExtenReg( UINT ExtenNo )
  354. {
  355. CChanExten* pExten = getExten(ExtenNo);
  356. if(pExten == NULL)
  357. {
  358. __addExten(ExtenNo);
  359. }
  360. else
  361. {
  362. if(pExten->isVoid()) // 若被丢弃,则改变丢弃状态
  363. pExten->discard(false);
  364. }
  365. #ifdef _DEBUG
  366. LOGGER(LOG_LEVEL_NORMAL, _T("{FsProxy}: 分机[%u]注册"), ExtenNo);
  367. #endif
  368. }
  369. /*****************************************************************
  370. **【函数名称】 onEslExtenUnreg
  371. **【函数功能】 分机注销的处理函数
  372. **【参数】
  373. **【返回值】
  374. ****************************************************************/
  375. void CFsProxy::onEslExtenUnreg( UINT ExtenNo )
  376. {
  377. __delExten(ExtenNo);
  378. #ifdef _DEBUG
  379. LOGGER(LOG_LEVEL_NORMAL, _T("{FsProxy}: 分机[%u]注销"), ExtenNo);
  380. #endif
  381. }
  382. /*****************************************************************
  383. **【函数名称】 onEslEvtBgJobDone
  384. **【函数功能】 后台任务执行结束事件处理
  385. **【参数】
  386. **【返回值】
  387. *****************************************************************/
  388. void CFsProxy::onEslEvtBgJobDone( PBG_JOB_NOTIFY pNotify )
  389. {
  390. ASSERT(m_pEventHandler != NULL);
  391. m_pEventHandler->onEslEvtBgJobDone(pNotify);
  392. }
  393. /*****************************************************************
  394. **【函数名称】 onEslEvtChannel
  395. **【函数功能】 通道事件处理
  396. **【参数】
  397. **【返回值】
  398. *****************************************************************/
  399. void CFsProxy::onEslEvtChannel( PCHAN_EVENT_NOTIFY pNotify )
  400. {
  401. ASSERT(pNotify != NULL);
  402. if (pNotify == NULL)
  403. return;
  404. CSession* pSession = __getSession(pNotify, true);
  405. ASSERT(pSession != NULL);
  406. if (pSession == NULL)
  407. {
  408. 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);
  409. return;
  410. }
  411. __try {
  412. pSession->onChanEvent(pNotify);
  413. if (pSession->isVoid())
  414. __delSession(pSession->id());
  415. }
  416. __except (EXCEPTION_EXECUTE_HANDLER)
  417. {
  418. 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);
  419. __delSession(pSession->id());
  420. }
  421. }
  422. /*****************************************************************
  423. **【函数名称】 onEslEvtDtmf
  424. **【函数功能】 DTMF事件处理
  425. **【参数】
  426. **【返回值】
  427. *****************************************************************/
  428. void CFsProxy::onEslEvtDtmf( PDTMF_NOTIFY pNotify )
  429. {
  430. ASSERT(pNotify != NULL);
  431. CSession* pSession = __getSession(pNotify->CallId);
  432. ASSERT(pSession != NULL);
  433. if(pSession != NULL)
  434. pSession->onChanDtmf(pNotify);
  435. }
  436. /*****************************************************************
  437. **【函数名称】 onEslEvtHold
  438. **【函数功能】 保持事件处理
  439. **【参数】
  440. **【返回值】
  441. *****************************************************************/
  442. void CFsProxy::onEslEvtHold( PHOLD_NOTIFY pNotify )
  443. {
  444. ASSERT(pNotify != NULL);
  445. CSession* pSession = __getSession(pNotify->CallId);
  446. ASSERT(pSession != NULL);
  447. if(pSession != NULL)
  448. pSession->onChanHold(pNotify);
  449. }
  450. /*****************************************************************
  451. **【函数名称】 getExten
  452. **【函数功能】 查找分机
  453. **【参数】
  454. **【返回值】
  455. ****************************************************************/
  456. CChanExten* CFsProxy::getExten( UINT ExtenNo )
  457. {
  458. CChanExten* pExten = NULL;
  459. m_MapChanExt.Lookup(ExtenNo, pExten);
  460. return pExten;
  461. }
  462. /*****************************************************************
  463. **【函数名称】 getTrunk
  464. **【函数功能】 查找中继
  465. **【参数】
  466. **【返回值】
  467. ****************************************************************/
  468. CChanTrunk* CFsProxy::getTrunk( UINT TrunkNo )
  469. {
  470. if (TrunkNo <= 0 || TrunkNo > (UINT)m_ArrayTrunk.GetCount())
  471. return NULL;
  472. --TrunkNo;
  473. return m_ArrayTrunk[TrunkNo];
  474. }
  475. /*****************************************************************
  476. **【函数名称】 delChan
  477. **【函数功能】 删除通道
  478. **【参数】
  479. **【返回值】
  480. ****************************************************************/
  481. void CFsProxy::delChan( CVirtualChan* pChan )
  482. {
  483. if(pChan->type() == DEV_RES_TYPE_EXT)
  484. __delExten(pChan->no());
  485. }
  486. /*****************************************************************
  487. **【函数名称】 getFreeTrunk
  488. **【函数功能】 查找空闲中继
  489. **【参数】
  490. **【返回值】
  491. ****************************************************************/
  492. CChanTrunk* CFsProxy::getFreeTrunk( void )
  493. {
  494. // 当前轮循到的索引
  495. static int PosStatic = 0;
  496. int CurPos = PosStatic;
  497. int BusyTruckCount = 0;
  498. // 保证遍历一轮
  499. for(int i = 0; i < m_ArrayTrunk.GetCount(); ++i)
  500. {
  501. // 保证POS是有效的
  502. if(PosStatic >= m_ArrayTrunk.GetCount())
  503. PosStatic = 0;
  504. CChanTrunk* pTrunk = m_ArrayTrunk[PosStatic++];
  505. ASSERT(pTrunk != NULL);
  506. // 当前外线是否空闲
  507. if (pTrunk->isFree())
  508. {
  509. return pTrunk;
  510. }
  511. else
  512. {
  513. BusyTruckCount++;
  514. }
  515. }
  516. LOGGER(LOG_LEVEL_WARNING, _T("{FsProxy}: 没有找到空闲中继通道,起始轮询索引=%d,当前轮循到的索引=%d,中继总数量=%d,忙通道数量=%d"), CurPos, PosStatic, m_ArrayTrunk.GetCount(), BusyTruckCount);
  517. return NULL;
  518. }
  519. /*****************************************************************
  520. **【函数名称】 getAssoChanInSession
  521. **【函数功能】 获取会话中关联通道
  522. **【参数】
  523. **【返回值】
  524. ****************************************************************/
  525. CVirtualChan* CFsProxy::getAssoChanInSession( CVirtualChan* pChan )
  526. {
  527. CSession* pSession = __getSession(pChan->sessionId());
  528. if(pSession != NULL)
  529. return pSession->getAssoChan(pChan);
  530. else
  531. return NULL;
  532. }
  533. /*****************************************************************
  534. **【函数名称】 getBusyChan
  535. **【函数功能】 获取忙通道
  536. **【参数】
  537. **【返回值】
  538. *****************************************************************/
  539. CVirtualChan* CFsProxy::getBusyChan( LPCTSTR ChanId )
  540. {
  541. CVirtualChan* pBusyChan = NULL;
  542. m_MapBusyChan.Lookup(ChanId, pBusyChan);
  543. return pBusyChan;
  544. }
  545. /*****************************************************************
  546. **【函数名称】 regBusyChan
  547. **【函数功能】 登记忙通道
  548. **【参数】
  549. **【返回值】
  550. *****************************************************************/
  551. void CFsProxy::regBusyChan( CVirtualChan* pChan )
  552. {
  553. m_MapBusyChan.SetAt(pChan->chanId(), pChan);
  554. }
  555. /*****************************************************************
  556. **【函数名称】 unregBusyChan
  557. **【函数功能】 取消登记忙通道
  558. **【参数】
  559. **【返回值】
  560. *****************************************************************/
  561. void CFsProxy::unregBusyChan( CVirtualChan* pChan )
  562. {
  563. m_MapBusyChan.RemoveKey(pChan->chanId());
  564. }
  565. /*****************************************************************
  566. **【函数名称】 ExtenCall
  567. **【函数功能】 分机呼叫
  568. **【参数】
  569. **【返回值】
  570. ****************************************************************/
  571. bool CFsProxy::ExtenCall( LONG JobId, CVirtualChan* pChan, LPCTSTR CallerNum, LPCTSTR CalleeNum )
  572. {
  573. CString EslCmd;
  574. EslCmd.Format(_T("bgapi originate {origination_caller_id_number=%lu}user/%lu %s XML %s\r\n%s: %ld"),
  575. pChan->no(), pChan->no(), CalleeNum, CConfig::extContext(), ESL_HEADER_JOB_UUID, JobId);
  576. return m_Gateway.sendCmd(EslCmd);
  577. }
  578. /*****************************************************************
  579. **【函数名称】 PredictionCall
  580. **【函数功能】 预测外呼
  581. **【参数】
  582. **【返回值】
  583. ****************************************************************/
  584. bool CFsProxy::PredictionCall( LONG JobId, CString CallerNum, CString CalleeNum )
  585. {
  586. CString CallString;
  587. if(!m_CallStringMaker.makeCallStringWithDefault(CallerNum, CalleeNum, CallString))
  588. return false;
  589. CString EslCmd;
  590. EslCmd.Format(_T("bgapi originate {origination_caller_id_number=%s,%s=%ld}%s %s XML %s\r\n%s: %ld"),
  591. CallerNum, ESL_VAR_OP_INSTANCE, JobId, CallString, CalleeNum, CConfig::pCallContext(), ESL_HEADER_JOB_UUID, JobId);
  592. return m_Gateway.sendCmd(EslCmd);
  593. }
  594. /*****************************************************************
  595. **【函数名称】 answer
  596. **【函数功能】 应答通道
  597. **【参数】
  598. **【返回值】
  599. ****************************************************************/
  600. bool CFsProxy::answer( LONG JobId, CVirtualChan* pChan )
  601. {
  602. return false;
  603. }
  604. /*****************************************************************
  605. **【函数名称】 kill
  606. **【函数功能】 挂断通道
  607. **【参数】
  608. **【返回值】
  609. ****************************************************************/
  610. bool CFsProxy::kill( LONG JobId, CVirtualChan* pChan )
  611. {
  612. return __kill(JobId, pChan->chanId());
  613. }
  614. /*****************************************************************
  615. **【函数名称】 consult
  616. **【函数功能】 协商呼叫
  617. **【参数】
  618. **【返回值】
  619. ****************************************************************/
  620. bool CFsProxy::consult( LONG JobId, CVirtualChan* pChan, CString DestNum )
  621. {
  622. CString CallerNum;
  623. CString CallString;
  624. if(!m_CallStringMaker.makeCallString(CallerNum, DestNum, CallString))
  625. return false;
  626. CString EslCmd;
  627. EslCmd.Format(_T("bgapi uuid_broadcast %s att_xfer::%s\r\n%s: %ld"), pChan->chanId(), CallString, ESL_HEADER_JOB_UUID, JobId);
  628. return m_Gateway.sendCmd(EslCmd);
  629. }
  630. /*****************************************************************
  631. **【函数名称】 insert
  632. **【函数功能】 强插
  633. **【参数】
  634. **【返回值】
  635. ****************************************************************/
  636. bool CFsProxy::insert( LONG JobId, CVirtualChan* pChan, LPCTSTR DestSessionId )
  637. {
  638. CString EslCmd;
  639. EslCmd.Format(_T("bgapi originate {origination_caller_id_number=%lu}user/%lu &three_way(%s)\r\n%s: %ld"),
  640. pChan->no(), pChan->no(), DestSessionId, ESL_HEADER_JOB_UUID, JobId);
  641. return m_Gateway.sendCmd(EslCmd);
  642. }
  643. /*****************************************************************
  644. **【函数名称】 intercept
  645. **【函数功能】 强截
  646. **【参数】
  647. **【返回值】
  648. ****************************************************************/
  649. bool CFsProxy::intercept( LONG JobId, CVirtualChan* pChan, LPCTSTR DestChanId )
  650. {
  651. CString EslCmd;
  652. EslCmd.Format(_T("bgapi originate {origination_caller_id_number=%lu}user/%lu &intercept(%s)\r\n%s: %ld"),
  653. pChan->no(), pChan->no(), DestChanId, ESL_HEADER_JOB_UUID, JobId);
  654. return m_Gateway.sendCmd(EslCmd);
  655. }
  656. /*****************************************************************
  657. **【函数名称】 listen
  658. **【函数功能】 监听
  659. **【参数】
  660. **【返回值】
  661. ****************************************************************/
  662. bool CFsProxy::listen( LONG JobId, CVirtualChan* pChan, LPCTSTR DestChanId )
  663. {
  664. CString EslCmd;
  665. EslCmd.Format(_T("bgapi originate {origination_caller_id_number=%lu}user/%lu &eavesdrop(%s)\r\n%s: %ld"),
  666. pChan->no(), pChan->no(), DestChanId, ESL_HEADER_JOB_UUID, JobId);
  667. return m_Gateway.sendCmd(EslCmd);
  668. }
  669. // ych
  670. std::string CFsProxy::EslCommand(std::string strFsIp, int FsPort, std::string strName, std::string strPsWd, std::string strCommand)
  671. {
  672. if (!m_EslHandle.connected)
  673. {
  674. esl_connect(&m_EslHandle, strFsIp.c_str(), FsPort, strName.c_str(), strPsWd.c_str());
  675. }
  676. if (m_EslHandle.connected)
  677. {
  678. esl_send_recv_timed(&m_EslHandle, strCommand.c_str(), 2000);
  679. if (m_EslHandle.last_sr_event && m_EslHandle.last_sr_event->body)
  680. {
  681. std::string strRet = m_EslHandle.last_sr_event->body;
  682. return strRet;
  683. }
  684. }
  685. return "";
  686. }
  687. /*****************************************************************
  688. **【函数名称】 meeting
  689. **【函数功能】 会议
  690. **【参数】
  691. **【返回值】
  692. ****************************************************************/
  693. bool CFsProxy::meeting( LONG JobId, CString CallerNum, CString DestNum, LPCTSTR MeetingId )
  694. {
  695. bool bMatchPrefix = m_CallStringMaker.isMatchPrefix(DestNum);
  696. TRUNK_MATCH* pMatch = NULL;
  697. CString CallString;
  698. if (!m_CallStringMaker.makeCallString(CallerNum, DestNum, CallString, pMatch))
  699. return false;
  700. if (pMatch != NULL)
  701. {
  702. SIP_ACCOUNT* pAccount = CConfig::sipAccount().getAccount(pMatch->TrunkItemId);
  703. if (bMatchPrefix && pAccount != NULL && pAccount->IsDynamicGw) // 外线且动态网关
  704. {
  705. std::string strSipAccount = pAccount->Account;
  706. std::string strGwIp = EslCommand(CConfig::fsAddr(), CConfig::fsPort(), "", CConfig::fsPwd(), "api sofia_contact " + strSipAccount);
  707. if (!strGwIp.empty())
  708. {
  709. size_t Index = strGwIp.find_first_of('@');
  710. if (Index != std::string::npos)
  711. {
  712. strGwIp = strGwIp.substr(Index);
  713. CallString = "sofia/internal/";
  714. CallString += DestNum;
  715. CallString += strGwIp.c_str();
  716. }
  717. }
  718. }
  719. }
  720. LOGGER(LOG_LEVEL_NORMAL, _T("{FsProxy}: 三方会议呼叫字符串: %s"), CallString);
  721. CString EslCmd;
  722. EslCmd.Format(_T("bgapi originate {origination_caller_id_number=%s,%s=%ld}%s %s XML %s\r\n%s: %ld"),
  723. CallerNum, ESL_VAR_OP_INSTANCE, JobId, CallString, MeetingId, CConfig::meetingContext(), ESL_HEADER_JOB_UUID, JobId);
  724. return m_Gateway.sendCmd(EslCmd);
  725. }
  726. /*****************************************************************
  727. **【函数名称】 muteOn
  728. **【函数功能】 静音
  729. **【参数】
  730. **【返回值】
  731. ****************************************************************/
  732. bool CFsProxy::muteOn( LONG JobId, CVirtualChan* pChan )
  733. {
  734. CString EslCmd;
  735. EslCmd.Format(_T("bgapi uuid_audio %s start write mute -4\r\n%s: %ld"), pChan->chanId(), ESL_HEADER_JOB_UUID, JobId);
  736. return m_Gateway.sendCmd(EslCmd);
  737. }
  738. /*****************************************************************
  739. **【函数名称】 muteOff
  740. **【函数功能】 取消静音
  741. **【参数】
  742. **【返回值】
  743. ****************************************************************/
  744. bool CFsProxy::muteOff( LONG JobId, CVirtualChan* pChan )
  745. {
  746. CString EslCmd;
  747. EslCmd.Format(_T("bgapi uuid_audio %s stop write mute -4\r\n%s: %ld"), pChan->chanId(), ESL_HEADER_JOB_UUID, JobId);
  748. return m_Gateway.sendCmd(EslCmd);
  749. }
  750. /*****************************************************************
  751. **【函数名称】 holdon
  752. **【函数功能】 保持
  753. **【参数】
  754. **【返回值】
  755. ****************************************************************/
  756. bool CFsProxy::holdon( LONG JobId, CVirtualChan* pChan )
  757. {
  758. CString EslCmd;
  759. EslCmd.Format(_T("bgapi uuid_hold %s\r\n%s: %ld"), pChan->chanId(), ESL_HEADER_JOB_UUID, JobId);
  760. return m_Gateway.sendCmd(EslCmd);
  761. }
  762. /*****************************************************************
  763. **【函数名称】 takeBack
  764. **【函数功能】 接回
  765. **【参数】
  766. **【返回值】
  767. ****************************************************************/
  768. bool CFsProxy::takeBack( LONG JobId, CVirtualChan* pChan )
  769. {
  770. CString EslCmd;
  771. EslCmd.Format(_T("bgapi uuid_hold off %s\r\n%s: %ld"), pChan->chanId(), ESL_HEADER_JOB_UUID, JobId);
  772. return m_Gateway.sendCmd(EslCmd);
  773. }
  774. /*****************************************************************
  775. **【函数名称】 record
  776. **【函数功能】 录音
  777. **【参数】
  778. **【返回值】
  779. ****************************************************************/
  780. bool CFsProxy::record( LONG JobId, CVirtualChan* pChan, LPCTSTR RcdFile )
  781. {
  782. CString EslCmd;
  783. EslCmd.Format(_T("bgapi uuid_record %s start %s\r\n%s: %ld"), pChan->chanId(), RcdFile, ESL_HEADER_JOB_UUID, JobId);
  784. return m_Gateway.sendCmd(EslCmd);
  785. }
  786. /*****************************************************************
  787. **【函数名称】 transfer
  788. **【函数功能】 呼叫转移
  789. **【参数】
  790. **【返回值】
  791. ****************************************************************/
  792. bool CFsProxy::transfer( LONG JobId, CVirtualChan* pChan, LPCTSTR DestNum )
  793. {
  794. CString EslCmd;
  795. EslCmd.Format(_T("bgapi uuid_transfer %s %s xml %s\r\n%s: %ld"), pChan->chanId(), DestNum, CConfig::extContext(), ESL_HEADER_JOB_UUID, JobId);
  796. return m_Gateway.sendCmd(EslCmd);
  797. }
  798. /*****************************************************************
  799. **【函数名称】 transfer2Context
  800. **【函数功能】 转移通道至其它Context
  801. **【参数】
  802. **【返回值】
  803. ****************************************************************/
  804. bool CFsProxy::transfer2Context( LONG JobId, LPCTSTR DestChanId, LPCTSTR Exten, LPCTSTR Context, bool BothSide /*= false*/ )
  805. {
  806. CString EslCmd;
  807. if(BothSide)
  808. EslCmd.Format(_T("bgapi uuid_transfer %s -both %s xml %s\r\n%s: %ld"), DestChanId, Exten, Context, ESL_HEADER_JOB_UUID, JobId);
  809. else
  810. EslCmd.Format(_T("bgapi uuid_transfer %s %s xml %s\r\n%s: %ld"), DestChanId, Exten, Context, ESL_HEADER_JOB_UUID, JobId);
  811. return m_Gateway.sendCmd(EslCmd);
  812. }
  813. /*****************************************************************
  814. **【函数名称】 cancel
  815. **【函数功能】 取消当前执行的应用
  816. **【参数】
  817. **【返回值】
  818. ****************************************************************/
  819. bool CFsProxy::cancel( CChanTrunk* pChan )
  820. {
  821. ASSERT(pChan != NULL);
  822. return m_Gateway.Execte2(ESL_APP_BREAK,NULL,pChan->chanId());
  823. }
  824. /*****************************************************************
  825. **【函数名称】 hangup
  826. **【函数功能】 挂机
  827. **【参数】
  828. **【返回值】
  829. ****************************************************************/
  830. bool CFsProxy::hangup( CChanTrunk* pChan )
  831. {
  832. ASSERT(pChan != NULL);
  833. return m_Gateway.execute(pChan->m_pEslHandle,ESL_APP_HANGUP,NULL);
  834. }
  835. /*****************************************************************
  836. **【函数名称】 leaveWord
  837. **【函数功能】 留言
  838. **【参数】
  839. **【返回值】
  840. ****************************************************************/
  841. bool CFsProxy::leaveWord( CChanTrunk* pChan, LPCTSTR FileName, UINT LimitTime, TCHAR FinishKey )
  842. {
  843. ASSERT(pChan != NULL);
  844. CString Param;
  845. Param.Format(_T("playback_terminators=%c"), FinishKey);
  846. m_Gateway.Execte2(ESL_APP_SET,Param,pChan->chanId());
  847. Param.Format(_T("%s %lu"), FileName, LimitTime);
  848. return m_Gateway.Execte2(ESL_APP_LEAVEWORD,Param,pChan->chanId());
  849. }
  850. /*****************************************************************
  851. **【函数名称】 playAndDtmf
  852. **【函数功能】 放音收按键
  853. **【参数】
  854. **【返回值】
  855. ****************************************************************/
  856. bool CFsProxy::playAndDtmf( CChanTrunk* pChan, PlayVoiceContent* pPlayContent )
  857. {
  858. ASSERT(pChan != NULL);
  859. ASSERT(pPlayContent != NULL);
  860. if(pChan==NULL||pPlayContent==NULL) return false;
  861. TCHAR AudioFile[MAX_PATH] = { 0 };
  862. // 如果使用了TTS,进行TTS转换
  863. switch(pPlayContent->nTts)
  864. {
  865. default:
  866. case PLAY_CONTENT_AUDIO: // 不使用TTS
  867. lstrcpy(AudioFile, pPlayContent->szFileName);
  868. break;
  869. case PLAY_CONTENT_TTS_STR: // TTS文本
  870. {
  871. ITtsInterface::getInstance().setTTSParam(pPlayContent->nTtsDigitMode, pPlayContent->nTtsSpeed, pPlayContent->nTtsVolume);
  872. if(!ITtsInterface::getInstance().string2Audio(pPlayContent->szFileName, AudioFile, MAX_PATH))
  873. {
  874. LOGGER(LOG_LEVEL_WARNING, _T("{FsProxy}: 中继通道[%lu]放音时TTS文本转换失败"), pChan->no());
  875. return false;
  876. }
  877. }
  878. break;
  879. case PLAY_CONTENT_TTS_FILE: // TTS文件
  880. {
  881. ITtsInterface::getInstance().setTTSParam(pPlayContent->nTtsDigitMode, pPlayContent->nTtsSpeed, pPlayContent->nTtsVolume);
  882. if(!ITtsInterface::getInstance().file2Audio(pPlayContent->szFileName, AudioFile, MAX_PATH))
  883. {
  884. LOGGER(LOG_LEVEL_WARNING, _T("{FsProxy}: 中继通道[%lu]放音时TTS文件转换失败, File = %s"), pChan->no(), pPlayContent->szFileName);
  885. return false;
  886. }
  887. }
  888. break;
  889. }
  890. CString Param;
  891. if(pPlayContent->nModel == PVM_PLAY_ONLY && pPlayContent->cDtmfEnd == 0)
  892. {
  893. Param.Format(_T("playback_terminators=none"));
  894. m_Gateway.Execte2(ESL_APP_SET,Param,pChan->chanId());
  895. //m_Gateway.execute(pChan->m_pEslHandle,ESL_APP_SET,Param);
  896. Param.Format(_T("%s"), AudioFile);
  897. return m_Gateway.Execte2(ESL_APP_PLAY,Param,pChan->chanId());
  898. //return m_Gateway.execute(pChan->m_pEslHandle,ESL_APP_PLAY,Param);
  899. }
  900. else
  901. {
  902. Param.Format(_T("%lu %lu 1 %lu %c %s silence_stream://250 %s"), pPlayContent->nDtmfCount, pPlayContent->nDtmfCount,
  903. pPlayContent->nDtmfCount * pPlayContent->nDtmfPeriod * 1000, pPlayContent->cDtmfEnd, AudioFile, ESL_VAR_DTMF_KEY);
  904. return m_Gateway.Execte2(ESL_APP_PLAY_DTMF,Param,pChan->chanId());
  905. //return m_Gateway.execute(pChan->m_pEslHandle,ESL_APP_PLAY_DTMF,Param);
  906. }
  907. }
  908. /*****************************************************************
  909. **【函数名称】 bridge
  910. **【函数功能】 桥接通道
  911. **【参数】
  912. **【返回值】
  913. ****************************************************************/
  914. bool CFsProxy::bridge( CChanTrunk* pChan, CString CallerNum, CString CalleeNum )
  915. {
  916. CString CallString;
  917. if(!m_CallStringMaker.makeCallString(CallerNum, CalleeNum, CallString))
  918. return false;
  919. CString Param;
  920. Param.Format(_T("ringback=${us-ring}"));
  921. m_Gateway.Execte2(ESL_APP_SET,Param,pChan->chanId());
  922. return m_Gateway.Execte2(ESL_APP_BRIDGE,CallString,pChan->chanId());
  923. }