中间件底层,websocket

FsProxy.cpp 39KB

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