MiddleWares_YiHe 郑州颐和医院随访系统中间件

FsProxy.cpp 35KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169
  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. std::cout << "m_MapSession.SetAt" << pNotify->CallId << endl;
  152. std::cout << "m_MapSession.SetAt" << pSession->id() << endl;
  153. LOGGER(LOG_LEVEL_NORMAL,_T("{CFsProxy}:Add Session[%s],ChanId[%s],EventId[%d],CallID[%s]"), pSession->id(), pNotify->ChanId, pNotify->EventId,pNotify->CallId);
  154. }
  155. return pSession;
  156. }
  157. /*****************************************************************
  158. **【函数名称】 __getSession
  159. **【函数功能】 查找会话
  160. **【参数】
  161. **【返回值】
  162. ****************************************************************/
  163. CSession* CFsProxy::__getSession( LPCTSTR SessionId )
  164. {
  165. CSession* pSession = NULL;
  166. m_MapSession.Lookup(SessionId, pSession);
  167. std::cout << "__getSession" << SessionId << endl;
  168. return pSession;
  169. }
  170. /*****************************************************************
  171. **【函数名称】 __delSession
  172. **【函数功能】 删除会话
  173. **【参数】
  174. **【返回值】
  175. ****************************************************************/
  176. void CFsProxy::__delSession( LPCTSTR SessionId )
  177. {
  178. if (SessionId == NULL)
  179. return;
  180. CSession* pSession = NULL;
  181. if(m_MapSession.Lookup(SessionId, pSession))
  182. {
  183. m_MapSession.RemoveKey(SessionId);
  184. LOGGER(LOG_LEVEL_NORMAL, _T("{FsProxy}: Delete Session[%s]"), pSession->id());
  185. FS_LINK_DELETE(pSession);
  186. }
  187. }
  188. /*****************************************************************
  189. **【函数名称】 __freeSession
  190. **【函数功能】 清空会话
  191. **【参数】
  192. **【返回值】
  193. ****************************************************************/
  194. void CFsProxy::__freeSession( void )
  195. {
  196. CString SessionId = 0;
  197. CSession* pSession = NULL;
  198. POSITION Pos = m_MapSession.GetStartPosition();
  199. while(Pos != NULL)
  200. {
  201. m_MapSession.GetNextAssoc(Pos, SessionId, pSession);
  202. FS_LINK_DELETE(pSession);
  203. }
  204. m_MapSession.RemoveAll();
  205. }
  206. /*****************************************************************
  207. **【函数名称】 __kill
  208. **【函数功能】 挂断通道
  209. **【参数】
  210. **【返回值】
  211. ****************************************************************/
  212. bool CFsProxy::__kill( LONG JobId, LPCTSTR ChanId )
  213. {
  214. CString EslCmd;
  215. if(JobId == FS_LINK_JOBID_INVALID)
  216. EslCmd.Format(_T("bgapi uuid_kill %s"), ChanId);
  217. else
  218. EslCmd.Format(_T("bgapi uuid_kill %s\r\n%s: %ld"), ChanId, ESL_HEADER_JOB_UUID, JobId);
  219. return m_Gateway.sendCmd(EslCmd);
  220. }
  221. /*****************************************************************
  222. **【函数名称】 init
  223. **【函数功能】 初始化
  224. **【参数】
  225. **【返回值】
  226. ****************************************************************/
  227. bool CFsProxy::init( IEslEventHandler* pEventHandler )
  228. {
  229. ASSERT(pEventHandler != NULL);
  230. m_pEventHandler = pEventHandler;
  231. __initTrunkChan();
  232. if(m_Gateway.start())
  233. {
  234. m_Gateway.hangupAll();
  235. if(m_Gateway.scanExten())
  236. {
  237. LOGGER(LOG_LEVEL_NORMAL, _T("{FsProxy}: FreeSWITCH代理初始化成功"));
  238. return true;
  239. }
  240. else
  241. {
  242. LOGGER(LOG_LEVEL_ERROR, _T("{FsProxy}: FreeSWITCH代理初始化失败, 扫描分机资源失败"));
  243. return false;
  244. }
  245. }
  246. else
  247. {
  248. LOGGER(LOG_LEVEL_ERROR, _T("{FsProxy}: FreeSWITCH代理初始化失败, ESL网关启动失败"));
  249. m_pEventHandler = NULL;
  250. return false;
  251. }
  252. }
  253. /*****************************************************************
  254. **【函数名称】 release
  255. **【函数功能】 释放资源
  256. **【参数】
  257. **【返回值】
  258. ****************************************************************/
  259. void CFsProxy::release( void )
  260. {
  261. // by 临时添加的esl_handle_t句柄
  262. esl_handle_t m_EslHandle;
  263. esl_disconnect(&m_EslHandle);
  264. m_Gateway.stop();
  265. __freeSession();
  266. __freeExten();
  267. __freeTrunkChan();
  268. }
  269. /*****************************************************************
  270. **【函数名称】 onChanRegist
  271. **【函数功能】 通道注册的处理函数
  272. **【参数】
  273. **【返回值】
  274. ****************************************************************/
  275. void CFsProxy::onChanRegist( DEV_RES_TYPE ChanType, UINT ChanNo, CHAN_LOGIC_STATE ChanState )
  276. {
  277. CDevControl::GetInstance().onEventResDetail(ChanType, ChanNo);
  278. CDevControl::GetInstance().onEventResState(ChanType, ChanNo, __transLogicState2CtiState(ChanType, ChanState));
  279. }
  280. /*****************************************************************
  281. **【函数名称】 onExtenDestroy
  282. **【函数功能】 分机销毁的处理函数
  283. **【参数】
  284. **【返回值】
  285. ****************************************************************/
  286. void CFsProxy::onExtenDestroy( UINT ExtenNo )
  287. {
  288. CDevControl::GetInstance().onEventResState(DEV_RES_TYPE_EXT, ExtenNo, INNER_STATE_REMOVE);
  289. }
  290. /*****************************************************************
  291. **【函数名称】 onExtenDirectOp
  292. **【函数功能】 分机直接操作启动
  293. **【参数】 OpType 启动的操作类型
  294. pHostChan 触发事件的通道
  295. pNotify 触发操作事件内容
  296. **【返回值】
  297. ****************************************************************/
  298. void CFsProxy::onExtenDirectOp( DEV_OP OpType, CVirtualChan* pHostChan, PCHAN_EVENT_NOTIFY pNotify )
  299. {
  300. switch(OpType)
  301. {
  302. case DEV_OP_CALL_OUT:
  303. {
  304. if(!COperationReactor::GetInstance().onExtenCallFromDev(pHostChan, pNotify))
  305. __kill(FS_LINK_JOBID_INVALID, pHostChan->chanId());
  306. }
  307. break;
  308. } // end switch
  309. }
  310. /*****************************************************************
  311. **【函数名称】 onChanStateUpdate
  312. **【函数功能】 通道状态更新处理
  313. **【参数】
  314. **【返回值】
  315. *****************************************************************/
  316. void CFsProxy::onChanStateUpdate( LONG OpInstance, CVirtualChan* pChan )
  317. {
  318. if(OpInstance != FS_LINK_INSTANCE_INVALID)
  319. m_pEventHandler->onEslEvtChanState(OpInstance, pChan);
  320. CDevControl::GetInstance().onEventResState(pChan->type(), pChan->no(), __transLogicState2CtiState(pChan->type(), pChan->state()), pChan->callerNum(), pChan->calleeNum());
  321. }
  322. /*****************************************************************
  323. **【函数名称】 onChanPoor
  324. **【函数功能】 空闲通道枯竭处理
  325. **【参数】
  326. **【返回值】
  327. *****************************************************************/
  328. void CFsProxy::onChanPoor( CSession* pSession, PCHAN_EVENT_NOTIFY pNotify )
  329. {
  330. __kill(FS_LINK_JOBID_INVALID, pNotify->ChanId);
  331. }
  332. /*****************************************************************
  333. **【函数名称】 onTrunkCallIn
  334. **【函数功能】 中继呼入
  335. **【参数】
  336. **【返回值】
  337. *****************************************************************/
  338. void CFsProxy::onTrunkCallIn( CChanTrunk* pTrunk )
  339. {
  340. CDevControl::GetInstance().onEventDevOperation(pTrunk->no(), DEV_OP_CALL_IN, pTrunk->callerNum(), pTrunk->calleeNum());
  341. }
  342. /*****************************************************************
  343. **【函数名称】 onEslDisconnect
  344. **【函数功能】 ESL连接中断处理
  345. **【参数】
  346. **【返回值】
  347. *****************************************************************/
  348. void CFsProxy::onEslDisconnect( void )
  349. {
  350. CDevControl::GetInstance().onEventDevDown();
  351. }
  352. /*****************************************************************
  353. **【函数名称】 onEslSipReg
  354. **【函数功能】 分机注册的处理函数
  355. **【参数】
  356. **【返回值】
  357. ****************************************************************/
  358. void CFsProxy::onEslExtenReg( UINT ExtenNo )
  359. {
  360. CChanExten* pExten = getExten(ExtenNo);
  361. if(pExten == NULL)
  362. {
  363. __addExten(ExtenNo);
  364. }
  365. else
  366. {
  367. if(pExten->isVoid()) // 若被丢弃,则改变丢弃状态
  368. pExten->discard(false);
  369. }
  370. #ifdef _DEBUG
  371. LOGGER(LOG_LEVEL_NORMAL, _T("{FsProxy}: 分机[%u]注册"), ExtenNo);
  372. #endif
  373. }
  374. /*****************************************************************
  375. **【函数名称】 onEslExtenUnreg
  376. **【函数功能】 分机注销的处理函数
  377. **【参数】
  378. **【返回值】
  379. ****************************************************************/
  380. void CFsProxy::onEslExtenUnreg( UINT ExtenNo )
  381. {
  382. __delExten(ExtenNo);
  383. #ifdef _DEBUG
  384. LOGGER(LOG_LEVEL_NORMAL, _T("{FsProxy}: 分机[%u]注销"), ExtenNo);
  385. #endif
  386. }
  387. /*****************************************************************
  388. **【函数名称】 onEslGwExten
  389. **【函数功能】 网关分机的处理函数
  390. **【参数】
  391. **【返回值】
  392. ****************************************************************/
  393. void CFsProxy::onEslGwExtenReg(LPCTSTR ExtenNo, LPCTSTR Ip)
  394. {
  395. m_MapAddrGwExt.SetAt(ExtenNo, Ip);
  396. return;
  397. }
  398. void CFsProxy::onEslGwExtenUnreg(LPCTSTR ExtenNo)
  399. {
  400. CString t_ip;
  401. if (m_MapAddrGwExt.Lookup(ExtenNo, t_ip))
  402. {
  403. t_ip.Empty();
  404. m_MapAddrGwExt.RemoveKey(ExtenNo);
  405. }
  406. }
  407. /*****************************************************************
  408. **【函数名称】 onEslEvtBgJobDone
  409. **【函数功能】 后台任务执行结束事件处理
  410. **【参数】
  411. **【返回值】
  412. *****************************************************************/
  413. void CFsProxy::onEslEvtBgJobDone( PBG_JOB_NOTIFY pNotify )
  414. {
  415. ASSERT(m_pEventHandler != NULL);
  416. m_pEventHandler->onEslEvtBgJobDone(pNotify);
  417. }
  418. /*****************************************************************
  419. **【函数名称】 onEslEvtChannel
  420. **【函数功能】 通道事件处理
  421. **【参数】
  422. **【返回值】
  423. *****************************************************************/
  424. void CFsProxy::onEslEvtChannel( PCHAN_EVENT_NOTIFY pNotify )
  425. {
  426. ASSERT(pNotify != NULL);
  427. if (pNotify == NULL)
  428. return;
  429. CSession* pSession = __getSession(pNotify, true);
  430. ASSERT(pSession != NULL);
  431. if (pSession == NULL)
  432. {
  433. 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);
  434. return;
  435. }
  436. else
  437. {
  438. std::cout << "m_MapSession.SetAt" << pNotify->CallId << endl;
  439. std::cout << "m_MapSession.SetAt" << pSession->id() << endl;
  440. }
  441. __try {
  442. pSession->onChanEvent(pNotify);
  443. if (pSession->isVoid())
  444. __delSession(pSession->id());
  445. }
  446. __except (EXCEPTION_EXECUTE_HANDLER)
  447. {
  448. 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);
  449. __delSession(pSession->id());
  450. }
  451. }
  452. /*****************************************************************
  453. **【函数名称】 onEslEvtDtmf
  454. **【函数功能】 DTMF事件处理
  455. **【参数】
  456. **【返回值】
  457. *****************************************************************/
  458. void CFsProxy::onEslEvtDtmf( PDTMF_NOTIFY pNotify )
  459. {
  460. ASSERT(pNotify != NULL);
  461. CSession* pSession = __getSession(pNotify->CallId);
  462. ASSERT(pSession != NULL);
  463. if(pSession != NULL)
  464. pSession->onChanDtmf(pNotify);
  465. }
  466. /*****************************************************************
  467. **【函数名称】 onEslEvtHold
  468. **【函数功能】 保持事件处理
  469. **【参数】
  470. **【返回值】
  471. *****************************************************************/
  472. void CFsProxy::onEslEvtHold( PHOLD_NOTIFY pNotify )
  473. {
  474. ASSERT(pNotify != NULL);
  475. CSession* pSession = __getSession(pNotify->CallId);
  476. ASSERT(pSession != NULL);
  477. if(pSession != NULL)
  478. pSession->onChanHold(pNotify);
  479. }
  480. /*****************************************************************
  481. **【函数名称】 getExten
  482. **【函数功能】 查找分机
  483. **【参数】
  484. **【返回值】
  485. ****************************************************************/
  486. CChanExten* CFsProxy::getExten( UINT ExtenNo )
  487. {
  488. CChanExten* pExten = NULL;
  489. m_MapChanExt.Lookup(ExtenNo, pExten);
  490. return pExten;
  491. }
  492. /*****************************************************************
  493. **【函数名称】 getTrunk
  494. **【函数功能】 查找中继
  495. **【参数】
  496. **【返回值】
  497. ****************************************************************/
  498. CChanTrunk* CFsProxy::getTrunk( UINT TrunkNo )
  499. {
  500. if (TrunkNo <= 0 || TrunkNo > (UINT)m_ArrayTrunk.GetCount())
  501. return NULL;
  502. --TrunkNo;
  503. return m_ArrayTrunk[TrunkNo];
  504. }
  505. /*****************************************************************
  506. **【函数名称】 delChan
  507. **【函数功能】 删除通道
  508. **【参数】
  509. **【返回值】
  510. ****************************************************************/
  511. void CFsProxy::delChan( CVirtualChan* pChan )
  512. {
  513. if(pChan->type() == DEV_RES_TYPE_EXT)
  514. __delExten(pChan->no());
  515. }
  516. /*****************************************************************
  517. **【函数名称】 getFreeTrunk
  518. **【函数功能】 查找空闲中继
  519. **【参数】
  520. **【返回值】
  521. ****************************************************************/
  522. CChanTrunk* CFsProxy::getFreeTrunk( void )
  523. {
  524. // 当前轮循到的索引
  525. static int PosStatic = 0;
  526. int CurPos = PosStatic;
  527. int BusyTruckCount = 0;
  528. // 保证遍历一轮
  529. for(int i = 0; i < m_ArrayTrunk.GetCount(); ++i)
  530. {
  531. // 保证POS是有效的
  532. if(PosStatic >= m_ArrayTrunk.GetCount())
  533. PosStatic = 0;
  534. CChanTrunk* pTrunk = m_ArrayTrunk[PosStatic++];
  535. ASSERT(pTrunk != NULL);
  536. // 当前外线是否空闲
  537. if (pTrunk->isFree())
  538. {
  539. return pTrunk;
  540. }
  541. else
  542. {
  543. BusyTruckCount++;
  544. }
  545. }
  546. LOGGER(LOG_LEVEL_WARNING, _T("{FsProxy}: 没有空闲中继通道,起始索引=%d,当前索引=%d,中继总数量=%d,忙通道数量=%d"), CurPos, PosStatic, m_ArrayTrunk.GetCount(), BusyTruckCount);
  547. //2019.3.7
  548. PosStatic = CurPos;
  549. for (int i = 0; i < m_ArrayTrunk.GetCount(); ++i)
  550. {
  551. // 保证POS是有效的
  552. if (PosStatic >= m_ArrayTrunk.GetCount())
  553. PosStatic = 0;
  554. CChanTrunk* pTrunk = m_ArrayTrunk[PosStatic++];
  555. ASSERT(pTrunk != NULL);
  556. // 当前外线是否空闲
  557. if (pTrunk->state() == CHAN_LOGIC_STATE_FREE)
  558. {
  559. if (pTrunk->currOp() != NULL) {
  560. COperationReactor::GetInstance().releaseOpResult(pTrunk->currOp());
  561. pTrunk->releaseOp(pTrunk->currOp());
  562. LOGGER(LOG_LEVEL_WARNING, _T("{FsProxy}:没有空闲中继通道,通道[%u],释放操作."), pTrunk->no());
  563. }
  564. return pTrunk;
  565. }
  566. }
  567. LOGGER(LOG_LEVEL_WARNING, _T("{FsProxy}: 没有空闲中继通道,起始索引=%d,当前索引=%d"), CurPos, PosStatic);
  568. return NULL;
  569. }
  570. /*****************************************************************
  571. **【函数名称】 getAssoChanInSession
  572. **【函数功能】 获取会话中关联通道
  573. **【参数】
  574. **【返回值】
  575. ****************************************************************/
  576. CVirtualChan* CFsProxy::getAssoChanInSession( CVirtualChan* pChan )
  577. {
  578. CSession* pSession = __getSession(pChan->sessionId());
  579. if(pSession != NULL)
  580. return pSession->getAssoChan(pChan);
  581. else
  582. return NULL;
  583. }
  584. /*****************************************************************
  585. **【函数名称】 getBusyChan
  586. **【函数功能】 获取忙通道
  587. **【参数】
  588. **【返回值】
  589. *****************************************************************/
  590. CVirtualChan* CFsProxy::getBusyChan( LPCTSTR ChanId )
  591. {
  592. CVirtualChan* pBusyChan = NULL;
  593. m_MapBusyChan.Lookup(ChanId, pBusyChan);
  594. return pBusyChan;
  595. }
  596. /*****************************************************************
  597. **【函数名称】 regBusyChan
  598. **【函数功能】 登记忙通道
  599. **【参数】
  600. **【返回值】
  601. *****************************************************************/
  602. void CFsProxy::regBusyChan( CVirtualChan* pChan )
  603. {
  604. m_MapBusyChan.SetAt(pChan->chanId(), pChan);
  605. }
  606. /*****************************************************************
  607. **【函数名称】 unregBusyChan
  608. **【函数功能】 取消登记忙通道
  609. **【参数】
  610. **【返回值】
  611. *****************************************************************/
  612. void CFsProxy::unregBusyChan( CVirtualChan* pChan )
  613. {
  614. m_MapBusyChan.RemoveKey(pChan->chanId());
  615. }
  616. /*****************************************************************
  617. **【函数名称】 ExtenCall
  618. **【函数功能】 分机呼叫
  619. **【参数】
  620. **【返回值】
  621. ****************************************************************/
  622. bool CFsProxy::ExtenCall( LONG JobId, CVirtualChan* pChan, LPCTSTR CallerNum, LPCTSTR CalleeNum )
  623. {
  624. CString EslCmd;
  625. EslCmd.Format(_T("bgapi originate {origination_caller_id_number=%lu}user/%lu %s XML %s\r\n%s: %ld"),
  626. pChan->no(), pChan->no(), CalleeNum, CConfig::extContext(), ESL_HEADER_JOB_UUID, JobId);
  627. return m_Gateway.sendCmd(EslCmd);
  628. }
  629. bool CFsProxy::ExtenCall(CVirtualChan* pChan)
  630. {
  631. CString EslCmd;
  632. EslCmd.Format(_T("bgapi originate user/1014 &echo\n\n"));
  633. return m_Gateway.sendCmd(EslCmd);
  634. }
  635. /*****************************************************************
  636. **【函数名称】 PredictionCall
  637. **【函数功能】 预测外呼
  638. **【参数】
  639. **【返回值】
  640. ****************************************************************/
  641. bool CFsProxy::PredictionCall( LONG JobId, CString CallerNum, CString CalleeNum )
  642. {
  643. CString CallString;
  644. if(!m_CallStringMaker.makeCallStringWithDefault(CallerNum, CalleeNum, CallString))
  645. return false;
  646. CString EslCmd;
  647. EslCmd.Format(_T("bgapi originate {origination_caller_id_number=%s,%s=%ld}%s %s XML %s\r\n%s: %ld"),
  648. CallerNum, ESL_VAR_OP_INSTANCE, JobId, CallString, CalleeNum, CConfig::pCallContext(), ESL_HEADER_JOB_UUID, JobId);
  649. return m_Gateway.sendCmd(EslCmd);
  650. }
  651. /*****************************************************************
  652. **【函数名称】 answer
  653. **【函数功能】 应答通道
  654. **【参数】
  655. **【返回值】
  656. ****************************************************************/
  657. bool CFsProxy::answer( LONG JobId, CVirtualChan* pChan )
  658. {
  659. return false;
  660. }
  661. /*****************************************************************
  662. **【函数名称】 kill
  663. **【函数功能】 挂断通道
  664. **【参数】
  665. **【返回值】
  666. ****************************************************************/
  667. bool CFsProxy::kill( LONG JobId, CVirtualChan* pChan )
  668. {
  669. return __kill(JobId, pChan->chanId());
  670. }
  671. /*****************************************************************
  672. **【函数名称】 consult
  673. **【函数功能】 协商呼叫
  674. **【参数】
  675. **【返回值】
  676. ****************************************************************/
  677. bool CFsProxy::consult( LONG JobId, CVirtualChan* pChan, CString DestNum )
  678. {
  679. CString CallerNum;
  680. CString CallString;
  681. if(!m_CallStringMaker.makeCallString(CallerNum, DestNum, CallString))
  682. return false;
  683. CString EslCmd;
  684. EslCmd.Format(_T("bgapi uuid_broadcast %s att_xfer::%s\r\n%s: %ld"), pChan->chanId(), CallString, ESL_HEADER_JOB_UUID, JobId);
  685. return m_Gateway.sendCmd(EslCmd);
  686. }
  687. /*****************************************************************
  688. **【函数名称】 insert
  689. **【函数功能】 强插
  690. **【参数】
  691. **【返回值】
  692. ****************************************************************/
  693. bool CFsProxy::insert( LONG JobId, CVirtualChan* pChan, LPCTSTR DestSessionId )
  694. {
  695. CString EslCmd;
  696. EslCmd.Format(_T("bgapi originate {origination_caller_id_number=%lu}user/%lu &three_way(%s)\r\n%s: %ld"),
  697. pChan->no(), pChan->no(), DestSessionId, ESL_HEADER_JOB_UUID, JobId);
  698. return m_Gateway.sendCmd(EslCmd);
  699. }
  700. /*****************************************************************
  701. **【函数名称】 intercept
  702. **【函数功能】 强截
  703. **【参数】
  704. **【返回值】
  705. ****************************************************************/
  706. bool CFsProxy::intercept( LONG JobId, CVirtualChan* pChan, LPCTSTR DestChanId )
  707. {
  708. CString EslCmd;
  709. EslCmd.Format(_T("bgapi originate {origination_caller_id_number=%lu}user/%lu &intercept(%s)\r\n%s: %ld"),
  710. pChan->no(), pChan->no(), DestChanId, ESL_HEADER_JOB_UUID, JobId);
  711. return m_Gateway.sendCmd(EslCmd);
  712. }
  713. /*****************************************************************
  714. **【函数名称】 listen
  715. **【函数功能】 监听
  716. **【参数】
  717. **【返回值】
  718. ****************************************************************/
  719. bool CFsProxy::listen( LONG JobId, CVirtualChan* pChan, LPCTSTR DestChanId )
  720. {
  721. CString EslCmd;
  722. EslCmd.Format(_T("bgapi originate {origination_caller_id_number=%lu}user/%lu &eavesdrop(%s)\r\n%s: %ld"),
  723. pChan->no(), pChan->no(), DestChanId, ESL_HEADER_JOB_UUID, JobId);
  724. return m_Gateway.sendCmd(EslCmd);
  725. }
  726. // ych
  727. std::string CFsProxy::EslCommand(std::string strFsIp, int FsPort, std::string strName, std::string strPsWd, std::string strCommand)
  728. {
  729. if (!m_EslHandle.connected)
  730. {
  731. esl_connect(&m_EslHandle, strFsIp.c_str(), FsPort, strName.c_str(), strPsWd.c_str());
  732. }
  733. if (m_EslHandle.connected)
  734. {
  735. esl_send_recv_timed(&m_EslHandle, strCommand.c_str(), 2000);
  736. if (m_EslHandle.last_sr_event && m_EslHandle.last_sr_event->body)
  737. {
  738. std::string strRet = m_EslHandle.last_sr_event->body;
  739. return strRet;
  740. }
  741. }
  742. return "";
  743. }
  744. /*****************************************************************
  745. **【函数名称】 meeting
  746. **【函数功能】 会议
  747. **【参数】
  748. **【返回值】
  749. ****************************************************************/
  750. bool CFsProxy::meeting( LONG JobId, CString CallerNum, CString DestNum, LPCTSTR MeetingId )
  751. {
  752. bool bMatchPrefix = m_CallStringMaker.isMatchPrefix(DestNum);
  753. TRUNK_MATCH* pMatch = NULL;
  754. CString CallString;
  755. if (!m_CallStringMaker.makeCallString(CallerNum, DestNum, CallString, pMatch))
  756. return false;
  757. if (pMatch != NULL)
  758. {
  759. SIP_ACCOUNT* pAccount = CConfig::sipAccount().getAccount(pMatch->TrunkItemId);
  760. if (bMatchPrefix && pAccount != NULL && pAccount->IsDynamicGw) // 外线且动态网关
  761. {
  762. std::string strSipAccount = pAccount->Account;
  763. std::string strGwIp = EslCommand(CConfig::fsAddr(), CConfig::fsPort(), "", CConfig::fsPwd(), "api sofia_contact " + strSipAccount);
  764. if (!strGwIp.empty())
  765. {
  766. size_t Index = strGwIp.find_first_of('@');
  767. if (Index != std::string::npos)
  768. {
  769. strGwIp = strGwIp.substr(Index);
  770. CallString = "sofia/internal/";
  771. CallString += DestNum;
  772. CallString += strGwIp.c_str();
  773. }
  774. }
  775. }
  776. }
  777. LOGGER(LOG_LEVEL_NORMAL, _T("{FsProxy}: 三方会议呼叫字符串: %s"), CallString);
  778. CString EslCmd;
  779. EslCmd.Format(_T("bgapi originate {origination_caller_id_number=%s,%s=%ld}%s %s XML %s\r\n%s: %ld"),
  780. CallerNum, ESL_VAR_OP_INSTANCE, JobId, CallString, MeetingId, CConfig::meetingContext(), ESL_HEADER_JOB_UUID, JobId);
  781. return m_Gateway.sendCmd(EslCmd);
  782. }
  783. /*****************************************************************
  784. **【函数名称】 muteOn
  785. **【函数功能】 静音
  786. **【参数】
  787. **【返回值】
  788. ****************************************************************/
  789. bool CFsProxy::muteOn( LONG JobId, CVirtualChan* pChan )
  790. {
  791. CString EslCmd;
  792. EslCmd.Format(_T("bgapi uuid_audio %s start write mute -4\r\n%s: %ld"), pChan->chanId(), ESL_HEADER_JOB_UUID, JobId);
  793. return m_Gateway.sendCmd(EslCmd);
  794. }
  795. /*****************************************************************
  796. **【函数名称】 muteOff
  797. **【函数功能】 取消静音
  798. **【参数】
  799. **【返回值】
  800. ****************************************************************/
  801. bool CFsProxy::muteOff( LONG JobId, CVirtualChan* pChan )
  802. {
  803. CString EslCmd;
  804. EslCmd.Format(_T("bgapi uuid_audio %s stop write mute -4\r\n%s: %ld"), pChan->chanId(), ESL_HEADER_JOB_UUID, JobId);
  805. return m_Gateway.sendCmd(EslCmd);
  806. }
  807. /*****************************************************************
  808. **【函数名称】 holdon
  809. **【函数功能】 保持
  810. **【参数】
  811. **【返回值】
  812. ****************************************************************/
  813. bool CFsProxy::holdon( LONG JobId, CVirtualChan* pChan )
  814. {
  815. // by 屏蔽了uuid_hold命令以及sendCmd函数
  816. CString EslCmd;
  817. EslCmd.Format(_T("bgapi uuid_hold %s\r\n%s"), pChan->chanId(),ESL_HEADER_JOB_UUID);
  818. return m_Gateway.sendCmd(EslCmd);
  819. /*EslCmd.Format(_T("bgapi uuid_hold %s\r\n%s: %ld"), pChan->chanId(), ESL_HEADER_JOB_UUID, JobId);
  820. return m_Gateway.sendCmd(EslCmd);*/
  821. }
  822. /*****************************************************************
  823. **【函数名称】 takeBack
  824. **【函数功能】 接回
  825. **【参数】
  826. **【返回值】
  827. ****************************************************************/
  828. bool CFsProxy::takeBack( LONG JobId, CVirtualChan* pChan )
  829. {
  830. CString EslCmd;
  831. EslCmd.Format(_T("bgapi uuid_hold off %s\r\n%s: %ld"), pChan->chanId(), ESL_HEADER_JOB_UUID, JobId);
  832. return m_Gateway.sendCmd(EslCmd);
  833. }
  834. /*****************************************************************
  835. **【函数名称】 record
  836. **【函数功能】 录音
  837. **【参数】
  838. **【返回值】
  839. ****************************************************************/
  840. bool CFsProxy::record( LONG JobId, CVirtualChan* pChan, LPCTSTR RcdFile )
  841. {
  842. CString EslCmd;
  843. EslCmd.Format(_T("bgapi uuid_record %s start %s\r\n%s: %ld"), pChan->chanId(), RcdFile, ESL_HEADER_JOB_UUID, JobId);
  844. return m_Gateway.sendCmd(EslCmd);
  845. }
  846. /*****************************************************************
  847. **【函数名称】 transfer
  848. **【函数功能】 呼叫转移
  849. **【参数】
  850. **【返回值】
  851. ****************************************************************/
  852. bool CFsProxy::transfer( LONG JobId, CVirtualChan* pChan, LPCTSTR DestNum )
  853. {
  854. CString EslCmd;
  855. EslCmd.Format(_T("bgapi uuid_transfer %s %s xml %s\r\n%s: %ld"), pChan->chanId(), DestNum, CConfig::extContext(), ESL_HEADER_JOB_UUID, JobId);
  856. return m_Gateway.sendCmd(EslCmd);
  857. }
  858. /*****************************************************************
  859. **【函数名称】 transfer2Context
  860. **【函数功能】 转移通道至其它Context
  861. **【参数】
  862. **【返回值】
  863. ****************************************************************/
  864. bool CFsProxy::transfer2Context( LONG JobId, LPCTSTR DestChanId, LPCTSTR Exten, LPCTSTR Context, bool BothSide /*= false*/ )
  865. {
  866. CString EslCmd;
  867. if(BothSide)
  868. EslCmd.Format(_T("bgapi uuid_transfer %s -both %s xml %s\r\n%s: %ld"), DestChanId, Exten, Context, ESL_HEADER_JOB_UUID, JobId);
  869. else
  870. EslCmd.Format(_T("bgapi uuid_transfer %s %s xml %s\r\n%s: %ld"), DestChanId, Exten, Context, ESL_HEADER_JOB_UUID, JobId);
  871. return m_Gateway.sendCmd(EslCmd);
  872. }
  873. /*****************************************************************
  874. **【函数名称】 cancel
  875. **【函数功能】 取消当前执行的应用
  876. **【参数】
  877. **【返回值】
  878. ****************************************************************/
  879. bool CFsProxy::cancel( CChanTrunk* pChan )
  880. {
  881. ASSERT(pChan != NULL);
  882. return m_Gateway.Execte2(ESL_APP_BREAK,NULL,pChan->chanId());
  883. }
  884. /*****************************************************************
  885. **【函数名称】 hangup
  886. **【函数功能】 挂机
  887. **【参数】
  888. **【返回值】
  889. ****************************************************************/
  890. bool CFsProxy::hangup( CChanTrunk* pChan )
  891. {
  892. ASSERT(pChan != NULL);
  893. return m_Gateway.execute(pChan->m_pEslHandle,ESL_APP_HANGUP,NULL);
  894. }
  895. /*****************************************************************
  896. **【函数名称】 leaveWord
  897. **【函数功能】 留言
  898. **【参数】
  899. **【返回值】
  900. ****************************************************************/
  901. bool CFsProxy::leaveWord( CChanTrunk* pChan, LPCTSTR FileName, UINT LimitTime, TCHAR FinishKey )
  902. {
  903. ASSERT(pChan != NULL);
  904. CString Param;
  905. Param.Format(_T("playback_terminators=%c"), FinishKey);
  906. m_Gateway.Execte2(ESL_APP_SET,Param,pChan->chanId());
  907. Param.Format(_T("%s %lu"), FileName, LimitTime);
  908. return m_Gateway.Execte2(ESL_APP_LEAVEWORD,Param,pChan->chanId());
  909. }
  910. /*****************************************************************
  911. **【函数名称】 playAndDtmf
  912. **【函数功能】 放音收按键
  913. **【参数】
  914. **【返回值】
  915. ****************************************************************/
  916. bool CFsProxy::playAndDtmf( CChanTrunk* pChan, PlayVoiceContent* pPlayContent )
  917. {
  918. ASSERT(pChan != NULL);
  919. ASSERT(pPlayContent != NULL);
  920. if(pChan==NULL||pPlayContent==NULL) return false;
  921. TCHAR AudioFile[MAX_PATH] = { 0 };
  922. // 如果使用了TTS,进行TTS转换
  923. switch(pPlayContent->nTts)
  924. {
  925. default:
  926. case PLAY_CONTENT_AUDIO: // 不使用TTS
  927. lstrcpy(AudioFile, pPlayContent->szFileName);
  928. break;
  929. case PLAY_CONTENT_TTS_STR: // TTS文本
  930. {
  931. ITtsInterface::getInstance().setTTSParam(pPlayContent->nTtsDigitMode, pPlayContent->nTtsSpeed, pPlayContent->nTtsVolume);
  932. if(!ITtsInterface::getInstance().string2Audio(pPlayContent->szFileName, AudioFile, MAX_PATH))
  933. {
  934. LOGGER(LOG_LEVEL_WARNING, _T("{FsProxy}: 中继通道[%lu]放音时TTS文本转换失败"), pChan->no());
  935. return false;
  936. }
  937. }
  938. break;
  939. case PLAY_CONTENT_TTS_FILE: // TTS文件
  940. {
  941. ITtsInterface::getInstance().setTTSParam(pPlayContent->nTtsDigitMode, pPlayContent->nTtsSpeed, pPlayContent->nTtsVolume);
  942. if(!ITtsInterface::getInstance().file2Audio(pPlayContent->szFileName, AudioFile, MAX_PATH))
  943. {
  944. LOGGER(LOG_LEVEL_WARNING, _T("{FsProxy}: 中继通道[%lu]放音时TTS文件转换失败, File = %s"), pChan->no(), pPlayContent->szFileName);
  945. return false;
  946. }
  947. }
  948. break;
  949. }
  950. CString Param;
  951. if(pPlayContent->nModel == PVM_PLAY_ONLY && pPlayContent->cDtmfEnd == 0)
  952. {
  953. Param.Format(_T("playback_terminators=none"));
  954. m_Gateway.Execte2(ESL_APP_SET,Param,pChan->chanId());
  955. //m_Gateway.execute(pChan->m_pEslHandle,ESL_APP_SET,Param);
  956. Param.Format(_T("%s"), AudioFile);
  957. //return m_Gateway.Execte2(ESL_APP_PLAY,Param,pChan->chanId());
  958. return m_Gateway.execute(pChan->m_pEslHandle,ESL_APP_PLAY,Param);
  959. }
  960. else
  961. {
  962. Param.Format(_T("%lu %lu 1 %lu %c %s slience_stream:0 %s"), pPlayContent->nDtmfCount, pPlayContent->nDtmfCount,
  963. pPlayContent->nDtmfCount * pPlayContent->nDtmfPeriod * 1000, pPlayContent->cDtmfEnd, AudioFile, ESL_VAR_DTMF_KEY);
  964. return m_Gateway.execute(pChan->m_pEslHandle,ESL_APP_PLAY_DTMF,Param);
  965. }
  966. }
  967. //by 2019-09-11
  968. bool CFsProxy::ExtenPlayback(LONG JobId, CChanExten* pChan, PlayVoiceContent* pPlayContent)
  969. {
  970. CString EslCmd;
  971. EslCmd.Format(_T("bgapi uuid_playback %s start %s\r\n%s: %ld"), pChan->chanId(), pPlayContent->szFileName, ESL_HEADER_JOB_UUID, JobId);
  972. return m_Gateway.sendCmd(EslCmd);;
  973. }
  974. bool CFsProxy::playAndDtmf(CChanExten* pChanExten, PlayVoiceContent* pPlayContent)
  975. {
  976. ASSERT(pChan != NULL);
  977. ASSERT(pPlayContent != NULL);
  978. if (pChanExten == NULL || pPlayContent == NULL) return false;
  979. TCHAR AudioFile[MAX_PATH] = { 0 };
  980. // 如果使用了TTS,进行TTS转换
  981. switch (pPlayContent->nTts)
  982. {
  983. default:
  984. case PLAY_CONTENT_AUDIO: // 不使用TTS
  985. lstrcpy(AudioFile, pPlayContent->szFileName);
  986. break;
  987. case PLAY_CONTENT_TTS_STR: // TTS文本
  988. {
  989. ITtsInterface::getInstance().setTTSParam(pPlayContent->nTtsDigitMode, pPlayContent->nTtsSpeed, pPlayContent->nTtsVolume);
  990. if (!ITtsInterface::getInstance().string2Audio(pPlayContent->szFileName, AudioFile, MAX_PATH))
  991. {
  992. LOGGER(LOG_LEVEL_WARNING, _T("{FsProxy}: 中继通道[%lu]放音时TTS文本转换失败"), pChanExten->no());
  993. return false;
  994. }
  995. }
  996. break;
  997. case PLAY_CONTENT_TTS_FILE: // TTS文件
  998. {
  999. ITtsInterface::getInstance().setTTSParam(pPlayContent->nTtsDigitMode, pPlayContent->nTtsSpeed, pPlayContent->nTtsVolume);
  1000. if (!ITtsInterface::getInstance().file2Audio(pPlayContent->szFileName, AudioFile, MAX_PATH))
  1001. {
  1002. LOGGER(LOG_LEVEL_WARNING, _T("{FsProxy}: 中继通道[%lu]放音时TTS文件转换失败, File = %s"), pChanExten->no(), pPlayContent->szFileName);
  1003. return false;
  1004. }
  1005. }
  1006. break;
  1007. }
  1008. CString Param;
  1009. if (pPlayContent->nModel == PVM_PLAY_ONLY && pPlayContent->cDtmfEnd == 0)
  1010. {
  1011. Param.Format(_T("playback_terminators=none"));
  1012. m_Gateway.Execte2(ESL_APP_SET, Param, pChanExten->chanId());
  1013. Param.Format(_T("%s"), AudioFile);
  1014. return m_Gateway.Execte2(ESL_APP_PLAY_DTMF, Param, pChanExten->chanId());
  1015. }
  1016. else
  1017. {
  1018. /*Param.Format(_T("playback_terminators=none"));
  1019. m_Gateway.Execte2(ESL_APP_SET, Param, pChanExten->chanId());*/
  1020. Param.Format(_T("%s"), AudioFile);
  1021. return m_Gateway.Execte2(ESL_APP_PLAY_DTMF, Param, pChanExten->chanId());
  1022. }
  1023. }
  1024. /*****************************************************************
  1025. **【函数名称】
  1026. **【函数功能】 桥接通道
  1027. **【参数】
  1028. **【返回值】
  1029. ****************************************************************/
  1030. bool CFsProxy::bridge( CChanTrunk* pChan, CString CallerNum, CString CalleeNum )
  1031. {
  1032. CString CallString;
  1033. CallerNum = "0000000000";
  1034. CalleeNum = "1030";
  1035. if(!m_CallStringMaker.makeCallString(CallerNum, CalleeNum, CallString))
  1036. return false;
  1037. CString Param;
  1038. Param.Format(_T("ringback=${us-ring}"));
  1039. m_Gateway.Execte2(ESL_APP_SET,Param,pChan->chanId());
  1040. return m_Gateway.Execte2(ESL_APP_BRIDGE,CallString,pChan->chanId());
  1041. /*CString EslCmd;
  1042. EslCmd.Format(_T("bgapi uuid_transfer %s %s xml"), pChan->chanId(), CalleeNum, "TurnOut.xml");
  1043. return m_Gateway.sendCmd(EslCmd);*/
  1044. }
  1045. bool CFsProxy::origine(CChanExten* pChan,CString CallerNum, CString CalleeNum,LONG JobId)
  1046. {
  1047. CString EslCmd;
  1048. EslCmd.Format(_T("bgapi originate user/%s &echo"),CalleeNum/*,pChan->chanId(), ESL_HEADER_JOB_UUID, JobId*/);
  1049. //EslCmd.Format(_T("originate{ origination_uuid = %s }user /1017"), pChan->chanId());
  1050. return m_Gateway.sendCmd(EslCmd);
  1051. }
  1052. bool CFsProxy::origine(CString ExtenID)
  1053. {
  1054. CString EslCmd;
  1055. EslCmd.Format(_T("bgapi originate user/%s &park"), ExtenID);
  1056. return m_Gateway.sendCmd(EslCmd);
  1057. }