-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy pathrules.go
122 lines (88 loc) · 2.12 KB
/
rules.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
package a2s
import (
"encoding/binary"
"errors"
)
const (
A2S_RULES_REQUEST = 0x56
A2S_RULES_RESPONSE = 0x45
)
var (
ErrBadRulesReply = errors.New("Bad rules reply")
)
type RulesInfo struct {
// Number of rules in the response.
Count uint16 `json:"Count"`
// KV map of rules name to value
Rules map[string]string `json:"Rules"`
}
type Rule struct {
Name string `json:"Name"`
Value string `json:"Value"`
}
func (c *Client) QueryRules() (*RulesInfo, error) {
/*
A2S_RULES
Request Format
Header byte 'V' (0x56)
Challenge int Challenge number, or -1 (0xFFFFFFFF) to receive a challenge number.
FF FF FF FF 56 FF FF FF FF ÿÿÿÿVÿÿÿÿ"
Example A2S_PLAYER request with the received challenge number:
FF FF FF FF 56 4B A1 D5 22 ÿÿÿÿVK¡Õ"
*/
ruleRequest := []byte{0xFF, 0xFF, 0xFF, 0xFF, A2S_RULES_REQUEST, 0xFF, 0xFF, 0xFF, 0xFF}
data, immediate, err := c.getChallenge(ruleRequest, A2S_RULES_RESPONSE)
if err != nil {
return nil, err
}
if !immediate {
if err := c.send([]byte{
0xff, 0xff, 0xff, 0xff,
A2S_RULES_REQUEST,
data[0], data[1], data[2], data[3],
}); err != nil {
return nil, err
}
data, err = c.receive()
if err != nil {
return nil, err
}
}
// Read header (long 4 bytes)
switch int32(binary.LittleEndian.Uint32(data)) {
case -1:
return parseRulesInfo(data)
case -2:
data, err = c.collectMultiplePacketResponse(data)
if err != nil {
return nil, err
}
return parseRulesInfo(data)
}
return nil, ErrBadPacketHeader
}
func parseRulesInfo(data []byte) (*RulesInfo, error) {
reader := NewPacketReader(data)
// Simple response now
if reader.ReadInt32() != -1 {
return nil, ErrBadPacketHeader
}
if reader.ReadUint8() != A2S_RULES_RESPONSE {
return nil, ErrBadRulesReply
}
rules := &RulesInfo{}
rules.Count = reader.ReadUint16()
rules.Rules = make(map[string]string, rules.Count)
for i := 0; i < int(rules.Count); i++ {
key, ok := reader.TryReadString()
if !ok {
break
}
val, ok := reader.TryReadString()
if !ok {
break
}
rules.Rules[key] = val
}
return rules, nil
}