datagrams now called packets duh

master
Jordan Orelli 8 years ago
parent 1d6dc6cc9c
commit 4e8f6127b0

@ -1,34 +0,0 @@
package main
import (
"fmt"
"github.com/golang/protobuf/proto"
)
// datagram represents the top-level envelope in the dota replay format. All
// data in the replay file is packed into datagram frames of at most 65kb.
type dataGram struct {
cmd datagramType
tick int64
body []byte
}
func (g dataGram) String() string {
if len(g.body) > 30 {
return fmt.Sprintf("{dataGram cmd: %v tick: %v size: %d body: %x...}", g.cmd, g.tick, len(g.body), g.body[:27])
}
return fmt.Sprintf("{dataGram cmd: %v tick: %v size: %d body: %x}", g.cmd, g.tick, len(g.body), g.body)
}
func (g *dataGram) Open(m *messageFactory, pbuf *proto.Buffer) (proto.Message, error) {
msg, err := m.BuildDatagram(g.cmd)
if err != nil {
return nil, err
}
pbuf.SetBuf(g.body)
if err := pbuf.Unmarshal(msg); err != nil {
return nil, err
}
return msg, nil
}

@ -20,7 +20,7 @@ var (
messageTypes = make(map[string]bool)
enumTypes = make(map[string]bool)
entityTypes = make(typeMap)
cmdTypes = make(typeMap)
packetTypes = make(typeMap)
cmdEnumType = "EDemoCommands"
entityEnumTypes = map[string]bool{
"NET_Messages": true,
@ -76,42 +76,43 @@ var (
////////////////////////////////////////////////////////////////////////////////
import (
"fmt"
"github.com/golang/protobuf/proto"
"github.com/jordanorelli/hyperstone/dota"
)
type datagramType int32
type packetType int32
type entityType int32
const (
EDemoCommands_DEM_Error datagramType = -1
{{- range $id, $spec := .Commands }}
{{$spec.EnumName}} datagramType = {{$id}}
EDemoCommands_DEM_Error packetType = -1
{{- range $id, $spec := .Packets }}
{{$spec.EnumName}} packetType = {{$id}}
{{- end }}
{{- range $id, $spec := .Entities }}
{{$spec.EnumName}} entityType = {{$id}}
{{- end }}
)
func (d datagramType) String() string {
switch d {
{{- range $id, $spec := .Commands }}
func (t packetType) String() string {
switch t {
{{- range $id, $spec := .Packets }}
case {{$spec.EnumName}}:
return "{{$spec.EnumName}}"
{{- end }}
default:
return "UnknownDatagramType"
return fmt.Sprintf("UnknownPacketType_%d", t)
}
}
func (e entityType) String() string {
switch e {
func (t entityType) String() string {
switch t {
{{- range $id, $spec := .Entities }}
case {{$spec.EnumName}}:
return "{{$spec.EnumName}}"
{{- end }}
default:
return "UnknownEntityType"
return fmt.Sprintf("UnknownEntityType_%d", t)
}
}
@ -133,16 +134,16 @@ func (m messageStatus) Error() string {
}
}
type datagramFactory map[datagramType]func() proto.Message
type packetFactory map[packetType]func() proto.Message
type entityFactory map[entityType]func() proto.Message
type messageFactory struct {
datagrams datagramFactory
packets packetFactory
entities entityFactory
}
func (m *messageFactory) BuildDatagram(id datagramType) (proto.Message, error) {
fn, ok := m.datagrams[id]
func (m *messageFactory) BuildPacket(id packetType) (proto.Message, error) {
fn, ok := m.packets[id]
if !ok {
return nil, m_Unknown
}
@ -158,8 +159,8 @@ func (m *messageFactory) BuildEntity(id entityType) (proto.Message, error) {
}
var messages = messageFactory{
datagramFactory{
{{- range $id, $spec := .Commands }}
packetFactory{
{{- range $id, $spec := .Packets }}
{{$spec.EnumName}}: func() proto.Message { return new(dota.{{$spec.TypeName}}) },
{{- end }}
},
@ -253,7 +254,7 @@ func processValueSpec(spec *ast.ValueSpec) {
if isEntityType {
entityTypes[n] = messageSpec{EnumName: name.Name}
} else {
cmdTypes[n] = messageSpec{EnumName: name.Name}
packetTypes[n] = messageSpec{EnumName: name.Name}
}
}
}
@ -347,14 +348,14 @@ func main() {
processPackage(name, pkg)
}
cmdTypes.fillTypeNames()
packetTypes.fillTypeNames()
entityTypes.fillTypeNames()
var ctx = struct {
Commands typeMap
Packets typeMap
Entities typeMap
}{
Commands: cmdTypes,
Packets: packetTypes,
Entities: entityTypes,
}

@ -25,31 +25,32 @@ package main
////////////////////////////////////////////////////////////////////////////////
import (
"fmt"
"github.com/golang/protobuf/proto"
"github.com/jordanorelli/hyperstone/dota"
)
type datagramType int32
type packetType int32
type entityType int32
const (
EDemoCommands_DEM_Error datagramType = -1
EDemoCommands_DEM_Stop datagramType = 0
EDemoCommands_DEM_FileHeader datagramType = 1
EDemoCommands_DEM_FileInfo datagramType = 2
EDemoCommands_DEM_SyncTick datagramType = 3
EDemoCommands_DEM_SendTables datagramType = 4
EDemoCommands_DEM_ClassInfo datagramType = 5
EDemoCommands_DEM_StringTables datagramType = 6
EDemoCommands_DEM_Packet datagramType = 7
EDemoCommands_DEM_SignonPacket datagramType = 8
EDemoCommands_DEM_ConsoleCmd datagramType = 9
EDemoCommands_DEM_CustomData datagramType = 10
EDemoCommands_DEM_CustomDataCallbacks datagramType = 11
EDemoCommands_DEM_UserCmd datagramType = 12
EDemoCommands_DEM_FullPacket datagramType = 13
EDemoCommands_DEM_SaveGame datagramType = 14
EDemoCommands_DEM_SpawnGroups datagramType = 15
EDemoCommands_DEM_Error packetType = -1
EDemoCommands_DEM_Stop packetType = 0
EDemoCommands_DEM_FileHeader packetType = 1
EDemoCommands_DEM_FileInfo packetType = 2
EDemoCommands_DEM_SyncTick packetType = 3
EDemoCommands_DEM_SendTables packetType = 4
EDemoCommands_DEM_ClassInfo packetType = 5
EDemoCommands_DEM_StringTables packetType = 6
EDemoCommands_DEM_Packet packetType = 7
EDemoCommands_DEM_SignonPacket packetType = 8
EDemoCommands_DEM_ConsoleCmd packetType = 9
EDemoCommands_DEM_CustomData packetType = 10
EDemoCommands_DEM_CustomDataCallbacks packetType = 11
EDemoCommands_DEM_UserCmd packetType = 12
EDemoCommands_DEM_FullPacket packetType = 13
EDemoCommands_DEM_SaveGame packetType = 14
EDemoCommands_DEM_SpawnGroups packetType = 15
NET_Messages_net_NOP entityType = 0
NET_Messages_net_Disconnect entityType = 1
NET_Messages_net_SplitScreenUser entityType = 3
@ -128,7 +129,6 @@ const (
EBaseUserMessages_UM_CloseCaptionPlaceholder entityType = 142
EBaseUserMessages_UM_CameraTransition entityType = 143
EBaseUserMessages_UM_AudioParameter entityType = 144
EBaseGameEvents_GE_VDebugGameSessionIDEvent entityType = 200
EBaseGameEvents_GE_PlaceDecalEvent entityType = 201
EBaseGameEvents_GE_ClearWorldDecalsEvent entityType = 202
EBaseGameEvents_GE_ClearEntityDecalsEvent entityType = 203
@ -235,8 +235,8 @@ const (
EDotaUserMessages_DOTA_UM_QuestStatus entityType = 559
)
func (d datagramType) String() string {
switch d {
func (t packetType) String() string {
switch t {
case EDemoCommands_DEM_Stop:
return "EDemoCommands_DEM_Stop"
case EDemoCommands_DEM_FileHeader:
@ -270,12 +270,12 @@ func (d datagramType) String() string {
case EDemoCommands_DEM_SpawnGroups:
return "EDemoCommands_DEM_SpawnGroups"
default:
return "UnknownDatagramType"
return fmt.Sprintf("UnknownPacketType_%d", t)
}
}
func (e entityType) String() string {
switch e {
func (t entityType) String() string {
switch t {
case NET_Messages_net_NOP:
return "NET_Messages_net_NOP"
case NET_Messages_net_Disconnect:
@ -432,8 +432,6 @@ func (e entityType) String() string {
return "EBaseUserMessages_UM_CameraTransition"
case EBaseUserMessages_UM_AudioParameter:
return "EBaseUserMessages_UM_AudioParameter"
case EBaseGameEvents_GE_VDebugGameSessionIDEvent:
return "EBaseGameEvents_GE_VDebugGameSessionIDEvent"
case EBaseGameEvents_GE_PlaceDecalEvent:
return "EBaseGameEvents_GE_PlaceDecalEvent"
case EBaseGameEvents_GE_ClearWorldDecalsEvent:
@ -643,7 +641,7 @@ func (e entityType) String() string {
case EDotaUserMessages_DOTA_UM_QuestStatus:
return "EDotaUserMessages_DOTA_UM_QuestStatus"
default:
return "UnknownEntityType"
return fmt.Sprintf("UnknownEntityType_%d", t)
}
}
@ -665,16 +663,16 @@ func (m messageStatus) Error() string {
}
}
type datagramFactory map[datagramType]func() proto.Message
type packetFactory map[packetType]func() proto.Message
type entityFactory map[entityType]func() proto.Message
type messageFactory struct {
datagrams datagramFactory
packets packetFactory
entities entityFactory
}
func (m *messageFactory) BuildDatagram(id datagramType) (proto.Message, error) {
fn, ok := m.datagrams[id]
func (m *messageFactory) BuildPacket(id packetType) (proto.Message, error) {
fn, ok := m.packets[id]
if !ok {
return nil, m_Unknown
}
@ -690,7 +688,7 @@ func (m *messageFactory) BuildEntity(id entityType) (proto.Message, error) {
}
var messages = messageFactory{
datagramFactory{
packetFactory{
EDemoCommands_DEM_Stop: func() proto.Message { return new(dota.CDemoStop) },
EDemoCommands_DEM_FileHeader: func() proto.Message { return new(dota.CDemoFileHeader) },
EDemoCommands_DEM_FileInfo: func() proto.Message { return new(dota.CDemoFileInfo) },
@ -787,7 +785,6 @@ var messages = messageFactory{
EBaseUserMessages_UM_CloseCaptionPlaceholder: func() proto.Message { return new(dota.CUserMessageCloseCaptionPlaceholder) },
EBaseUserMessages_UM_CameraTransition: func() proto.Message { return new(dota.CUserMessageCameraTransition) },
EBaseUserMessages_UM_AudioParameter: func() proto.Message { return new(dota.CUserMessageAudioParameter) },
EBaseGameEvents_GE_VDebugGameSessionIDEvent: func() proto.Message { return new(dota.CMsgVDebugGameSessionIDEvent) },
EBaseGameEvents_GE_PlaceDecalEvent: func() proto.Message { return new(dota.CMsgPlaceDecalEvent) },
EBaseGameEvents_GE_ClearWorldDecalsEvent: func() proto.Message { return new(dota.CMsgClearWorldDecalsEvent) },
EBaseGameEvents_GE_ClearEntityDecalsEvent: func() proto.Message { return new(dota.CMsgClearEntityDecalsEvent) },

@ -49,8 +49,6 @@ type options struct {
f string // input file
memprofile string
cpuprofile string
datagrams bool // dump datagrams or no
packets bool // dump packets or no
}
func (o options) input() (io.Reader, error) {
@ -105,8 +103,6 @@ func main() {
flag.BoolVar(&opts.b, "b", false, "input is expected to be bzip-compressed")
flag.BoolVar(&opts.v, "v", false, "verbose mode")
flag.StringVar(&opts.f, "f", "--", "input file to be used. -- means stdin")
flag.BoolVar(&opts.datagrams, "datagrams", false, "dump top-level datagram info to stdout")
flag.BoolVar(&opts.packets, "packets", false, "dump packets to stdout")
flag.StringVar(&opts.memprofile, "memprofile", "", "memory profile destination")
flag.StringVar(&opts.cpuprofile, "cpuprofile", "", "cpu profile destination")
flag.Parse()
@ -125,8 +121,6 @@ func main() {
}
p := newParser(r)
p.dumpDatagrams = opts.datagrams
p.dumpPackets = opts.packets
if err := p.start(); err != nil {
bail(1, "parse error: %v", err)
}

@ -15,9 +15,6 @@ type parser struct {
// the source of replay bytes. Must NOT be compressed.
source *bufio.Reader
dumpDatagrams bool
dumpPackets bool
scratch []byte
pbuf *proto.Buffer
}
@ -43,26 +40,22 @@ func (p *parser) start() error {
func (p *parser) run() error {
for {
gram, err := p.readDatagram()
gram, err := p.readPacket()
if err != nil {
return wrap(err, "read datagram error in run loop")
}
p.handleDataGram(gram)
return wrap(err, "read packet error in run loop")
}
p.handlePacket(gram)
}
func (p *parser) handleDataGram(d *dataGram) error {
if p.dumpDatagrams {
fmt.Println(d)
}
func (p *parser) handlePacket(d *packet) error {
if len(d.body) == 0 {
return nil
}
msg, err := d.Open(&messages, p.pbuf)
if err != nil {
fmt.Printf("datagram open error: %v\n", err)
fmt.Printf("packet open error: %v\n", err)
return nil
}
@ -89,9 +82,6 @@ func (p *parser) handleDemoPacket(packet *dota.CDemoPacket) error {
default:
return err
}
if p.dumpPackets {
fmt.Printf("\t%v\n", entity{t: t, size: uint32(s), body: b})
}
e, err := messages.BuildEntity(t)
if err != nil {
fmt.Printf("\tskipping entity of size %d, type %s: %v\n", len(b), t, err)
@ -158,13 +148,13 @@ func (p *parser) checkHeader() (bool, error) {
return string(buf) == replayHeader, nil
}
// reads the next datagram type indicator off the wire. Also looks for a
// reads the next packet type indicator off the wire. Also looks for a
// compression flag, returning true if the contents to follow are snappy
// compressed, false otherwise.
func (p *parser) readDatagramType() (datagramType, bool, error) {
func (p *parser) readPacketType() (packetType, bool, error) {
n, err := p.decodeVarint()
if err != nil {
return EDemoCommands_DEM_Error, false, wrap(err, "readDatagramType couldn't read varint")
return EDemoCommands_DEM_Error, false, wrap(err, "readPacketType couldn't read varint")
}
compressed := false
@ -172,42 +162,42 @@ func (p *parser) readDatagramType() (datagramType, bool, error) {
compressed = true
n &^= 0x40
}
return datagramType(n), compressed, nil
return packetType(n), compressed, nil
}
func (p *parser) readDatagram() (*dataGram, error) {
cmd, compressed, err := p.readDatagramType()
func (p *parser) readPacket() (*packet, error) {
cmd, compressed, err := p.readPacketType()
if err != nil {
return nil, wrap(err, "readDatagram couldn't get a command")
return nil, wrap(err, "readPacket couldn't get a command")
}
tick, err := p.decodeVarint()
if err != nil {
return nil, wrap(err, "readDatagram couldn't read the tick value")
return nil, wrap(err, "readPacket couldn't read the tick value")
}
size, err := p.decodeVarint()
if err != nil {
return nil, wrap(err, "readDatagram couldn't read the size value")
return nil, wrap(err, "readPacket couldn't read the size value")
}
if size > 0 {
buf := make([]byte, int(size))
if _, err := io.ReadFull(p.source, buf); err != nil {
return nil, wrap(err, "readDatagram couldn't read datagram body")
return nil, wrap(err, "readPacket couldn't read packet body")
}
if compressed {
var err error
buf, err = snappy.Decode(nil, buf)
if err != nil {
return nil, wrap(err, "readDatagram couldn't snappy decode body")
return nil, wrap(err, "readPacket couldn't snappy decode body")
}
}
// TODO: pool these!
return &dataGram{cmd, int64(tick), buf}, nil
return &packet{cmd, int64(tick), buf}, nil
}
// TODO: pool these!
return &dataGram{cmd, int64(tick), nil}, nil
return &packet{cmd, int64(tick), nil}, nil
}

Loading…
Cancel
Save