//--------------------------------------------------------------------------- #include #include #include "VMSCommLibF.h" #pragma hdrstop #include "FrmNetworkF.h" #include "PacketHandllingF.h" #include "ClientSessionF.h" #include "ClientSessionManagerF.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TFrmNetwork *FrmNetwork; //--------------------------------------------------------------------------- __fastcall TFrmNetwork::TFrmNetwork(TComponent* Owner) : TForm(Owner) { FInitialize = false; FStart = false; FLastErr = 0; FListenSock = INVALID_SOCKET; reMsg->Lines->Clear(); } //--------------------------------------------------------------------------- void __fastcall TFrmNetwork::FormClose(TObject *Sender, TCloseAction &Action) { Hide(); } //--------------------------------------------------------------------------- void __fastcall TFrmNetwork::FormDestroy(TObject *Sender) { Stop(); } //--------------------------------------------------------------------------- bool __fastcall TFrmNetwork::InitSock() { /// À©¼Ó ÃʱâÈ­ WSADATA wsa ; if (WSAStartup(MAKEWORD(2,2), &wsa) != 0) reMsg->Lines->Add("Network library initialize failed"); FInitialize = true; return true; } //--------------------------------------------------------------------------- void __fastcall TFrmNetwork::TermSock() { // À©¼Ó Á¾·á if (FInitialize) { WSACleanup(); } FInitialize = false; } //--------------------------------------------------------------------------- int TFrmNetwork::LogWrite(int ALogKind, char *AFmt, ...) { va_list ap; int cnt = 0; char szFmtData[MAX_LOG_BUFFER]; bool bLog = false; switch(ALogKind) { case eLOG_INFO : bLog = g_LogCfg.Info; break; case eLOG_DATA : bLog = g_LogCfg.Data; break; case eLOG_ERROR : bLog = g_LogCfg.Error; break; case eLOG_WARNING: bLog = g_LogCfg.Warning; break; case eLOG_DEBUG : bLog = g_LogCfg.Debug; break; case eLOG_DETAIL : bLog = g_LogCfg.Detail; break; } if (!bLog) return -1; try { va_start(ap, AFmt); cnt = vsprintf(szFmtData, AFmt, ap); va_end(ap); IPC_LOG_MESSAGE *pLog = g_logBuff.GetBuff(); if (pLog) { memset(pLog->Msg, 0x00, sizeof(pLog->Msg)); pLog->From = from_srvTcp; pLog->Target = log_sys; pLog->Kind = ALogKind; pLog->Flag = 0; pLog->Write = true; pLog->Tm = Now(); pLog->Type = 'S'; pLog->Obj = ITSLog; pLog->Ctlr = NULL; sprintf(pLog->Msg, "+SVR %s", szFmtData); pLog->Len = strlen(pLog->Msg); LogWrite((void*)pLog); g_logQ.PushTimeout((DWORD)pLog, 2000); } } catch(Exception &e) { } return cnt; } //--------------------------------------------------------------------------- #if 1 void TFrmNetwork::LogWrite(void *pLog) { IPC_LOG_MESSAGE *ALog = (IPC_LOG_MESSAGE*)pLog; if (!ALog) return; try { AnsiString sLogKind = " [XXX] "; #if 0 bool bLog = false; switch(ALog->Kind) { case eLOG_INFO : bLog = g_LogCfg.Info; sLogKind = " [INF] "; break; case eLOG_DATA : bLog = g_LogCfg.Data; sLogKind = " [DAT] "; break; case eLOG_ERROR : bLog = g_LogCfg.Error; sLogKind = " [ERR] "; break; case eLOG_WARNING: bLog = g_LogCfg.Warning; sLogKind = " [WAN] "; break; case eLOG_DEBUG : bLog = g_LogCfg.Debug; sLogKind = " [DBG] "; break; case eLOG_DETAIL : bLog = g_LogCfg.Detail; sLogKind = " [DET] "; break; } if (!bLog) return -1; #else switch(ALog->Kind) { case eLOG_INFO : sLogKind = " [INF] "; break; case eLOG_DATA : sLogKind = " [DAT] "; break; case eLOG_ERROR : sLogKind = " [ERR] "; break; case eLOG_WARNING: sLogKind = " [WAN] "; break; case eLOG_DEBUG : sLogKind = " [DBG] "; break; case eLOG_DETAIL : sLogKind = " [DET] "; break; } #endif try { if (reMsg->Lines->Count >= g_AppCfg.nMaxLogLines) reMsg->Lines->Clear(); reMsg->Lines->Add(ALog->Tm.FormatString("hh:nn:ss") + "." + Now().FormatString("ss") + sLogKind + String(ALog->Msg)); } catch(Exception &e) { } } __finally { } } #endif //--------------------------------------------------------------------------- bool __fastcall TFrmNetwork::Start() { SOCKET listenSock = INVALID_SOCKET; SOCKADDR_IN sockAddr; FLastErr = 0; if (!InitSock()) { SocketError(); LERROR("Socket library loading fail: %d.%s", FLastErr, FErrorString.c_str()); return false; } listenSock = socket(AF_INET, SOCK_STREAM, 0); if (listenSock == INVALID_SOCKET) { SocketError(); LERROR("Socket socket error: %d.%s", FLastErr, FErrorString.c_str()); return false; } int opt = 1; setsockopt(listenSock, SOL_SOCKET, SO_REUSEADDR, (const char*)&opt, sizeof(int)); ZeroMemory(&sockAddr, sizeof(sockAddr)); sockAddr.sin_family = AF_INET; sockAddr.sin_addr.s_addr = INADDR_ANY; sockAddr.sin_port = htons(g_AppCfg.comm.nListenPort); FLastErr = bind(listenSock, (SOCKADDR FAR *)&sockAddr, sizeof(sockAddr)); if (FLastErr != 0) { SocketError(); LERROR("Socket bind error: %d.%s", FLastErr, FErrorString.c_str()); CloseSocket(listenSock); return false; } FLastErr = listen(listenSock, 50); if (FLastErr < 0) { SocketError(); LERROR("Socket listen error: %d.%s", FLastErr, FErrorString.c_str()); CloseSocket(listenSock); return false; } FLastErr = WSAAsyncSelect(listenSock, this->Handle, WM_SOCKET_ACCEPT, FD_ACCEPT); if (FLastErr != 0) { SocketError(); LERROR("Socket WSAAsyncSelect error: %d.%s", FLastErr, FErrorString.c_str()); CloseSocket(listenSock); return false; } FStart = true; FListenSock = listenSock; LINFO("TCP Server Start ok: %d", listenSock); return true; } //--------------------------------------------------------------------------- void __fastcall TFrmNetwork::Stop() { if (FListenSock != INVALID_SOCKET) { CloseSocket(FListenSock); FStart = false; FLastErr = 0; FListenSock = INVALID_SOCKET; } TermSock(); } //--------------------------------------------------------------------------- void __fastcall TFrmNetwork::OnAcceptClient(TMessage &Msg) { SOCKET sLinstenSock = (SOCKET)Msg.WParam; WORD nErr = WSAGETSELECTERROR(Msg.LParam); WORD nEvent = WSAGETSELECTEVENT(Msg.LParam); TClientSession *pSession = NULL; if (nErr != NO_ERROR) { SocketError(nErr); LERROR("Accept Event error: %d.%s", FLastErr, FErrorString.c_str()); return; } LINFO("TCP Client Connect Request"); if (nEvent != FD_ACCEPT) { LERROR("OnAcceptClient Unknown Event: %d", nEvent); return ; } SOCKADDR_IN addrClient; int nAddrClient; SOCKET sClientSock = INVALID_SOCKET; nAddrClient = sizeof(addrClient); sClientSock = accept(sLinstenSock, (struct sockaddr *)&addrClient, (int FAR *)&nAddrClient); if (sClientSock == INVALID_SOCKET) { SocketError(); LERROR("Accept accept error: %d.%s", FLastErr, FErrorString.c_str()); return ; } pSession = ClientSessionManager->CreateClientSession(sClientSock, &addrClient); if (!pSession) { SocketError(); LERROR("Accept session allocation failed: %s, %d.%s", pSession->IpAddress.c_str(), FLastErr, FErrorString.c_str()); CloseSocket(sClientSock); return ; } IPC_JOB_MESSAGE *pMsg = g_jobBuff.GetBuff(); pMsg->ObjPtr = (DWORD)pSession; //if (WSAAsyncSelect(pSession->Socket, this->Handle, WM_SOCKET_SELECT, FD_READ | FD_WRITE | FD_CLOSE) > 0) if (WSAAsyncSelect(pSession->Socket, this->Handle, WM_SOCKET_SELECT, FD_READ | FD_CLOSE) > 0) { SocketError(); CloseSocket(sClientSock); LERROR("OnAcceptClient WSAAsyncSelect error: %d.%s", FLastErr, FErrorString.c_str()); pSession->State = eSS_OnDisconnect; pMsg->Type = eTcpClose; g_jobQ.PushBlocking((DWORD)pMsg); return ; } LINFO("TCP Client Connect Accept: %s [%d]", pSession->IpAddress.c_str(), sClientSock);//pSession->Port); pMsg->Type = eTcpConnect; g_jobQ.PushBlocking((DWORD)pMsg); } //--------------------------------------------------------------------------- void __fastcall TFrmNetwork::OnSelectClient(TMessage &Msg) { SOCKET sClientSock = (SOCKET)Msg.WParam; WORD nErr = WSAGETSELECTERROR(Msg.LParam); WORD nEvent = WSAGETSELECTEVENT(Msg.LParam); TClientSession *pSession = NULL; u_long nInBytes; int nFreeSize; int nRecvLen; AnsiString sIpAddress; SOCKADDR_IN addrClient; int addrlen = sizeof(addrClient); getpeername(sClientSock, (SOCKADDR*)&addrClient, &addrlen); sIpAddress.printf("%s[%d]", inet_ntoa(addrClient.sin_addr), sClientSock); pSession = ClientSessionManager->FindClientSession(sClientSock); if (!pSession) { LERROR("Select client not found from session manager: %s", sIpAddress.c_str()); CloseSocket(sClientSock); return ; } IPC_JOB_MESSAGE *pMsg = g_jobBuff.GetBuff(); if (nErr != NO_ERROR) { SocketError(nErr); LERROR("Socket Select Client Event Error: %d.%s", FLastErr, FErrorString.c_str()); pMsg->Type = eTcpErrorEvent; pMsg->ObjPtr = (DWORD)pSession; pSession->State = eSS_OnDisconnect; g_jobQ.PushBlocking((DWORD)pMsg); //pSession->Disconnect(); return; } switch(nEvent) { case FD_READ: { pMsg->Type = eTcpRecv; pMsg->ObjPtr = (DWORD)pSession; nFreeSize = pSession->GetFreeSpaceSize(); nFreeSize = (nFreeSize < MAX_TCP_BUFF) ? nFreeSize : MAX_TCP_BUFF; nRecvLen = recv(pSession->Socket, pMsg->Buff, nFreeSize, 0); if (nRecvLen == SOCKET_ERROR) { if (WSAGetLastError() != WSAEWOULDBLOCK) { SocketError(); LERROR("Select client recv error: %s, %d.%s", sIpAddress.c_str(), FLastErr, FErrorString.c_str()); pSession->State = eSS_OnDisconnect; pMsg->Type = eTcpErrorRecv; } } if (nRecvLen == 0) { PostMessage(this->Handle, WM_SOCKET_SELECT, sClientSock, FD_READ); LERROR("Select client recv length zero: %s, %d.%s", sIpAddress.c_str(), FLastErr, FErrorString.c_str()); return; } else { pMsg->Len = nRecvLen; LDEBUG("Select client recv: %s, %6d bytes recv", sIpAddress.c_str(), pMsg->Len); } #if 0 int nRcvSize = pSession->GetFreeBuffSize(); char *pRcvBuff = pSession->GetBuff(); nErr = ioctlsocket(pSession->Socket, FIONREAD, &nInBytes); if (nErr == SOCKET_ERROR) { SocketError(); LERROR("Select client ioctlsocket error: %s, %d.%s", sIpAddress.c_str(), FLastErr, FErrorString.c_str()); pSession->State = eSS_OnDisconnect; pMsg->Type = eTcpErrorRecv; } else { nRcvSize = nRcvSize > (int)nInBytes ? nInBytes : nRcvSize; int nRecvLen = recv(pSession->Socket, pRcvBuff, nRcvSize, 0); if (nRecvLen != nRcvSize) { SocketError(); LERROR("Select client recv error: %s, %d.%s", sIpAddress.c_str(), FLastErr, FErrorString.c_str()); pSession->State = eSS_OnDisconnect; } else { LDEBUG("Select client recv: %s, %6d bytes recv, %d InBytes", sIpAddress.c_str(), nRecvLen, (int)nInBytes); } } #endif } break; case FD_WRITE: break; case FD_CLOSE: pMsg->Type = eTcpClose; pMsg->ObjPtr = (DWORD)pSession; pSession->State = eSS_OnDisconnect; LERROR("Socket Select client OnClose: %s", sIpAddress.c_str()); break; } g_jobQ.PushBlocking((DWORD)pMsg); } //--------------------------------------------------------------------------- int __fastcall TFrmNetwork::CloseSocket(SOCKET& ASock) { LINGER linger; int res = 0; if (ASock == INVALID_SOCKET) { return 0; } linger.l_onoff = 1; linger.l_linger = 0; setsockopt(ASock, SOL_SOCKET, SO_LINGER, (CHAR FAR *)&linger, sizeof(linger)); res = closesocket(ASock); ASock = INVALID_SOCKET; return res; } //--------------------------------------------------------------------------- int __fastcall TFrmNetwork::SocketError(int AError/*=-1*/) { if (AError == -1) FLastErr = WSAGetLastError(); else FLastErr = AError; LPVOID lpMsgBuf = NULL; try { try { FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, FLastErr, //MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL ); char *pData = (char*)lpMsgBuf; if (strlen(pData) > 2) { pData[strlen(pData)-2] = 0x00; pData[strlen(pData)-1] = 0x00; } FErrorString.printf("%s", pData); } catch(Exception &e) { FErrorString.printf("%s, %s", AnsiString(e.ClassName()).c_str(), AnsiString(e.Message).c_str()); } } __finally { if (lpMsgBuf) LocalFree(lpMsgBuf); lpMsgBuf = NULL; } return FLastErr; } //---------------------------------------------------------------------------