int DisconnectPlc(PLC *plc) { if (plc==NULL) return(0); Log(LOG_DEBUG,"Entering DisconnectPlc (%s)\n",plc->PlcName); if (plc->Connection!=NULL) { Log(LOG_DEBUG,"DisconnectPlc : Connection %p (%d References)\n",plc->Connection,plc->Connection->References); plc->Connection->References--; if (plc->Connection->References<=0) { Log(LOG_DEBUG,"DisconnectPlc : No more Reference to Connection %p, closing\n",plc->Connection); KillConnection(plc->Connection); } } if (plc->Session!=NULL) { Log(LOG_DEBUG,"DisconnectPlc : Session %p (%d References)\n",plc->Session,plc->Session->References); plc->Session->References--; if (plc->Session->References<=0) { Log(LOG_DEBUG,"DisconnectPlc : No more Reference to Session %p, closing\n",plc->Session); KillSession(plc->Session); } } plc->Connection=NULL; plc->Session=NULL; return(0); }
Connection::~Connection() { LogMessage("[%d] Connection Destroyed\n", m_RecvThreadHandle); KillConnection(); // Let thread know it is terminated. if (!m_TcpThreadTerminated) { m_TcpThreadTerminated = true; WakeupThread(); m_Mutex.Lock(); Sleep(1); m_Mutex.Unlock(); } delete m_SendQueue; }
void Connection::RunRecvThread() { bool isSocketReady = false; // Used for checking Socket state int numretries = 0; int received; unsigned short bytes; short opcode; EnbTcpHeader header; char *ptr_hdr = (char*)&header; memset(&header, 0, sizeof(header)); while (!g_ServerShutdown && !m_TcpThreadTerminated) { while (m_TcpThreadRunning) { // Do the key exchange if it hasn't been done yet if (!m_KeysExchanged) { if (!RunKeyExchange()) { // Key Exchange failed. KillConnection(); break; } else { m_KeysExchanged = true; } } // Main Loop isSocketReady = SocketReady(1); // One Second Timeout if ( isSocketReady && (recv(m_Socket, ptr_hdr, 4, 0) == 4) ) { m_InactivityTimer = 0; if (m_PacketLoggingEnabled) { LogMessage("[%d] Received 4 byte header (encrypted):\n", m_RecvThreadHandle); DumpBuffer((unsigned char *) &header, 4); } if (m_ServerType != CONNECTION_TYPE_SECTOR_SERVER_TO_PROXY && m_ServerType != CONNECTION_TYPE_GLOBAL_PROXY_TO_SERVER) { m_CryptIn.RC4((unsigned char *) &header, 4); } if (m_PacketLoggingEnabled) { LogMessage("[%d] Received 4 byte header (decrypted):\n", m_RecvThreadHandle); DumpBuffer((unsigned char *) &header, 4); } bytes = header.size - sizeof(EnbTcpHeader); // Bytes to fetch opcode = header.opcode; // Opcode for this packet // This buffer check MUST be in place if ( (bytes > MAX_BUFFER) ) { LogMessage("[%d] Received packet with incorrect payload length: opcode = 0x%02x, length = %d. Aborting.\n", m_RecvThreadHandle, opcode, bytes); KillConnection(); // We're not permitting a 2nd chance. break; } //LogMessage("Received packet: opcode = 0x%02x, length = %d\n", opcode, bytes); received = recv(m_Socket, (char *) m_RecvBuffer, bytes, 0); numretries = 0; while ( received != bytes && // Did we fetch everything? SocketReady() && // Can we still get more? numretries < MAX_RETRIES && // Can we still retry to get more? m_TcpThreadRunning ) // And we haven't been told to stop? { int rcv = recv(m_Socket, (char *) (m_RecvBuffer + received), bytes - received, 0); if (rcv > 0) { received += rcv; } else break; numretries++; // Prevent an infinite loop } if ( received == bytes && m_TcpThreadRunning ) // We got the whole package and we haven't been told top stop { if (m_ServerType != CONNECTION_TYPE_SECTOR_SERVER_TO_PROXY && m_ServerType != CONNECTION_TYPE_GLOBAL_PROXY_TO_SERVER) { m_CryptIn.RC4(m_RecvBuffer, bytes); } if (m_PacketLoggingEnabled) { LogMessage("[%d] Received %d byte packet\n", m_RecvThreadHandle, received); DumpBuffer(m_RecvBuffer,bytes); } switch (m_ServerType) { case CONNECTION_TYPE_CLIENT_TO_GLOBAL_SERVER : ProcessGlobalServerOpcode(opcode, bytes); break; case CONNECTION_TYPE_CLIENT_TO_MASTER_SERVER : ProcessMasterServerOpcode(opcode, bytes); break; case CONNECTION_TYPE_CLIENT_TO_SECTOR_SERVER : //ProcessSectorServerOpcode(opcode, bytes); LogMessage("[%d] ERROR!!: Sector Server opcode received!\n", m_RecvThreadHandle); break; case CONNECTION_TYPE_MASTER_SERVER_TO_SECTOR_SERVER : ProcessMasterServerToSectorServerOpcode(opcode, bytes); break; case CONNECTION_TYPE_SECTOR_SERVER_TO_SECTOR_SERVER : ProcessSectorServerToSectorServerOpcode(opcode, bytes); break; case CONNECTION_TYPE_SECTOR_SERVER_TO_PROXY: ProcessProxyClientOpcode(opcode, bytes); break; case CONNECTION_TYPE_GLOBAL_PROXY_TO_SERVER: ProcessProxyGlobalOpcode(opcode, bytes); break; default: LogMessage("[%d] ERROR: Unknown type of connection.\n", m_RecvThreadHandle); m_TcpThreadRunning = false; // Shouldn't happen (but was able to with a buffer overflow). break; } } else { // Error Stage if (m_TcpThreadRunning) // We weren't told to stop, but never got our whole packet { LogMessage("[%d] Error receiving TCP packet on port %d, got %d bytes, expecting %d -- aborting!\n", m_RecvThreadHandle,m_TcpPort, received, bytes); if (received > 0 && g_Debug && received < 10000) DumpBuffer(m_RecvBuffer, received); } m_TcpThreadRunning = false; } } else { // Check Connection Status DWORD error = WSAGetLastError(); if ( !isSocketReady && error == 0 ) { m_InactivityTimer++; if ( (m_MaxInactivityTime > 0) && (m_InactivityTimer > m_MaxInactivityTime) ) { LogMessage("[%d] TCP connection on port %d exceeded maximum inactivity. Aborting.\n", m_RecvThreadHandle, m_TcpPort); m_TcpThreadRunning = false; } } else { switch (error) { case 0: LogMessage("[%d] TCP connection on port %d gracefully closed\n", m_RecvThreadHandle, m_TcpPort); break; case WSAECONNRESET: LogMessage("[%d] TCP connection on port %d was reset\n", m_RecvThreadHandle, m_TcpPort); break; default: LogMessage("[%d] TCP error on port %d (Error %d). Aborting.\n", m_RecvThreadHandle, m_TcpPort, error); break; } m_TcpThreadRunning = false; } } } KillConnection(); // m_TcpThreadRunning was set to false. Go to sleep... #ifdef WIN32 SuspendThread(m_RecvThreadHandle); #else pthread_cond_wait(&m_RecvThreadCond, &m_RecvThreadMtx); #endif } m_TcpThreadTerminated = true; }