ClientSessionF.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  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], %4d 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. char* TClientSession::GetPacket()
  212. {
  213. return FRecvBuff;
  214. }
  215. //---------------------------------------------------------------------------
  216. bool TClientSession::ResetPacket(int APktLen)
  217. {
  218. if (APktLen > FRecvIdx) return false;
  219. FRecvIdx -= APktLen;
  220. if (FRecvIdx > 0)
  221. {
  222. memmove(FRecvBuff, FRecvBuff+APktLen, FRecvIdx);
  223. //FRecvIdx = 0;
  224. }
  225. return true;
  226. }
  227. //---------------------------------------------------------------------------
  228. int TClientSession::LogData(char *ASndRcv, BYTE *AData, int ALen)
  229. {
  230. // Hex Data 파일에 저장하고
  231. // FrmCommLog 창에 뿌리는거
  232. TCDSCtlr* pCDSCtlr = FCDSLogCtlr;
  233. if (!pCDSCtlr)
  234. {
  235. ITSLog->LogData(ASndRcv, AData, ALen);
  236. return -1;
  237. }
  238. if (!pCDSCtlr) return -1;
  239. if (!pCDSCtlr->FSLog->FLogCfg.Data) return -1;
  240. try
  241. {
  242. if (pCDSCtlr->FSLog->FLogCfg.Data) pCDSCtlr->FSLog->LogData(ASndRcv, AData, ALen);
  243. if (!pCDSCtlr->FDispLog) return -1;
  244. IPC_LOG_MESSAGE *pLog = g_logBuff.GetBuff();
  245. if (pLog)
  246. {
  247. memset(pLog->Msg, 0x00, sizeof(pLog->Msg));
  248. pLog->From = from_srvTcp;
  249. pLog->Target = log_com;
  250. pLog->Kind = eLOG_DATA;
  251. pLog->Flag = ASndRcv[0] == 'S' ? 1 : 2;
  252. pLog->Write = false;
  253. pLog->Tm = Now();
  254. pLog->Type = 'S';
  255. pLog->Obj = pCDSCtlr->FSLog;
  256. pLog->Ctlr = pCDSCtlr;
  257. pLog->Len = ALen > MAX_LOG_BUFFER ? MAX_LOG_BUFFER-1 : ALen;
  258. memcpy(pLog->Msg, (char*)AData, pLog->Len);
  259. g_logQ.PushTimeout((DWORD)pLog, 2000);
  260. }
  261. }
  262. catch(Exception &e)
  263. {
  264. }
  265. return 0;
  266. }
  267. //---------------------------------------------------------------------------
  268. int TClientSession::LogWrite(int ALogKind, char *AFmt, ...)
  269. {
  270. va_list ap;
  271. int cnt = 0;
  272. char szFmtData[MAX_LOG_BUFFER];
  273. // FrmCommLog 창에 뿌리는거
  274. TCDSCtlr* pCDSCtlr = FCDSLogCtlr;
  275. if (!pCDSCtlr) return -1;
  276. // if (!pCDSCtlr->FDispLog) return -1;
  277. bool bLog = false;
  278. switch(ALogKind)
  279. {
  280. case eLOG_INFO : bLog = pCDSCtlr->FSLog->FLogCfg.Info; break;
  281. case eLOG_DATA : bLog = pCDSCtlr->FSLog->FLogCfg.Data; break;
  282. case eLOG_ERROR : bLog = pCDSCtlr->FSLog->FLogCfg.Error; break;
  283. case eLOG_WARNING: bLog = pCDSCtlr->FSLog->FLogCfg.Warning; break;
  284. case eLOG_DEBUG : bLog = pCDSCtlr->FSLog->FLogCfg.Debug; break;
  285. case eLOG_DETAIL : bLog = pCDSCtlr->FSLog->FLogCfg.Detail; break;
  286. }
  287. if (!bLog) return -1;
  288. try
  289. {
  290. IPC_LOG_MESSAGE *pLog = g_logBuff.GetBuff();
  291. if (pLog)
  292. {
  293. va_start(ap, AFmt);
  294. cnt = vsprintf(szFmtData, AFmt, ap);
  295. va_end(ap);
  296. memset(pLog->Msg, 0x00, sizeof(pLog->Msg));
  297. pLog->From = from_srvTcp;
  298. pLog->Target = log_com;
  299. pLog->Kind = ALogKind;
  300. pLog->Flag = 0;
  301. pLog->Write = true;
  302. pLog->Tm = Now();
  303. pLog->Type = 'S';
  304. pLog->Obj = pCDSCtlr->FSLog;
  305. pLog->Ctlr = pCDSCtlr;
  306. sprintf(pLog->Msg, "+SVR %s, %s", pCDSCtlr->CTLR_NMBR.c_str(), szFmtData);
  307. pLog->Len = strlen(pLog->Msg);
  308. g_logQ.PushTimeout((DWORD)pLog, 2000);
  309. }
  310. }
  311. catch(Exception &e)
  312. {
  313. }
  314. return cnt;
  315. }
  316. //---------------------------------------------------------------------------
  317. int TClientSession::SysLogWrite(int ALogKind, char *AFmt, ...)
  318. {
  319. va_list ap;
  320. int cnt = 0;
  321. char szFmtData[MAX_LOG_BUFFER];
  322. // FrmSysLog 창에 뿌리는거
  323. TCDSCtlr* pCDSCtlr = FCDSLogCtlr;
  324. if (!pCDSCtlr) return -1;
  325. if (!pCDSCtlr->FSLog) return -1;
  326. bool bLog = false;
  327. switch(ALogKind)
  328. {
  329. case eLOG_INFO : bLog = pCDSCtlr->FSLog->FLogCfg.Info; break;
  330. case eLOG_DATA : bLog = pCDSCtlr->FSLog->FLogCfg.Data; break;
  331. case eLOG_ERROR : bLog = pCDSCtlr->FSLog->FLogCfg.Error; break;
  332. case eLOG_WARNING: bLog = pCDSCtlr->FSLog->FLogCfg.Warning; break;
  333. case eLOG_DEBUG : bLog = pCDSCtlr->FSLog->FLogCfg.Debug; break;
  334. case eLOG_DETAIL : bLog = pCDSCtlr->FSLog->FLogCfg.Detail; break;
  335. }
  336. if (!bLog) return -1;
  337. try
  338. {
  339. IPC_LOG_MESSAGE *pLog = g_logBuff.GetBuff();
  340. if (pLog)
  341. {
  342. va_start(ap, AFmt);
  343. cnt = vsprintf(szFmtData, AFmt, ap);
  344. va_end(ap);
  345. memset(pLog->Msg, 0x00, sizeof(pLog->Msg));
  346. pLog->From = from_srvTcp;
  347. pLog->Target = log_sys;
  348. pLog->Kind = ALogKind;
  349. pLog->Flag = 0;
  350. pLog->Write = true;
  351. pLog->Tm = Now();
  352. pLog->Type = 'S';
  353. pLog->Obj = pCDSCtlr->FSLog;
  354. pLog->Ctlr = pCDSCtlr;
  355. sprintf(pLog->Msg, "+SVR %s, %s", pCDSCtlr->CTLR_NMBR.c_str(), szFmtData);
  356. pLog->Len = strlen(szFmtData);
  357. g_logQ.PushTimeout((DWORD)pLog, 2000);
  358. }
  359. }
  360. catch(Exception &e)
  361. {
  362. }
  363. return cnt;
  364. }
  365. //---------------------------------------------------------------------------