forked from rumblefrog/go-a2s
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathchallenge.go
76 lines (62 loc) · 2.07 KB
/
challenge.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
package a2s
import (
"errors"
"fmt"
)
const (
A2S_PLAYER_CHALLENGE_REPLY_HEADER = 0x41
)
var (
ErrBadChallengeResponse = errors.New("Bad challenge response")
)
func (c *Client) getChallenge(header []byte, fullResult byte) ([]byte, bool, error) {
if err := c.send(header); err != nil {
return nil, false, fmt.Errorf("failed to send request: %w", err)
}
data, err := c.receive()
if err != nil {
return nil, false, fmt.Errorf("failed to receive data: %w", err)
}
// Handle the case where the server might not send any data
if len(data) == 0 {
return nil, false, fmt.Errorf("no data received from server, possibly offline or unresponsive")
}
// Ensure the packet is large enough to contain the required uint32
if len(data) < 4 {
return nil, false, fmt.Errorf("received data is too short: length %d, expected at least 4 bytes", len(data))
}
reader := NewPacketReader(data)
packetType, ok := reader.TryReadInt32()
if !ok {
return nil, false, fmt.Errorf("failed to read packet type: %v", data)
}
switch packetType {
case -2:
// Handle multi-packet response
fullData, err := c.collectMultiplePacketResponse(data)
if err != nil {
return nil, false, fmt.Errorf("failed to collect multi-packet response: %w", err)
}
return fullData, true, nil
case -1:
// Single packet, continue processing
default:
return nil, false, fmt.Errorf("unexpected packet header: %v", packetType)
}
// Check if there is at least one more byte for the header
if reader.Pos()+1 > len(reader.buffer) {
return nil, false, fmt.Errorf("insufficient data to read challenge header: %v", data)
}
headerByte := reader.ReadUint8()
if headerByte == A2S_PLAYER_CHALLENGE_REPLY_HEADER {
// Check if there are at least 4 more bytes for the challenge number
if reader.Pos()+4 > len(reader.buffer) {
return nil, false, fmt.Errorf("insufficient data for challenge number: %v", data)
}
return data[reader.Pos() : reader.Pos()+4], false, nil
} else if headerByte == fullResult {
// We have received the full result
return data, true, nil
}
return nil, false, ErrBadChallengeResponse
}