-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathpacket.go
164 lines (132 loc) · 4.09 KB
/
packet.go
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
package d2prox
import (
"encoding/binary"
"encoding/hex"
"fmt"
"net"
)
// Packet is a wrapper around a byte array with some utility features
type Packet []byte
// GsMsgID attempts to extract a game server message id from the packet. May panic
func (p Packet) GsMsgID() byte {
return p[0]
}
// RealmMsgID attempts to extract a realm server message id from the packet. May panic
func (p Packet) RealmMsgID() byte {
return p[2]
}
// BnetMsgID attempts to extract a battle.net message id from the packet. May panic
func (p Packet) BnetMsgID() byte {
return p[1]
}
//
// battle.net packets
//
type BnetAuthCheckPacket Packet
// NumKeys returns the number of cd keys in the packet
func (p BnetAuthCheckPacket) NumKeys() int {
pb := PacketBuffer(p)
return pb.Uint32(16)
}
// KeyHash returns a cd key public value by index
func (p BnetAuthCheckPacket) KeyHash(index int) string {
const keyOffset = 24
const keyLen = 4 * 9
offset := keyOffset + index*keyLen + 8
hashBytes := p[offset : offset+4]
return hex.EncodeToString(hashBytes)
}
// KeysHash returns a hash of all the keys (their combined public values)
func (p BnetAuthCheckPacket) KeysHash() string {
hash := ""
for i := 0; i < p.NumKeys(); i++ {
hash += p.KeyHash(i)
}
return hash
}
// LogonRealmExPacket wraps SID_LOGONREALMEX (S->C)
// https://redux.bnetdocs.org/?op=packet&pid=237
type LogonRealmExPacket Packet
// RealmIP returns the realm server ip
func (p LogonRealmExPacket) RealmIP() net.IP {
return net.IP(p[20:24])
}
// RealmPort returns the realm port number
func (p LogonRealmExPacket) RealmPort() int {
return int(binary.BigEndian.Uint16(p[24:26]))
}
// RealmTarget returns a connection string combining the realm ip and the realm port
func (p LogonRealmExPacket) RealmTarget() string {
return fmt.Sprintf("%s:%d", p.RealmIP(), p.RealmPort())
}
// Token returns all the MCP chunk data required to authenticate with the realm server as a hex string
func (p LogonRealmExPacket) Token() string {
token := make([]byte, 64)
copy(token[0:16], p[4:20])
copy(token[16:64], p[28:76])
return hex.EncodeToString(token)
}
// SetRealmPort modifies the realm port
func (p LogonRealmExPacket) SetRealmPort(port int) {
binary.BigEndian.PutUint16(p[24:26], uint16(port))
}
// SetRealmIP modifies the realm ip
func (p LogonRealmExPacket) SetRealmIP(ip net.IP) {
copy(p[20:24], ip)
}
//
// realm server packets
//
// McpStartupPacket wraps MCP_STARTUP (C->S)
// https://redux.bnetdocs.org/?op=packet&pid=320
type McpStartupPacket Packet
// Token returns all the MCP chunk data required to authenticate with the realm server as a hex string
func (p McpStartupPacket) Token() string {
return hex.EncodeToString(p[3:67])
}
// McpJoinedGamePacket wraps MCP_JOINGAME (S->C)
// https://redux.bnetdocs.org/?op=packet&pid=107
type McpJoinedGamePacket Packet
// Hash returns the game hash as a byte array
func (p McpJoinedGamePacket) Hash() []byte {
return p[13:17]
}
// Token returns the game token as a byte array
func (p McpJoinedGamePacket) Token() []byte {
return p[5:7]
}
// GameIP returns the game server ip & port as a string
func (p McpJoinedGamePacket) GameIP() net.IP {
return net.IP(p[9:13])
}
// SetGameIP modifies the game server ip
func (p McpJoinedGamePacket) SetGameIP(ip net.IP) {
copy(p[9:13], ip)
}
// Status returns the join game status code
func (p McpJoinedGamePacket) Status() int {
return int(binary.LittleEndian.Uint32(p[17:21]))
}
//
// game server packets
//
// GsGameLogonPacket wraps D2GS_GAMELOGON (S->C)
// https://redux.bnetdocs.org/?op=packet&pid=131
type GsGameLogonPacket Packet
// Token returns game hash + game token as a hexadecimal string
func (p GsGameLogonPacket) Token() string {
return hex.EncodeToString(p[1:7])
}
// GsChatMessagePacket represents a chat message sent from the client
type GsChatMessagePacket Packet
// Message returns the chat message as a string
func (p GsChatMessagePacket) Message() string {
pb := PacketBuffer(p)
return pb.NullString(3)
}
// Target returns the message target as a string
func (p GsChatMessagePacket) Target() string {
pb := PacketBuffer(p)
start := pb.IndexOf(0x00, 3) + 1
return pb.NullString(start)
}