compat pass 2
This commit is contained in:
parent
9cc3273a81
commit
c692b25ac0
@ -8,7 +8,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// ProtoPacket handles low-level protocol features including EQ2-specific operations
|
// ProtoPacket handles low-level protocol features including EQ2-specific operations
|
||||||
// Merges functionality from EQProtocolPacket and EQ2Packet
|
|
||||||
type ProtoPacket struct {
|
type ProtoPacket struct {
|
||||||
*Packet
|
*Packet
|
||||||
|
|
||||||
@ -16,7 +15,7 @@ type ProtoPacket struct {
|
|||||||
flags uint8 // bit 0: compressed, bit 1: prepared, bit 2: encrypted, bit 3: acked
|
flags uint8 // bit 0: compressed, bit 1: prepared, bit 2: encrypted, bit 3: acked
|
||||||
|
|
||||||
// EQ2-specific
|
// EQ2-specific
|
||||||
LoginOp opcodes.EmuOpcode // From EQ2Packet
|
LoginOp opcodes.EmuOpcode
|
||||||
|
|
||||||
// Reliability and sequencing
|
// Reliability and sequencing
|
||||||
Sequence int32
|
Sequence int32
|
||||||
@ -39,7 +38,7 @@ const (
|
|||||||
FlagAcked
|
FlagAcked
|
||||||
)
|
)
|
||||||
|
|
||||||
// Default compression threshold (compress packets larger than this)
|
// Default compression threshold
|
||||||
const DefaultCompressThreshold = 100
|
const DefaultCompressThreshold = 100
|
||||||
|
|
||||||
// NewProtoPacket creates a protocol packet with opcode and buffer
|
// NewProtoPacket creates a protocol packet with opcode and buffer
|
||||||
@ -190,7 +189,7 @@ func (p *ProtoPacket) EncodeChat() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if IsChatPacket(p.Opcode) {
|
if p.IsChatPacket() {
|
||||||
ChatEncode(p.Buffer, p.EncodeKey)
|
ChatEncode(p.Buffer, p.EncodeKey)
|
||||||
p.SetEncrypted(true)
|
p.SetEncrypted(true)
|
||||||
}
|
}
|
||||||
@ -206,6 +205,29 @@ func (p *ProtoPacket) DecodeChat() {
|
|||||||
p.SetEncrypted(false)
|
p.SetEncrypted(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsChatPacket checks if this is a chat packet using opcode manager
|
||||||
|
func (p *ProtoPacket) IsChatPacket() bool {
|
||||||
|
if p.manager == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get emulator opcode
|
||||||
|
emuOp := p.manager.EQToEmu(p.Opcode)
|
||||||
|
|
||||||
|
// Check against known chat opcodes
|
||||||
|
switch emuOp {
|
||||||
|
case opcodes.OP_ChatMsg,
|
||||||
|
opcodes.OP_TellMsg,
|
||||||
|
opcodes.OP_ChatLeaveChannelMsg,
|
||||||
|
opcodes.OP_ChatTellChannelMsg,
|
||||||
|
opcodes.OP_ChatTellUserMsg,
|
||||||
|
opcodes.OP_GuildsayMsg:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Copy creates a deep copy of this protocol packet
|
// Copy creates a deep copy of this protocol packet
|
||||||
func (p *ProtoPacket) Copy() *ProtoPacket {
|
func (p *ProtoPacket) Copy() *ProtoPacket {
|
||||||
newPacket := &ProtoPacket{
|
newPacket := &ProtoPacket{
|
||||||
@ -255,7 +277,7 @@ func (p *ProtoPacket) Serialize(dest []byte, offset int8) uint32 {
|
|||||||
return uint32(len(p.Buffer)-int(offset)) + uint32(pos)
|
return uint32(len(p.Buffer)-int(offset)) + uint32(pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
// PreparePacket prepares an EQ2 packet for transmission (from EQ2Packet)
|
// PreparePacket prepares an EQ2 packet for transmission
|
||||||
func (p *ProtoPacket) PreparePacket(maxLen int16) int8 {
|
func (p *ProtoPacket) PreparePacket(maxLen int16) int8 {
|
||||||
if p.IsPrepared() {
|
if p.IsPrepared() {
|
||||||
return 0
|
return 0
|
||||||
@ -367,53 +389,122 @@ func (p *ProtoPacket) MakeApplicationPacket(opcodeSize uint8) *AppPacket {
|
|||||||
return app
|
return app
|
||||||
}
|
}
|
||||||
|
|
||||||
// AppCombine combines this packet with another for efficient transmission (from EQ2Packet)
|
// AppCombine combines this packet with another for efficient transmission
|
||||||
func (p *ProtoPacket) AppCombine(rhs *ProtoPacket) bool {
|
func (p *ProtoPacket) AppCombine(rhs *ProtoPacket) bool {
|
||||||
const opAppCombined = 0x19 // OP_AppCombined value
|
const opAppCombined = 0x19 // OP_AppCombined
|
||||||
|
|
||||||
// Apply compression to both packets before combining
|
// Calculate sizes
|
||||||
p.CompressPacket()
|
lhsSize := p.Size()
|
||||||
rhs.CompressPacket()
|
rhsSize := rhs.Size()
|
||||||
|
|
||||||
// Case 1: This packet is already a combined packet
|
// Check max combined size
|
||||||
if p.Opcode == opAppCombined && (len(p.Buffer)+len(rhs.Buffer)+3) < 255 {
|
if lhsSize+rhsSize > MaxCombinedSize {
|
||||||
tmpSize := len(rhs.Buffer) - 2
|
return false
|
||||||
overSized := tmpSize >= 255
|
}
|
||||||
|
|
||||||
|
// If this packet is already combined, add to it
|
||||||
|
if p.Opcode == opAppCombined {
|
||||||
|
// Calculate new size
|
||||||
var newSize int
|
var newSize int
|
||||||
if overSized {
|
if rhsSize >= 255 {
|
||||||
newSize = len(p.Buffer) + tmpSize + 3
|
newSize = len(p.Buffer) + int(rhsSize) + 3 // oversized header
|
||||||
} else {
|
} else {
|
||||||
newSize = len(p.Buffer) + tmpSize + 1
|
newSize = len(p.Buffer) + int(rhsSize) + 1 // normal header
|
||||||
}
|
}
|
||||||
|
|
||||||
tmpBuffer := make([]byte, newSize)
|
// Check size limit
|
||||||
|
if newSize > MaxCombinedSize {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create new buffer
|
||||||
|
newBuffer := make([]byte, newSize)
|
||||||
pos := 0
|
pos := 0
|
||||||
|
|
||||||
// Copy existing combined packet data
|
// Copy existing combined data
|
||||||
copy(tmpBuffer, p.Buffer)
|
copy(newBuffer, p.Buffer)
|
||||||
pos += len(p.Buffer)
|
pos = len(p.Buffer)
|
||||||
|
|
||||||
// Add size information for the new packet
|
// Add new packet with size header
|
||||||
if overSized {
|
if rhsSize >= 255 {
|
||||||
tmpBuffer[pos] = 255
|
newBuffer[pos] = 255 // Oversized marker
|
||||||
pos++
|
pos++
|
||||||
binary.BigEndian.PutUint16(tmpBuffer[pos:], uint16(tmpSize))
|
binary.BigEndian.PutUint16(newBuffer[pos:], uint16(rhsSize))
|
||||||
pos += 2
|
pos += 2
|
||||||
} else {
|
} else {
|
||||||
tmpBuffer[pos] = byte(tmpSize)
|
newBuffer[pos] = byte(rhsSize)
|
||||||
pos++
|
pos++
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy the new packet data (skip first 2 bytes which are opcode)
|
// Serialize rhs packet
|
||||||
if len(rhs.Buffer) > 2 {
|
tmpBuf := make([]byte, rhsSize)
|
||||||
copy(tmpBuffer[pos:], rhs.Buffer[2:])
|
rhs.Serialize(tmpBuf, 0)
|
||||||
}
|
copy(newBuffer[pos:], tmpBuf)
|
||||||
|
|
||||||
p.Buffer = tmpBuffer
|
p.Buffer = newBuffer
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Case 2: Create new combined packet (simplified)
|
// Create new combined packet from two non-combined packets
|
||||||
return false
|
// Calculate total size: size1(1-3) + packet1 + size2(1-3) + packet2
|
||||||
|
var totalSize int
|
||||||
|
if lhsSize >= 255 {
|
||||||
|
totalSize += 3 + int(lhsSize)
|
||||||
|
} else {
|
||||||
|
totalSize += 1 + int(lhsSize)
|
||||||
|
}
|
||||||
|
if rhsSize >= 255 {
|
||||||
|
totalSize += 3 + int(rhsSize)
|
||||||
|
} else {
|
||||||
|
totalSize += 1 + int(rhsSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check size limit
|
||||||
|
if totalSize > MaxCombinedSize {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build combined packet
|
||||||
|
newBuffer := make([]byte, totalSize)
|
||||||
|
pos := 0
|
||||||
|
|
||||||
|
// Add first packet with size header
|
||||||
|
if lhsSize >= 255 {
|
||||||
|
newBuffer[pos] = 255
|
||||||
|
pos++
|
||||||
|
binary.BigEndian.PutUint16(newBuffer[pos:], uint16(lhsSize))
|
||||||
|
pos += 2
|
||||||
|
} else {
|
||||||
|
newBuffer[pos] = byte(lhsSize)
|
||||||
|
pos++
|
||||||
|
}
|
||||||
|
|
||||||
|
// Serialize first packet
|
||||||
|
tmpBuf := make([]byte, lhsSize)
|
||||||
|
p.Serialize(tmpBuf, 0)
|
||||||
|
copy(newBuffer[pos:], tmpBuf)
|
||||||
|
pos += int(lhsSize)
|
||||||
|
|
||||||
|
// Add second packet with size header
|
||||||
|
if rhsSize >= 255 {
|
||||||
|
newBuffer[pos] = 255
|
||||||
|
pos++
|
||||||
|
binary.BigEndian.PutUint16(newBuffer[pos:], uint16(rhsSize))
|
||||||
|
pos += 2
|
||||||
|
} else {
|
||||||
|
newBuffer[pos] = byte(rhsSize)
|
||||||
|
pos++
|
||||||
|
}
|
||||||
|
|
||||||
|
// Serialize second packet
|
||||||
|
tmpBuf = make([]byte, rhsSize)
|
||||||
|
rhs.Serialize(tmpBuf, 0)
|
||||||
|
copy(newBuffer[pos:], tmpBuf)
|
||||||
|
|
||||||
|
// Update this packet to be combined
|
||||||
|
p.Opcode = opAppCombined
|
||||||
|
p.Buffer = newBuffer
|
||||||
|
p.SetPrepared(false) // Need to re-prepare
|
||||||
|
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
@ -95,7 +95,7 @@ func (f *StreamFactory) OnBoot(eng gnet.Engine) gnet.Action {
|
|||||||
func (f *StreamFactory) OnOpen(c gnet.Conn) ([]byte, gnet.Action) {
|
func (f *StreamFactory) OnOpen(c gnet.Conn) ([]byte, gnet.Action) {
|
||||||
// Create stream configuration
|
// Create stream configuration
|
||||||
streamCfg := &Config{
|
streamCfg := &Config{
|
||||||
SessionID: uint32(time.Now().UnixNano()), // Generate session ID
|
SessionID: uint32(time.Now().UnixNano()),
|
||||||
CRCKey: f.crcKey,
|
CRCKey: f.crcKey,
|
||||||
MaxPacketSize: f.maxPacketSize,
|
MaxPacketSize: f.maxPacketSize,
|
||||||
EncodeKey: f.encodeKey,
|
EncodeKey: f.encodeKey,
|
||||||
@ -181,13 +181,17 @@ func (f *StreamFactory) OnTraffic(c gnet.Conn) gnet.Action {
|
|||||||
return gnet.None
|
return gnet.None
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnTick called periodically
|
// OnTick called periodically to process stream queues
|
||||||
func (f *StreamFactory) OnTick() (time.Duration, gnet.Action) {
|
func (f *StreamFactory) OnTick() (time.Duration, gnet.Action) {
|
||||||
f.mu.RLock()
|
f.mu.RLock()
|
||||||
defer f.mu.RUnlock()
|
streams := make([]*Stream, 0, len(f.streams))
|
||||||
|
|
||||||
// Process retransmissions for all streams
|
|
||||||
for _, stream := range f.streams {
|
for _, stream := range f.streams {
|
||||||
|
streams = append(streams, stream)
|
||||||
|
}
|
||||||
|
f.mu.RUnlock()
|
||||||
|
|
||||||
|
// Process queues for all streams
|
||||||
|
for _, stream := range streams {
|
||||||
stream.processQueues()
|
stream.processQueues()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
1032
stream/stream.go
1032
stream/stream.go
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user