中间件底层,websocket

NetworkCti.cpp 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. #include "StdAfx.h"
  2. #include "NetworkCti.h"
  3. #include "LineHolder.h"
  4. #include "IvrFlowHolder.h"
  5. #include "Logger.h"
  6. #include "MsgCenter.h"
  7. #include "Config.h"
  8. #include "CtiDataDef.h"
  9. #include "TaskMgr.h"
  10. SINGLETON_IMPLEMENT(CNetworkCti)
  11. CNetworkCti::CNetworkCti(void) : m_IsAcdConnected(FALSE), m_IsIvrConnected(FALSE)
  12. {
  13. }
  14. void CNetworkCti::__procRegDevListMsg(CPduEntity & a_PduEntity)
  15. {
  16. auto devList = a_PduEntity.GetDataString(0);
  17. CString dev;
  18. dev.Format("|%d|", PDU_DEV_TYPE_IVR);
  19. bool newIvrConnected = devList.Find(dev) < 0 ? false : true;
  20. dev.Format("|%d|", PDU_DEV_TYPE_ACD);
  21. auto newAcdConnected = devList.Find(dev) < 0 ? false : true;
  22. if (!m_IsAcdConnected && newAcdConnected) { // acd 连接
  23. m_IsAcdConnected = newAcdConnected;
  24. ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_NORMAL, "[ACD]---已连接");
  25. // 通知线路类Acd连接成功
  26. CLineHolder::GetInstance().onAcdConnected();
  27. }
  28. else if (m_IsAcdConnected && !newAcdConnected) { // acd连接断开
  29. m_IsAcdConnected = newAcdConnected;
  30. ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_ERROR, "[ACD]---连接断开");
  31. }
  32. if (m_IsIvrConnected && !newIvrConnected) { // ivr掉线
  33. m_IsIvrConnected = newIvrConnected;
  34. ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_ERROR, "[IVR]---连接断开");
  35. // 通知IvrFlow IVR连接断开
  36. CIvrFlowHolder::GetInstance().onIvrDisconnect();
  37. }
  38. else if (!m_IsIvrConnected && newIvrConnected) { // ivr上线
  39. m_IsIvrConnected = newIvrConnected;
  40. ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_NORMAL, "[IVR]---已连接");
  41. }
  42. }
  43. CNetworkCti::~CNetworkCti(void)
  44. {
  45. }
  46. /*****************************************************************
  47. **【函数名称】 __procRegMsg
  48. **【函数功能】 处理注册命令
  49. **【参数】 a_PduEntity:注册命令
  50. **【返回值】
  51. ****************************************************************/
  52. void CNetworkCti::__procRegMsg(CPduEntity& a_PduEntity)
  53. {
  54. bool RegResult = false;
  55. switch (a_PduEntity.GetLocalDevType())
  56. {
  57. case PDU_DEV_TYPE_ACD:
  58. RegResult = m_DevAcd.DevId == -1 ? true : false;
  59. break;
  60. case PDU_DEV_TYPE_IVR:
  61. RegResult = m_DevIvr.DevId == -1 ? true : false;
  62. break;
  63. default:
  64. ASSERT(FALSE);
  65. break;
  66. }
  67. // 发送注册结果
  68. a_PduEntity.SetToExecReturn();
  69. a_PduEntity.SetDataBool(0, RegResult);
  70. CNetInterface::getNetInstance()->Send(&a_PduEntity, a_PduEntity.GetLocalDevType(), a_PduEntity.GetLocalDevId());
  71. }
  72. /*****************************************************************
  73. **【函数名称】 __onRegSuccess
  74. **【函数功能】 设备注册成功处理函数
  75. **【参数】 linkContent:注册段信息
  76. **【返回值】
  77. ****************************************************************/
  78. void CNetworkCti::__onRegSuccess(const PduLinkContent& linkContent)
  79. {
  80. switch (linkContent.nFarType)
  81. {
  82. case PDU_DEV_TYPE_ACD:
  83. {
  84. // 保存设备信息
  85. m_DevAcd.DevId = linkContent.nLocalId;
  86. lstrcpy(m_DevAcd.szIpAddress, linkContent.szFarIp);
  87. m_DevAcd.Port = linkContent.nFarPort;
  88. m_IsAcdConnected = TRUE;
  89. // 通知线路类Acd连接成功
  90. CLineHolder::GetInstance().onAcdConnected();
  91. }
  92. break;
  93. case PDU_DEV_TYPE_IVR:
  94. {
  95. // 保存设备信息
  96. m_DevIvr.DevId = linkContent.nLocalId;
  97. lstrcpy(m_DevIvr.szIpAddress, linkContent.szFarIp);
  98. m_DevIvr.Port = linkContent.nFarPort;
  99. m_IsIvrConnected = TRUE;
  100. }
  101. break;
  102. default:
  103. ASSERT(FALSE);
  104. break;
  105. }
  106. }
  107. /*****************************************************************
  108. **【函数名称】 __onDisconnect
  109. **【函数功能】 设备连接断开处理函数
  110. **【参数】 linkContent:连接断开端信息
  111. **【返回值】
  112. ****************************************************************/
  113. void CNetworkCti::__onDisconnect(const PduLinkContent& linkContent)
  114. {
  115. switch (linkContent.nFarType)
  116. {
  117. case PDU_DEV_TYPE_ACD:
  118. {
  119. if (m_DevAcd.DevId != linkContent.nLocalId) return;
  120. if (strcmp(m_DevAcd.szIpAddress, linkContent.szFarIp) != 0) return;
  121. if (m_DevAcd.Port != linkContent.nFarPort) return;
  122. memset(&m_DevAcd, 0, sizeof(m_DevAcd));
  123. m_DevAcd.DevId = -1;
  124. m_IsAcdConnected = FALSE;
  125. }
  126. break;
  127. case PDU_DEV_TYPE_IVR:
  128. {
  129. if (m_DevIvr.DevId != linkContent.nLocalId) return;
  130. if (strcmp(m_DevIvr.szIpAddress, linkContent.szFarIp) != 0) return;
  131. if (m_DevIvr.Port != linkContent.nFarPort) return;
  132. memset(&m_DevIvr, 0, sizeof(m_DevIvr));
  133. m_DevIvr.DevId = -1;
  134. // 通知IvrFlow IVR连接断开
  135. CIvrFlowHolder::GetInstance().onIvrDisconnect();
  136. m_IsIvrConnected = FALSE;
  137. }
  138. break;
  139. default:
  140. break;
  141. }
  142. }
  143. /*****************************************************************
  144. **【函数名称】 OnLinkStateChanged
  145. **【函数功能】 连接状态信息变化
  146. **【参数】
  147. **【返回值】
  148. ****************************************************************/
  149. void CNetworkCti::OnLinkStateChanged(const PduLinkContent& linkContent)
  150. {
  151. CString Msg;
  152. LOG_LEVEL Level = LOG_LEVEL_NORMAL;
  153. switch (linkContent.nLinkState)
  154. {
  155. case PDU_LINK_STATE_SUCCESSED: // 请求连接成功
  156. Msg.Format(_T("{Net}: Far End[IP = %s, Port = %d], Hint = 网络连接成功..."),
  157. linkContent.szFarIp,
  158. linkContent.nFarPort);
  159. break;
  160. case PDU_LINK_STATE_FAILED: // 请求连接失败
  161. Msg.Format(_T("{Net}: Far End[IP = %s, Port = %d], Hint = 网络连接失败..."),
  162. linkContent.szFarIp,
  163. linkContent.nFarPort);
  164. Level = LOG_LEVEL_ERROR;
  165. break;
  166. case PDU_LINK_STATE_ACCEPTED: // 已接受对端连接
  167. Msg.Format(_T("{Net}: Far End[IP = %s, Port = %d], Hint = 已接受远端网络连接..."),
  168. linkContent.szFarIp,
  169. linkContent.nFarPort);
  170. break;
  171. case PDU_LINK_STATE_DISCONNECTED: // 连接已断开
  172. {
  173. Msg.Format(_T("{Net}: Far End[IP = %s, Port = %d], Hint = 网络连接已断开..."),
  174. linkContent.szFarIp,
  175. linkContent.nFarPort);
  176. Level = LOG_LEVEL_ERROR;
  177. // 通知IvrFlow IVR连接断开
  178. CIvrFlowHolder::GetInstance().onIvrDisconnect();
  179. m_IsIvrConnected = FALSE;
  180. m_IsAcdConnected = FALSE;
  181. }
  182. break;
  183. case PDU_LINK_STATE_REG_OK: // 注册成功
  184. {
  185. Msg.Format(_T("{Net}: Far End[Type = %d, ID = %d, IP = %s, Port = %d], Hint = 网络连接注册成功..."),
  186. linkContent.nFarType,
  187. linkContent.nFarId,
  188. linkContent.szFarIp,
  189. linkContent.nFarPort);
  190. }
  191. break;
  192. case PDU_LINK_STATE_REG_FAILED: // 注册失败
  193. Msg.Format(_T("{Net}: Far End[IP = %s, Port = %d], Hint = 网络连接注册失败, 通讯禁止..."),
  194. linkContent.szFarIp,
  195. linkContent.nFarPort);
  196. Level = LOG_LEVEL_ERROR;
  197. break;
  198. default:
  199. Msg.Format(_T("{Net}: Far End[Type = %d, ID = %d, IP = %s, Port = %d]"),
  200. linkContent.nFarType,
  201. linkContent.nFarId,
  202. linkContent.szFarIp,
  203. linkContent.nFarPort);
  204. break;
  205. } // end switch
  206. ILogger::getInstance().log(LOG_CLASS_SOCKET, Level, "%s", Msg);
  207. }
  208. /*****************************************************************
  209. **【函数名称】 OnRecvCommand
  210. **【函数功能】 Pdu命令处理接口
  211. **【参数】 a_pPduEntity:消息实体
  212. **【返回值】
  213. ****************************************************************/
  214. void CNetworkCti::OnRecvCommand(CPduEntity* a_pPduEntity)
  215. {
  216. ASSERT(a_pPduEntity != NULL);
  217. if (a_pPduEntity->GetCmdType() != PDU_CMD_LISTEN) // 心跳命令不打印
  218. {
  219. ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, _T("{CNetworkCti}:OnRecvCommand,CmdType=%d,LocalDevType[%d]"), a_pPduEntity->GetCmdType(), a_pPduEntity->GetLocalDevType());
  220. }
  221. switch (a_pPduEntity->GetCmdType())
  222. {
  223. case PDU_CMD_REG: // 注册命令
  224. __procRegMsg(*a_pPduEntity);
  225. break;
  226. case PDU_CMD_DEV_ONLINE_LIST: // 设备在线列表
  227. __procRegDevListMsg(*a_pPduEntity);
  228. break;
  229. case PDU_CMD_CTI_IVR_CALLIN: // CallIn返回命令
  230. case PDU_CMD_CTI_IVR_TURNIVR: // 转IVR返回命令
  231. case PDU_CMD_IVR_HANGUP: // IVR通知CTI挂机
  232. case PDU_CMD_IVR_END: // IVR通知CTI流程结束
  233. case PDU_CMD_IVR_WANT_AGENT: // IVR通知CTI请求排队(包括ACD返回)
  234. case PDU_CMD_IVR_QUEUE_CONTINUE: // IVR通知CTI继续排队(包括ACD返回)
  235. case PDU_CMD_IVR_QUEUE_CANCEL: // IVR通知CTI取消排队
  236. case PDU_CMD_IVR_TURN_AGENT: // IVR通知CTI转坐席
  237. case PDU_CMD_IVR_PLAY_DTMF: // IVR通知CTI放音收按键
  238. case PDU_CMD_IVR_CALL_OUT: // IVR通知CTI自动呼叫某个号码
  239. case PDU_CMD_IVR_TURN_OUTLINE: // IVR呼叫转移
  240. case PDU_CMD_IVR_FAX: // IVR通知收发传真
  241. case PDU_CMD_IVR_LEAVE_WORD: // IVR通知留言
  242. CIvrFlowHolder::GetInstance().onPduMessage(*a_pPduEntity);
  243. break;
  244. case PDU_CMD_LISTEN:
  245. return;
  246. case PDU_CMD_IVR_WAITER_COUNT: //2019 - 9 - 6 配合4.0acd返回排队人数
  247. {
  248. send2ACD(*a_pPduEntity); //发送至ACD
  249. int WaiterCount = a_pPduEntity->GetDataUInt(0);
  250. // m_WaiterCount.onWaiterCount(WaiterCount);
  251. ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_NORMAL, "{NetWorkCti}:收到排队数量%d", WaiterCount);
  252. }
  253. break;
  254. default:
  255. {
  256. __try {
  257. CTaskMgr::GetInstance().onPduMessage(*a_pPduEntity);
  258. }
  259. __except (EXCEPTION_EXECUTE_HANDLER)
  260. {
  261. ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{CNetworkCti}:OnRecvCommand,CTaskMgr异常,CmdType=%d,mdw5.1.19.1"), a_pPduEntity->GetCmdType());
  262. }
  263. break;
  264. }
  265. break;
  266. }
  267. }
  268. /*****************************************************************
  269. **【函数名称】 init
  270. **【函数功能】 初始化
  271. **【参数】
  272. **【返回值】 成功TRUE,失败FALSE
  273. ****************************************************************/
  274. BOOL CNetworkCti::init()
  275. {
  276. // 初始化客户端设备信息
  277. memset(&m_DevAcd, 0, sizeof(m_DevAcd));
  278. memset(&m_DevIvr, 0, sizeof(m_DevIvr));
  279. m_DevAcd.DevId = -1;
  280. m_DevIvr.DevId = -1;
  281. auto pClient = CNetInterface::getNetInstance();
  282. pClient->setLinkStateChanged(std::bind(&CNetworkCti::OnLinkStateChanged, this, std::placeholders::_1));
  283. pClient->setRecvCommand(std::bind(&CNetworkCti::OnRecvCommand, this, std::placeholders::_1));
  284. //连接ws服务器端
  285. CString Ip = CConfig::GetInstance().wsIP();
  286. int Port = CConfig::GetInstance().wsPort();
  287. if(pClient->CreatePduClient(Ip, Port, PDU_DEV_TYPE_CTI, 1, true))
  288. {
  289. ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_NORMAL, "{Net}: 连接ws服务端成功,IP=%s,ListenPort = %d", Ip,Port);
  290. return TRUE;
  291. }
  292. else
  293. {
  294. ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_ERROR, "{Net}: 连接ws服务端失败,IP=%s,ListenPort = %d", Ip, Port);
  295. return FALSE;
  296. }
  297. return TRUE;
  298. }
  299. /*****************************************************************
  300. **【函数名称】 release
  301. **【函数功能】 释放资源
  302. **【参数】
  303. **【返回值】 成功TRUE,失败FALSE
  304. ****************************************************************/
  305. void CNetworkCti::release(void)
  306. {
  307. CNetInterface::getNetInstance()->ClosePduClient(PDU_DEV_TYPE_CTI, 1);
  308. }
  309. /*****************************************************************
  310. **【函数名称】 send2ACD
  311. **【函数功能】 发送PDU到ACD
  312. **【参数】 a_PduEntity:待发送的PDU
  313. **【返回值】
  314. ****************************************************************/
  315. BOOL CNetworkCti::send2ACD(CPduEntity& a_PduEntity)
  316. {
  317. return CNetInterface::getNetInstance()->Send(&a_PduEntity, PDU_DEV_TYPE_ACD, m_DevAcd.DevId);
  318. }
  319. /*****************************************************************
  320. **【函数名称】 send2IVR
  321. **【函数功能】 发送PDU到IVR
  322. **【参数】 a_PduEntity:待发送的PDU
  323. **【返回值】
  324. ****************************************************************/
  325. BOOL CNetworkCti::send2IVR(CPduEntity& a_PduEntity)
  326. {
  327. return CNetInterface::getNetInstance()->Send(&a_PduEntity, PDU_DEV_TYPE_IVR, m_DevIvr.DevId);
  328. }