uint32 EQProtocolPacket::Decompress(const unsigned char *buffer, const uint32 length, unsigned char *newbuf, uint32 newbufsize) { uint32 newlen=0; uint32 flag_offset=0; newbuf[0]=buffer[0]; if (buffer[0]==0x00) { flag_offset=2; newbuf[1]=buffer[1]; } else flag_offset=1; if (length>2 && buffer[flag_offset]==0x5a) { newlen=InflatePacket(buffer+flag_offset+1,length-(flag_offset+1)-2,newbuf+flag_offset,newbufsize-flag_offset)+2; newbuf[newlen++]=buffer[length-2]; newbuf[newlen++]=buffer[length-1]; } else if (length>2 && buffer[flag_offset]==0xa5) { memcpy(newbuf+flag_offset,buffer+flag_offset+1,length-(flag_offset+1)); newlen=length-1; } else { memcpy(newbuf,buffer,length); newlen=length; } return newlen; }
bool EmuTCPConnection::ProcessReceivedDataAsPackets(char* errbuf) { if (errbuf) errbuf[0] = 0; int32 base = 0; int32 size = 7; uchar* buffer; ServerPacket* pack = 0; while ((recvbuf_used - base) >= size) { EmuTCPNetPacket_Struct* tnps = (EmuTCPNetPacket_Struct*) &recvbuf[base]; buffer = tnps->buffer; size = tnps->size; if (size >= MaxTCPReceiveBuffferSize) { #if TCPN_DEBUG_Memory >= 1 std::cout << "TCPConnection[" << GetID() << "]::ProcessReceivedDataAsPackets(): size[" << size << "] >= MaxTCPReceiveBuffferSize" << std::endl; DumpPacket(&recvbuf[base], 16); #endif if (errbuf) snprintf(errbuf, TCPConnection_ErrorBufferSize, "EmuTCPConnection::ProcessReceivedDataAsPackets(): size >= MaxTCPReceiveBuffferSize"); return false; } if ((recvbuf_used - base) >= size) { // ok, we got enough data to make this packet! pack = new ServerPacket; pack->size = size - sizeof(EmuTCPNetPacket_Struct); // read headers pack->opcode = tnps->opcode; if (tnps->flags.compressed) { pack->compressed = true; pack->InflatedSize = *((int32*)buffer); pack->size -= 4; buffer += 4; } if (tnps->flags.destination) { pack->destination = *((int32*)buffer); pack->size -= 4; buffer += 4; } // end read headers if (pack->size > 0) { if (tnps->flags.compressed) { // Lets decompress the packet here pack->compressed = false; pack->pBuffer = new uchar[pack->InflatedSize]; pack->size = InflatePacket(buffer, pack->size, pack->pBuffer, pack->InflatedSize); } else { pack->pBuffer = new uchar[pack->size]; memcpy(pack->pBuffer, buffer, pack->size); } } if (pack->opcode == 0) { if (pack->size) { #if TCPN_DEBUG >= 2 std::cout << "Received TCP Network layer packet" << std::endl; #endif ProcessNetworkLayerPacket(pack); } #if TCPN_DEBUG >= 5 else { std::cout << "Received TCP keepalive packet. (opcode=0)" << std::endl; } #endif // keepalive, no need to process safe_delete(pack); } else { #if TCPN_LOG_PACKETS >= 1 if (pack && pack->opcode != 0) { struct in_addr in; in.s_addr = GetrIP(); CoutTimestamp(true); std::cout << ": Logging incoming TCP packet. OPCode: 0x" << hex << setw(4) << setfill('0') << pack->opcode << dec << ", size: " << setw(5) << setfill(' ') << pack->size << " " << inet_ntoa(in) << ":" << GetrPort() << std::endl; #if TCPN_LOG_PACKETS == 2 if (pack->size >= 32) DumpPacket(pack->pBuffer, 32); else DumpPacket(pack); #endif #if TCPN_LOG_PACKETS >= 3 DumpPacket(pack); #endif } #endif if (RelayServer && Server && pack->destination) { EmuTCPConnection* con = Server->FindConnection(pack->destination); if (!con) { #if TCPN_DEBUG >= 1 std::cout << "Error relaying packet: con = 0" << std::endl; #endif safe_delete(pack); } else con->OutQueuePush(pack); } else OutQueuePush(pack); } base += size; size = 7; } } if (base != 0) { if (base >= recvbuf_used) { safe_delete_array(recvbuf); } else { uchar* tmpbuf = new uchar[recvbuf_size - base]; memcpy(tmpbuf, &recvbuf[base], recvbuf_used - base); safe_delete_array(recvbuf); recvbuf = tmpbuf; recvbuf_used -= base; recvbuf_size -= base; } } return true; }