-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This adds an extremely basic sample SQP server which can be queried.
- Loading branch information
Showing
11 changed files
with
462 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# SvrSample package | ||
|
||
This server sample package provides sample libraries for providing basic responses to server query requests. | ||
It is not designed to implement the full specs of protocols, however it will provide enough to respond to basic | ||
server information requests. | ||
|
||
The sample implementation here will be enough to satisfy the requirements for Multiplay's scaling system to query | ||
the server for health, player counts and other useful information. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package common | ||
|
||
// QueryResponder represents an interface to a concrete type which responds | ||
// to query requests. | ||
type QueryResponder interface { | ||
Respond(clientAddress string, buf []byte) ([]byte, error) | ||
} | ||
|
||
// QueryState represents the state of a currently running game. | ||
type QueryState struct { | ||
CurrentPlayers int32 | ||
MaxPlayers int32 | ||
ServerName string | ||
GameType string | ||
Map string | ||
Port uint16 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
package common | ||
|
||
import ( | ||
"bytes" | ||
"encoding/binary" | ||
"reflect" | ||
) | ||
|
||
// WireEncoder is an interface which allows for different query implementations | ||
// to write data to a byte buffer in a specific format. | ||
type WireEncoder interface { | ||
WriteString(resp *bytes.Buffer, s string) error | ||
Write(resp *bytes.Buffer, v interface{}) error | ||
} | ||
|
||
// Encoder is a struct which implements proto.WireEncoder | ||
type Encoder struct{} | ||
|
||
// WriteString writes a string to the provided buffer. | ||
func (e *Encoder) WriteString(resp *bytes.Buffer, s string) error { | ||
if err := binary.Write(resp, binary.BigEndian, byte(len(s))); err != nil { | ||
return err | ||
} | ||
|
||
return binary.Write(resp, binary.BigEndian, []byte(s)) | ||
} | ||
|
||
// Write writes arbitrary data to the provided buffer. | ||
func (e *Encoder) Write(resp *bytes.Buffer, v interface{}) error { | ||
return binary.Write(resp, binary.BigEndian, v) | ||
} | ||
|
||
// WireWrite writes the provided data to resp with the provided WireEncoder w. | ||
func WireWrite(resp *bytes.Buffer, w WireEncoder, data interface{}) error { | ||
t := reflect.TypeOf(data) | ||
vs := reflect.Indirect(reflect.ValueOf(data)) | ||
for i := 0; i < t.NumField(); i++ { | ||
f := t.Field(i) | ||
v := vs.FieldByName(f.Name) | ||
|
||
// Dereference pointer | ||
if f.Type.Kind() == reflect.Ptr { | ||
if v.IsNil() { | ||
continue | ||
} | ||
v = v.Elem() | ||
} | ||
|
||
switch v.Kind() { | ||
case reflect.Struct: | ||
if err := WireWrite(resp, w, v.Interface()); err != nil { | ||
return err | ||
} | ||
|
||
case reflect.String: | ||
if err := w.WriteString(resp, v.String()); err != nil { | ||
return err | ||
} | ||
|
||
default: | ||
if err := w.Write(resp, v.Interface()); err != nil { | ||
return err | ||
} | ||
} | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package sqp | ||
|
||
import ( | ||
"github.com/multiplay/go-svrquery/lib/svrsample/common" | ||
) | ||
|
||
// ServerInfo holds the ServerInfo chunk data. | ||
type ServerInfo struct { | ||
CurrentPlayers uint16 | ||
MaxPlayers uint16 | ||
ServerName string | ||
GameType string | ||
BuildID string | ||
GameMap string | ||
Port uint16 | ||
} | ||
|
||
// QueryStateToServerInfo converts proto.QueryState to ServerInfo. | ||
func QueryStateToServerInfo(qs common.QueryState) ServerInfo { | ||
return ServerInfo{ | ||
CurrentPlayers: uint16(qs.CurrentPlayers), | ||
MaxPlayers: uint16(qs.MaxPlayers), | ||
ServerName: qs.ServerName, | ||
GameType: qs.GameType, | ||
GameMap: qs.Map, | ||
Port: qs.Port, | ||
} | ||
} | ||
|
||
// Size returns the number of bytes sqpServerInfo will use on the wire. | ||
func (si ServerInfo) Size() uint32 { | ||
return uint32( | ||
2 + // CurrentPlayers | ||
2 + // MaxPlayers | ||
len([]byte(si.ServerName)) + 1 + | ||
len([]byte(si.GameType)) + 1 + | ||
len([]byte(si.BuildID)) + 1 + | ||
len([]byte(si.GameMap)) + 1 + | ||
2, // Port | ||
) | ||
} |
Oops, something went wrong.