FlowControlFSM.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  1. #include "stdafx.h"
  2. #include "FlowControlFSM.h"
  3. #define LOG_EVT_EXIT_ACM_FLOW 0x30500002 //退出坐席控制流程
  4. //错误码
  5. #define LOG_ERR_S0_ANSACMFLOW 0x30500080
  6. #define LOG_ERR_S0_REQAGENTFLOW 0x30500081
  7. #define LOG_ERR_S1_REQAGENTFLOW_FAILED 0x30500082
  8. #define LOG_ERR_S2_ANSAGENTFLOW_FAILED 0x30500083
  9. #define LOG_ERR_S2_NTFENTFLOW_FAILED 0x30500084
  10. #define LOG_ERR_S3_ANSACMFLOW_FAILED 0x30500085
  11. #define LOG_ERR_S5_DISCTRL_FAILED 0x30500086
  12. #define LOG_ERR_S5_REQAGENTFLOW_FAILED 0x30500087
  13. #define LOG_ERR_S7_ENTRY 0x30500088
  14. #define LOG_ERR_S1_ASSIS_IDEL 0x30500089
  15. #define LOG_ERR_S2_ASSIS_IDEL 0x3050008a
  16. #define LOG_ERR_S3_ASSIS_IDEL 0x3050008b
  17. #define LOG_ERR_S5_ASSIS_IDEL 0x3050008c
  18. #define LOG_EVT_CONNEC_ASSISTCHAN_FAILED 0x3050008d
  19. void ChannelClient::OnMessage( ErrorCodeEnum Error, ChannelService_State_Info &Msg, CSmartPointer<IReleasable> pData )
  20. {
  21. if (Error == Error_Succeed) {
  22. if (Msg.state == eChannelState_Connected) {
  23. m_pFSM->PostEventFIFO(new FSMEvent(USER_EVT_CHAN_ON));
  24. }
  25. else if (Msg.state == eChannelState_Idle) {
  26. m_pFSM->PostEventFIFO(new FSMEvent(USER_EVT_CHAN_OFF));
  27. }
  28. }
  29. }
  30. void ChannelClient::OnMessage( ErrorCodeEnum Error, ChannelService_Packet_Info &Msg, CSmartPointer<IReleasable> pData )
  31. {
  32. if (Error == Error_Succeed) {
  33. m_pFSM->ProcessPacket(Msg.sub_type, Msg.data);
  34. }
  35. }
  36. CFlowControlFSM::CFlowControlFSM(): m_bIspad(FALSE), m_pClient(NULL)
  37. {
  38. }
  39. CFlowControlFSM::~CFlowControlFSM()
  40. {
  41. }
  42. void CFlowControlFSM::OnStateTrans( int iSrcState, int iDstState )
  43. {
  44. ChanState evt;
  45. evt.state = iDstState;
  46. evt.status = CSimpleStringA::Format("OnStateTrans from state %d to %d", iSrcState, iDstState);
  47. SpSendBroadcast(GetEntityBase()->GetFunction(), SP_MSG_OF(ChanState), SP_MSG_SIG_OF(ChanState), evt);
  48. switch (iDstState) {
  49. case s0:
  50. SetState("O", "Offline"); // offline
  51. break;
  52. case s1:
  53. SetState("F", "FrontFlow"); // frontflow
  54. break;
  55. case s2:
  56. SetState("B", "BackFlow"); // backflow
  57. break;
  58. case s3:
  59. SetState("C", "FrontCall"); // front call
  60. break;
  61. case s5:
  62. SetState("T", "Transferring"); // Transferring
  63. break;
  64. default:
  65. break;
  66. }
  67. }
  68. ErrorCodeEnum CFlowControlFSM::OnInit()
  69. {
  70. m_bConnectAssit = false;
  71. AddStateHooker(this);
  72. return Error_Succeed;
  73. }
  74. ErrorCodeEnum CFlowControlFSM::OnExit()
  75. {
  76. if (m_pClient != NULL) {
  77. m_pClient->GetFunction()->CloseSession();
  78. m_pClient = NULL;
  79. }
  80. RemoveStateHooker(this);
  81. void FinishClose(CEntityBase *pEntity, ErrorCodeEnum Error = Error_Succeed);
  82. FinishClose(m_pEntity);
  83. return Error_Succeed;
  84. }
  85. bool CFlowControlFSM::IsAssistchanEntityAvailable()
  86. {
  87. if (Error_Succeed == ConnectToAssistchan(false)) {
  88. return true;
  89. }
  90. else {
  91. return false;
  92. }
  93. }
  94. ErrorCodeEnum CFlowControlFSM::ConnectToAssistchan(bool blogevt)
  95. {
  96. if (!IsAssistchanConnectSessionOK()) {
  97. FreeAssistchanClient();
  98. m_pClient = new ChannelClient(m_pEntity, this);
  99. ErrorCodeEnum errorCode = m_pClient->Connect();
  100. if (Error_Succeed != errorCode) {
  101. m_pClient->SafeDelete();
  102. m_pClient = NULL;
  103. if (blogevt) {
  104. LogWarn(Severity_Middle, Error_InvalidState, LOG_EVT_CONNEC_ASSISTCHAN_FAILED,
  105. CSimpleStringA::Format("Connect to assistchan entity failed:0x%08x.", errorCode));
  106. }
  107. return Error_InvalidState;
  108. }
  109. else {
  110. if (blogevt) {
  111. DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Connect to assistchan Client Succeed!");
  112. }
  113. ChannelService_BeginState_Sub ChannelSub;
  114. errorCode = m_pClient->BeginState(ChannelSub);
  115. if (Error_Succeed != errorCode)
  116. {
  117. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("BeginState biz channel failed!");
  118. m_pClient->GetFunction()->CloseSession();
  119. m_pClient = NULL;
  120. return errorCode;
  121. }
  122. ChannelService_BeginRecv_Sub Sub;
  123. Sub.type = ACM_TYPE_FLW;
  124. errorCode = m_pClient->BeginRecv(Sub);
  125. if (Error_Succeed != errorCode)
  126. {
  127. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("Register ACM_TYPE_FLW failed!");
  128. m_pClient->GetFunction()->CloseSession();
  129. m_pClient = NULL;
  130. return errorCode;
  131. }
  132. }
  133. }
  134. return Error_Succeed;
  135. }
  136. bool CFlowControlFSM::IsAssistchanConnectSessionOK()
  137. {
  138. return (m_pClient != NULL && !m_pClient->QuerySessionClosed());
  139. }
  140. void CFlowControlFSM::FreeAssistchanClient()
  141. {
  142. if (m_pClient) {
  143. m_pClient->GetFunction()->CloseSession();
  144. m_pClient = NULL;
  145. }
  146. }
  147. unsigned int CFlowControlFSM::s0_on_event(FSMEvent* event)
  148. {
  149. if (event->iEvt == USER_EVT_ANSACMFLOW) {
  150. AgentFlowResult evt;
  151. evt.error = Error_NetBroken;
  152. SpSendBroadcast(m_pEntity->GetFunction(), SP_MSG_OF(AgentFlowResult), SP_MSG_SIG_OF(AgentFlowResult), evt);
  153. LogWarn(Severity_Low, Error_Debug, LOG_ERR_S0_ANSACMFLOW, "s0 receive ANSACMFLOW");
  154. } else if (event->iEvt == USER_EVT_REQAGENTFLOW) {
  155. AgentFlowResult evt;
  156. evt.error = Error_NetBroken;
  157. SpSendBroadcast(m_pEntity->GetFunction(), SP_MSG_OF(AgentFlowResult), SP_MSG_SIG_OF(AgentFlowResult), evt);
  158. LogWarn(Severity_Low, Error_Debug, LOG_ERR_S0_REQAGENTFLOW, "s0 receive REQAGENTFLOW");
  159. }
  160. else if (event->iEvt == USER_EVT_ASSIS_IDEL)
  161. {
  162. if (Error_Succeed == ConnectToAssistchan(false)) {
  163. m_bConnectAssit = true;
  164. }
  165. }
  166. return 0;
  167. }
  168. unsigned int CFlowControlFSM::s1_on_event(FSMEvent* event)
  169. {
  170. if (event->iEvt == USER_EVT_REQAGENTFLOW) {
  171. ReqAgentFlowEvent *rafe = static_cast<ReqAgentFlowEvent*>(event);
  172. ErrorCodeEnum Error;
  173. if (m_pClient) {
  174. ChannelService_Send_Info Info;
  175. Info.compress = true;
  176. Info.encrypt = true;
  177. Info.sub_type = ACM_SUBTYPE_REQ_FLOW;
  178. Info.type = ACM_TYPE_FLW;
  179. SpBuffer buf;
  180. buf.OpenWrite();
  181. #if defined(RVC_OS_WIN)
  182. buf& rafe->req_context;
  183. #else
  184. CSimpleString16Bit reqContext = CSimpleStringW216Bit(rafe->req_context);
  185. buf& reqContext;
  186. #endif //RVC_OS_WIN
  187. Info.data = buf.ToBlob();
  188. Error = m_pClient->Send(Info);
  189. }
  190. else {
  191. Error = Error_NetBroken;
  192. LogWarn(Severity_Low, Error_Debug, LOG_ERR_S1_REQAGENTFLOW_FAILED, "s1 receive REQAGENTFLOW but chan is off.");
  193. }
  194. return Error == Error_Succeed ? 1 : 0;
  195. }
  196. else if (event->iEvt == USER_EVT_NTFENTFLOW) {
  197. NotifyEnterFlowEvent *nef = static_cast<NotifyEnterFlowEvent*>(event);
  198. NotifyEnterFlow evt;
  199. SpSendBroadcast(m_pEntity->GetFunction(), SP_MSG_OF(NotifyEnterFlow), SP_MSG_SIG_OF(NotifyEnterFlow), evt);
  200. }
  201. else if (event->iEvt == USER_EVT_ASSIS_IDEL)
  202. {
  203. LogWarn(Severity_Low, Error_Debug, LOG_ERR_S1_ASSIS_IDEL, "s1 ASSIS_IDEL.");
  204. if (Error_Succeed == ConnectToAssistchan(false)) {
  205. m_bConnectAssit = true;
  206. }
  207. }
  208. return 0;
  209. }
  210. unsigned int CFlowControlFSM::s2_on_event(FSMEvent* event)
  211. {
  212. if (event->iEvt == USER_EVT_CHAN_OFF) {
  213. // notify UI to unlock the screen
  214. AgentFlowResult evt;
  215. evt.error = Error_NetBroken;
  216. SpSendBroadcast(m_pEntity->GetFunction(), SP_MSG_OF(AgentFlowResult), SP_MSG_SIG_OF(AgentFlowResult), evt);
  217. }
  218. else if (event->iEvt == USER_EVT_ANSAGENTFLOW) {
  219. AnsAgentFlowEvent *afe = static_cast<AnsAgentFlowEvent*>(event);
  220. AgentFlowResult evt;
  221. #if defined(RVC_OS_WIN)
  222. evt.ans_context = afe->ans_context;
  223. #else
  224. CSimpleStringW ans_context = CSimpleString16Bit2W(afe->ans_context);
  225. evt.ans_context = ans_context;
  226. #endif //RVC_OS_WIN
  227. evt.error = afe->err ? Error_Unexpect : Error_Succeed;
  228. if (evt.error != Error_Succeed){
  229. LogWarn(Severity_Low, Error_Debug, LOG_ERR_S2_ANSAGENTFLOW_FAILED, "s2 receive ANSAGENTFLOW error.");
  230. }
  231. SpSendBroadcast(m_pEntity->GetFunction(), SP_MSG_OF(AgentFlowResult), SP_MSG_SIG_OF(AgentFlowResult), evt);
  232. }
  233. else if (event->iEvt == USER_EVT_REQACMFLOW) {
  234. ReqACMFlowEvent *afe = static_cast<ReqACMFlowEvent *>(event);
  235. ACMFlowInvoke evt;
  236. #if defined(RVC_OS_WIN)
  237. evt.req_context = afe->req_context;
  238. #else
  239. CSimpleStringW req_context = CSimpleString16Bit2W(afe->req_context);
  240. evt.req_context = req_context;
  241. #endif //RVC_OS_WIN
  242. SpSendBroadcast(m_pEntity->GetFunction(), SP_MSG_OF(ACMFlowInvoke), SP_MSG_SIG_OF(ACMFlowInvoke), evt);
  243. }
  244. else if (event->iEvt == USER_EVT_NTFENTFLOW) {
  245. ErrorCodeEnum result = DisallowControl();
  246. if (result != Error_Succeed){
  247. LogWarn(Severity_Low, Error_Debug, LOG_ERR_S2_NTFENTFLOW_FAILED, "s2 send NTFENTFLOW error.");
  248. }
  249. }
  250. else if (event->iEvt == USER_EVT_ASSIS_IDEL){
  251. LogWarn(Severity_Low, Error_Debug, LOG_ERR_S2_ASSIS_IDEL, "s2 ASSIS_IDEL.");
  252. if (Error_Succeed == ConnectToAssistchan(false)) {
  253. m_bConnectAssit = true;
  254. }
  255. }
  256. return 0;
  257. }
  258. void CFlowControlFSM::s2_on_exit()
  259. {
  260. //only pad vervison use
  261. if (m_bIspad)
  262. {
  263. LogEvent(Severity_Middle,LOG_EVT_EXIT_ACM_FLOW,"exit acm flow");
  264. }
  265. }
  266. void CFlowControlFSM::s3_on_entry()
  267. {
  268. }
  269. void CFlowControlFSM::s3_on_exit() {}
  270. unsigned int CFlowControlFSM::s3_on_event(FSMEvent* event)
  271. {
  272. if (event->iEvt == USER_EVT_ANSACMFLOW) {
  273. AnsACMFlowEvent *afe = static_cast<AnsACMFlowEvent*>(event);
  274. ErrorCodeEnum Error;
  275. if (m_pClient) {
  276. ChannelService_Send_Info Info;
  277. Info.compress = true;
  278. Info.encrypt = true;
  279. Info.sub_type = ACM_SUBTYPE_ANS_FLOW;
  280. Info.type = ACM_TYPE_FLW;
  281. SpBuffer buf;
  282. buf.OpenWrite();
  283. #if defined(RVC_OS_WIN)
  284. buf& afe->ans_context;
  285. #else
  286. CSimpleString16Bit ansContext = CSimpleStringW216Bit(afe->ans_context);
  287. buf& ansContext;
  288. #endif //RVC_OS_WIN
  289. Info.data = buf.ToBlob();
  290. Error = m_pClient->Send(Info);
  291. } else {
  292. Error = Error_NetBroken;
  293. LogWarn(Severity_Low, Error_Debug, LOG_ERR_S3_ANSACMFLOW_FAILED, "s3 send ANSACMFLOW error.");
  294. }
  295. return Error == Error_Succeed ? 1 : 0;
  296. } else if (event->iEvt == USER_EVT_CHAN_OFF) {
  297. AgentFlowResult evt;
  298. evt.error = Error_NetBroken;
  299. SpSendBroadcast(m_pEntity->GetFunction(), SP_MSG_OF(AgentFlowResult), SP_MSG_SIG_OF(AgentFlowResult), evt);
  300. }
  301. else if (event->iEvt == USER_EVT_ASSIS_IDEL)
  302. {
  303. LogWarn(Severity_Low, Error_Debug, LOG_ERR_S3_ASSIS_IDEL, "s3 ASSIS_IDEL.");
  304. if (Error_Succeed == ConnectToAssistchan(false)) {
  305. m_bConnectAssit = true;
  306. }
  307. }
  308. return 0;
  309. }
  310. void CFlowControlFSM::s5_on_entry()
  311. {
  312. }
  313. void CFlowControlFSM::s5_on_exit() { }
  314. unsigned int CFlowControlFSM::s5_on_event(FSMEvent* event)
  315. {
  316. if (event->iEvt == USER_EVT_DISCTRL) {
  317. ErrorCodeEnum result = DisallowControl();
  318. if (result != Error_Succeed) {
  319. LogWarn(Severity_Low, Error_Debug, LOG_ERR_S5_DISCTRL_FAILED, "s5 send DISCTRL error.");
  320. }
  321. }
  322. else if (event->iEvt == USER_EVT_REQAGENTFLOW) {
  323. ReqAgentFlowEvent* rafe = static_cast<ReqAgentFlowEvent*>(event);
  324. ErrorCodeEnum Error;
  325. if (m_pClient) {
  326. ChannelService_Send_Info Info;
  327. Info.compress = true;
  328. Info.encrypt = true;
  329. Info.sub_type = ACM_SUBTYPE_REQ_FLOW;
  330. Info.type = ACM_TYPE_FLW;
  331. SpBuffer buf;
  332. buf.OpenWrite();
  333. #if defined(RVC_OS_WIN)
  334. buf& rafe->req_context;
  335. #else
  336. CSimpleString16Bit reqContext = CSimpleStringW216Bit(rafe->req_context);
  337. buf& reqContext;
  338. #endif //RVC_OS_WIN
  339. Info.data = buf.ToBlob();
  340. Error = m_pClient->Send(Info);
  341. }
  342. else {
  343. Error = Error_NetBroken;
  344. LogWarn(Severity_Low, Error_Debug, LOG_ERR_S5_REQAGENTFLOW_FAILED, "s5 send REQAGENTFLOW error.");
  345. }
  346. return Error == Error_Succeed ? 1 : 0;
  347. }
  348. else if (event->iEvt == USER_EVT_ASSIS_IDEL)
  349. {
  350. LogWarn(Severity_Low, Error_Debug, LOG_ERR_S5_ASSIS_IDEL, "s5 ASSIS_IDEL.");
  351. if (Error_Succeed == ConnectToAssistchan(false)) {
  352. m_bConnectAssit = true;
  353. }
  354. }
  355. return 0;
  356. }
  357. void CFlowControlFSM::s7_on_entry()
  358. {
  359. LogWarn(Severity_Low, Error_Debug, LOG_ERR_S7_ENTRY, "s7 ENTRY.");
  360. }
  361. unsigned int CFlowControlFSM::s7_on_event(FSMEvent* event)
  362. {
  363. if (event->iEvt == USER_EVT_ASSIS_IDEL){
  364. if (Error_Succeed == ConnectToAssistchan(false)) {
  365. m_bConnectAssit = true;
  366. }
  367. }
  368. return 0;
  369. }
  370. void CFlowControlFSM::ProcessPacket( int sub_type, CBlob &blob )
  371. {
  372. if (sub_type == ACM_SUBTYPE_ANS_FLOW) {
  373. AnsAgentFlowEvent *e = new AnsAgentFlowEvent();
  374. SpBuffer buf;
  375. buf.OpenRead((const char*)blob.m_pData, blob.m_iLength);
  376. buf.SetLength(blob.m_iLength);
  377. buf & e->err & e->ans_context;
  378. PostEventFIFO(e);
  379. } else if (sub_type == ACM_SUBTYPE_REQ_FLOW) {
  380. ReqACMFlowEvent *e = new ReqACMFlowEvent();
  381. SpBuffer buf;
  382. buf.OpenRead((const char*)blob.m_pData, blob.m_iLength);
  383. buf.SetLength(blob.m_iLength);
  384. buf & e->req_context;
  385. PostEventFIFO(e);
  386. } else if (sub_type == ACM_SUBTYPE_NTF_ENTFLOW) {
  387. NotifyEnterFlowEvent *e = new NotifyEnterFlowEvent();
  388. e->m_pFSM = this;
  389. SpBuffer buf;
  390. buf.OpenRead((const char*)blob.m_pData, blob.m_iLength);
  391. buf.SetLength(blob.m_iLength);
  392. buf & e->context;
  393. PostEventFIFO(e);
  394. } else {
  395. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("unknown sub_type from agent!");
  396. }
  397. }
  398. ErrorCodeEnum CFlowControlFSM::SetState(const char *s, const char *sdesc)
  399. {
  400. return m_pEntity->GetFunction()->SetSysVar("BackInitiative", s);
  401. }
  402. ErrorCodeEnum CFlowControlFSM::DisallowControl()
  403. {
  404. if (m_pClient) {
  405. ChannelService_Send_Info Info;
  406. Info.compress = false;
  407. Info.encrypt = true;
  408. Info.id = 0;
  409. Info.sub_type = ACM_SUBTYPE_DIS_CONTROL;
  410. Info.type = ACM_TYPE_FLW;
  411. return m_pClient->Send(Info);
  412. } else {
  413. return Error_NetBroken;
  414. }
  415. }
  416. void NotifyEnterFlowEvent::OnUnhandled()
  417. {
  418. m_pFSM->DisallowControl();
  419. }