ClientSessionF.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. //---------------------------------------------------------------------------
  2. #pragma hdrstop
  3. #include "ClientSessionF.h"
  4. #include "PacketHandllingF.h"
  5. #include "VMSCommLibF.h"
  6. //---------------------------------------------------------------------------
  7. #pragma package(smart_init)
  8. TClientSession::TClientSession(SOCKET ASock, SOCKADDR_IN* ASockAddr)
  9. {
  10. Create(ASock, ASockAddr);
  11. }
  12. //---------------------------------------------------------------------------
  13. TClientSession::TClientSession()
  14. {
  15. FSocket = INVALID_SOCKET;
  16. FState = eSS_none;
  17. FIpAddress = "";
  18. FPort = 0;
  19. Init();
  20. }
  21. //---------------------------------------------------------------------------
  22. void TClientSession::Create(SOCKET ASock, SOCKADDR_IN* ASockAddr)
  23. {
  24. FSocket = ASock;
  25. FState = eSS_OnConnect;
  26. memcpy(&FSocketAddr, ASockAddr, sizeof(SOCKADDR_IN));
  27. FIpAddress.printf("%s", inet_ntoa(FSocketAddr.sin_addr));
  28. FPort = ntohs(FSocketAddr.sin_port);
  29. Init();
  30. }
  31. //---------------------------------------------------------------------------
  32. void TClientSession::Init()
  33. {
  34. FConnected = false;
  35. FRecvIdx = 0;
  36. FSendIdx = 0;
  37. FPacketLen = 0;
  38. FPacketSent = 0;
  39. FPacketPtr = NULL;
  40. FCDSCtlr = NULL;
  41. FCDSLogCtlr = NULL;
  42. FCloseTick = 0;
  43. FChkRecvTO = false;
  44. FTmrSend = Now();
  45. FTmrRecv = Now();
  46. }
  47. //---------------------------------------------------------------------------
  48. TClientSession::~TClientSession()
  49. {
  50. }
  51. //---------------------------------------------------------------------------
  52. int TClientSession::SocketError()
  53. {
  54. FLastErr = WSAGetLastError();
  55. LPVOID lpMsgBuf = NULL;
  56. try
  57. {
  58. try
  59. {
  60. FormatMessage(
  61. FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  62. NULL,
  63. FLastErr,
  64. //MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  65. MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
  66. (LPTSTR) &lpMsgBuf,
  67. 0,
  68. NULL
  69. );
  70. char *pData = (char*)lpMsgBuf;
  71. if (strlen(pData) > 2)
  72. {
  73. pData[strlen(pData)-2] = 0x00;
  74. pData[strlen(pData)-1] = 0x00;
  75. }
  76. FErrorString.printf("%s", pData);
  77. }
  78. catch(Exception &e)
  79. {
  80. FErrorString.printf("%s, %s", AnsiString(e.ClassName()).c_str(), AnsiString(e.Message).c_str());
  81. }
  82. }
  83. __finally
  84. {
  85. if (lpMsgBuf) LocalFree(lpMsgBuf);
  86. lpMsgBuf = NULL;
  87. }
  88. return FLastErr;
  89. }
  90. //---------------------------------------------------------------------------
  91. bool TClientSession::OnConnect()
  92. {
  93. FConnected = true;
  94. if (!CheckLoginClient())
  95. {
  96. Disconnect();
  97. return false;
  98. }
  99. // 소켓을 넌블러킹으로 바꾸고
  100. u_long arg = 1 ;
  101. ioctlsocket(FSocket, FIONBIO, &arg) ;
  102. /// nagle 알고리즘 끄기
  103. int opt = 1 ;
  104. setsockopt(FSocket, IPPROTO_TCP, TCP_NODELAY, (const char*)&opt, sizeof(int));
  105. FTmrConn = Now();
  106. return true;
  107. }
  108. //---------------------------------------------------------------------------
  109. int TClientSession::GetFreeSpaceSize()
  110. {
  111. return (SESSION_RECV_BUFFER - FRecvIdx);
  112. }
  113. //---------------------------------------------------------------------------
  114. char* TClientSession::GetBuffer()
  115. {
  116. return (char*)FRecvBuff+FRecvIdx;
  117. }
  118. //---------------------------------------------------------------------------
  119. void TClientSession::RecvBuffCommit(int ARecvLen)
  120. {
  121. FRecvIdx += ARecvLen;
  122. }
  123. //---------------------------------------------------------------------------
  124. void TClientSession::Disconnect()
  125. {
  126. OnDisconnected();
  127. if (!IsConnected) return;
  128. // 즉각 해제
  129. LINGER linger;
  130. linger.l_onoff = 1;
  131. linger.l_linger = 0;
  132. // no TCP TIME_WAIT
  133. if (SOCKET_ERROR == setsockopt(FSocket, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(LINGER)))
  134. {
  135. // printf_s("[DEBUG] setsockopt linger option error: %d\n", GetLastError());
  136. // return;
  137. }
  138. closesocket(FSocket);
  139. //FSocket = INVALID_SOCKET; ==> 여기서 초기화 하면 ClientSessionManager에서 삭제할때 오류발생 소켓을 키로 사용함
  140. FConnected = false ;
  141. FState = eSS_OnDisconnect;
  142. FCDSCtlr = NULL;
  143. FCloseTick = 0;
  144. FState = eSS_none;
  145. FSocket = INVALID_SOCKET;
  146. }
  147. //---------------------------------------------------------------------------
  148. void TClientSession::OnWriteComplete(int ASendLen, int AReqLen)
  149. {
  150. /// 보내기 완료한 데이터는 버퍼에서 제거
  151. if (FSendIdx >= ASendLen) FSendIdx -= ASendLen;
  152. }
  153. //---------------------------------------------------------------------------
  154. bool TClientSession::SendRequest(char *AData, int ADataLen)
  155. {
  156. if (!IsConnected)
  157. {
  158. MERROR("+SVR Session SendRequest: %s[%d], already closed", FIpAddress.c_str(), FSocket);
  159. Disconnect();
  160. return false;
  161. }
  162. if (ADataLen > (SESSION_SEND_BUFFER - FSendIdx))
  163. {
  164. /// 버퍼 용량 부족인 경우는 끊어버림
  165. MERROR("+SVR Session SendRequest: %s[%d], Send Buffer Overflow, will be closed.", FIpAddress.c_str(), FSocket);
  166. Disconnect();
  167. return false;
  168. }
  169. FPacketLen = ADataLen;
  170. FPacketSent= 0;
  171. FPacketPtr = FSendBuff+FSendIdx;
  172. memcpy(FSendBuff+FSendIdx, AData, ADataLen);
  173. FSendIdx += ADataLen;
  174. return true;
  175. }
  176. //---------------------------------------------------------------------------
  177. bool TClientSession::SendFlush()
  178. {
  179. if (!IsConnected)
  180. {
  181. MERROR("+SVR Session SendFlush: %s[%d], already closed", FIpAddress.c_str(), FSocket);
  182. Disconnect();
  183. return false;
  184. }
  185. /// 보낼 데이터가 없으면 그냥 리턴
  186. if (FSendIdx == 0)
  187. return true;
  188. DWORD sendbytes = 0;
  189. DWORD flags = 0;
  190. int nLeft = FSendIdx;
  191. char *buf = (char*)FSendBuff;//+FSendIdx;
  192. int nSendedBytes = send(FSocket, buf, nLeft, 0);
  193. if (nSendedBytes <= 0)
  194. {
  195. MERROR("+SVR Session SendFlush: %s[%d]: send error: %d, %d", FIpAddress.c_str(), FSocket, nSendedBytes, WSAGetLastError());
  196. Disconnect();
  197. return false;
  198. }
  199. MDEBUG("+SVR Sessionclient send: %s[%d], %6d bytes send", FIpAddress.c_str(), FSocket, nSendedBytes);
  200. OnWriteComplete(nSendedBytes, nLeft);
  201. FPacketSent += nSendedBytes;
  202. if (FPacketSent >= FPacketLen)
  203. {
  204. OnWrite(FPacketPtr, FPacketLen);
  205. FPacketSent -= FPacketLen;
  206. FPacketPtr = FSendBuff + FPacketSent;
  207. }
  208. return true;
  209. }
  210. //---------------------------------------------------------------------------
  211. bool TClientSession::SendFlushComplete()
  212. {
  213. while (true)
  214. {
  215. if (!SendFlush())
  216. {
  217. return false;
  218. }
  219. if (FSendIdx == 0)
  220. {
  221. break;
  222. }
  223. Sleep(10);
  224. }
  225. Sleep(20);
  226. return true;
  227. }
  228. //---------------------------------------------------------------------------
  229. char* TClientSession::GetPacket()
  230. {
  231. return FRecvBuff;
  232. }
  233. //---------------------------------------------------------------------------
  234. bool TClientSession::ResetPacket(int APktLen)
  235. {
  236. if (APktLen > FRecvIdx) return false;
  237. FRecvIdx -= APktLen;
  238. if (FRecvIdx > 0)
  239. {
  240. memmove(FRecvBuff, FRecvBuff+APktLen, FRecvIdx);
  241. //FRecvIdx = 0;
  242. }
  243. return true;
  244. }
  245. //---------------------------------------------------------------------------
  246. int TClientSession::LogData(char *ASndRcv, BYTE *AData, int ALen)
  247. {
  248. // Hex Data 파일에 저장하고
  249. // FrmCommLog 창에 뿌리는거
  250. TCDSCtlr* pCDSCtlr = FCDSLogCtlr;
  251. if (!pCDSCtlr)
  252. {
  253. ITSLog->LogData(ASndRcv, AData, ALen);
  254. return -1;
  255. }
  256. if (!pCDSCtlr) return -1;
  257. if (!pCDSCtlr->FSLog->FLogCfg.Data) return -1;
  258. try
  259. {
  260. if (pCDSCtlr->FSLog->FLogCfg.Data) pCDSCtlr->FSLog->LogData(ASndRcv, AData, ALen);
  261. if (!pCDSCtlr->FDispLog) return -1;
  262. IPC_LOG_MESSAGE *pLog = g_logBuff.GetBuff();
  263. if (pLog)
  264. {
  265. memset(pLog->Msg, 0x00, sizeof(pLog->Msg));
  266. pLog->From = from_srvTcp;
  267. pLog->Target = log_com;
  268. pLog->Kind = eLOG_DATA;
  269. pLog->Flag = ASndRcv[0] == 'S' ? 1 : 2;
  270. pLog->Write = false;
  271. pLog->Tm = Now();
  272. pLog->Type = 'S';
  273. pLog->Obj = pCDSCtlr->FSLog;
  274. pLog->Ctlr = pCDSCtlr;
  275. pLog->Len = ALen > MAX_LOG_BUFFER ? MAX_LOG_BUFFER-1 : ALen;
  276. memcpy(pLog->Msg, (char*)AData, pLog->Len);
  277. g_logQ.PushTimeout((DWORD)pLog, 2000);
  278. }
  279. }
  280. catch(Exception &e)
  281. {
  282. }
  283. return 0;
  284. }
  285. //---------------------------------------------------------------------------
  286. int TClientSession::LogWrite(int ALogKind, char *AFmt, ...)
  287. {
  288. va_list ap;
  289. int cnt = 0;
  290. char szFmtData[MAX_LOG_BUFFER];
  291. // FrmCommLog 창에 뿌리는거
  292. TCDSCtlr* pCDSCtlr = FCDSLogCtlr;
  293. if (!pCDSCtlr) return -1;
  294. // if (!pCDSCtlr->FDispLog) return -1;
  295. bool bLog = false;
  296. switch(ALogKind)
  297. {
  298. case eLOG_INFO : bLog = pCDSCtlr->FSLog->FLogCfg.Info; break;
  299. case eLOG_DATA : bLog = pCDSCtlr->FSLog->FLogCfg.Data; break;
  300. case eLOG_ERROR : bLog = pCDSCtlr->FSLog->FLogCfg.Error; break;
  301. case eLOG_WARNING: bLog = pCDSCtlr->FSLog->FLogCfg.Warning; break;
  302. case eLOG_DEBUG : bLog = pCDSCtlr->FSLog->FLogCfg.Debug; break;
  303. case eLOG_DETAIL : bLog = pCDSCtlr->FSLog->FLogCfg.Detail; break;
  304. }
  305. if (!bLog) return -1;
  306. try
  307. {
  308. IPC_LOG_MESSAGE *pLog = g_logBuff.GetBuff();
  309. if (pLog)
  310. {
  311. va_start(ap, AFmt);
  312. cnt = vsprintf(szFmtData, AFmt, ap);
  313. va_end(ap);
  314. memset(pLog->Msg, 0x00, sizeof(pLog->Msg));
  315. pLog->From = from_srvTcp;
  316. pLog->Target = log_com;
  317. pLog->Kind = ALogKind;
  318. pLog->Flag = 0;
  319. pLog->Write = true;
  320. pLog->Tm = Now();
  321. pLog->Type = 'S';
  322. pLog->Obj = pCDSCtlr->FSLog;
  323. pLog->Ctlr = pCDSCtlr;
  324. sprintf(pLog->Msg, "+SVR %s, %s", pCDSCtlr->CTLR_NMBR.c_str(), szFmtData);
  325. pLog->Len = strlen(pLog->Msg);
  326. g_logQ.PushTimeout((DWORD)pLog, 2000);
  327. }
  328. }
  329. catch(Exception &e)
  330. {
  331. }
  332. return cnt;
  333. }
  334. //---------------------------------------------------------------------------
  335. int TClientSession::SysLogWrite(int ALogKind, char *AFmt, ...)
  336. {
  337. va_list ap;
  338. int cnt = 0;
  339. char szFmtData[MAX_LOG_BUFFER];
  340. // FrmSysLog 창에 뿌리는거
  341. TCDSCtlr* pCDSCtlr = FCDSLogCtlr;
  342. if (!pCDSCtlr) return -1;
  343. if (!pCDSCtlr->FSLog) return -1;
  344. bool bLog = false;
  345. switch(ALogKind)
  346. {
  347. case eLOG_INFO : bLog = pCDSCtlr->FSLog->FLogCfg.Info; break;
  348. case eLOG_DATA : bLog = pCDSCtlr->FSLog->FLogCfg.Data; break;
  349. case eLOG_ERROR : bLog = pCDSCtlr->FSLog->FLogCfg.Error; break;
  350. case eLOG_WARNING: bLog = pCDSCtlr->FSLog->FLogCfg.Warning; break;
  351. case eLOG_DEBUG : bLog = pCDSCtlr->FSLog->FLogCfg.Debug; break;
  352. case eLOG_DETAIL : bLog = pCDSCtlr->FSLog->FLogCfg.Detail; break;
  353. }
  354. if (!bLog) return -1;
  355. try
  356. {
  357. IPC_LOG_MESSAGE *pLog = g_logBuff.GetBuff();
  358. if (pLog)
  359. {
  360. va_start(ap, AFmt);
  361. cnt = vsprintf(szFmtData, AFmt, ap);
  362. va_end(ap);
  363. memset(pLog->Msg, 0x00, sizeof(pLog->Msg));
  364. pLog->From = from_srvTcp;
  365. pLog->Target = log_sys;
  366. pLog->Kind = ALogKind;
  367. pLog->Flag = 0;
  368. pLog->Write = true;
  369. pLog->Tm = Now();
  370. pLog->Type = 'S';
  371. pLog->Obj = pCDSCtlr->FSLog;
  372. pLog->Ctlr = pCDSCtlr;
  373. sprintf(pLog->Msg, "+SVR %s, %s", pCDSCtlr->CTLR_NMBR.c_str(), szFmtData);
  374. pLog->Len = strlen(szFmtData);
  375. g_logQ.PushTimeout((DWORD)pLog, 2000);
  376. }
  377. }
  378. catch(Exception &e)
  379. {
  380. }
  381. return cnt;
  382. }
  383. //---------------------------------------------------------------------------