summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/Philipp15b/go-steam/protocol/packet.go
blob: d6b2e425c42e8571764c1421dc42a41099057e8f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
package protocol

import (
	"bytes"
	"github.com/golang/protobuf/proto"
	"encoding/binary"
	"fmt"
	. "github.com/Philipp15b/go-steam/protocol/steamlang"
)

// TODO: Headers are always deserialized twice.

// Represents an incoming, partially unread message.
type Packet struct {
	EMsg        EMsg
	IsProto     bool
	TargetJobId JobId
	SourceJobId JobId
	Data        []byte
}

func NewPacket(data []byte) (*Packet, error) {
	var rawEMsg uint32
	err := binary.Read(bytes.NewReader(data), binary.LittleEndian, &rawEMsg)
	if err != nil {
		return nil, err
	}
	eMsg := NewEMsg(rawEMsg)
	buf := bytes.NewReader(data)
	if eMsg == EMsg_ChannelEncryptRequest || eMsg == EMsg_ChannelEncryptResult {
		header := NewMsgHdr()
		header.Msg = eMsg
		err = header.Deserialize(buf)
		if err != nil {
			return nil, err
		}
		return &Packet{
			EMsg:        eMsg,
			IsProto:     false,
			TargetJobId: JobId(header.TargetJobID),
			SourceJobId: JobId(header.SourceJobID),
			Data:        data,
		}, nil
	} else if IsProto(rawEMsg) {
		header := NewMsgHdrProtoBuf()
		header.Msg = eMsg
		err = header.Deserialize(buf)
		if err != nil {
			return nil, err
		}
		return &Packet{
			EMsg:        eMsg,
			IsProto:     true,
			TargetJobId: JobId(header.Proto.GetJobidTarget()),
			SourceJobId: JobId(header.Proto.GetJobidSource()),
			Data:        data,
		}, nil
	} else {
		header := NewExtendedClientMsgHdr()
		header.Msg = eMsg
		err = header.Deserialize(buf)
		if err != nil {
			return nil, err
		}
		return &Packet{
			EMsg:        eMsg,
			IsProto:     false,
			TargetJobId: JobId(header.TargetJobID),
			SourceJobId: JobId(header.SourceJobID),
			Data:        data,
		}, nil
	}
}

func (p *Packet) String() string {
	return fmt.Sprintf("Packet{EMsg = %v, Proto = %v, Len = %v, TargetJobId = %v, SourceJobId = %v}", p.EMsg, p.IsProto, len(p.Data), p.TargetJobId, p.SourceJobId)
}

func (p *Packet) ReadProtoMsg(body proto.Message) *ClientMsgProtobuf {
	header := NewMsgHdrProtoBuf()
	buf := bytes.NewBuffer(p.Data)
	header.Deserialize(buf)
	proto.Unmarshal(buf.Bytes(), body)
	return &ClientMsgProtobuf{ // protobuf messages have no payload
		Header: header,
		Body:   body,
	}
}

func (p *Packet) ReadClientMsg(body MessageBody) *ClientMsg {
	header := NewExtendedClientMsgHdr()
	buf := bytes.NewReader(p.Data)
	header.Deserialize(buf)
	body.Deserialize(buf)
	payload := make([]byte, buf.Len())
	buf.Read(payload)
	return &ClientMsg{
		Header:  header,
		Body:    body,
		Payload: payload,
	}
}

func (p *Packet) ReadMsg(body MessageBody) *Msg {
	header := NewMsgHdr()
	buf := bytes.NewReader(p.Data)
	header.Deserialize(buf)
	body.Deserialize(buf)
	payload := make([]byte, buf.Len())
	buf.Read(payload)
	return &Msg{
		Header:  header,
		Body:    body,
		Payload: payload,
	}
}