修改三方通话功能,在发起三方通话时,先保持住主叫,然后再拉回主叫到会议

ProxyShell.cpp 45KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659
  1. #include "StdAfx.h"
  2. #include "ProxyShell.h"
  3. #include "MC.h"
  4. #include "MsgCenter.h"
  5. #include "ProxyDti.h"
  6. #include "ProxyVoip.h"
  7. #include "ProxyExten.h"
  8. #include "NetLinkMgr.h"
  9. #include "ReqBase.h"
  10. #include "Config.h"
  11. #include "SessionShell.h"
  12. #include "ControlShell.h"
  13. #include "PlaySoundReq.h"
  14. #include "MakeCallReq.h"
  15. #include "TrunkTurnReq.h"
  16. #include "TurnAgentReq.h"
  17. #include "AnswerCallReq.h"
  18. #include "PredictionCallReq.h"
  19. #include "TransferReq.h"
  20. #include "MeetingReq.h"
  21. #include "InsteadReq.h"
  22. #include "InterceptReq.h"
  23. #include "InsertReq.h"
  24. #include "ListenReq.h"
  25. #include "FaxReq.h"
  26. #include "LeaveWordReq.h"
  27. #include "MuteReq.h"
  28. #include "ConsultCallReq.h"
  29. #include "OneLeg.h"
  30. #include "ChannelResource.h"
  31. #include "VoipChannel.h"
  32. #include "TrunkAidedAllocator.h"
  33. SINGLETON_IMPLEMENT(CProxyShell)
  34. CProxyShell::CProxyShell(void)
  35. {
  36. }
  37. CProxyShell::~CProxyShell(void)
  38. {
  39. __free();
  40. }
  41. /*****************************************************************
  42. **【函数名称】 __free
  43. **【函数功能】 释放资源
  44. **【参数】
  45. **【返回值】
  46. ****************************************************************/
  47. void CProxyShell::__free( void )
  48. {
  49. UINT LineId;
  50. CProxyExten* pExten;
  51. POSITION Pos = m_ExtenMap.GetStartPosition();
  52. while(Pos != NULL)
  53. {
  54. m_ExtenMap.GetNextAssoc(Pos, LineId, pExten);
  55. ASSERT(pExten != NULL);
  56. delete pExten;
  57. }
  58. m_ExtenMap.RemoveAll();
  59. CProxyVoip* pVoip;
  60. Pos = m_VoipMap.GetStartPosition();
  61. while(Pos != NULL)
  62. {
  63. m_VoipMap.GetNextAssoc(Pos, LineId, pVoip);
  64. ASSERT(pVoip != NULL);
  65. delete pVoip;
  66. }
  67. m_VoipMap.RemoveAll();
  68. CProxyDti* pDti;
  69. Pos = m_DtiMap.GetStartPosition();
  70. while(Pos != NULL)
  71. {
  72. m_DtiMap.GetNextAssoc(Pos, LineId, pDti);
  73. ASSERT(pDti != NULL);
  74. delete pDti;
  75. }
  76. m_DtiMap.RemoveAll();
  77. }
  78. /*****************************************************************
  79. **【函数名称】 __getProxyExten
  80. **【函数功能】 根据分机号查找内线代理并绑定VOIP线路
  81. **【参数】 ExtnNum 内线分机号
  82. **【返回值】
  83. ****************************************************************/
  84. CProxyExten* CProxyShell::__getProxyExten( UINT ExtnNum )
  85. {
  86. CProxyExten* pExten = NULL;
  87. m_ExtenMap.Lookup(ExtnNum, pExten);
  88. return pExten;
  89. }
  90. /*****************************************************************
  91. **【函数名称】 __getProxyVoip
  92. **【函数功能】 根据VOIP号查找VOIP线路
  93. **【参数】 VoipId 线路ID
  94. **【返回值】
  95. ****************************************************************/
  96. CProxyVoip* CProxyShell::__getProxyVoip( UINT VoipId )
  97. {
  98. CProxyVoip* pVoip = NULL;
  99. m_VoipMap.Lookup(VoipId, pVoip);
  100. return pVoip;
  101. }
  102. /*****************************************************************
  103. **【函数名称】 __getProxyTrunk
  104. **【函数功能】 根据外线ID查找外线代理
  105. **【参数】 TrunkId 外线ID
  106. **【返回值】
  107. ****************************************************************/
  108. CVirtualProxy* CProxyShell::__getProxyTrunk( UINT TrunkId )
  109. {
  110. CProxyDti* pDti = NULL;
  111. if(m_DtiMap.Lookup(TrunkId, pDti))
  112. return pDti;
  113. CProxyVoip* pVoip = NULL;
  114. m_VoipMap.Lookup(TrunkId, pVoip);
  115. return pVoip;
  116. }
  117. /*****************************************************************
  118. **【函数名称】 onNetworkClientConnect
  119. **【函数功能】 网络客户端连接的处理函数
  120. **【参数】
  121. **【返回值】
  122. ****************************************************************/
  123. void CProxyShell::onNetworkClientReg( PDU_DEV_TYPE DestType, int DestId )
  124. {
  125. UINT LineId;
  126. CProxyExten* pExten;
  127. POSITION Pos = m_ExtenMap.GetStartPosition();
  128. while(Pos != NULL)
  129. {
  130. m_ExtenMap.GetNextAssoc(Pos, LineId, pExten);
  131. ASSERT(pExten != NULL);
  132. if(!pExten->invalidFlag())
  133. pExten->notifyLineInfo(DestType, DestId);
  134. }
  135. CProxyVoip* pVoip;
  136. Pos = m_VoipMap.GetStartPosition();
  137. while(Pos != NULL)
  138. {
  139. m_VoipMap.GetNextAssoc(Pos, LineId, pVoip);
  140. ASSERT(pVoip != NULL);
  141. if(!pVoip->invalidFlag())
  142. pVoip->notifyLineInfo(DestType, DestId);
  143. }
  144. CProxyDti* pDti;
  145. Pos = m_DtiMap.GetStartPosition();
  146. while(Pos != NULL)
  147. {
  148. m_DtiMap.GetNextAssoc(Pos, LineId, pDti);
  149. ASSERT(pDti != NULL);
  150. if(!pDti->invalidFlag())
  151. pDti->notifyLineInfo(DestType, DestId);
  152. }
  153. if(CMC::GetInstance().isPbxOK(0))
  154. notifyDevResourceState(DEV_RES_TYPE_MB, 0, DEVICE_STATE_ENABLE);
  155. }
  156. /*****************************************************************
  157. **【函数名称】 onNetworkClientReq
  158. **【函数功能】 网络客户端请求的处理函数
  159. **【参数】
  160. **【返回值】
  161. ****************************************************************/
  162. void CProxyShell::onNetworkClientReq( CPduEntity* pReq )
  163. {
  164. ASSERT(pReq != NULL);
  165. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, _T("{ClientProxy}: 网络客户端请求, Req = %d"), pReq->GetCmdType());
  166. bool Res = false;
  167. // 根据操作类型进行分类处理
  168. switch(pReq->GetCmdType())
  169. {
  170. case PDU_CMD_SC_REQ_MAKECALL: // 座席外呼
  171. Res = __procReqMakeCall(*pReq);
  172. break;
  173. case PDU_CMD_SC_REQ_ANSWER: // 应答呼叫
  174. Res = __procReqAnswerCall(*pReq);
  175. break;
  176. case PDU_CMD_SC_REQ_PCALL: // 预测外呼
  177. Res = __procReqPCall(*pReq);
  178. break;
  179. case PDU_CMD_SC_REQ_HANGUP: // 挂机
  180. Res = __procReqHangUp(*pReq);
  181. break;
  182. case PDU_CMD_SC_REQ_TRANSFER: // 呼叫转移
  183. Res = __procReqTransfer(*pReq);
  184. break;
  185. case PDU_CMD_SC_REQ_TRUNKTURN: // 转外线
  186. Res = __procReqTrunkTurn(*pReq);
  187. break;
  188. case PDU_CMD_SC_REQ_TURNAGENT: // 转坐席
  189. Res = __procReqTurnAgent(*pReq);
  190. break;
  191. case PDU_CMD_SC_REQ_TURNIVR: // 转IVR
  192. Res = __procReqTurnIvr(*pReq);
  193. break;
  194. case PDU_CMD_SC_REQ_MEETING: // 单步会议
  195. Res = __procReqMeeting(*pReq);
  196. break;
  197. case PDU_CMD_SC_REQ_LISTEN: // 监听
  198. Res = __procReqListen(*pReq);
  199. break;
  200. case PDU_CMD_SC_REQ_INSERT: // 强插
  201. Res = __procReqInsert(*pReq);
  202. break;
  203. case PDU_CMD_SC_REQ_RESET: // 重置
  204. Res = __procReqReset(*pReq);
  205. break;
  206. case PDU_CMD_SC_REQ_INSTEAD: // 代接
  207. Res = __procReqInstead(*pReq);
  208. break;
  209. case PDU_CMD_SC_REQ_INTERCEPT: // 强截
  210. Res = __procReqIntercept(*pReq);
  211. break;
  212. case PDU_CMD_SC_REQ_INFOTRANSFER: // 信息交互
  213. Res = __procReqInfoTransfer(*pReq);
  214. break;
  215. case PDU_CMD_SC_REQ_PLAY: // 放音收号
  216. Res = __procReqPlaySound(*pReq);
  217. break;
  218. case PDU_CMD_SC_REQ_FAX: // 传真
  219. Res = __procReqFax(*pReq);
  220. break;
  221. case PDU_CMD_SC_REQ_RECORD: // 录音
  222. Res = __procReqRecord(*pReq);
  223. break;
  224. case PDU_CMD_SC_REQ_LEAVEWORD: // 留言
  225. Res = __procReqLeaveWord(*pReq);
  226. break;
  227. case PDU_CMD_SC_REQ_MUTE:
  228. {
  229. if(pReq->GetDataUInt(3) == CLIENT_REQ_MUTE_ON)
  230. Res = __procReqMuteOn(*pReq); // 静音开始
  231. else
  232. Res = __procReqMuteOff(*pReq); // 静音结束
  233. }
  234. break;
  235. case PDU_CMD_SC_REQ_LINECHECK: // 线路自检
  236. Res = __procReqLineCheck(*pReq);
  237. break;
  238. case PDU_CMD_SC_REQ_CONSULTCALL: // 协商呼叫启动
  239. Res = __procReqConsultCall(*pReq);
  240. break;
  241. case PDU_CMD_SC_REQ_CONSULTCONFIRM: // 协商呼叫确认
  242. Res = __procReqConsultCallConfirm(*pReq);
  243. break;
  244. default:
  245. ASSERT(FALSE);
  246. } // end switch
  247. pReq->SetDataBool(1, Res);
  248. CNetLinkMgr::GetInstance().send(pReq, pReq->GetLocalDevType(), pReq->GetLocalDevId());
  249. }
  250. /*****************************************************************
  251. **【函数名称】 __beginLineReq
  252. **【函数功能】 启动线路操作
  253. **【参数】 pLineReq 线路操作实体
  254. **【返回值】
  255. ****************************************************************/
  256. bool CProxyShell::__beginLineReq( CReqBase* pLineReq )
  257. {
  258. if(!pLineReq->request())
  259. {
  260. pLineReq->detachHostLine();
  261. delete pLineReq;
  262. return false;
  263. } // end if
  264. return true;
  265. }
  266. /*****************************************************************
  267. **【函数名称】 __procReqInfoTransfer
  268. **【函数功能】 数据交互
  269. **【参数】
  270. **【返回值】 启动操作是否成功
  271. ****************************************************************/
  272. bool CProxyShell::__procReqInfoTransfer( CPduEntity& a_Req )
  273. {
  274. // 通过设备资源查找主控线路
  275. CVirtualProxy* pHostLine = getProxyExtenWrapped(a_Req.GetDataUInt(2));
  276. if(pHostLine == NULL)
  277. {
  278. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行数据交换请求失败, 未找到线路[%lu], Instance = %d"),
  279. a_Req.GetDataUInt(2), a_Req.GetDataLong(0));
  280. return false;
  281. }
  282. // 查找线路关联的操作
  283. CReqBase* pCurrReq = pHostLine->currLineReq();
  284. if(pCurrReq == NULL)
  285. {
  286. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行数据交换请求失败, 线路[%lu]当前空闲, Instance = %d"),
  287. a_Req.GetDataUInt(2), a_Req.GetDataLong(0));
  288. return false;
  289. }
  290. // 执行信息交互
  291. pCurrReq->setAssoInfo(a_Req);
  292. return true;
  293. }
  294. /*****************************************************************
  295. **【函数名称】 __procReqPlayVoice
  296. **【函数功能】 线路放音收号
  297. **【参数】
  298. **【返回值】
  299. ****************************************************************/
  300. bool CProxyShell::__procReqPlaySound( CPduEntity& a_Req )
  301. {
  302. // 通过设备资源查找主控线路
  303. CVirtualProxy* pLine = getProxy(a_Req.GetDataUInt(2));
  304. if(pLine == NULL)
  305. {
  306. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行放音请求失败, 未找到线路[%lu], mode = %d, AudioFile = %s"),
  307. a_Req.GetDataUInt(2), a_Req.GetDataInt(3), a_Req.GetDataString(12));
  308. return false;
  309. }
  310. CReqBase* pCurrReq = pLine->currLineReq();
  311. if(a_Req.GetDataInt(3) == PVM_STOP_PLAY) // 停止放音
  312. {
  313. // 如果线路未在执行放音操作
  314. if(pCurrReq == NULL || dynamic_cast<CPlaySoundReq*>(pCurrReq) == NULL)
  315. {
  316. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行停止放音请求失败, 线路[%lu]未执行放音操作"), a_Req.GetDataUInt(2));
  317. return false;
  318. }
  319. else
  320. return pCurrReq->cancel(a_Req.GetDataLong(0)); // 执行取消操作
  321. }
  322. else // 启动放音
  323. {
  324. // 如果线路正在执行其它操作
  325. if(pCurrReq != NULL)
  326. {
  327. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行放音请求失败, 线路[%lu]忙, mode = %d, AudioFile = %s"),
  328. a_Req.GetDataUInt(2), a_Req.GetDataInt(3), a_Req.GetDataString(12));
  329. return false;
  330. }
  331. // 生成放音操作类
  332. CReqBase* pLineReq = new CPlaySoundReq(this, a_Req);
  333. pLineReq->attachHostLine(pLine);
  334. // 启动操作
  335. return __beginLineReq(pLineReq);
  336. } // end if
  337. }
  338. /*****************************************************************
  339. **【函数名称】 __procReqMakeCall
  340. **【函数功能】 坐席外呼处理
  341. **【参数】
  342. **【返回值】
  343. ****************************************************************/
  344. bool CProxyShell::__procReqMakeCall( CPduEntity& a_Req )
  345. {
  346. // 通过设备资源查找主控线路
  347. CProxyExten* pLine = getProxyExtenWrapped(a_Req.GetDataUInt(2));
  348. if(pLine == NULL)
  349. {
  350. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行呼叫请求失败, 未找到线路[%lu], DestNum = %s"),
  351. a_Req.GetDataUInt(2), a_Req.GetDataString(3));
  352. return false;
  353. }
  354. // 如果线路正在执行其它操作
  355. if(pLine->currLineReq() != NULL)
  356. {
  357. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行呼叫请求失败, 线路[%lu]忙, DestNum = %s"),
  358. a_Req.GetDataUInt(2), a_Req.GetDataString(3));
  359. return false;
  360. }
  361. // 生成外呼操作类
  362. CReqBase* pLineReq = new CMakeCallReq(this, a_Req);
  363. pLineReq->attachHostLine(pLine);
  364. // 启动操作
  365. return __beginLineReq(pLineReq);
  366. }
  367. /*****************************************************************
  368. **【函数名称】 __procReqHangUp
  369. **【函数功能】 挂机操作处理
  370. **【参数】
  371. **【返回值】
  372. ****************************************************************/
  373. bool CProxyShell::__procReqHangUp( CPduEntity& a_Req )
  374. {
  375. long InstanceCall = a_Req.GetDataLong(0);
  376. // 查找要挂机的线路
  377. CVirtualProxy* pLine = getProxy(a_Req.GetDataUInt(2));
  378. if(pLine == NULL)
  379. {
  380. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行挂机请求失败, 未找到线路[%lu], Instance = %d"),
  381. a_Req.GetDataUInt(2), InstanceCall);
  382. return false;
  383. } // end if
  384. // 如果线路正在执行其它操作
  385. if(pLine->currLineReq() != NULL)
  386. return pLine->currLineReq()->hangUp(InstanceCall);
  387. // 执行挂机操作
  388. if(CMC::GetInstance().dropCall(pLine->devId(), false))
  389. {
  390. notifyReqResult(a_Req, InstanceCall, true);
  391. return true;
  392. } // end if
  393. return false;
  394. }
  395. /*****************************************************************
  396. **【函数名称】 __procReqTrunkTurn
  397. **【函数功能】 外线呼叫跳转
  398. **【参数】
  399. **【返回值】
  400. ****************************************************************/
  401. bool CProxyShell::__procReqTrunkTurn( CPduEntity& a_Req )
  402. {
  403. // 通过设备资源查找主控线路
  404. CVirtualProxy* pLine = __getProxyTrunk(a_Req.GetDataUInt(2));
  405. if(pLine == NULL)
  406. {
  407. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行中继呼叫跳转失败, 未找到中继线路[%lu], DestNum = %s"),
  408. a_Req.GetDataUInt(2), a_Req.GetDataString(3));
  409. return false;
  410. }
  411. // 当前线路是否正在进行其它操作
  412. if(pLine->currLineReq() != NULL)
  413. {
  414. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行中继呼叫跳转失败, 中继线路[%lu]忙, DestNum = %s"),
  415. a_Req.GetDataUInt(2), a_Req.GetDataString(3));
  416. return false;
  417. }
  418. // 生成外线呼叫转移操作类
  419. CReqBase* pLineReq = new CTrunkTurnReq(this, a_Req);
  420. pLineReq->attachHostLine(pLine);
  421. // 启动操作
  422. return __beginLineReq(pLineReq);
  423. }
  424. /*****************************************************************
  425. **【函数名称】 __procReqTurnAgent
  426. **【函数功能】 外线转坐席
  427. **【参数】
  428. **【返回值】
  429. ****************************************************************/
  430. bool CProxyShell::__procReqTurnAgent( CPduEntity& a_Req )
  431. {
  432. // 通过设备资源查找主控线路
  433. CVirtualProxy* pLine = __getProxyTrunk(a_Req.GetDataUInt(2));
  434. if(pLine == NULL)
  435. {
  436. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行中继转座席失败, 未找到中继线路[%lu], ExtenNum = %s"),
  437. a_Req.GetDataUInt(2), a_Req.GetDataString(3));
  438. return false;
  439. }
  440. // 当前线路是否正在进行其它操作
  441. if(pLine->currLineReq() != NULL)
  442. {
  443. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行中继转座席失败, 中继线路[%lu]忙, ExtenNum = %s"),
  444. a_Req.GetDataUInt(2), a_Req.GetDataString(3));
  445. return false;
  446. }
  447. // 生成外线呼叫转移操作类
  448. CReqBase* pLineReq = new CTurnAgentReq(this, a_Req);
  449. pLineReq->attachHostLine(pLine);
  450. // 启动操作
  451. return __beginLineReq(pLineReq);
  452. }
  453. /*****************************************************************
  454. **【函数名称】 __procReqAnswerCall
  455. **【函数功能】 应答呼叫
  456. **【参数】
  457. **【返回值】
  458. ****************************************************************/
  459. bool CProxyShell::__procReqAnswerCall( CPduEntity& a_Req )
  460. {
  461. // 查找要应答呼叫的线路
  462. CVirtualProxy* pLine = getProxyExtenWrapped(a_Req.GetDataUInt(2));
  463. if(pLine == NULL)
  464. {
  465. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行应答请求失败, 未找到线路[%lu], Instance = %d"),
  466. a_Req.GetDataUInt(2), a_Req.GetDataLong(0));
  467. return false;
  468. } // end if
  469. // 如果线路正在执行其它操作
  470. if(pLine->currLineReq() != NULL)
  471. {
  472. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行应答请求失败, 线路[%lu]忙, Instance = %d"),
  473. a_Req.GetDataUInt(2), a_Req.GetDataLong(0));
  474. return false;
  475. }
  476. // 生成应答呼叫操作类
  477. CReqBase* pLineReq = new CAnswerCallReq(this, a_Req);
  478. pLineReq->attachHostLine(pLine);
  479. // 启动操作
  480. return __beginLineReq(pLineReq);
  481. }
  482. /*****************************************************************
  483. **【函数名称】 __procReqPCall
  484. **【函数功能】 预测外呼
  485. **【参数】
  486. **【返回值】
  487. ****************************************************************/
  488. bool CProxyShell::__procReqPCall( CPduEntity& a_Req )
  489. {
  490. // 生成自动呼叫操作类
  491. CReqBase* pLineReq = new CPredictionCallReq(this, a_Req);
  492. // 启动操作
  493. return __beginLineReq(pLineReq);
  494. }
  495. /*****************************************************************
  496. **【函数名称】 __procReqTransfer
  497. **【函数功能】 座席呼叫转移
  498. **【参数】
  499. **【返回值】
  500. ****************************************************************/
  501. bool CProxyShell::__procReqTransfer( CPduEntity& a_Req )
  502. {
  503. // 通过设备资源查找主控线路
  504. CProxyExten* pLine = getProxyExtenWrapped(a_Req.GetDataUInt(2));
  505. if(pLine == NULL)
  506. {
  507. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行呼叫转移请求失败, 未找到线路[%lu], DestNum = %s"),
  508. a_Req.GetDataUInt(2), a_Req.GetDataString(3));
  509. return false;
  510. }
  511. // 如果线路正在执行其它操作
  512. if(pLine->currLineReq() != NULL)
  513. {
  514. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行呼叫转移请求失败, 线路[%lu]忙, DestNum = %s"),
  515. a_Req.GetDataUInt(2), a_Req.GetDataString(3));
  516. return false;
  517. }
  518. CReqBase* pLineReq = new CTransferReq(this, a_Req);
  519. pLineReq->attachHostLine(pLine);
  520. // 启动操作
  521. return __beginLineReq(pLineReq);
  522. }
  523. /*****************************************************************
  524. **【函数名称】 __procReqMeeting
  525. **【函数功能】 单步会议
  526. **【参数】
  527. **【返回值】
  528. ****************************************************************/
  529. bool CProxyShell::__procReqMeeting( CPduEntity& a_Req )
  530. {
  531. // 通过设备资源查找主控线路
  532. CProxyExten* pLine = getProxyExtenWrapped(a_Req.GetDataUInt(2));
  533. if(pLine == NULL)
  534. {
  535. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行会议请求失败, 未找到线路[%lu], DestNum = %s"),
  536. a_Req.GetDataUInt(2), a_Req.GetDataString(3));
  537. return false;
  538. }
  539. // 如果线路正在执行其它操作
  540. if(pLine->currLineReq() != NULL)
  541. {
  542. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行会议请求失败, 线路[%lu]忙, DestNum = %s"),
  543. a_Req.GetDataUInt(2), a_Req.GetDataString(3));
  544. return false;
  545. }
  546. CReqBase* pLineReq = new CMeetingReq(this, a_Req);
  547. pLineReq->attachHostLine(pLine);
  548. // 启动操作
  549. return __beginLineReq(pLineReq);
  550. }
  551. /*****************************************************************
  552. **【函数名称】 __procReqTurnIvr
  553. **【函数功能】 转IVR
  554. **【参数】
  555. **【返回值】
  556. ****************************************************************/
  557. bool CProxyShell::__procReqTurnIvr( CPduEntity& a_Req )
  558. {
  559. // 查找要转IVR的线路
  560. CVirtualProxy* pLine = getProxyExtenWrapped(a_Req.GetDataUInt(2));
  561. if(pLine == NULL)
  562. {
  563. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行跳转IVR请求失败, 未找到线路[%lu], Instance = %d"),
  564. a_Req.GetDataUInt(2), a_Req.GetDataLong(0));
  565. return false;
  566. } // end if
  567. // 条件过滤
  568. if(pLine->currLineReq() != NULL || pLine->state() != VIRTUAL_LINE_STATE_TALKING)
  569. {
  570. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行跳转IVR请求失败, 线路[%lu]忙, Instance = %d"),
  571. a_Req.GetDataUInt(2), a_Req.GetDataLong(0));
  572. return false;
  573. } // end if
  574. // 执行转IVR操作
  575. if(CSessionShell::GetInstance().procReqLeave(pLine->activeCallId(), pLine->devId()))
  576. {
  577. notifyReqResult(a_Req, a_Req.GetDataLong(0), true);
  578. return true;
  579. } // end if
  580. return false;
  581. }
  582. /*****************************************************************
  583. **【函数名称】 __procReqInstead
  584. **【函数功能】 代接
  585. **【参数】
  586. **【返回值】
  587. ****************************************************************/
  588. bool CProxyShell::__procReqInstead( CPduEntity& a_Req )
  589. {
  590. // 通过设备资源查找主控线路
  591. CProxyExten* pLine = getProxyExtenWrapped(a_Req.GetDataUInt(2));
  592. if(pLine == NULL)
  593. {
  594. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行代接请求失败, 未找到线路[%lu], DestNum = %lu"),
  595. a_Req.GetDataUInt(2), a_Req.GetDataUInt(3));
  596. return false;
  597. }
  598. // 如果线路正在执行其它操作
  599. if(pLine->currLineReq() != NULL)
  600. {
  601. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行代接请求失败, 线路[%lu]忙, DestNum = %lu"),
  602. a_Req.GetDataUInt(2), a_Req.GetDataUInt(3));
  603. return false;
  604. }
  605. CReqBase* pLineReq = new CInsteadReq(this, a_Req);
  606. pLineReq->attachHostLine(pLine);
  607. // 启动操作
  608. return __beginLineReq(pLineReq);
  609. }
  610. /*****************************************************************
  611. **【函数名称】 __procReqIntercept
  612. **【函数功能】 强截
  613. **【参数】
  614. **【返回值】
  615. ****************************************************************/
  616. bool CProxyShell::__procReqIntercept( CPduEntity& a_Req )
  617. {
  618. // 通过设备资源查找主控线路
  619. CProxyExten* pLine = getProxyExtenWrapped(a_Req.GetDataUInt(2));
  620. if(pLine == NULL)
  621. {
  622. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行强截请求失败, 未找到线路[%lu], DestNum = %lu"),
  623. a_Req.GetDataUInt(2), a_Req.GetDataUInt(3));
  624. return false;
  625. }
  626. // 如果线路正在执行其它操作
  627. if(pLine->currLineReq() != NULL)
  628. {
  629. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行强截请求失败, 线路[%lu]忙, DestNum = %lu"),
  630. a_Req.GetDataUInt(2), a_Req.GetDataUInt(3));
  631. return false;
  632. }
  633. CReqBase* pLineReq = new CInterceptReq(this, a_Req);
  634. pLineReq->attachHostLine(pLine);
  635. // 启动操作
  636. return __beginLineReq(pLineReq);
  637. }
  638. /*****************************************************************
  639. **【函数名称】 __procReqInsert
  640. **【函数功能】 强插
  641. **【参数】
  642. **【返回值】
  643. ****************************************************************/
  644. bool CProxyShell::__procReqInsert( CPduEntity& a_Req )
  645. {
  646. // 通过设备资源查找主控线路
  647. CProxyExten* pLine = getProxyExtenWrapped(a_Req.GetDataUInt(2));
  648. if(pLine == NULL)
  649. {
  650. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行强插请求失败, 未找到线路[%lu], DestNum = %lu"),
  651. a_Req.GetDataUInt(2), a_Req.GetDataUInt(3));
  652. return false;
  653. }
  654. // 如果线路正在执行其它操作
  655. if(pLine->currLineReq() != NULL)
  656. {
  657. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行强插请求失败, 线路[%lu]忙, DestNum = %lu"),
  658. a_Req.GetDataUInt(2), a_Req.GetDataUInt(3));
  659. return false;
  660. }
  661. // 生成强插操作类
  662. CReqBase* pLineReq = new CInsertReq(this, a_Req);
  663. pLineReq->attachHostLine(pLine);
  664. // 启动操作
  665. return __beginLineReq(pLineReq);
  666. }
  667. /*****************************************************************
  668. **【函数名称】 __procReqListen
  669. **【函数功能】 监听
  670. **【参数】
  671. **【返回值】
  672. ****************************************************************/
  673. bool CProxyShell::__procReqListen( CPduEntity& a_Req )
  674. {
  675. // 通过设备资源查找主控线路
  676. CProxyExten* pLine = getProxyExtenWrapped(a_Req.GetDataUInt(2));
  677. if(pLine == NULL)
  678. {
  679. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行监听请求失败, 未找到线路[%lu], DestNum = %lu"),
  680. a_Req.GetDataUInt(2), a_Req.GetDataUInt(3));
  681. return false;
  682. }
  683. // 如果线路正在执行其它操作
  684. if(pLine->currLineReq() != NULL)
  685. {
  686. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行监听请求失败, 线路[%lu]忙, DestNum = %lu"),
  687. a_Req.GetDataUInt(2), a_Req.GetDataUInt(3));
  688. return false;
  689. }
  690. // 生成强插操作类
  691. CReqBase* pLineReq = new CListenReq(this, a_Req);
  692. pLineReq->attachHostLine(pLine);
  693. // 启动操作
  694. return __beginLineReq(pLineReq);
  695. }
  696. /*****************************************************************
  697. **【函数名称】 __procReqReset
  698. **【函数功能】 重置
  699. **【参数】
  700. **【返回值】
  701. ****************************************************************/
  702. bool CProxyShell::__procReqReset( CPduEntity& a_Req )
  703. {
  704. // 通过设备资源查找主控线路
  705. CProxyExten* pLine = getProxyExtenWrapped(a_Req.GetDataUInt(2));
  706. if(pLine == NULL)
  707. {
  708. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行线路重置请求失败, 未找到线路[%lu]"),
  709. a_Req.GetDataUInt(2));
  710. return false;
  711. }
  712. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, _T("{ClientProxy}: 执行线路重置请求, Line = %lu"), a_Req.GetDataUInt(2));
  713. // 清除关联操作
  714. CReqBase* pLineOp = pLine->currLineReq();
  715. if(pLineOp != NULL)
  716. {
  717. pLineOp->hangUp(0);
  718. pLineOp->detachHostLine();
  719. delete pLineOp;
  720. }
  721. else
  722. {
  723. CMC::GetInstance().dropCall(pLine->devId(), false);
  724. } // end if
  725. return true;
  726. }
  727. /*****************************************************************
  728. **【函数名称】 __procReqFax
  729. **【函数功能】 传真
  730. **【参数】
  731. **【返回值】
  732. ****************************************************************/
  733. bool CProxyShell::__procReqFax( CPduEntity& a_Req )
  734. {
  735. // 通过设备资源查找主控线路
  736. CVirtualProxy* pProxy = __getProxyTrunk(a_Req.GetDataUInt(2));
  737. if(pProxy == NULL)
  738. {
  739. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行传真请求失败, 未找到线路[%lu], FaxFile = %s"),
  740. a_Req.GetDataUInt(2), a_Req.GetDataString(4));
  741. return false;
  742. }
  743. // 如果线路正在执行其它操作
  744. if(pProxy->currLineReq() != NULL)
  745. {
  746. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行传真请求失败, 线路[%lu]忙, FaxFile = %s"),
  747. a_Req.GetDataUInt(2), a_Req.GetDataString(4));
  748. return false;
  749. }
  750. // 生成强插操作类
  751. CReqBase* pLineReq = new CFaxReq(this, a_Req);
  752. pLineReq->attachHostLine(pProxy);
  753. // 启动操作
  754. return __beginLineReq(pLineReq);
  755. }
  756. /*****************************************************************
  757. **【函数名称】 __procReqRecord
  758. **【函数功能】 线路录音
  759. **【参数】
  760. **【返回值】
  761. ****************************************************************/
  762. bool CProxyShell::__procReqRecord( CPduEntity& a_Req )
  763. {
  764. // 查找要录音的线路
  765. CVirtualProxy* pLine = getProxy(a_Req.GetDataUInt(2));
  766. if(pLine == NULL)
  767. {
  768. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行线路录音请求失败, 未找到线路[%lu]"), a_Req.GetDataUInt(2));
  769. return false;
  770. } // end if
  771. // 如果线路正在执行其它操作
  772. if(pLine->currLineReq() != NULL)
  773. {
  774. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行线路录音请求失败, 线路[%lu]忙"), a_Req.GetDataUInt(2));
  775. return false;
  776. }
  777. // 查找线路所属的活动呼叫
  778. long Call = pLine->activeCallId();
  779. if(Call == SESSION_INVALID_CALL)
  780. {
  781. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行线路录音请求失败, 线路[%lu]未在通话中"), a_Req.GetDataUInt(2));
  782. return false;
  783. } // end if
  784. // 执行录音操作
  785. return CSessionShell::GetInstance().procReqRecord(Call, pLine->devId(), a_Req.GetDataString(3));
  786. }
  787. /*****************************************************************
  788. **【函数名称】 __procReqLeaveWord
  789. **【函数功能】 留言录音
  790. **【参数】
  791. **【返回值】
  792. ****************************************************************/
  793. bool CProxyShell::__procReqLeaveWord( CPduEntity& a_Req )
  794. {
  795. // 查找要留言的线路
  796. CVirtualProxy* pLine = __getProxyTrunk(a_Req.GetDataUInt(2)); // 外线
  797. if(pLine == NULL)
  798. {
  799. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行留言请求失败, 未找到线路[%lu], SaveFile = %s"),
  800. a_Req.GetDataUInt(2), a_Req.GetDataString(5));
  801. return false;
  802. } // end if
  803. // 如果线路正在执行其它操作
  804. if(pLine->currLineReq() != NULL)
  805. {
  806. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行留言请求失败, 线路[%lu]忙, SaveFile = %s"),
  807. a_Req.GetDataUInt(2), a_Req.GetDataString(5));
  808. return false;
  809. }
  810. // 生成留言操作类
  811. CReqBase* pLineReq = new CLeaveWordReq(this, a_Req);
  812. pLineReq->attachHostLine(pLine);
  813. // 启动操作
  814. return __beginLineReq(pLineReq);
  815. }
  816. /*****************************************************************
  817. **【函数名称】 __procReqMuteBegin
  818. **【函数功能】 静音启动
  819. **【参数】
  820. **【返回值】
  821. ****************************************************************/
  822. bool CProxyShell::__procReqMuteOn( CPduEntity& a_Req )
  823. {
  824. // 通过设备资源查找主控线路
  825. CProxyExten* pLine = getProxyExtenWrapped(a_Req.GetDataUInt(2));
  826. if(pLine == NULL)
  827. {
  828. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行静音请求失败, 未找到线路[%lu], Instance = %d"),
  829. a_Req.GetDataUInt(2), a_Req.GetDataLong(0));
  830. return false;
  831. }
  832. // 如果线路正在执行其它操作
  833. if(pLine->currLineReq() != NULL)
  834. {
  835. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行静音请求失败, 线路[%lu]忙, Instance = %d"),
  836. a_Req.GetDataUInt(2), a_Req.GetDataLong(0));
  837. return false;
  838. }
  839. // 生成静音操作类
  840. CReqBase* pLineReq = new CMuteReq(this, a_Req);
  841. pLineReq->attachHostLine(pLine);
  842. // 启动操作
  843. return __beginLineReq(pLineReq);
  844. }
  845. /*****************************************************************
  846. **【函数名称】 __procReqMuteEnd
  847. **【函数功能】 静音结束
  848. **【参数】
  849. **【返回值】
  850. ****************************************************************/
  851. bool CProxyShell::__procReqMuteOff( CPduEntity& a_Req )
  852. {
  853. // 通过设备资源查找主控线路
  854. CProxyExten* pLine = getProxyExtenWrapped(a_Req.GetDataUInt(2));
  855. if(pLine == NULL)
  856. {
  857. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行取消静音请求失败, 未找到线路[%lu], Instance = %d"),
  858. a_Req.GetDataUInt(2), a_Req.GetDataLong(0));
  859. return false;
  860. }
  861. // 如果线路正在执行其它操作
  862. CReqBase* pCurrReq = pLine->currLineReq();
  863. if(pCurrReq == NULL || dynamic_cast<CMuteReq*>(pCurrReq) == NULL)
  864. {
  865. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行取消静音请求失败, 线路[%lu]忙, Instance = %d"),
  866. a_Req.GetDataUInt(2), a_Req.GetDataLong(0));
  867. return false;
  868. }
  869. // 执行取消静音操作
  870. return pCurrReq->cancel(a_Req.GetDataLong(0));
  871. }
  872. /*****************************************************************
  873. **【函数名称】 __procReqSelfCheck
  874. **【函数功能】 线路自检(当前只对模拟外线有效)
  875. **【参数】
  876. **【返回值】
  877. ****************************************************************/
  878. bool CProxyShell::__procReqLineCheck( CPduEntity& a_Req )
  879. {
  880. return false;
  881. }
  882. /*****************************************************************
  883. **【函数名称】 __procReqConsultCall
  884. **【函数功能】 协商呼叫启动
  885. **【参数】
  886. **【返回值】
  887. ****************************************************************/
  888. bool CProxyShell::__procReqConsultCall( CPduEntity& a_Req )
  889. {
  890. // 通过设备资源查找主控线路
  891. CProxyExten* pLine = getProxyExtenWrapped(a_Req.GetDataUInt(2));
  892. if(pLine == NULL)
  893. {
  894. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行协商呼叫请求失败, 未找到线路[%lu], DestNum = %s"),
  895. a_Req.GetDataUInt(2), a_Req.GetDataString(3));
  896. return false;
  897. }
  898. // 如果线路正在执行其它操作
  899. if(pLine->currLineReq() != NULL)
  900. {
  901. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行协商呼叫请求失败, 线路[%lu]忙, DestNum = %s"),
  902. a_Req.GetDataUInt(2), a_Req.GetDataString(3));
  903. return false;
  904. }
  905. // 生成协商呼叫操作类
  906. CReqBase* pCurrReq = new CConsultCallReq(this, a_Req);
  907. pCurrReq->attachHostLine(pLine);
  908. // 启动操作
  909. return __beginLineReq(pCurrReq);
  910. }
  911. /*****************************************************************
  912. **【函数名称】 __procReqConsultCallConfirm
  913. **【函数功能】 协商呼叫确认
  914. **【参数】
  915. **【返回值】
  916. ****************************************************************/
  917. bool CProxyShell::__procReqConsultCallConfirm( CPduEntity& a_Req )
  918. {
  919. // 通过设备资源查找主控线路
  920. CProxyExten* pLine = getProxyExtenWrapped(a_Req.GetDataUInt(2));
  921. if(pLine == NULL)
  922. {
  923. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行协商确认失败, 未找到线路[%lu], Instance = %d"),
  924. a_Req.GetDataUInt(2), a_Req.GetDataLong(0));
  925. return false;
  926. }
  927. // 如果线路未执行协商呼叫操作
  928. CReqBase* pCurrReq = pLine->currLineReq();
  929. if(pCurrReq == NULL || dynamic_cast<CConsultCallReq*>(pCurrReq) == NULL)
  930. {
  931. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{ClientProxy}: 执行协商确认失败, 线路[%lu]忙, Instance = %d"),
  932. a_Req.GetDataUInt(2), a_Req.GetDataLong(0));
  933. return false;
  934. }
  935. // 执行操作确认
  936. if(!pCurrReq->resume(a_Req.GetDataLong(0), a_Req.GetDataInt(3)))
  937. {
  938. pCurrReq->detachHostLine();
  939. delete pCurrReq;
  940. return false;
  941. } // end if
  942. return true;
  943. }
  944. /*****************************************************************
  945. **【函数名称】 __procFunCodeDevEvent
  946. **【函数功能】 收取功能键事件处理函数
  947. **【参数】
  948. **【返回值】
  949. ****************************************************************/
  950. bool CProxyShell::__procFunCodeDevEvent( CVirtualProxy* pLine, LPCTSTR lpContent, UINT ExtenId )
  951. {
  952. CProxyExten* pExten = __getProxyExten(ExtenId);
  953. ASSERT(pExten != NULL);
  954. if(pExten == NULL)
  955. return false;
  956. ASSERT(pLine->state() == VIRTUAL_LINE_STATE_FREE);
  957. // 如果线路正在执行其它操作
  958. if(pLine->currLineReq() != NULL || pExten->currLineReq() != NULL)
  959. return false;
  960. pLine->wrap(pExten);
  961. pExten->wrap(pLine);
  962. // 生成外呼操作类
  963. CPduEntity CallPdu(PDU_CMD_SC_REQ_MAKECALL);
  964. CReqBase* pLineReq = new CMakeCallReq(this, CallPdu);
  965. pLineReq->attachHostLine(pExten);
  966. if(!pLineReq->request(lpContent))
  967. {
  968. pLineReq->detachHostLine();
  969. delete pLineReq;
  970. return false;
  971. } // end if
  972. return true;
  973. }
  974. /*****************************************************************
  975. **【函数名称】 __procHoldOnDevEvent
  976. **【函数功能】 分机保持事件处理函数
  977. **【参数】
  978. **【返回值】
  979. ****************************************************************/
  980. bool CProxyShell::__procHoldOnDevEvent( CVirtualProxy* pLine, UINT ExtenId )
  981. {
  982. CProxyExten* pExten = __getProxyExten(ExtenId);
  983. ASSERT(pExten != NULL);
  984. if(pExten == NULL)
  985. return false;
  986. ASSERT(pLine->state() == VIRTUAL_LINE_STATE_TALKING);
  987. // 如果线路正在执行其它操作
  988. if(pLine->currLineReq() != NULL || pExten->currLineReq() != NULL)
  989. return false;
  990. return pExten->holdOn();
  991. }
  992. /*****************************************************************
  993. **【函数名称】 __procTakeBackDevEvent
  994. **【函数功能】 分机接回事件处理函数
  995. **【参数】
  996. **【返回值】
  997. ****************************************************************/
  998. bool CProxyShell::__procTakeBackDevEvent( CVirtualProxy* pLine, UINT ExtenId )
  999. {
  1000. CProxyExten* pExten = __getProxyExten(ExtenId);
  1001. ASSERT(pExten != NULL);
  1002. if(pExten == NULL)
  1003. return false;
  1004. ASSERT(pLine->state() == VIRTUAL_LINE_STATE_TALKING);
  1005. // 如果线路正在执行其它操作
  1006. if(pLine->currLineReq() != NULL || pExten->currLineReq() != NULL)
  1007. return false;
  1008. return pExten->takeBack();
  1009. }
  1010. /*****************************************************************
  1011. **【函数名称】 getProxyExten
  1012. **【函数功能】 根据分机号查找内线代理
  1013. **【参数】 ExtnNum 内线分机号
  1014. **【返回值】
  1015. ****************************************************************/
  1016. CProxyExten* CProxyShell::getProxyExtenWrapped( UINT ExtnNum )
  1017. {
  1018. CProxyExten* pExten = NULL;
  1019. if(m_ExtenMap.Lookup(ExtnNum, pExten))
  1020. {
  1021. ASSERT(pExten != NULL);
  1022. if(pExten->isVoipExten() && pExten->isNull())
  1023. {
  1024. // 向底层申请VOIP通道
  1025. CVoipChannel* pVoipChan = CMC::GetInstance().allocVoipCh4Exten(DEVICE_NODE_NO_ANY);
  1026. ASSERT(pVoipChan != NULL);
  1027. if(pVoipChan == NULL)
  1028. return NULL;
  1029. // 查找通道对应代理
  1030. CVirtualProxy* pVoipProxy = __getProxyVoip(pVoipChan->id().toIntId());
  1031. ASSERT(pVoipProxy != NULL);
  1032. if(pVoipProxy == NULL) // 代理为空则创建
  1033. pVoipProxy = onLineNew(pVoipChan->id());
  1034. ASSERT(pVoipProxy != NULL);
  1035. pExten->wrap(pVoipProxy);
  1036. pVoipProxy->wrap(pExten);
  1037. }
  1038. }
  1039. return pExten;
  1040. }
  1041. /*****************************************************************
  1042. **【函数名称】 getProxy
  1043. **【函数功能】 根据ID查找线路代理
  1044. **【参数】 LineDevId 线路设备ID
  1045. **【返回值】
  1046. ****************************************************************/
  1047. CVirtualProxy* CProxyShell::getProxy( UINT ResId )
  1048. {
  1049. CVirtualProxy* pProxy = __getProxyExten(ResId);
  1050. if(pProxy == NULL)
  1051. pProxy = __getProxyTrunk(ResId);
  1052. return pProxy;
  1053. }
  1054. /*****************************************************************
  1055. **【函数名称】 setEnv4Calling
  1056. **【函数功能】 设置呼叫环境
  1057. **【参数】
  1058. **【返回值】
  1059. ****************************************************************/
  1060. CVirtualProxy* CProxyShell::setEnv4Calling(CString& CallerNum, CString& CalleeNum, DEV_RES_TYPE& LineType, int& SipAccountId)
  1061. {
  1062. TRUNK_ITEM* pItem = NULL;
  1063. COneLeg* pLeg = CTrunkAidedAllocator::GetInstance().aidedAlloc(CallerNum, CalleeNum, &pItem);
  1064. if(pLeg != NULL) // 被叫是外线
  1065. {
  1066. ASSERT(pItem != NULL);
  1067. SipAccountId = pItem->SipAccountId;
  1068. LineType = DEV_RES_TYPE_TRUNK;
  1069. return __getProxyTrunk(pLeg->resourceAttribute()->id().toIntId());
  1070. }
  1071. else // 被叫是内线
  1072. {
  1073. SipAccountId = INVALID_ID_SIP_ACCOUNT;
  1074. LineType = DEV_RES_TYPE_EXT;
  1075. UINT ExtNum = 0;
  1076. sscanf_s(CalleeNum, "%lu", &ExtNum);
  1077. return getProxyExtenWrapped(ExtNum);
  1078. }
  1079. }
  1080. /*****************************************************************
  1081. **【函数名称】 setEnv4PredictionCall
  1082. **【函数功能】 设置预测外呼环境
  1083. **【参数】
  1084. **【返回值】
  1085. ****************************************************************/
  1086. CVirtualProxy* CProxyShell::setEnv4PredictionCall( CString& CallerNum, CString& CalleeNum, int& SipAccountId )
  1087. {
  1088. TRUNK_ITEM* pItem = NULL;
  1089. COneLeg* pLeg = CTrunkAidedAllocator::GetInstance().aidedAllocWithDefault(CallerNum, CalleeNum, &pItem);
  1090. if(pLeg != NULL)
  1091. {
  1092. ASSERT(pItem != NULL);
  1093. SipAccountId = pItem->SipAccountId;
  1094. return __getProxyTrunk(pLeg->resourceAttribute()->id().toIntId());
  1095. }
  1096. else return NULL;
  1097. }
  1098. /*****************************************************************
  1099. **【函数名称】 notifyResourceDetail
  1100. **【函数功能】 向客户端发送设备资源明细
  1101. **【参数】
  1102. **【返回值】
  1103. ****************************************************************/
  1104. void CProxyShell::notifyResourceDetail( DEV_RES_TYPE ResType, UINT ResID )
  1105. {
  1106. CPduEntity ResPdu(PDU_CMD_SC_RES_DETAIL);
  1107. ResPdu.SetDataUInt(0, ResType);
  1108. ResPdu.SetDataUInt(1, ResID);
  1109. CNetLinkMgr::GetInstance().send(&ResPdu);
  1110. }
  1111. /*****************************************************************
  1112. **【函数名称】 notifyResourceDetail
  1113. **【函数功能】 向客户端发送设备资源明细
  1114. **【参数】
  1115. **【返回值】
  1116. ****************************************************************/
  1117. void CProxyShell::notifyResourceDetail( PDU_DEV_TYPE DestType, int DestId, DEV_RES_TYPE ResType, UINT ResID )
  1118. {
  1119. CPduEntity ResPdu(PDU_CMD_SC_RES_DETAIL);
  1120. ResPdu.SetDataUInt(0, ResType);
  1121. ResPdu.SetDataUInt(1, ResID);
  1122. CNetLinkMgr::GetInstance().send(&ResPdu, DestType, DestId);
  1123. }
  1124. /*****************************************************************
  1125. **【函数名称】 __notifyDevResourceState
  1126. **【函数功能】 向客户端发送设备资源状态信息
  1127. **【参数】
  1128. **【返回值】
  1129. ****************************************************************/
  1130. void CProxyShell::notifyDevResourceState( DEV_RES_TYPE ResType, UINT ResID, UINT State, LPCTSTR CallerNum /*= NULL*/, LPCTSTR CalleeNum /*= NULL*/ )
  1131. {
  1132. CPduEntity ResStatePdu(PDU_CMD_SC_RES_STATE);
  1133. ResStatePdu.SetDataUInt(0, ResType);
  1134. ResStatePdu.SetDataUInt(1, ResID);
  1135. ResStatePdu.SetDataUInt(2, State);
  1136. if(CallerNum != NULL)
  1137. ResStatePdu.SetDataString(3, CallerNum);
  1138. if(CalleeNum != NULL)
  1139. ResStatePdu.SetDataString(4, CalleeNum);
  1140. CNetLinkMgr::GetInstance().send(&ResStatePdu);
  1141. }
  1142. /*****************************************************************
  1143. **【函数名称】 __notifyDevResourceState
  1144. **【函数功能】 向客户端发送设备资源状态信息
  1145. **【参数】
  1146. **【返回值】
  1147. ****************************************************************/
  1148. void CProxyShell::notifyDevResourceState( PDU_DEV_TYPE DestType, int DestId, DEV_RES_TYPE ResType, UINT ResID, UINT State, LPCTSTR CallerNum /*= NULL*/, LPCTSTR CalleeNum /*= NULL*/ )
  1149. {
  1150. CPduEntity ResStatePdu(PDU_CMD_SC_RES_STATE);
  1151. ResStatePdu.SetDataUInt(0, ResType);
  1152. ResStatePdu.SetDataUInt(1, ResID);
  1153. ResStatePdu.SetDataUInt(2, State);
  1154. if(CallerNum != NULL)
  1155. ResStatePdu.SetDataString(3, CallerNum);
  1156. if(CalleeNum != NULL)
  1157. ResStatePdu.SetDataString(4, CalleeNum);
  1158. CNetLinkMgr::GetInstance().send(&ResStatePdu, DestType, DestId);
  1159. }
  1160. /*****************************************************************
  1161. **【函数名称】 notifyLineEvent
  1162. **【函数功能】 通知设备主动操作事件
  1163. **【参数】 LineID 线路ID
  1164. EvtTp 事件类型
  1165. CallerNum 主叫号码
  1166. CalleeNum 被叫号码
  1167. **【返回值】
  1168. ****************************************************************/
  1169. void CProxyShell::notifyLineOpEvent( UINT ResID, DEV_OP OpTp, const CString& CallerNum, const CString& CalleeNum )
  1170. {
  1171. CPduEntity EvtPdu(PDU_CMD_SC_ACTIVE_EVENT);
  1172. EvtPdu.SetDataUInt(0, ResID);
  1173. EvtPdu.SetDataUInt(1, OpTp);
  1174. EvtPdu.SetDataString(2, CallerNum);
  1175. EvtPdu.SetDataString(3, CalleeNum);
  1176. CNetLinkMgr::GetInstance().send(&EvtPdu);
  1177. }
  1178. /*****************************************************************
  1179. **【函数名称】 notifyOpProcess
  1180. **【函数功能】 通知请求进展
  1181. **【参数】 LineReq 线路请求
  1182. HostLine 主控线路ID
  1183. AssoLine 关联线路ID
  1184. AssoLineType 关联线路类型
  1185. lpCallerNum 主叫号码
  1186. lpCalleeNum 被叫号码
  1187. **【返回值】
  1188. ****************************************************************/
  1189. void CProxyShell::notifyReqProcess( CReqBase& LineReq, UINT HostLine, UINT AssoLine, DEV_RES_TYPE AssoLineType, LPCTSTR lpCallerNum, LPCTSTR lpCalleeNum )
  1190. {
  1191. CPduEntity ProcessPdu(PDU_CMD_SC_REQ_PROCESS);
  1192. ProcessPdu.SetDataLong(0, LineReq.callInstance());
  1193. ProcessPdu.SetDataUInt(1, HostLine);
  1194. ProcessPdu.SetDataUInt(2, AssoLine);
  1195. ProcessPdu.SetDataUInt(3, AssoLineType);
  1196. ProcessPdu.SetDataString(4, lpCallerNum);
  1197. ProcessPdu.SetDataString(5, lpCalleeNum);
  1198. CNetLinkMgr::GetInstance().send(&ProcessPdu, LineReq.comeFrom().GetLocalDevType(), LineReq.comeFrom().GetLocalDevId());
  1199. }
  1200. /*****************************************************************
  1201. **【函数名称】 notifyReqResult
  1202. **【函数功能】 通知请求执行结果
  1203. **【参数】 Instance 调用实例
  1204. ToWhere 发往哪里
  1205. IsSucceed 是否成功
  1206. lpData 执行结果返回的随路数据
  1207. **【返回值】
  1208. ****************************************************************/
  1209. void CProxyShell::notifyReqResult( CPduEntity& SrcReq, long Instance, bool IsSucceed, LPCTSTR lpData /*= NULL*/ )
  1210. {
  1211. CPduEntity ResultPdu(PDU_CMD_SC_REQ_RESULT);
  1212. ResultPdu.SetDataLong(0, Instance);
  1213. ResultPdu.SetDataBool(1, IsSucceed);
  1214. if(lpData != NULL)
  1215. ResultPdu.SetDataString(2, lpData);
  1216. CNetLinkMgr::GetInstance().send(&ResultPdu, SrcReq.GetLocalDevType(), SrcReq.GetLocalDevId());
  1217. }
  1218. /*****************************************************************
  1219. **【函数名称】 onLineReqEnd
  1220. **【函数功能】 线路请求结束的处理函数
  1221. **【参数】 LineReq 线路请求实例
  1222. IsSucceed 是否成功
  1223. lpData 执行结果返回的随路数据
  1224. **【返回值】
  1225. ****************************************************************/
  1226. void CProxyShell::onLineReqEnd( CReqBase* pLineReq, bool IsSucceed, LPCTSTR lpData /*= NULL*/ )
  1227. {
  1228. ASSERT(pLineReq != NULL);
  1229. // 关闭线路关联
  1230. pLineReq->detachHostLine();
  1231. // 返回执行结果
  1232. notifyReqResult(pLineReq->comeFrom(), pLineReq->callInstance(), IsSucceed, lpData);
  1233. // 关闭操作
  1234. delete pLineReq;
  1235. }
  1236. /*****************************************************************
  1237. **【函数名称】 onLineNew
  1238. **【函数功能】 线路初始信息事件通知
  1239. **【参数】 LineDevId 线路的设备ID
  1240. **【返回值】
  1241. ****************************************************************/
  1242. CVirtualProxy* CProxyShell::onLineNew( CRDRID LineDevId )
  1243. {
  1244. switch(LineDevId.ResType)
  1245. {
  1246. case DEV_RES_TYPE_EXT:
  1247. {
  1248. CProxyExten* pExtn = NULL;
  1249. if(!m_ExtenMap.Lookup(LineDevId.ChanNo, pExtn))
  1250. {
  1251. // 生成分机实体类
  1252. pExtn = new CProxyExten(this, LineDevId);
  1253. ASSERT(pExtn != NULL);
  1254. m_ExtenMap.SetAt(LineDevId.ChanNo, pExtn);
  1255. // 通知业务逻辑分机信息
  1256. pExtn->notifyLineInfo();
  1257. }
  1258. else
  1259. {
  1260. if(pExtn->invalidFlag())
  1261. pExtn->invalidFlag() = false;
  1262. }
  1263. return pExtn;
  1264. }
  1265. break;
  1266. case DEV_RES_TYPE_TRUNK:
  1267. {
  1268. CProxyDti* pDti = NULL;
  1269. if(!m_DtiMap.Lookup(LineDevId.toIntId(), pDti))
  1270. {
  1271. // 生成外线实体类
  1272. pDti = new CProxyDti(this, LineDevId);
  1273. ASSERT(pDti != NULL);
  1274. m_DtiMap.SetAt(LineDevId.toIntId(), pDti);
  1275. // 通知业务逻辑外线信息
  1276. pDti->notifyLineInfo();
  1277. }
  1278. else
  1279. {
  1280. if(pDti->invalidFlag())
  1281. pDti->invalidFlag() = false;
  1282. }
  1283. return pDti;
  1284. }
  1285. break;
  1286. case DEV_RES_TYPE_VOIP:
  1287. {
  1288. CProxyVoip* pVoip = NULL;
  1289. if(!m_VoipMap.Lookup(LineDevId.toIntId(), pVoip))
  1290. {
  1291. // 生成外线实体类
  1292. pVoip = new CProxyVoip(this, LineDevId);
  1293. ASSERT(pVoip != NULL);
  1294. m_VoipMap.SetAt(LineDevId.toIntId(), pVoip);
  1295. // 通知业务逻辑外线信息
  1296. pVoip->notifyLineInfo();
  1297. }
  1298. else
  1299. {
  1300. if(pVoip->invalidFlag())
  1301. pVoip->invalidFlag() = false;
  1302. }
  1303. return pVoip;
  1304. }
  1305. break;
  1306. default:
  1307. return NULL;
  1308. }
  1309. }
  1310. /*****************************************************************
  1311. **【函数名称】 onLineDelete
  1312. **【函数功能】 线路删除
  1313. **【参数】 LineDevId 线路的设备ID
  1314. **【返回值】
  1315. ****************************************************************/
  1316. void CProxyShell::onLineDelete( CRDRID LineDevId )
  1317. {
  1318. switch(LineDevId.ResType)
  1319. {
  1320. case DEV_RES_TYPE_EXT:
  1321. {
  1322. // 删除分机代理类
  1323. CProxyExten* pExtn = NULL;
  1324. m_ExtenMap.Lookup(LineDevId.ChanNo, pExtn);
  1325. if (pExtn != NULL)
  1326. {
  1327. if(pExtn->isFree())
  1328. {
  1329. m_ExtenMap.RemoveKey(LineDevId.ChanNo);
  1330. delete pExtn;
  1331. }
  1332. else
  1333. pExtn->invalidFlag() = true;
  1334. }
  1335. }
  1336. break;
  1337. case DEV_RES_TYPE_TRUNK:
  1338. {
  1339. // 删除分机代理类
  1340. CProxyDti* pDti = NULL;
  1341. m_DtiMap.Lookup(LineDevId.toIntId(), pDti);
  1342. if (pDti != NULL)
  1343. {
  1344. if(pDti->isFree())
  1345. {
  1346. m_DtiMap.RemoveKey(LineDevId.toIntId());
  1347. delete pDti;
  1348. }
  1349. else
  1350. pDti->invalidFlag() = true;
  1351. }
  1352. }
  1353. break;
  1354. case DEV_RES_TYPE_VOIP:
  1355. {
  1356. // 删除分机代理类
  1357. CProxyVoip* pVoip = NULL;
  1358. m_VoipMap.Lookup(LineDevId.toIntId(), pVoip);
  1359. if (pVoip != NULL)
  1360. {
  1361. if(pVoip->isFree())
  1362. {
  1363. m_VoipMap.RemoveKey(LineDevId.toIntId());
  1364. delete pVoip;
  1365. }
  1366. else
  1367. pVoip->invalidFlag() = true;
  1368. }
  1369. }
  1370. break;
  1371. default:
  1372. ASSERT(FALSE);
  1373. }
  1374. }
  1375. /*****************************************************************
  1376. **【函数名称】 onNewCall
  1377. **【函数功能】 线路进入会话事件
  1378. **【参数】 LineDevId 线路设备ID
  1379. Call 线路当前所属的主会话ID
  1380. SubCall 线路当前所属的子会话ID
  1381. **【返回值】
  1382. ****************************************************************/
  1383. void CProxyShell::onNewCall( CRDRID LineDevId, long Call, long SubCall )
  1384. {
  1385. CVirtualProxy* pLine = getProxy(LineDevId.toIntId());
  1386. ASSERT(pLine != NULL);
  1387. if(pLine != NULL)
  1388. pLine->onNewCall(Call, SubCall);
  1389. }
  1390. /*****************************************************************
  1391. **【函数名称】 onLineStateUpdated
  1392. **【函数功能】 线路状态变化事件通知
  1393. **【参数】 LineDevId 线路设备ID
  1394. Call 线路当前所属的主会话ID
  1395. SubCall 线路当前所属的子会话ID
  1396. Status 线路当前状态
  1397. lpCallerNum 主叫号码
  1398. lpCalleeNum 被叫号码
  1399. **【返回值】
  1400. ****************************************************************/
  1401. void CProxyShell::onLineStateUpdated( CRDRID LineDevId, long Call, long SubCall, VIRTUAL_LINE_STATE State, LPCTSTR lpCallerNum/* = NULL*/, LPCTSTR lpCalleeNum /*= NULL*/ )
  1402. {
  1403. CVirtualProxy* pLine = getProxy(LineDevId.toIntId());
  1404. ASSERT(pLine != NULL);
  1405. if(pLine != NULL)
  1406. {
  1407. pLine->onLineStateChanged(Call, SubCall, State, lpCallerNum, lpCalleeNum);
  1408. if(pLine->invalidFlag() && pLine->isFree())
  1409. onLineDelete(pLine->devId());
  1410. }
  1411. }
  1412. /*****************************************************************
  1413. **【函数名称】 onDevChannelEvent
  1414. **【函数功能】 设备通道向上层发送的设备主动事件
  1415. **【参数】 LineDevId 触发事件的线路ID
  1416. EvtType 事件类型
  1417. lpContent 事件内容
  1418. **【返回值】
  1419. *****************************************************************/
  1420. bool CProxyShell::onDevChannelEvent( CRDRID LineDevId, DEV_CH_EVT_TYPE EvtType, LPCTSTR lpContent, UINT ExtenId )
  1421. {
  1422. // 获取触发事件的线路
  1423. CVirtualProxy* pLine = getProxy(LineDevId.toIntId());
  1424. ASSERT(pLine != NULL);
  1425. if(pLine == NULL)
  1426. return false;
  1427. // 进行分类处理
  1428. switch(EvtType)
  1429. {
  1430. case DEV_CH_EVT_PLAY_END: // 放音结束
  1431. case DEV_CH_EVT_OFF_HOOK: // 内线已摘机
  1432. case DEV_CH_EVT_FAX_OK: // 传真成功
  1433. case DEV_CH_EVT_FAX_FAILED: // 传真失败
  1434. case DEV_CH_EVT_REC_END: // 录音结束
  1435. case DEV_CH_EVT_MEETING_RESULT: // 会议结果
  1436. case DEV_CH_EVT_CALL_FAILD_CAUSE: // 呼叫失败原因
  1437. {
  1438. pLine->onDevChEvent(EvtType, lpContent);
  1439. }
  1440. break;
  1441. case DEV_CH_EVT_FUN_CODE: // 收取功能键
  1442. return __procFunCodeDevEvent(pLine, lpContent, ExtenId);
  1443. case DEV_CH_EVT_HOLD_ON:
  1444. return __procHoldOnDevEvent(pLine, ExtenId);
  1445. case DEV_CH_EVT_TAKE_BACK:
  1446. return __procTakeBackDevEvent(pLine, ExtenId);
  1447. }
  1448. return true;
  1449. }