clean EQPacket
This commit is contained in:
parent
6401247809
commit
a8c533f012
File diff suppressed because it is too large
Load Diff
@ -1,28 +1,13 @@
|
|||||||
/*
|
// EQ2Emulator: Everquest II Server Emulator
|
||||||
EQ2Emulator: Everquest II Server Emulator
|
// Copyright (C) 2007 EQ2EMulator Development Team
|
||||||
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
|
// Licensed under GPL v3 - see <http://www.gnu.org/licenses/>
|
||||||
|
|
||||||
This file is part of EQ2Emulator.
|
|
||||||
|
|
||||||
EQ2Emulator is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
EQ2Emulator is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
#ifndef _EQPACKET_H
|
#ifndef _EQPACKET_H
|
||||||
#define _EQPACKET_H
|
#define _EQPACKET_H
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
@ -36,59 +21,103 @@
|
|||||||
#include "op_codes.h"
|
#include "op_codes.h"
|
||||||
#include "packet_dump.h"
|
#include "packet_dump.h"
|
||||||
|
|
||||||
|
// Forward declarations
|
||||||
class OpcodeManager;
|
class OpcodeManager;
|
||||||
|
|
||||||
class EQStream;
|
class EQStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for all EverQuest packet types.
|
||||||
|
* Provides common functionality for packet management, opcode handling,
|
||||||
|
* and network information tracking.
|
||||||
|
*/
|
||||||
class EQPacket {
|
class EQPacket {
|
||||||
friend class EQStream;
|
friend class EQStream;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
unsigned char *pBuffer;
|
// Packet data
|
||||||
uint32 size;
|
unsigned char* pBuffer; // Raw packet data buffer
|
||||||
uint32 src_ip,dst_ip;
|
uint32 size; // Size of packet data
|
||||||
uint16 src_port,dst_port;
|
|
||||||
uint32 priority;
|
// Network information
|
||||||
timeval timestamp;
|
uint32 src_ip, dst_ip; // Source and destination IP addresses
|
||||||
int16 version;
|
uint16 src_port, dst_port; // Source and destination ports
|
||||||
|
uint32 priority; // Packet priority for processing
|
||||||
|
timeval timestamp; // Packet timestamp
|
||||||
|
int16 version; // Protocol version
|
||||||
|
|
||||||
~EQPacket();
|
~EQPacket();
|
||||||
|
|
||||||
|
// Debug and display methods
|
||||||
void DumpRawHeader(uint16 seq = 0xffff, FILE* to = stdout) const;
|
void DumpRawHeader(uint16 seq = 0xffff, FILE* to = stdout) const;
|
||||||
void DumpRawHeaderNoTime(uint16 seq = 0xffff, FILE* to = stdout) const;
|
void DumpRawHeaderNoTime(uint16 seq = 0xffff, FILE* to = stdout) const;
|
||||||
void DumpRaw(FILE* to = stdout) const;
|
void DumpRaw(FILE* to = stdout) const;
|
||||||
const char* GetOpcodeName();
|
const char* GetOpcodeName();
|
||||||
|
|
||||||
|
// Packet information setters
|
||||||
void setVersion(int16 new_version) { version = new_version; }
|
void setVersion(int16 new_version) { version = new_version; }
|
||||||
void setSrcInfo(uint32 sip, uint16 sport) { src_ip = sip; src_port = sport; }
|
void setSrcInfo(uint32 sip, uint16 sport) { src_ip = sip; src_port = sport; }
|
||||||
void setDstInfo(uint32 dip, uint16 dport) { dst_ip = dip; dst_port = dport; }
|
void setDstInfo(uint32 dip, uint16 dport) { dst_ip = dip; dst_port = dport; }
|
||||||
void setTimeInfo(uint32 ts_sec, uint32 ts_usec) { timestamp.tv_sec=ts_sec; timestamp.tv_usec=ts_usec; }
|
void setTimeInfo(uint32 ts_sec, uint32 ts_usec) {
|
||||||
void copyInfo(const EQPacket *p) { src_ip=p->src_ip; src_port=p->src_port; dst_ip=p->dst_ip; dst_port=p->dst_port; timestamp.tv_sec=p->timestamp.tv_sec; timestamp.tv_usec=p->timestamp.tv_usec; }
|
timestamp.tv_sec = ts_sec;
|
||||||
|
timestamp.tv_usec = ts_usec;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy network and timing info from another packet
|
||||||
|
void copyInfo(const EQPacket* p) {
|
||||||
|
src_ip = p->src_ip;
|
||||||
|
src_port = p->src_port;
|
||||||
|
dst_ip = p->dst_ip;
|
||||||
|
dst_port = p->dst_port;
|
||||||
|
timestamp.tv_sec = p->timestamp.tv_sec;
|
||||||
|
timestamp.tv_usec = p->timestamp.tv_usec;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get total packet size including opcode
|
||||||
uint32 Size() const { return size + 2; }
|
uint32 Size() const { return size + 2; }
|
||||||
|
|
||||||
//no reason to have this method in zone or world
|
// Get raw opcode value
|
||||||
|
uint16 GetRawOpcode() const { return opcode; }
|
||||||
|
|
||||||
uint16 GetRawOpcode() const { return(opcode); }
|
// Comparison operator for timestamp-based sorting
|
||||||
|
bool operator<(const EQPacket& rhs) const {
|
||||||
|
return (timestamp.tv_sec < rhs.timestamp.tv_sec ||
|
||||||
inline bool operator<(const EQPacket &rhs) {
|
(timestamp.tv_sec == rhs.timestamp.tv_sec &&
|
||||||
return (timestamp.tv_sec < rhs.timestamp.tv_sec || (timestamp.tv_sec==rhs.timestamp.tv_sec && timestamp.tv_usec < rhs.timestamp.tv_usec));
|
timestamp.tv_usec < rhs.timestamp.tv_usec));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set the protocol opcode
|
||||||
void SetProtocolOpcode(int16 new_opcode) {
|
void SetProtocolOpcode(int16 new_opcode) {
|
||||||
opcode = new_opcode;
|
opcode = new_opcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
uint16 opcode;
|
uint16 opcode; // Packet opcode
|
||||||
|
|
||||||
EQPacket(const uint16 op, const unsigned char *buf, const uint32 len);
|
// Constructors (protected to enforce proper inheritance)
|
||||||
|
EQPacket(uint16 op, const unsigned char* buf, uint32 len);
|
||||||
EQPacket(const EQPacket& p) { version = 0; }
|
EQPacket(const EQPacket& p) { version = 0; }
|
||||||
EQPacket() { opcode=0; pBuffer=NULL; size=0; version = 0; setTimeInfo(0, 0); }
|
EQPacket() {
|
||||||
|
opcode = 0;
|
||||||
|
pBuffer = nullptr;
|
||||||
|
size = 0;
|
||||||
|
version = 0;
|
||||||
|
setTimeInfo(0, 0);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Forward declaration
|
||||||
class EQApplicationPacket;
|
class EQApplicationPacket;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Protocol-level packet class for EverQuest network communication.
|
||||||
|
* Handles low-level protocol features like compression, encryption,
|
||||||
|
* sequencing, and packet combining.
|
||||||
|
*/
|
||||||
class EQProtocolPacket : public EQPacket {
|
class EQProtocolPacket : public EQPacket {
|
||||||
public:
|
public:
|
||||||
EQProtocolPacket(uint16 op, const unsigned char *buf, uint32 len) : EQPacket(op,buf,len) {
|
// Constructor with opcode and buffer
|
||||||
|
EQProtocolPacket(uint16 op, const unsigned char* buf, uint32 len)
|
||||||
|
: EQPacket(op, buf, len) {
|
||||||
eq2_compressed = false;
|
eq2_compressed = false;
|
||||||
packet_prepared = false;
|
packet_prepared = false;
|
||||||
packet_encrypted = false;
|
packet_encrypted = false;
|
||||||
@ -97,109 +126,181 @@ public:
|
|||||||
attempt_count = 0;
|
attempt_count = 0;
|
||||||
acked = false;
|
acked = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Constructor from raw buffer with optional opcode override
|
||||||
EQProtocolPacket(const unsigned char* buf, uint32 len, int in_opcode = -1);
|
EQProtocolPacket(const unsigned char* buf, uint32 len, int in_opcode = -1);
|
||||||
|
|
||||||
|
// Packet manipulation methods
|
||||||
bool combine(const EQProtocolPacket* rhs);
|
bool combine(const EQProtocolPacket* rhs);
|
||||||
uint32 serialize(unsigned char* dest, int8 offset = 0) const;
|
uint32 serialize(unsigned char* dest, int8 offset = 0) const;
|
||||||
|
|
||||||
|
// Static utility methods for packet processing
|
||||||
static bool ValidateCRC(const unsigned char* buffer, int length, uint32 Key);
|
static bool ValidateCRC(const unsigned char* buffer, int length, uint32 Key);
|
||||||
static uint32 Decompress(const unsigned char *buffer, const uint32 length, unsigned char *newbuf, uint32 newbufsize);
|
static uint32 Decompress(const unsigned char* buffer, uint32 length,
|
||||||
static uint32 Compress(const unsigned char *buffer, const uint32 length, unsigned char *newbuf, uint32 newbufsize);
|
unsigned char* newbuf, uint32 newbufsize);
|
||||||
|
static uint32 Compress(const unsigned char* buffer, uint32 length,
|
||||||
|
unsigned char* newbuf, uint32 newbufsize);
|
||||||
static void ChatDecode(unsigned char* buffer, int size, int DecodeKey);
|
static void ChatDecode(unsigned char* buffer, int size, int DecodeKey);
|
||||||
static void ChatEncode(unsigned char* buffer, int size, int EncodeKey);
|
static void ChatEncode(unsigned char* buffer, int size, int EncodeKey);
|
||||||
static bool IsProtocolPacket(const unsigned char* in_buff, uint32_t len, bool bTrimCRC);
|
static bool IsProtocolPacket(const unsigned char* in_buff, uint32_t len, bool bTrimCRC);
|
||||||
|
|
||||||
|
// Create a copy of this packet
|
||||||
EQProtocolPacket* Copy() {
|
EQProtocolPacket* Copy() {
|
||||||
EQProtocolPacket* new_packet = new EQProtocolPacket(opcode,pBuffer,size);
|
auto new_packet = new EQProtocolPacket(opcode, pBuffer, size);
|
||||||
new_packet->eq2_compressed = this->eq2_compressed;
|
new_packet->eq2_compressed = this->eq2_compressed;
|
||||||
new_packet->packet_prepared = this->packet_prepared;
|
new_packet->packet_prepared = this->packet_prepared;
|
||||||
new_packet->packet_encrypted = this->packet_encrypted;
|
new_packet->packet_encrypted = this->packet_encrypted;
|
||||||
return new_packet;
|
return new_packet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Convert to application-level packet
|
||||||
EQApplicationPacket* MakeApplicationPacket(uint8 opcode_size = 0) const;
|
EQApplicationPacket* MakeApplicationPacket(uint8 opcode_size = 0) const;
|
||||||
bool eq2_compressed;
|
|
||||||
bool packet_prepared;
|
// Protocol packet state flags
|
||||||
bool packet_encrypted;
|
bool eq2_compressed; // Packet is compressed
|
||||||
bool acked;
|
bool packet_prepared; // Packet has been prepared for sending
|
||||||
int32 sent_time;
|
bool packet_encrypted; // Packet is encrypted
|
||||||
int8 attempt_count;
|
bool acked; // Packet has been acknowledged
|
||||||
int32 sequence;
|
|
||||||
|
// Reliability and sequencing
|
||||||
|
int32 sent_time; // Timestamp when packet was sent
|
||||||
|
int8 attempt_count; // Number of send attempts
|
||||||
|
int32 sequence; // Sequence number for ordering
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EQProtocolPacket(const EQProtocolPacket &p) { }
|
// Prevent copy construction
|
||||||
//bool dont_combine;
|
EQProtocolPacket(const EQProtocolPacket& p) = delete;
|
||||||
|
EQProtocolPacket& operator=(const EQProtocolPacket& p) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* EverQuest 2 specific packet class.
|
||||||
|
* Handles EQ2-specific packet operations like application combining
|
||||||
|
* and login opcode management.
|
||||||
|
*/
|
||||||
class EQ2Packet : public EQProtocolPacket {
|
class EQ2Packet : public EQProtocolPacket {
|
||||||
public:
|
public:
|
||||||
EQ2Packet(const EmuOpcode in_login_op, const unsigned char *buf, uint32 len) : EQProtocolPacket(OP_Packet,buf,len){
|
// Constructor with EQ2 login opcode
|
||||||
|
EQ2Packet(EmuOpcode in_login_op, const unsigned char* buf, uint32 len)
|
||||||
|
: EQProtocolPacket(OP_Packet, buf, len) {
|
||||||
login_op = in_login_op;
|
login_op = in_login_op;
|
||||||
eq2_compressed = false;
|
eq2_compressed = false;
|
||||||
packet_prepared = false;
|
packet_prepared = false;
|
||||||
packet_encrypted = false;
|
packet_encrypted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EQ2-specific packet operations
|
||||||
bool AppCombine(EQ2Packet* rhs);
|
bool AppCombine(EQ2Packet* rhs);
|
||||||
|
int8 PreparePacket(int16 MaxLen);
|
||||||
|
const char* GetOpcodeName();
|
||||||
|
|
||||||
|
// Create a copy of this EQ2 packet
|
||||||
EQ2Packet* Copy() {
|
EQ2Packet* Copy() {
|
||||||
EQ2Packet* new_packet = new EQ2Packet(login_op,pBuffer,size);
|
auto new_packet = new EQ2Packet(login_op, pBuffer, size);
|
||||||
new_packet->eq2_compressed = this->eq2_compressed;
|
new_packet->eq2_compressed = this->eq2_compressed;
|
||||||
new_packet->packet_prepared = this->packet_prepared;
|
new_packet->packet_prepared = this->packet_prepared;
|
||||||
new_packet->packet_encrypted = this->packet_encrypted;
|
new_packet->packet_encrypted = this->packet_encrypted;
|
||||||
return new_packet;
|
return new_packet;
|
||||||
}
|
}
|
||||||
int8 PreparePacket(int16 MaxLen);
|
|
||||||
const char* GetOpcodeName();
|
EmuOpcode login_op; // EQ2 login/application opcode
|
||||||
EmuOpcode login_op;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Application-level packet class for EverQuest.
|
||||||
|
* Handles high-level game opcodes and application data.
|
||||||
|
* This is the main packet type used by game logic.
|
||||||
|
*/
|
||||||
class EQApplicationPacket : public EQPacket {
|
class EQApplicationPacket : public EQPacket {
|
||||||
friend class EQProtocolPacket;
|
friend class EQProtocolPacket;
|
||||||
friend class EQStream;
|
friend class EQStream;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
EQApplicationPacket() : EQPacket(0,NULL,0) { emu_opcode = OP_Unknown; app_opcode_size=default_opcode_size; }
|
// Default constructor
|
||||||
EQApplicationPacket(const EmuOpcode op) : EQPacket(0,NULL,0) { SetOpcode(op); app_opcode_size=default_opcode_size; }
|
EQApplicationPacket() : EQPacket(0, nullptr, 0) {
|
||||||
EQApplicationPacket(const EmuOpcode op, const uint32 len) : EQPacket(0,NULL,len) { SetOpcode(op); app_opcode_size=default_opcode_size; }
|
emu_opcode = OP_Unknown;
|
||||||
EQApplicationPacket(const EmuOpcode op, const unsigned char *buf, const uint32 len) : EQPacket(0,buf,len) { SetOpcode(op); app_opcode_size=default_opcode_size; }
|
app_opcode_size = default_opcode_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructor with opcode only
|
||||||
|
EQApplicationPacket(EmuOpcode op) : EQPacket(0, nullptr, 0) {
|
||||||
|
SetOpcode(op);
|
||||||
|
app_opcode_size = default_opcode_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructor with opcode and size
|
||||||
|
EQApplicationPacket(EmuOpcode op, uint32 len) : EQPacket(0, nullptr, len) {
|
||||||
|
SetOpcode(op);
|
||||||
|
app_opcode_size = default_opcode_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructor with opcode, buffer, and size
|
||||||
|
EQApplicationPacket(EmuOpcode op, const unsigned char* buf, uint32 len)
|
||||||
|
: EQPacket(0, buf, len) {
|
||||||
|
SetOpcode(op);
|
||||||
|
app_opcode_size = default_opcode_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Packet operations
|
||||||
bool combine(const EQApplicationPacket* rhs);
|
bool combine(const EQApplicationPacket* rhs);
|
||||||
uint32 serialize(unsigned char* dest) const;
|
uint32 serialize(unsigned char* dest) const;
|
||||||
uint32 Size() const { return size + app_opcode_size; }
|
uint32 Size() const { return size + app_opcode_size; }
|
||||||
|
|
||||||
|
// Create a deep copy of this packet
|
||||||
EQApplicationPacket* Copy() const {
|
EQApplicationPacket* Copy() const {
|
||||||
EQApplicationPacket *it = new EQApplicationPacket;
|
auto it = std::make_unique<EQApplicationPacket>();
|
||||||
try {
|
try {
|
||||||
|
if (size > 0) {
|
||||||
it->pBuffer = new unsigned char[size];
|
it->pBuffer = new unsigned char[size];
|
||||||
memcpy(it->pBuffer, pBuffer, size);
|
memcpy(it->pBuffer, pBuffer, size);
|
||||||
|
}
|
||||||
it->size = size;
|
it->size = size;
|
||||||
it->opcode = opcode;
|
it->opcode = opcode;
|
||||||
it->emu_opcode = emu_opcode;
|
it->emu_opcode = emu_opcode;
|
||||||
it->version = version;
|
it->version = version;
|
||||||
return(it);
|
return it.release();
|
||||||
}
|
}
|
||||||
catch( bad_alloc &ba )
|
catch (const std::bad_alloc& ba) {
|
||||||
{
|
// Memory allocation failed - return nullptr
|
||||||
cout << ba.what() << endl;
|
return nullptr;
|
||||||
if( NULL != it )
|
|
||||||
delete it;
|
|
||||||
}
|
}
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Opcode management
|
||||||
void SetOpcodeSize(uint8 s) { app_opcode_size = s; }
|
void SetOpcodeSize(uint8 s) { app_opcode_size = s; }
|
||||||
void SetOpcode(EmuOpcode op);
|
void SetOpcode(EmuOpcode op);
|
||||||
const EmuOpcode GetOpcodeConst() const;
|
const EmuOpcode GetOpcodeConst() const;
|
||||||
inline const EmuOpcode GetOpcode() const { return(GetOpcodeConst()); }
|
|
||||||
//caching version of get
|
|
||||||
inline const EmuOpcode GetOpcode() { EmuOpcode r = GetOpcodeConst(); emu_opcode = r; return(r); }
|
|
||||||
|
|
||||||
|
// Get opcode (const version)
|
||||||
|
const EmuOpcode GetOpcode() const { return GetOpcodeConst(); }
|
||||||
|
|
||||||
|
// Get opcode (caching version for performance)
|
||||||
|
EmuOpcode GetOpcode() {
|
||||||
|
EmuOpcode r = GetOpcodeConst();
|
||||||
|
emu_opcode = r;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default opcode size for all application packets
|
||||||
static uint8 default_opcode_size;
|
static uint8 default_opcode_size;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
//this is just a cache so we dont look it up several times on Get()
|
// Cached emulator opcode to avoid repeated lookups
|
||||||
EmuOpcode emu_opcode;
|
EmuOpcode emu_opcode;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//this constructor should only be used by EQProtocolPacket, as it
|
// Constructor used by EQProtocolPacket - assumes first bytes are opcode
|
||||||
//assumes the first two bytes of buf are the opcode.
|
|
||||||
EQApplicationPacket(const unsigned char* buf, uint32 len, uint8 opcode_size = 0);
|
EQApplicationPacket(const unsigned char* buf, uint32 len, uint8 opcode_size = 0);
|
||||||
EQApplicationPacket(const EQApplicationPacket &p) { emu_opcode = OP_Unknown; app_opcode_size=default_opcode_size; }
|
|
||||||
|
|
||||||
|
// Prevent copy construction
|
||||||
|
EQApplicationPacket(const EQApplicationPacket& p) = delete;
|
||||||
|
EQApplicationPacket& operator=(const EQApplicationPacket& p) = delete;
|
||||||
|
|
||||||
|
// Size of the opcode in bytes (1 or 2)
|
||||||
uint8 app_opcode_size;
|
uint8 app_opcode_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Packet debugging and display functions
|
||||||
void DumpPacketHex(const EQApplicationPacket* app);
|
void DumpPacketHex(const EQApplicationPacket* app);
|
||||||
void DumpPacket(const EQProtocolPacket* app);
|
void DumpPacket(const EQProtocolPacket* app);
|
||||||
void DumpPacketAscii(const EQApplicationPacket* app);
|
void DumpPacketAscii(const EQApplicationPacket* app);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user