From 833a46544df2ed2a7afdba08ebfe02ed7741d86a Mon Sep 17 00:00:00 2001 From: Arda Serdar Pektezol <1669855+pektezol@users.noreply.github.com> Date: Tue, 8 Nov 2022 22:48:20 +0300 Subject: net/svc messages --- main.go | 2 +- packets/message.go | 83 --------------------------- packets/messages/message.go | 50 +++++++++++++++++ packets/messages/types/NetDisconnect.go | 11 ++++ packets/messages/types/NetFile.go | 17 ++++++ packets/messages/types/NetNop.go | 3 + packets/messages/types/NetSetConVar.go | 28 ++++++++++ packets/messages/types/NetSignOnState.go | 31 ++++++++++ packets/messages/types/NetSplitScreenUser.go | 13 +++++ packets/messages/types/NetStringCmd.go | 13 +++++ packets/messages/types/NetTick.go | 17 ++++++ packets/messages/types/SvcClassInfo.go | 42 ++++++++++++++ packets/messages/types/SvcSendTable.go | 17 ++++++ packets/messages/types/SvcServerInfo.go | 43 ++++++++++++++ packets/messages/types/SvcSetPause.go | 11 ++++ packets/packet.go | 84 ++++++++++++++++++++++++++++ packets/types.go | 9 ++- 17 files changed, 387 insertions(+), 87 deletions(-) delete mode 100644 packets/message.go create mode 100644 packets/messages/message.go create mode 100644 packets/messages/types/NetDisconnect.go create mode 100644 packets/messages/types/NetFile.go create mode 100644 packets/messages/types/NetNop.go create mode 100644 packets/messages/types/NetSetConVar.go create mode 100644 packets/messages/types/NetSignOnState.go create mode 100644 packets/messages/types/NetSplitScreenUser.go create mode 100644 packets/messages/types/NetStringCmd.go create mode 100644 packets/messages/types/NetTick.go create mode 100644 packets/messages/types/SvcClassInfo.go create mode 100644 packets/messages/types/SvcSendTable.go create mode 100644 packets/messages/types/SvcServerInfo.go create mode 100644 packets/messages/types/SvcSetPause.go create mode 100644 packets/packet.go diff --git a/main.go b/main.go index 9f33161..8f05c2b 100644 --- a/main.go +++ b/main.go @@ -23,7 +23,7 @@ func main() { reader := bitreader.Reader(file, true) packets.ParseHeader(reader) for { - code := packets.ParseMessage(reader) + code := packets.ParsePacket(reader) if code == 7 { break } diff --git a/packets/message.go b/packets/message.go deleted file mode 100644 index 922f918..0000000 --- a/packets/message.go +++ /dev/null @@ -1,83 +0,0 @@ -package packets - -import ( - "fmt" - - "github.com/pektezol/bitreader" - "github.com/pektezol/demoparser/packets/classes" -) - -const MSSC = 2 - -func ParseMessage(reader *bitreader.ReaderType) (status int) { - messageType := reader.TryReadInt8() - messageTick := reader.TryReadInt32() - messageSlot := reader.TryReadInt8() - switch messageType { - case 0x01: // TODO: SignOn - Data - signOn := SignOn{ - PacketInfo: classes.ParseCmdInfo(reader, MSSC), - InSequence: int32(reader.TryReadInt32()), - OutSequence: int32(reader.TryReadInt32()), - Size: int32(reader.TryReadInt32()), - } - reader.SkipBytes(int(signOn.Size)) - fmt.Printf("[%d] (%d) {%d} SignOn: %v\n", messageTick, messageType, messageSlot, signOn) - return 1 - case 0x02: // TODO: Packet - Data - packet := Packet{ - PacketInfo: classes.ParseCmdInfo(reader, MSSC), - InSequence: int32(reader.TryReadInt32()), - OutSequence: int32(reader.TryReadInt32()), - Size: int32(reader.TryReadInt32()), - } - reader.SkipBytes(int(packet.Size)) - //fmt.Printf("[%d] (%d) Packet: %v\n", messageTick, messageType, packet) - return 2 - case 0x03: - syncTick := SyncTick{} - fmt.Printf("[%d] (%d) SyncTick: %v\n", messageTick, messageType, syncTick) - return 3 - case 0x04: - consoleCmd := ConsoleCmd{ - Size: int32(reader.TryReadInt32()), - } - consoleCmd.Data = reader.TryReadStringLen(int(consoleCmd.Size)) - //fmt.Printf("[%d] (%d) ConsoleCmd: %s\n", messageTick, messageType, consoleCmd.Data) - return 4 - case 0x05: // TODO: UserCmd - Buttons - userCmd := UserCmd{ - Cmd: int32(reader.TryReadInt32()), - Size: int32(reader.TryReadInt32()), - } - userCmd.Data = classes.ParseUserCmdInfo(reader.TryReadBytesToSlice(int(userCmd.Size))) - // fmt.Printf("[%d] (%d) UserCmd: %v\n", messageTick, messageType, userCmd) - return 5 - case 0x06: // TODO: DataTables - val := reader.TryReadInt32() - reader.SkipBytes(int(val)) - // fmt.Printf("[%d] (%d) DataTables: \n", messageTick, messageType) - return 6 - case 0x07: - stop := Stop{ - RemainingData: nil, - } - fmt.Printf("[%d] (%d) Stop: %v\n", messageTick, messageType, stop) - return 7 - case 0x08: // TODO: CustomData - reader.SkipBytes(4) - val := reader.TryReadInt32() - reader.SkipBytes(int(val)) - // fmt.Printf("[%d] (%d) CustomData: \n", messageTick, messageType) - return 8 - case 0x09: // TODO: StringTables - Data - stringTables := StringTables{ - Size: int32(reader.TryReadInt32()), - } - stringTables.Data = classes.ParseStringTable(reader.TryReadBytesToSlice(int(stringTables.Size))) - // fmt.Printf("[%d] (%d) StringTables: %v\n", messageTick, messageType, stringTables) - return 9 - default: - return 0 - } -} diff --git a/packets/messages/message.go b/packets/messages/message.go new file mode 100644 index 0000000..c508bfa --- /dev/null +++ b/packets/messages/message.go @@ -0,0 +1,50 @@ +package messages + +import ( + "bytes" + + "github.com/pektezol/bitreader" + "github.com/pektezol/demoparser/packets/messages/types" +) + +func ParseMessage(data []byte) []Message { + reader := bitreader.Reader(bytes.NewReader(data), true) + var messages []Message + for { + messageType, err := reader.ReadBits(6) + if err != nil { + break + } + switch messageType { + case 0x00: + messages = append(messages, Message{Data: types.NetNop{}}) + case 0x01: + messages = append(messages, Message{Data: types.ParseNetDisconnect(reader)}) + case 0x02: + messages = append(messages, Message{Data: types.ParseNetFile(reader)}) + case 0x03: + messages = append(messages, Message{Data: types.ParseNetSplitScreenUser(reader)}) + case 0x04: + messages = append(messages, Message{Data: types.ParseNetTick(reader)}) + case 0x05: + messages = append(messages, Message{Data: types.ParseNetStringCmd(reader)}) + case 0x06: + messages = append(messages, Message{Data: types.ParseNetSetConVar(reader)}) + case 0x07: + messages = append(messages, Message{Data: types.ParseNetSignOnState(reader)}) + case 0x08: + messages = append(messages, Message{Data: types.ParseSvcServerInfo(reader)}) + case 0x09: + messages = append(messages, Message{Data: types.ParseSvcSendTable(reader)}) + case 0x10: + messages = append(messages, Message{Data: types.ParseSvcClassInfo(reader)}) + case 0x11: + messages = append(messages, Message{Data: types.ParseSvcSetPause(reader)}) + } + } + return messages +} + +type Message struct { + Data any +} diff --git a/packets/messages/types/NetDisconnect.go b/packets/messages/types/NetDisconnect.go new file mode 100644 index 0000000..8b65568 --- /dev/null +++ b/packets/messages/types/NetDisconnect.go @@ -0,0 +1,11 @@ +package types + +import "github.com/pektezol/bitreader" + +type NetDisconnect struct { + Text string +} + +func ParseNetDisconnect(reader *bitreader.ReaderType) NetDisconnect { + return NetDisconnect{Text: reader.TryReadString()} +} diff --git a/packets/messages/types/NetFile.go b/packets/messages/types/NetFile.go new file mode 100644 index 0000000..c65873d --- /dev/null +++ b/packets/messages/types/NetFile.go @@ -0,0 +1,17 @@ +package types + +import "github.com/pektezol/bitreader" + +type NetFile struct { + TransferId uint32 + FileName string + FileRequested bool +} + +func ParseNetFile(reader *bitreader.ReaderType) NetFile { + return NetFile{ + TransferId: reader.TryReadInt32(), + FileName: reader.TryReadString(), + FileRequested: reader.TryReadBool(), + } +} diff --git a/packets/messages/types/NetNop.go b/packets/messages/types/NetNop.go new file mode 100644 index 0000000..d0a1f7a --- /dev/null +++ b/packets/messages/types/NetNop.go @@ -0,0 +1,3 @@ +package types + +type NetNop struct{} diff --git a/packets/messages/types/NetSetConVar.go b/packets/messages/types/NetSetConVar.go new file mode 100644 index 0000000..b502953 --- /dev/null +++ b/packets/messages/types/NetSetConVar.go @@ -0,0 +1,28 @@ +package types + +import "github.com/pektezol/bitreader" + +type NetSetConVar struct { + Length uint8 + ConVars []ConVar +} + +type ConVar struct { + Name string + Value string +} + +func ParseNetSetConVar(reader *bitreader.ReaderType) NetSetConVar { + var convars []ConVar + netsetconvar := NetSetConVar{ + Length: reader.TryReadInt8(), + } + for i := 0; i < int(netsetconvar.Length); i++ { + convars = append(convars, ConVar{ + Name: reader.TryReadString(), + Value: reader.TryReadString(), + }) + } + netsetconvar.ConVars = convars + return netsetconvar +} diff --git a/packets/messages/types/NetSignOnState.go b/packets/messages/types/NetSignOnState.go new file mode 100644 index 0000000..3d02e91 --- /dev/null +++ b/packets/messages/types/NetSignOnState.go @@ -0,0 +1,31 @@ +package types + +import ( + "fmt" + + "github.com/pektezol/bitreader" +) + +type NetSignOnState struct { + SignonState int8 + SpawnCount uint32 + NumServerPlayers uint32 + IdsLength uint32 + PlayersNetworkIds []byte + MapNameLength uint32 + MapName string +} + +func ParseNetSignOnState(reader *bitreader.ReaderType) NetSignOnState { + netsignonstate := NetSignOnState{ + SignonState: int8(reader.TryReadInt8()), + SpawnCount: reader.TryReadInt32(), + NumServerPlayers: reader.TryReadInt32(), + IdsLength: reader.TryReadInt32(), + } + fmt.Println(netsignonstate.IdsLength) + netsignonstate.PlayersNetworkIds = reader.TryReadBytesToSlice(int(netsignonstate.IdsLength)) + netsignonstate.MapNameLength = reader.TryReadInt32() + netsignonstate.MapName = reader.TryReadStringLen(int(netsignonstate.MapNameLength)) + return netsignonstate +} diff --git a/packets/messages/types/NetSplitScreenUser.go b/packets/messages/types/NetSplitScreenUser.go new file mode 100644 index 0000000..66a7c85 --- /dev/null +++ b/packets/messages/types/NetSplitScreenUser.go @@ -0,0 +1,13 @@ +package types + +import "github.com/pektezol/bitreader" + +type NetSplitScreenUser struct { + Unknown bool +} + +func ParseNetSplitScreenUser(reader *bitreader.ReaderType) NetSplitScreenUser { + return NetSplitScreenUser{ + Unknown: reader.TryReadBool(), + } +} diff --git a/packets/messages/types/NetStringCmd.go b/packets/messages/types/NetStringCmd.go new file mode 100644 index 0000000..1ee9f67 --- /dev/null +++ b/packets/messages/types/NetStringCmd.go @@ -0,0 +1,13 @@ +package types + +import "github.com/pektezol/bitreader" + +type NetStringCmd struct { + Command string +} + +func ParseNetStringCmd(reader *bitreader.ReaderType) NetStringCmd { + return NetStringCmd{ + Command: reader.TryReadString(), + } +} diff --git a/packets/messages/types/NetTick.go b/packets/messages/types/NetTick.go new file mode 100644 index 0000000..9dae14b --- /dev/null +++ b/packets/messages/types/NetTick.go @@ -0,0 +1,17 @@ +package types + +import "github.com/pektezol/bitreader" + +type NetTick struct { + Tick uint32 + HostFrameTime float32 + HostFrameTimeStdDeviation float32 +} + +func ParseNetTick(reader *bitreader.ReaderType) NetTick { + return NetTick{ + Tick: reader.TryReadInt32(), + HostFrameTime: float32(reader.TryReadInt16()) / 1e5, + HostFrameTimeStdDeviation: float32(reader.TryReadInt16()) / 1e5, + } +} diff --git a/packets/messages/types/SvcClassInfo.go b/packets/messages/types/SvcClassInfo.go new file mode 100644 index 0000000..58e43b7 --- /dev/null +++ b/packets/messages/types/SvcClassInfo.go @@ -0,0 +1,42 @@ +package types + +import ( + "math" + + "github.com/pektezol/bitreader" +) + +type SvcClassInfo struct { + Length uint16 + CreateOnClient bool + ServerClasses []ServerClass +} + +type ServerClass struct { + ClassId int32 + ClassName string + DataTableName string +} + +func ParseSvcClassInfo(reader *bitreader.ReaderType) SvcClassInfo { + var serverclasses []ServerClass + svcclassinfo := SvcClassInfo{ + Length: reader.TryReadInt16(), + CreateOnClient: reader.TryReadBool(), + } + if svcclassinfo.CreateOnClient { + for i := 0; i < int(svcclassinfo.Length); i++ { + id, err := reader.ReadBits(int(math.Log2(float64(svcclassinfo.Length))) + 1) + if err != nil { + panic(err) + } + serverclasses = append(serverclasses, ServerClass{ + ClassId: int32(id), + ClassName: reader.TryReadString(), + DataTableName: reader.TryReadString(), + }) + } + } + svcclassinfo.ServerClasses = serverclasses + return svcclassinfo +} diff --git a/packets/messages/types/SvcSendTable.go b/packets/messages/types/SvcSendTable.go new file mode 100644 index 0000000..f76aadb --- /dev/null +++ b/packets/messages/types/SvcSendTable.go @@ -0,0 +1,17 @@ +package types + +import "github.com/pektezol/bitreader" + +type SvcSendTable struct { + NeedsDecoder bool + Length uint8 + Props int32 +} + +func ParseSvcSendTable(reader *bitreader.ReaderType) SvcSendTable { + return SvcSendTable{ + NeedsDecoder: reader.TryReadBool(), + Length: reader.TryReadInt8(), + } + // No one cares about SvcSendTable +} diff --git a/packets/messages/types/SvcServerInfo.go b/packets/messages/types/SvcServerInfo.go new file mode 100644 index 0000000..9d2648b --- /dev/null +++ b/packets/messages/types/SvcServerInfo.go @@ -0,0 +1,43 @@ +package types + +import "github.com/pektezol/bitreader" + +type SvcServerInfo struct { + Protocol uint16 + ServerCount uint32 + IsHltv bool + IsDedicated bool + ClientCrc int32 + MaxClasses uint16 + MapCrc uint32 + PlayerSlot uint8 + MaxClients uint8 + Unk uint32 + TickInterval float32 + COs byte + GameDir string + MapName string + SkyName string + HostName string +} + +func ParseSvcServerInfo(reader *bitreader.ReaderType) SvcServerInfo { + return SvcServerInfo{ + Protocol: reader.TryReadInt16(), + ServerCount: reader.TryReadInt32(), + IsHltv: reader.TryReadBool(), + IsDedicated: reader.TryReadBool(), + ClientCrc: int32(reader.TryReadInt32()), + MaxClasses: reader.TryReadInt16(), + MapCrc: reader.TryReadInt32(), + PlayerSlot: reader.TryReadInt8(), + MaxClients: reader.TryReadInt8(), + Unk: reader.TryReadInt32(), + TickInterval: reader.TryReadFloat32(), + COs: reader.TryReadInt8(), + GameDir: reader.TryReadString(), + MapName: reader.TryReadString(), + SkyName: reader.TryReadString(), + HostName: reader.TryReadString(), + } +} diff --git a/packets/messages/types/SvcSetPause.go b/packets/messages/types/SvcSetPause.go new file mode 100644 index 0000000..040fb6a --- /dev/null +++ b/packets/messages/types/SvcSetPause.go @@ -0,0 +1,11 @@ +package types + +import "github.com/pektezol/bitreader" + +type SvcSetPause struct { + Paused bool +} + +func ParseSvcSetPause(reader *bitreader.ReaderType) SvcSetPause { + return SvcSetPause{Paused: reader.TryReadBool()} +} diff --git a/packets/packet.go b/packets/packet.go new file mode 100644 index 0000000..23a21e6 --- /dev/null +++ b/packets/packet.go @@ -0,0 +1,84 @@ +package packets + +import ( + "fmt" + + "github.com/pektezol/bitreader" + "github.com/pektezol/demoparser/packets/classes" + "github.com/pektezol/demoparser/packets/messages" +) + +const MSSC = 2 + +func ParsePacket(reader *bitreader.ReaderType) (status int) { + messageType := reader.TryReadInt8() + messageTick := reader.TryReadInt32() + messageSlot := reader.TryReadInt8() + switch messageType { + case 0x01: // TODO: SignOn - Data + signOn := SignOn{ + PacketInfo: classes.ParseCmdInfo(reader, MSSC), + InSequence: int32(reader.TryReadInt32()), + OutSequence: int32(reader.TryReadInt32()), + Size: int32(reader.TryReadInt32()), + } + reader.SkipBytes(int(signOn.Size)) + fmt.Printf("[%d] (%d) {%d} SignOn: %v\n", messageTick, messageType, messageSlot, signOn) + return 1 + case 0x02: // TODO: Packet - Data + packet := Packet{ + PacketInfo: classes.ParseCmdInfo(reader, MSSC), + InSequence: int32(reader.TryReadInt32()), + OutSequence: int32(reader.TryReadInt32()), + Size: int32(reader.TryReadInt32()), + } + packet.Data = messages.ParseMessage(reader.TryReadBytesToSlice(int(packet.Size))) + fmt.Printf("[%d] (%d) Packet: %v\n", messageTick, messageType, packet) + return 2 + case 0x03: + syncTick := SyncTick{} + fmt.Printf("[%d] (%d) SyncTick: %v\n", messageTick, messageType, syncTick) + return 3 + case 0x04: + consoleCmd := ConsoleCmd{ + Size: int32(reader.TryReadInt32()), + } + consoleCmd.Data = reader.TryReadStringLen(int(consoleCmd.Size)) + //fmt.Printf("[%d] (%d) ConsoleCmd: %s\n", messageTick, messageType, consoleCmd.Data) + return 4 + case 0x05: // TODO: UserCmd - Buttons + userCmd := UserCmd{ + Cmd: int32(reader.TryReadInt32()), + Size: int32(reader.TryReadInt32()), + } + userCmd.Data = classes.ParseUserCmdInfo(reader.TryReadBytesToSlice(int(userCmd.Size))) + // fmt.Printf("[%d] (%d) UserCmd: %v\n", messageTick, messageType, userCmd) + return 5 + case 0x06: // TODO: DataTables + val := reader.TryReadInt32() + reader.SkipBytes(int(val)) + // fmt.Printf("[%d] (%d) DataTables: \n", messageTick, messageType) + return 6 + case 0x07: + stop := Stop{ + RemainingData: nil, + } + fmt.Printf("[%d] (%d) Stop: %v\n", messageTick, messageType, stop) + return 7 + case 0x08: // TODO: CustomData + reader.SkipBytes(4) + val := reader.TryReadInt32() + reader.SkipBytes(int(val)) + // fmt.Printf("[%d] (%d) CustomData: \n", messageTick, messageType) + return 8 + case 0x09: // TODO: StringTables - Data + stringTables := StringTables{ + Size: int32(reader.TryReadInt32()), + } + stringTables.Data = classes.ParseStringTable(reader.TryReadBytesToSlice(int(stringTables.Size))) + // fmt.Printf("[%d] (%d) StringTables: %v\n", messageTick, messageType, stringTables) + return 9 + default: + return 0 + } +} diff --git a/packets/types.go b/packets/types.go index 2a4cf4b..9a1f667 100644 --- a/packets/types.go +++ b/packets/types.go @@ -1,6 +1,9 @@ package packets -import "github.com/pektezol/demoparser/packets/classes" +import ( + "github.com/pektezol/demoparser/packets/classes" + "github.com/pektezol/demoparser/packets/messages" +) type Header struct { DemoFileStamp string @@ -21,7 +24,7 @@ type SignOn struct { InSequence int32 OutSequence int32 Size int32 - Data []byte + Data []messages.Message } type Packet struct { @@ -29,7 +32,7 @@ type Packet struct { InSequence int32 OutSequence int32 Size int32 - Data []byte + Data []messages.Message } type SyncTick struct{} -- cgit v1.2.3