312 lines
8.6 KiB
Markdown
312 lines
8.6 KiB
Markdown
# EverQuest 2 Network Protocol Documentation
|
|
|
|
## Overview
|
|
|
|
The EverQuest 2 protocol is a custom UDP-based protocol that provides reliable delivery, encryption, compression, and session management. This document describes the protocol structure for reimplementation.
|
|
|
|
## 1. Protocol Architecture
|
|
|
|
### 1.1 Protocol Layers
|
|
```
|
|
Application Layer - Game logic packets (EQApplicationPacket)
|
|
Protocol Layer - Session management, reliability (EQProtocolPacket)
|
|
Transport Layer - UDP with custom reliability
|
|
Network Layer - Standard IP
|
|
```
|
|
|
|
### 1.2 Packet Types
|
|
- **EQProtocolPacket**: Low-level protocol control packets
|
|
- **EQApplicationPacket**: High-level game data packets
|
|
- **EQ2Packet**: EQ2-specific application packets with login opcodes
|
|
|
|
## 2. Session Management
|
|
|
|
### 2.1 Session Establishment
|
|
```
|
|
Client -> Server: OP_SessionRequest
|
|
Server -> Client: OP_SessionResponse
|
|
```
|
|
|
|
#### SessionRequest Structure
|
|
```c
|
|
struct SessionRequest {
|
|
uint32 UnknownA; // Usually 0
|
|
uint32 Session; // Proposed session ID
|
|
uint32 MaxLength; // Maximum packet length
|
|
};
|
|
```
|
|
|
|
#### SessionResponse Structure
|
|
```c
|
|
struct SessionResponse {
|
|
uint32 Session; // Confirmed session ID
|
|
uint32 Key; // Encryption key
|
|
uint8 UnknownA; // Usually 2
|
|
uint8 Format; // Flags: 0x01=compressed, 0x04=encoded
|
|
uint8 UnknownB; // Usually 0
|
|
uint32 MaxLength; // Maximum packet length
|
|
uint32 UnknownD; // Usually 0
|
|
};
|
|
```
|
|
|
|
### 2.2 Session Termination
|
|
```
|
|
Either -> Other: OP_SessionDisconnect
|
|
```
|
|
|
|
## 3. Protocol Opcodes
|
|
|
|
### 3.1 Core Protocol Opcodes
|
|
```c
|
|
#define OP_SessionRequest 0x01
|
|
#define OP_SessionResponse 0x02
|
|
#define OP_Combined 0x03
|
|
#define OP_SessionDisconnect 0x05
|
|
#define OP_KeepAlive 0x06
|
|
#define OP_ServerKeyRequest 0x07
|
|
#define OP_SessionStatResponse 0x08
|
|
#define OP_Packet 0x09
|
|
#define OP_Fragment 0x0D
|
|
#define OP_OutOfOrderAck 0x11
|
|
#define OP_Ack 0x15
|
|
#define OP_AppCombined 0x19
|
|
#define OP_OutOfSession 0x1D
|
|
```
|
|
|
|
## 4. Reliable Delivery System
|
|
|
|
### 4.1 Sequence Numbers
|
|
- 16-bit sequence numbers for ordered delivery
|
|
- Wrap-around handling at 65536
|
|
- Window-based flow control (default window size: 2048)
|
|
|
|
### 4.2 Acknowledgments
|
|
- **OP_Ack**: Acknowledges packets up to sequence number
|
|
- **OP_OutOfOrderAck**: Acknowledges specific out-of-order packet
|
|
- Retransmission on timeout (default: 500ms * 3.0 multiplier, max 5000ms)
|
|
|
|
### 4.3 Packet Structure for Sequenced Data
|
|
```
|
|
[2 bytes: Sequence Number][Payload Data]
|
|
```
|
|
|
|
## 5. Encryption System
|
|
|
|
### 5.1 Key Exchange
|
|
1. RSA key exchange during initial handshake
|
|
2. 8-byte encrypted key transmitted in packet
|
|
3. RC4 encryption initialized with exchanged key
|
|
|
|
### 5.2 RC4 Encryption
|
|
- Applied to packet payload after headers
|
|
- Separate encryption state per connection
|
|
- Encryption offset varies by packet type and compression
|
|
|
|
### 5.3 CRC Validation
|
|
- 16-bit CRC appended to most packets
|
|
- CRC calculated using session key
|
|
- Some packets (SessionRequest, SessionResponse, OutOfSession) not CRC'd
|
|
|
|
## 6. Compression System
|
|
|
|
### 6.1 zlib Compression
|
|
- Individual packets compressed using zlib deflate
|
|
- Compression applied when packet size > 128 bytes
|
|
- Compression markers:
|
|
- `0x5A`: zlib compressed data follows
|
|
- `0xA5`: uncompressed data (small packets)
|
|
|
|
### 6.2 Compression Process
|
|
```
|
|
1. Check if packet size > compression threshold
|
|
2. Apply zlib deflate compression
|
|
3. Prepend compression marker
|
|
4. If compressed size >= original, use uncompressed with 0xA5 marker
|
|
```
|
|
|
|
## 7. Packet Combination
|
|
|
|
### 7.1 Protocol-Level Combination (OP_Combined)
|
|
Multiple protocol packets combined into single UDP datagram:
|
|
```
|
|
[1 byte: Packet1 Size][Packet1 Data]
|
|
[1 byte: Packet2 Size][Packet2 Data]
|
|
...
|
|
```
|
|
If size >= 255:
|
|
```
|
|
[1 byte: 0xFF][2 bytes: Actual Size][Packet Data]
|
|
```
|
|
|
|
### 7.2 Application-Level Combination (OP_AppCombined)
|
|
Multiple application packets combined:
|
|
```
|
|
[1 byte: Packet1 Size][Packet1 Data without opcode header]
|
|
[1 byte: Packet2 Size][Packet2 Data without opcode header]
|
|
...
|
|
```
|
|
|
|
## 8. Fragmentation
|
|
|
|
### 8.1 Large Packet Handling
|
|
Packets larger than MaxLength are fragmented using OP_Fragment:
|
|
|
|
**First Fragment:**
|
|
```
|
|
[2 bytes: Sequence][4 bytes: Total Length][Payload Chunk]
|
|
```
|
|
|
|
**Subsequent Fragments:**
|
|
```
|
|
[2 bytes: Sequence][Payload Chunk]
|
|
```
|
|
|
|
### 8.2 Reassembly
|
|
1. Allocate buffer based on total length from first fragment
|
|
2. Collect fragments in sequence order
|
|
3. Reconstruct original packet when all fragments received
|
|
|
|
## 9. Data Structure System
|
|
|
|
### 9.1 Data Types
|
|
```c
|
|
#define DATA_STRUCT_INT8 1
|
|
#define DATA_STRUCT_INT16 2
|
|
#define DATA_STRUCT_INT32 3
|
|
#define DATA_STRUCT_INT64 4
|
|
#define DATA_STRUCT_FLOAT 5
|
|
#define DATA_STRUCT_DOUBLE 6
|
|
#define DATA_STRUCT_COLOR 7
|
|
#define DATA_STRUCT_SINT8 8
|
|
#define DATA_STRUCT_SINT16 9
|
|
#define DATA_STRUCT_SINT32 10
|
|
#define DATA_STRUCT_CHAR 11
|
|
#define DATA_STRUCT_EQ2_8BIT_STRING 12
|
|
#define DATA_STRUCT_EQ2_16BIT_STRING 13
|
|
#define DATA_STRUCT_EQ2_32BIT_STRING 14
|
|
#define DATA_STRUCT_EQUIPMENT 15
|
|
#define DATA_STRUCT_ARRAY 16
|
|
#define DATA_STRUCT_ITEM 17
|
|
#define DATA_STRUCT_SINT64 18
|
|
```
|
|
|
|
### 9.2 String Types
|
|
- **EQ2_8BitString**: [1 byte length][string data]
|
|
- **EQ2_16BitString**: [2 bytes length][string data]
|
|
- **EQ2_32BitString**: [4 bytes length][string data]
|
|
|
|
### 9.3 Color Structure
|
|
```c
|
|
struct EQ2_Color {
|
|
uint8 red;
|
|
uint8 green;
|
|
uint8 blue;
|
|
};
|
|
```
|
|
|
|
### 9.4 Equipment Structure
|
|
```c
|
|
struct EQ2_EquipmentItem {
|
|
uint16 type;
|
|
EQ2_Color color;
|
|
EQ2_Color highlight;
|
|
};
|
|
```
|
|
|
|
## 10. Application Opcodes
|
|
|
|
### 10.1 Opcode System
|
|
- Two-byte opcodes for game servers (WorldServer, ZoneServer)
|
|
- One-byte opcodes for login servers
|
|
- Version-specific opcode mappings stored in database
|
|
- Translation between internal EmuOpcodes and client opcodes
|
|
|
|
### 10.2 Key Application Opcodes
|
|
```c
|
|
// Login Operations
|
|
OP_LoginRequestMsg
|
|
OP_LoginReplyMsg
|
|
OP_AllCharactersDescRequestMsg
|
|
OP_AllCharactersDescReplyMsg
|
|
OP_CreateCharacterRequestMsg
|
|
OP_CreateCharacterReplyMsg
|
|
|
|
// World Operations
|
|
OP_ZoneInfoMsg
|
|
OP_UpdateCharacterSheetMsg
|
|
OP_UpdateInventoryMsg
|
|
OP_ClientCmdMsg
|
|
|
|
// Chat Operations
|
|
OP_ChatTellUserMsg
|
|
OP_ChatJoinChannelMsg
|
|
```
|
|
|
|
## 11. Implementation Guidelines
|
|
|
|
### 11.1 Connection State Machine
|
|
```
|
|
CLOSED -> SessionRequest -> ESTABLISHED
|
|
ESTABLISHED -> SessionDisconnect -> CLOSING -> CLOSED
|
|
```
|
|
|
|
### 11.2 Buffer Management
|
|
- Maintain separate inbound/outbound queues
|
|
- Implement sliding window for flow control
|
|
- Handle out-of-order packet storage
|
|
- Implement packet combining logic
|
|
|
|
### 11.3 Threading Considerations
|
|
- Separate reader/writer threads recommended
|
|
- Reader processes incoming UDP packets
|
|
- Writer sends outbound packets and handles retransmission
|
|
- Combine packet processor for optimization
|
|
|
|
### 11.4 Error Handling
|
|
- Validate CRC on all received packets
|
|
- Handle malformed packets gracefully
|
|
- Implement connection timeout detection
|
|
- Retry logic for failed transmissions
|
|
|
|
### 11.5 Performance Optimizations
|
|
- Packet combination to reduce UDP overhead
|
|
- Compression for large packets
|
|
- Rate limiting and congestion control
|
|
- Efficient data structure serialization
|
|
|
|
## 12. Stream Types
|
|
|
|
Different stream types have different characteristics:
|
|
|
|
```c
|
|
enum EQStreamType {
|
|
LoginStream, // 1-byte opcodes, no compression/encryption
|
|
WorldStream, // 2-byte opcodes, compression, no encryption
|
|
ZoneStream, // 2-byte opcodes, compression, no encryption
|
|
ChatStream, // 1-byte opcodes, no compression, encoding
|
|
EQ2Stream // 2-byte opcodes, no compression/encryption
|
|
};
|
|
```
|
|
|
|
## 13. Sample Packet Flow
|
|
|
|
### 13.1 Login Sequence
|
|
```
|
|
1. Client -> Server: OP_SessionRequest
|
|
2. Server -> Client: OP_SessionResponse (with key, compression flags)
|
|
3. Client -> Server: OP_Packet[OP_LoginRequestMsg] (with credentials)
|
|
4. Server -> Client: OP_Packet[OP_LoginReplyMsg] (success/failure)
|
|
5. Client -> Server: OP_Packet[OP_AllCharactersDescRequestMsg]
|
|
6. Server -> Client: OP_Packet[OP_AllCharactersDescReplyMsg] (character list)
|
|
```
|
|
|
|
### 13.2 Reliable Data Transfer
|
|
```
|
|
1. Sender: Assign sequence number, add to retransmit queue
|
|
2. Sender: Transmit OP_Packet[seq][data]
|
|
3. Receiver: Process packet, send OP_Ack[seq]
|
|
4. Sender: Receive ack, remove from retransmit queue
|
|
5. On timeout: Retransmit packet up to max attempts
|
|
```
|
|
|
|
This documentation provides the foundation for implementing the EQ2 protocol in any programming language while maintaining compatibility with the existing server and client implementations. |