Implement stage binaries, stack locking, and logkeys

This commit is contained in:
Andrew Gutekanst
2020-02-03 22:56:54 -05:00
parent 5924db9b42
commit 4e1cef9bf3
8 changed files with 136 additions and 23 deletions

View File

@@ -6,7 +6,14 @@ import (
) )
// MsgSysGetStageBinary represents the MSG_SYS_GET_STAGE_BINARY // MsgSysGetStageBinary represents the MSG_SYS_GET_STAGE_BINARY
type MsgSysGetStageBinary struct{} type MsgSysGetStageBinary struct {
AckHandle uint32
BinaryType0 uint8
BinaryType1 uint8
Unk0 uint32 // Hardcoded 0
StageIDLength uint8
StageID string
}
// Opcode returns the ID associated with this packet type. // Opcode returns the ID associated with this packet type.
func (m *MsgSysGetStageBinary) Opcode() network.PacketID { func (m *MsgSysGetStageBinary) Opcode() network.PacketID {
@@ -15,7 +22,13 @@ func (m *MsgSysGetStageBinary) Opcode() network.PacketID {
// Parse parses the packet from binary // Parse parses the packet from binary
func (m *MsgSysGetStageBinary) Parse(bf *byteframe.ByteFrame) error { func (m *MsgSysGetStageBinary) Parse(bf *byteframe.ByteFrame) error {
panic("Not implemented") m.AckHandle = bf.ReadUint32()
m.BinaryType0 = bf.ReadUint8()
m.BinaryType1 = bf.ReadUint8()
m.Unk0 = bf.ReadUint32()
m.StageIDLength = bf.ReadUint8()
m.StageID = string(bf.ReadBytes(uint(m.StageIDLength)))
return nil
} }
// Build builds a binary packet from the current data. // Build builds a binary packet from the current data.

View File

@@ -6,7 +6,11 @@ import (
) )
// MsgSysIssueLogkey represents the MSG_SYS_ISSUE_LOGKEY // MsgSysIssueLogkey represents the MSG_SYS_ISSUE_LOGKEY
type MsgSysIssueLogkey struct{} type MsgSysIssueLogkey struct {
AckHandle uint32
Unk0 uint16 // Hardcoded 00 01 in binary
Unk1 uint16 // Hardcoded 0 in binary.
}
// Opcode returns the ID associated with this packet type. // Opcode returns the ID associated with this packet type.
func (m *MsgSysIssueLogkey) Opcode() network.PacketID { func (m *MsgSysIssueLogkey) Opcode() network.PacketID {
@@ -15,7 +19,10 @@ func (m *MsgSysIssueLogkey) Opcode() network.PacketID {
// Parse parses the packet from binary // Parse parses the packet from binary
func (m *MsgSysIssueLogkey) Parse(bf *byteframe.ByteFrame) error { func (m *MsgSysIssueLogkey) Parse(bf *byteframe.ByteFrame) error {
panic("Not implemented") m.AckHandle = bf.ReadUint32()
m.Unk0 = bf.ReadUint16()
m.Unk1 = bf.ReadUint16()
return nil
} }
// Build builds a binary packet from the current data. // Build builds a binary packet from the current data.

View File

@@ -6,7 +6,13 @@ import (
) )
// MsgSysLockStage represents the MSG_SYS_LOCK_STAGE // MsgSysLockStage represents the MSG_SYS_LOCK_STAGE
type MsgSysLockStage struct{} type MsgSysLockStage struct {
AckHandle uint32
Unk0 uint8 // Hardcoded 1 in the binary
Unk1 uint8 // Hardcoded 1 in the binary
StageIDLength uint8
StageID string
}
// Opcode returns the ID associated with this packet type. // Opcode returns the ID associated with this packet type.
func (m *MsgSysLockStage) Opcode() network.PacketID { func (m *MsgSysLockStage) Opcode() network.PacketID {
@@ -15,7 +21,12 @@ func (m *MsgSysLockStage) Opcode() network.PacketID {
// Parse parses the packet from binary // Parse parses the packet from binary
func (m *MsgSysLockStage) Parse(bf *byteframe.ByteFrame) error { func (m *MsgSysLockStage) Parse(bf *byteframe.ByteFrame) error {
panic("Not implemented") m.AckHandle = bf.ReadUint32()
m.Unk0 = bf.ReadUint8()
m.Unk1 = bf.ReadUint8()
m.StageIDLength = bf.ReadUint8()
m.StageID = string(bf.ReadBytes(uint(m.StageIDLength)))
return nil
} }
// Build builds a binary packet from the current data. // Build builds a binary packet from the current data.

View File

@@ -7,8 +7,8 @@ import (
// MsgSysSetStageBinary represents the MSG_SYS_SET_STAGE_BINARY // MsgSysSetStageBinary represents the MSG_SYS_SET_STAGE_BINARY
type MsgSysSetStageBinary struct { type MsgSysSetStageBinary struct {
Unk0 uint8 BinaryType0 uint8
BinaryType uint8 // Index BinaryType1 uint8 // Index
StageIDLength uint8 // <= 0x20 StageIDLength uint8 // <= 0x20
DataSize uint16 // <= 0x400 DataSize uint16 // <= 0x400
StageID string StageID string
@@ -22,8 +22,8 @@ func (m *MsgSysSetStageBinary) Opcode() network.PacketID {
// Parse parses the packet from binary // Parse parses the packet from binary
func (m *MsgSysSetStageBinary) Parse(bf *byteframe.ByteFrame) error { func (m *MsgSysSetStageBinary) Parse(bf *byteframe.ByteFrame) error {
m.Unk0 = bf.ReadUint8() m.BinaryType0 = bf.ReadUint8()
m.BinaryType = bf.ReadUint8() m.BinaryType1 = bf.ReadUint8()
m.StageIDLength = bf.ReadUint8() m.StageIDLength = bf.ReadUint8()
m.DataSize = bf.ReadUint16() m.DataSize = bf.ReadUint16()
m.StageID = string(bf.ReadBytes(uint(m.StageIDLength))) m.StageID = string(bf.ReadBytes(uint(m.StageIDLength)))

View File

@@ -15,7 +15,8 @@ func (m *MsgSysUnlockStage) Opcode() network.PacketID {
// Parse parses the packet from binary // Parse parses the packet from binary
func (m *MsgSysUnlockStage) Parse(bf *byteframe.ByteFrame) error { func (m *MsgSysUnlockStage) Parse(bf *byteframe.ByteFrame) error {
panic("Not implemented") // No data
return nil
} }
// Build builds a binary packet from the current data. // Build builds a binary packet from the current data.

View File

@@ -2,6 +2,7 @@ package channelserver
import ( import (
"bytes" "bytes"
"crypto/rand"
"encoding/base64" "encoding/base64"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
@@ -246,7 +247,26 @@ func handleMsgSysCastedBinary(s *Session, p mhfpacket.MHFPacket) {}
func handleMsgSysGetFile(s *Session, p mhfpacket.MHFPacket) {} func handleMsgSysGetFile(s *Session, p mhfpacket.MHFPacket) {}
func handleMsgSysIssueLogkey(s *Session, p mhfpacket.MHFPacket) {} func handleMsgSysIssueLogkey(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgSysIssueLogkey)
// Make a random log key for this session.
logKey := make([]byte, 8)
_, err := rand.Read(logKey)
if err != nil {
panic(err)
}
s.Lock()
s.logKey = logKey
s.Unlock()
// Issue it.
resp := byteframe.NewByteFrame()
resp.WriteBytes(logKey)
resp.WriteBytes([]byte{0x8E, 0x8E}) // Unk
doSizedAckResp(s, pkt.AckHandle, resp.Data())
}
func handleMsgSysRecordLog(s *Session, p mhfpacket.MHFPacket) {} func handleMsgSysRecordLog(s *Session, p mhfpacket.MHFPacket) {}
@@ -383,7 +403,11 @@ func handleMsgSysMoveStage(s *Session, p mhfpacket.MHFPacket) {}
func handleMsgSysLeaveStage(s *Session, p mhfpacket.MHFPacket) {} func handleMsgSysLeaveStage(s *Session, p mhfpacket.MHFPacket) {}
func handleMsgSysLockStage(s *Session, p mhfpacket.MHFPacket) {} func handleMsgSysLockStage(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgSysLockStage)
// TODO(Andoryuuta): What does this packet _actually_ do?
s.QueueAck(pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})
}
func handleMsgSysUnlockStage(s *Session, p mhfpacket.MHFPacket) {} func handleMsgSysUnlockStage(s *Session, p mhfpacket.MHFPacket) {}
@@ -403,9 +427,56 @@ func handleMsgSysSetStagePass(s *Session, p mhfpacket.MHFPacket) {}
func handleMsgSysWaitStageBinary(s *Session, p mhfpacket.MHFPacket) {} func handleMsgSysWaitStageBinary(s *Session, p mhfpacket.MHFPacket) {}
func handleMsgSysSetStageBinary(s *Session, p mhfpacket.MHFPacket) {} func handleMsgSysSetStageBinary(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgSysSetStageBinary)
func handleMsgSysGetStageBinary(s *Session, p mhfpacket.MHFPacket) {} // Try to get the stage
stageID := stripNullTerminator(pkt.StageID)
s.server.stagesLock.Lock()
stage, gotStage := s.server.stages[stageID]
s.server.stagesLock.Unlock()
// If we got the stage, lock and set the data.
if gotStage {
stage.Lock()
stage.rawBinaryData[stageBinaryKey{pkt.BinaryType0, pkt.BinaryType1}] = pkt.RawDataPayload
stage.Unlock()
} else {
s.logger.Warn("Failed to get stage", zap.String("StageID", stageID))
}
s.logger.Debug("handleMsgSysSetStageBinary Done!")
}
func handleMsgSysGetStageBinary(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgSysGetStageBinary)
// Try to get the stage
stageID := stripNullTerminator(pkt.StageID)
s.server.stagesLock.Lock()
stage, gotStage := s.server.stages[stageID]
s.server.stagesLock.Unlock()
// If we got the stage, lock and try to get the data.
var stageBinary []byte
var gotBinary bool
if gotStage {
stage.Lock()
stageBinary, gotBinary = stage.rawBinaryData[stageBinaryKey{pkt.BinaryType0, pkt.BinaryType1}]
stage.Unlock()
} else {
s.logger.Warn("Failed to get stage", zap.String("StageID", stageID))
}
if gotBinary {
doSizedAckResp(s, pkt.AckHandle, stageBinary)
} else {
s.logger.Warn("Failed to get stage binary", zap.Uint8("BinaryType0", pkt.BinaryType0), zap.Uint8("pkt.BinaryType1", pkt.BinaryType1))
s.logger.Warn("Sending blank stage binary")
doSizedAckResp(s, pkt.AckHandle, []byte{})
}
s.logger.Debug("MsgSysGetStageBinary Done!")
}
func handleMsgSysEnumerateClient(s *Session, p mhfpacket.MHFPacket) { func handleMsgSysEnumerateClient(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgSysEnumerateClient) pkt := p.(*mhfpacket.MsgSysEnumerateClient)
@@ -431,6 +502,8 @@ func handleMsgSysEnumerateClient(s *Session, p mhfpacket.MHFPacket) {
stage.RUnlock() stage.RUnlock()
doSizedAckResp(s, pkt.AckHandle, resp.Data()) doSizedAckResp(s, pkt.AckHandle, resp.Data())
s.logger.Debug("MsgSysEnumerateClient Done!")
} }
func handleMsgSysEnumerateStage(s *Session, p mhfpacket.MHFPacket) { func handleMsgSysEnumerateStage(s *Session, p mhfpacket.MHFPacket) {

View File

@@ -24,6 +24,7 @@ type Session struct {
stageID string stageID string
stage *Stage stage *Stage
charID uint32 charID uint32
logKey []byte
} }
// NewSession creates a new Session type. // NewSession creates a new Session type.

View File

@@ -15,6 +15,11 @@ type StageObject struct {
x, y, z float32 x, y, z float32
} }
type stageBinaryKey struct {
id0 uint8
id1 uint8
}
// Stage holds stage-specific information // Stage holds stage-specific information
type Stage struct { type Stage struct {
sync.RWMutex sync.RWMutex
@@ -22,6 +27,7 @@ type Stage struct {
gameObjectCount uint32 // Total count of objects ever created for this stage. Used for ObjID generation. gameObjectCount uint32 // Total count of objects ever created for this stage. Used for ObjID generation.
objects map[uint32]*StageObject // Map of ObjID -> StageObject objects map[uint32]*StageObject // Map of ObjID -> StageObject
clients map[*Session]uint32 // Map of session -> charID clients map[*Session]uint32 // Map of session -> charID
rawBinaryData map[stageBinaryKey][]byte // Raw binary data set by the client.
} }
// NewStage creates a new stage with intialized values. // NewStage creates a new stage with intialized values.
@@ -30,6 +36,7 @@ func NewStage(ID string) *Stage {
id: ID, id: ID,
objects: make(map[uint32]*StageObject), objects: make(map[uint32]*StageObject),
clients: make(map[*Session]uint32), clients: make(map[*Session]uint32),
rawBinaryData: make(map[stageBinaryKey][]byte),
gameObjectCount: 1, gameObjectCount: 1,
} }