Skip to content

Commit db72ae1

Browse files
committed
Restructure project
1 parent 715d845 commit db72ae1

File tree

10 files changed

+122
-83
lines changed

10 files changed

+122
-83
lines changed

README.md

+26-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,31 @@
11
# gamequery
22
A Golang package for querying game servers
33

4-
**This package is WIP and should not be used in production.**
5-
64
## Supported protocols:
75
Source Query
8-
Minecraft TCP & UDP
6+
Minecraft TCP & UDP
7+
8+
## Sample code:
9+
```go
10+
package main
11+
12+
import (
13+
"fmt"
14+
"github.com/wisp-gg/gamequery"
15+
"github.com/wisp-gg/gamequery/api"
16+
)
17+
18+
func main() {
19+
res, protocol, err := gamequery.Detect(api.Request{
20+
IP: "127.0.0.1",
21+
Port: 27015,
22+
})
23+
if err != nil {
24+
fmt.Printf("failed to query: %s", err)
25+
return
26+
}
27+
28+
fmt.Printf("Detected the protocol: %s\n", protocol)
29+
fmt.Printf("%+v\n", res)
30+
}
31+
```

api/structs.go

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package api
2+
3+
import "time"
4+
5+
// Representation of a query request for a specific game server.
6+
type Request struct {
7+
Game string // The game protocol to use, can be left out for the `Detect` function.
8+
IP string // The game server's query IP
9+
Port uint16 // The game server's query port
10+
Timeout *time.Duration // Timeout for a single send/receive operation in the game's protocol.
11+
}
12+
13+
// Representation of a query result for a specific game server.
14+
type Response struct {
15+
// TODO: Decide the structure of this
16+
17+
Raw interface{} // Contains the original, raw response received from the game's protocol.
18+
}

gamequery.go

+16-22
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,22 @@ package gamequery
22

33
import (
44
"errors"
5-
"github.com/wisp-gg/gamequery/protocols"
5+
"github.com/wisp-gg/gamequery/api"
6+
"github.com/wisp-gg/gamequery/internal"
7+
"github.com/wisp-gg/gamequery/internal/protocols"
68
"sort"
79
"sync"
810
"time"
911
)
1012

11-
// Representation of a query request for a specific game server.
12-
type Request struct {
13-
Game string // The game protocol to use, can be left out for the `Detect` function.
14-
IP string // The game server's query IP
15-
Port uint16 // The game server's query port
16-
Timeout *time.Duration // Timeout for a single send/receive operation in the game's protocol.
17-
}
18-
19-
var queryProtocols = []protocols.Protocol{
13+
var queryProtocols = []internal.Protocol{
2014
protocols.SourceQuery{},
2115
protocols.MinecraftUDP{},
2216
protocols.MinecraftTCP{},
2317
}
2418

25-
func findProtocols(name string) []protocols.Protocol {
26-
found := make([]protocols.Protocol, 0)
19+
func findProtocols(name string) []internal.Protocol {
20+
found := make([]internal.Protocol, 0)
2721
for _, protocol := range queryProtocols {
2822
if protocol.Name() == name {
2923
found = append(found, protocol)
@@ -43,35 +37,35 @@ type queryResult struct {
4337
Name string
4438
Priority uint16
4539
Err error
46-
Response protocols.Response
40+
Response api.Response
4741
}
4842

4943
// Query the game server by detecting the protocol (trying all available protocols).
5044
// This usually should be used as the initial query function and then use `Query` function
5145
// with the returned protocol if the query succeeds. Otherwise each function call will take always
5246
// <req.Timeout> duration even if the response was received earlier from one of the protocols.
53-
func Detect(req Request) (protocols.Response, string, error) {
47+
func Detect(req api.Request) (api.Response, string, error) {
5448
return query(req, queryProtocols)
5549
}
5650

5751
// Query the game server using the protocol provided in req.Game.
58-
func Query(req Request) (protocols.Response, error) {
52+
func Query(req api.Request) (api.Response, error) {
5953
chosenProtocols := findProtocols(req.Game)
6054
if len(chosenProtocols) < 1 {
61-
return protocols.Response{}, errors.New("could not find protocols for the game")
55+
return api.Response{}, errors.New("could not find protocols for the game")
6256
}
6357

6458
response, _, err := query(req, chosenProtocols)
6559
return response, err
6660
}
6761

68-
func query(req Request, chosenProtocols []protocols.Protocol) (protocols.Response, string, error) {
62+
func query(req api.Request, chosenProtocols []internal.Protocol) (api.Response, string, error) {
6963
var wg sync.WaitGroup
7064
wg.Add(len(chosenProtocols))
7165

7266
queryResults := make([]queryResult, len(chosenProtocols))
7367
for index, queryProtocol := range chosenProtocols {
74-
go func(queryProtocol protocols.Protocol, index int) {
68+
go func(queryProtocol internal.Protocol, index int) {
7569
defer wg.Done()
7670

7771
var port = queryProtocol.DefaultPort()
@@ -84,12 +78,12 @@ func query(req Request, chosenProtocols []protocols.Protocol) (protocols.Respons
8478
timeout = *req.Timeout
8579
}
8680

87-
networkHelper := protocols.NetworkHelper{}
81+
networkHelper := internal.NetworkHelper{}
8882
if err := networkHelper.Initialize(queryProtocol.Network(), req.IP, port, timeout); err != nil {
8983
queryResults[index] = queryResult{
9084
Priority: queryProtocol.Priority(),
9185
Err: err,
92-
Response: protocols.Response{},
86+
Response: api.Response{},
9387
}
9488
return
9589
}
@@ -100,7 +94,7 @@ func query(req Request, chosenProtocols []protocols.Protocol) (protocols.Respons
10094
queryResults[index] = queryResult{
10195
Priority: queryProtocol.Priority(),
10296
Err: err,
103-
Response: protocols.Response{},
97+
Response: api.Response{},
10498
}
10599
return
106100
}
@@ -130,5 +124,5 @@ func query(req Request, chosenProtocols []protocols.Protocol) (protocols.Respons
130124
}
131125
}
132126

133-
return protocols.Response{}, "", firstError
127+
return api.Response{}, "", firstError
134128
}

protocols/network_helper.go renamed to internal/network_helper.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package protocols
1+
package internal
22

33
import (
44
"fmt"

protocols/packet.go renamed to internal/packet.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package protocols
1+
package internal
22

33
import (
44
"encoding/binary"

internal/protocol.go

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package internal
2+
3+
import (
4+
"github.com/wisp-gg/gamequery/api"
5+
)
6+
7+
type Protocol interface {
8+
Name() string
9+
Aliases() []string
10+
DefaultPort() uint16
11+
Priority() uint16
12+
Network() string
13+
14+
Execute(helper NetworkHelper) (api.Response, error)
15+
}

protocols/minecraft_tcp.go renamed to internal/protocols/minecraft_tcp.go

+13-11
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import (
55
"encoding/json"
66
"errors"
77
"fmt"
8+
"github.com/wisp-gg/gamequery/api"
9+
"github.com/wisp-gg/gamequery/internal"
810
)
911

1012
type MinecraftTCP struct{}
@@ -58,11 +60,11 @@ func (mc MinecraftTCP) Network() string {
5860
return "tcp"
5961
}
6062

61-
func buildMCPacket(bulkData ...interface{}) *Packet {
62-
packet := Packet{}
63+
func buildMCPacket(bulkData ...interface{}) *internal.Packet {
64+
packet := internal.Packet{}
6365
packet.SetOrder(binary.BigEndian)
6466

65-
tmpPacket := Packet{}
67+
tmpPacket := internal.Packet{}
6668
tmpPacket.SetOrder(binary.BigEndian)
6769
for _, data := range bulkData {
6870
switch val := data.(type) {
@@ -86,26 +88,26 @@ func buildMCPacket(bulkData ...interface{}) *Packet {
8688
return &packet
8789
}
8890

89-
func (mc MinecraftTCP) Execute(helper NetworkHelper) (Response, error) {
91+
func (mc MinecraftTCP) Execute(helper internal.NetworkHelper) (api.Response, error) {
9092
err := helper.Send(buildMCPacket([]byte{0x00, 0x00}, helper.GetIP(), helper.GetPort(), 0x01).GetBuffer())
9193
if err != nil {
92-
return Response{}, err
94+
return api.Response{}, err
9395
}
9496

9597
err = helper.Send(buildMCPacket(0x00).GetBuffer())
9698
if err != nil {
97-
return Response{}, err
99+
return api.Response{}, err
98100
}
99101

100102
responsePacket, err := helper.Receive()
101103
if err != nil {
102-
return Response{}, err
104+
return api.Response{}, err
103105
}
104106

105107
packetLength := responsePacket.ReadVarint()
106108
packetId := responsePacket.ReadVarint()
107109
if packetId != 0 {
108-
return Response{}, errors.New("received something else than a status response")
110+
return api.Response{}, errors.New("received something else than a status response")
109111
}
110112

111113
if packetId > packetLength {
@@ -119,14 +121,14 @@ func (mc MinecraftTCP) Execute(helper NetworkHelper) (Response, error) {
119121
raw := MinecraftTCPRaw{}
120122
err = json.Unmarshal([]byte(jsonBody), &raw)
121123
if err != nil {
122-
return Response{}, err
124+
return api.Response{}, err
123125
}
124126

125127
if responsePacket.IsInvalid() {
126-
return Response{}, errors.New("received packet is invalid")
128+
return api.Response{}, errors.New("received packet is invalid")
127129
}
128130

129-
return Response{
131+
return api.Response{
130132
Raw: raw,
131133
}, nil
132134
}

protocols/minecraft_udp.go renamed to internal/protocols/minecraft_udp.go

+15-13
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import (
44
"bytes"
55
"encoding/binary"
66
"errors"
7+
"github.com/wisp-gg/gamequery/api"
8+
"github.com/wisp-gg/gamequery/internal"
79
"math/rand"
810
"strconv"
911
"time"
@@ -68,36 +70,36 @@ func parseChallengeToken(challengeToken string) ([]byte, error) {
6870
return buf.Bytes()[buf.Len()-4:], nil
6971
}
7072

71-
func (mc MinecraftUDP) Execute(helper NetworkHelper) (Response, error) {
73+
func (mc MinecraftUDP) Execute(helper internal.NetworkHelper) (api.Response, error) {
7274
sessionId := generateSessionID()
7375

74-
packet := Packet{}
76+
packet := internal.Packet{}
7577
packet.SetOrder(binary.BigEndian)
7678
packet.WriteRaw(0xFE, 0xFD, 0x09)
7779
packet.WriteInt32(sessionId)
7880

7981
err := helper.Send(packet.GetBuffer())
8082
if err != nil {
81-
return Response{}, err
83+
return api.Response{}, err
8284
}
8385

8486
handshakePacket, err := helper.Receive()
8587
if err != nil {
86-
return Response{}, err
88+
return api.Response{}, err
8789
}
8890

8991
handshakePacket.SetOrder(binary.BigEndian)
9092
if handshakePacket.ReadUint8() != 0x09 {
91-
return Response{}, errors.New("sent a handshake, but didn't receive handshake response back")
93+
return api.Response{}, errors.New("sent a handshake, but didn't receive handshake response back")
9294
}
9395

9496
if handshakePacket.ReadInt32() != sessionId {
95-
return Response{}, errors.New("received handshake for wrong session id")
97+
return api.Response{}, errors.New("received handshake for wrong session id")
9698
}
9799

98100
challengeToken, err := parseChallengeToken(handshakePacket.ReadString())
99101
if err != nil {
100-
return Response{}, err
102+
return api.Response{}, err
101103
}
102104

103105
packet.Clear()
@@ -108,21 +110,21 @@ func (mc MinecraftUDP) Execute(helper NetworkHelper) (Response, error) {
108110

109111
err = helper.Send(packet.GetBuffer())
110112
if err != nil {
111-
return Response{}, err
113+
return api.Response{}, err
112114
}
113115

114116
responsePacket, err := helper.Receive()
115117
if err != nil {
116-
return Response{}, err
118+
return api.Response{}, err
117119
}
118120

119121
responsePacket.SetOrder(binary.BigEndian)
120122
if responsePacket.ReadUint8() != 0x00 {
121-
return Response{}, errors.New("sent a full stat request, but didn't receive stat response back")
123+
return api.Response{}, errors.New("sent a full stat request, but didn't receive stat response back")
122124
}
123125

124126
if responsePacket.ReadInt32() != sessionId {
125-
return Response{}, errors.New("received handshake for wrong session id")
127+
return api.Response{}, errors.New("received handshake for wrong session id")
126128
}
127129

128130
responsePacket.Forward(11)
@@ -175,10 +177,10 @@ func (mc MinecraftUDP) Execute(helper NetworkHelper) (Response, error) {
175177
}
176178

177179
if responsePacket.IsInvalid() {
178-
return Response{}, errors.New("received packet is invalid")
180+
return api.Response{}, errors.New("received packet is invalid")
179181
}
180182

181-
return Response{
183+
return api.Response{
182184
Raw: raw,
183185
}, nil
184186
}

0 commit comments

Comments
 (0)