Skip to content

Commit

Permalink
Mostly working things
Browse files Browse the repository at this point in the history
  • Loading branch information
j-bro committed Oct 30, 2023
1 parent 856f8d4 commit 99639f0
Show file tree
Hide file tree
Showing 15 changed files with 391 additions and 570 deletions.
2 changes: 1 addition & 1 deletion cmd/cli/bulk.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ func processBulkEntry(entry string) (*BulkResponseItem, error) {
return item, nil
}

client, err := svrquery.NewClient(querySection, addressSection, options...)
client, err := svrquery.NewUDPClient(querySection, addressSection, options...)
if err != nil {
item.Error = fmt.Sprintf("create client: %s", err)
return item, nil
Expand Down
2 changes: 1 addition & 1 deletion cmd/cli/bulk_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ func TestCreateClient(t *testing.T) {
// Validate key setting
if tc.expKey != "" {
require.Len(t, options, 1)
c := svrquery.Client{}
c := svrquery.UDPClient{}
require.NoError(t, options[0](&c))
require.Equal(t, tc.expKey, c.Key())
}
Expand Down
69 changes: 32 additions & 37 deletions cmd/cli/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"flag"
"fmt"
"github.com/multiplay/go-svrquery/lib/svrquery"
"github.com/multiplay/go-svrquery/lib/svrquery/protocol"
"github.com/multiplay/go-svrquery/lib/svrsample"
"github.com/multiplay/go-svrquery/lib/svrsample/common"
"log"
Expand All @@ -13,7 +14,7 @@ import (

func main() {
clientAddr := flag.String("addr", "", "Address to connect to e.g. 127.0.0.1:12345")
proto := flag.String("proto", "", "Protocol e.g. sqp, tf2e, tf2e-v7, tf2e-v8")
proto := flag.String("proto", "", "Protocol e.g. sqp, tf2e, tf2e-v7, tf2e-v8, prom")
key := flag.String("key", "", "Key to use to authenticate")
file := flag.String("file", "", "Bulk file to execute to get basic server information")
serverAddr := flag.String("server", "", "Address to start server e.g. 127.0.0.1:12121, :23232")
Expand All @@ -36,12 +37,12 @@ func main() {
switch {
case *serverAddr != "":
if *proto == "" {
bail(l, "No protocol provided in client mode")
bail(l, "No protocol provided in server mode")
}
serverMode(l, *proto, *serverAddr)
case *clientAddr != "":
if *proto == "" {
bail(l, "Protocol required in server mode")
bail(l, "Protocol required in client mode")
}
queryMode(l, *proto, *clientAddr, *key)
default:
Expand All @@ -50,24 +51,34 @@ func main() {
}

func queryMode(l *log.Logger, proto, address, key string) {
if err := query(proto, address, key); err != nil {
client, err := getClient(proto, address, key)
if err != nil {
l.Fatal(err)
}
}
defer client.Close()

func query(proto, address, key string) error {
options := make([]svrquery.Option, 0)
if key != "" {
options = append(options, svrquery.WithKey(key))
if err := query(client); err != nil {
l.Fatal(err)
}
}

c, err := svrquery.NewClient(proto, address, options...)
if err != nil {
return err
func getClient(proto, address, key string) (protocol.Client, error) {
switch proto {
case "sqp":
options := make([]svrquery.Option, 0)
if key != "" {
options = append(options, svrquery.WithKey(key))
}
return svrquery.NewUDPClient(proto, address, options...)
case "prom":
return svrquery.NewHTTPClient(proto, address)
default:
return nil, fmt.Errorf("protocol %s not supported", proto)
}
defer c.Close()
}

r, err := c.Query()
func query(client protocol.Client) error {
r, err := client.Query()
if err != nil {
return err
}
Expand All @@ -91,11 +102,7 @@ func server(l *log.Logger, proto, address string) error {

transport, err := svrsample.GetTransport(proto, address)
if err != nil {
return err
}
err = transport.Setup()
if err != nil {
return err
return fmt.Errorf("create transport: %w", err)
}

responder, err := svrsample.GetResponder(proto, common.QueryState{
Expand All @@ -107,28 +114,16 @@ func server(l *log.Logger, proto, address string) error {
Port: 1000,
})
if err != nil {
return err
return fmt.Errorf("create responder: %w", err)
}

for {
buf := make([]byte, 16)
err = transport.Read(buf)
if err != nil {
l.Println("read", err)
continue
}

resp, err := responder.Respond(transport.Addr(), buf)
if err != nil {
l.Println("responding to query", err)
continue
}

if err = transport.Write(resp); err != nil {
l.Println("writing response")
}
// this function will block until the transport is closed
err = transport.Start(responder)
if err != nil {
return fmt.Errorf("transport error")
}

return nil
}

func bail(l *log.Logger, msg string) {
Expand Down
9 changes: 7 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,23 @@ module github.com/multiplay/go-svrquery
go 1.20

require (
github.com/prometheus/client_golang v1.15.1
github.com/prometheus/common v0.44.0
github.com/stretchr/testify v1.7.0
)

require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect
github.com/prometheus/procfs v0.9.0 // indirect
github.com/stretchr/objx v0.3.0 // indirect
golang.org/x/sys v0.8.0 // indirect
google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
20 changes: 13 additions & 7 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
Expand All @@ -6,22 +10,23 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v1.15.1 h1:8tXpTmJbyH5lydzFPoxSIJ0J46jdh3tylbvM1xCv0LI=
github.com/prometheus/client_golang v1.15.1/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk=
github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 h1:v7DLqVdK4VrYkVD5diGdl4sxJurKJEMnODWRJlxV9oM=
github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU=
github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY=
github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI=
github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.3.0 h1:NGXK3lHquSN08v5vWalVI/L8XU9hdzE/G6xsrze47As=
Expand All @@ -30,7 +35,8 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
Expand All @@ -39,5 +45,5 @@ google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
84 changes: 67 additions & 17 deletions lib/svrquery/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,16 @@ var (
DefaultNetwork = "udp"
)

// Option represents a Client option.
type Option func(*Client) error
var (
_ protocol.Client = (*UDPClient)(nil)
_ protocol.Client = (*HTTPClient)(nil)
)

// Client provides the ability to query a server.
type Client struct {
// Option represents a UDPClient option.
type Option func(*UDPClient) error

// UDPClient provides the ability to query a server.
type UDPClient struct {
protocol string
network string
addr string
Expand All @@ -34,28 +39,28 @@ type Client struct {

// WithKey sets the key used for request by for the client.
func WithKey(key string) Option {
return func(c *Client) error {
return func(c *UDPClient) error {
c.key = key
return nil
}
}

// WithTimeout sets the read and write timeout for the client.
func WithTimeout(t time.Duration) Option {
return func(c *Client) error {
return func(c *UDPClient) error {
c.timeout = t
return nil
}
}

// NewClient creates a new client that talks to addr.
func NewClient(proto, addr string, options ...Option) (*Client, error) {
// NewUDPClient creates a new client that talks to addr.
func NewUDPClient(proto, addr string, options ...Option) (*UDPClient, error) {
f, err := protocol.Get(proto)
if err != nil {
return nil, err
}

c := &Client{
c := &UDPClient{
protocol: proto,
addr: addr,
network: DefaultNetwork,
Expand All @@ -81,7 +86,7 @@ func NewClient(proto, addr string, options ...Option) (*Client, error) {
}

// Write implements io.Writer.
func (c *Client) Write(b []byte) (int, error) {
func (c *UDPClient) Write(b []byte) (int, error) {
if err := c.c.SetWriteDeadline(time.Now().Add(c.timeout)); err != nil {
return 0, err
}
Expand All @@ -90,7 +95,7 @@ func (c *Client) Write(b []byte) (int, error) {
}

// Read implements io.Reader.
func (c *Client) Read(b []byte) (int, error) {
func (c *UDPClient) Read(b []byte) (int, error) {
if err := c.c.SetReadDeadline(time.Now().Add(c.timeout)); err != nil {
return 0, err
}
Expand All @@ -107,21 +112,66 @@ func (c *Client) Read(b []byte) (int, error) {
}

// Close implements io.Closer.
func (c *Client) Close() error {
func (c *UDPClient) Close() error {
return c.c.Close()
}

// Key implements protocol.Client.
func (c *Client) Key() string {
// Key implements protocol.UDPClient.
func (c *UDPClient) Key() string {
return c.key
}

// Address implements protocol.Client.
func (c *Client) Address() string {
// Address implements protocol.UDPClient.
func (c *UDPClient) Address() string {
return c.addr
}

// Protocol returns the protocol of the client.
func (c *Client) Protocol() string {
func (c *UDPClient) Protocol() string {
return c.protocol
}

type HTTPClient struct {
protocol.Queryer
address string
}

func NewHTTPClient(proto, address string) (*HTTPClient, error) {
queryerCreator, err := protocol.Get(proto)
if err != nil {
return nil, err
}
client := &HTTPClient{address: address}
client.Queryer = queryerCreator(client)

return client, nil
}

func (c *HTTPClient) Read(p []byte) (n int, err error) {
//TODO implement me
panic("implement me")
}

func (c *HTTPClient) Write(p []byte) (n int, err error) {
//TODO implement me
panic("implement me")
}

func (c *HTTPClient) Query() (protocol.Responser, error) {
return c.Queryer.Query()
}

func (c *HTTPClient) Key() string {
//TODO implement me
panic("implement me")
}

func (c *HTTPClient) Address() string {
return c.address
}

// Close implements io.Closer.
func (c *HTTPClient) Close() error {
// no-op
return nil
}
4 changes: 2 additions & 2 deletions lib/svrquery/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func TestNewClient(t *testing.T) {

for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
c, err := NewClient(tc.protocol, tc.addr, WithKey("test"), WithTimeout(time.Second))
c, err := NewUDPClient(tc.protocol, tc.addr, WithKey("test"), WithTimeout(time.Second))
if tc.err {
require.Error(t, err)
require.Nil(t, c)
Expand All @@ -52,7 +52,7 @@ func TestQuery(t *testing.T) {
t.Skip("env TEST_QUERY_PROTO not set")
}

c, err := NewClient(proto, addr)
c, err := NewUDPClient(proto, addr)
require.NoError(t, err)
for i := 0; i < 5; i++ {
r, err := c.Query()
Expand Down
1 change: 1 addition & 0 deletions lib/svrquery/protocol/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type Mapper interface {
// Client is an interface which is implemented by types which can act a query transport.
type Client interface {
io.ReadWriteCloser
Queryer
Key() string
Address() string
}
Loading

0 comments on commit 99639f0

Please sign in to comment.