-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstatus_query.go
144 lines (127 loc) · 3.22 KB
/
status_query.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
package main
import (
"bytes"
"encoding/binary"
"fmt"
log "github.com/sirupsen/logrus"
"io"
"net"
"time"
)
func QueryStatus(hostPort string, timeout time.Duration, signer Signer) bool {
dialer := net.Dialer{Timeout: timeout}
conn, err := dialer.Dial("tcp", hostPort)
if err != nil {
log.Errorf("Status query error connecting: %s", err)
return false
}
hostname, _ := MakeHostname(signer,
"mcprot.com", "127.0.0.1", "25565")
buff := &bytes.Buffer{}
buff.Write(VarInt(47))
buff.Write(String(hostname)) //TODO make use encrypted hostname to bypass plugin
buff.Write(VarShort(25565))
buff.Write(VarInt(1))
//send basic info
err = writePacket(0x00, buff.Bytes(), conn)
if err != nil {
log.Errorf("Status query error sending handshake: %s, host: %v", err, hostPort)
conn.Close()
return false
}
err = writePacket(0x00, []byte{}, conn)
if err != nil {
log.Errorf("Status query error sending status req: %s, host: %v", err, hostPort)
conn.Close()
return false
}
packetId, payload, err := ReadPacket(conn)
if err != nil {
log.Errorf("Status query error reading status packet: %s, host: %v", err, hostPort)
conn.Close()
return false
}
if packetId != 0x00 {
log.Errorf("Status query invalid status packet id: %d, host: %v", packetId, hostPort)
conn.Close()
return false
}
_, err = readUtf8(bytes.NewReader(payload))
if err != nil {
log.Errorf("Status query error reading status data: %s, host: %v", err, hostPort)
conn.Close()
return false
}
conn.Close()
return true
}
func packVarint(c int) []byte {
var buf [8]byte
n := binary.PutUvarint(buf[:], uint64(uint32(c)))
return buf[:n]
}
func readVarint(reader io.Reader) (int, error) {
br, ok := reader.(io.ByteReader)
if !ok {
br = dummyByteReader{reader, [1]byte{}}
}
x, err := binary.ReadUvarint(br)
return int(int32(uint32(x))), err
}
type dummyByteReader struct {
io.Reader
buf [1]byte
}
func (b dummyByteReader) ReadByte() (byte, error) {
_, err := b.Read(b.buf[:])
return b.buf[0], err
}
func writePacket(id int, payload []byte, writer io.Writer) error {
idEnc := packVarint(id)
l := len(idEnc) + len(payload)
lEnc := packVarint(l)
d := make([]byte, len(lEnc)+len(idEnc)+len(payload))
n := copy(d[0:], lEnc)
m := copy(d[n:], idEnc)
k := copy(d[n+m:], payload)
if k < len(payload) {
panic("k < len(payload)")
}
_, err := writer.Write(d[0:])
return err
}
func ReadPacket(reader io.Reader) (id int, payload []byte, err error) {
l, err := readVarint(reader) // dlugosc zawiera tez id pakietu
if err != nil {
return
}
if l > 32768 || l < 0 {
err = fmt.Errorf("read_packet: bad length %d", l)
return
}
lr := &io.LimitedReader{R: reader, N: 10} // hack zeby wiedziec ile varint zajmowal
id, err = readVarint(lr)
if err != nil {
return
}
payloadLen := l - (10 - int(lr.N))
if payloadLen < 0 {
err = fmt.Errorf("read_packet: bad payload length %d (full packet %d)", payloadLen, l)
return
}
payload = make([]byte, payloadLen) // read rest of packet
_, err = io.ReadFull(reader, payload)
return
}
func readUtf8(reader io.Reader) (s string, err error) {
length, err := readVarint(reader)
if err != nil {
return
}
d := make([]byte, length)
_, err = reader.Read(d)
if err != nil {
return
}
return string(d), nil
}