Improve source query diagnostics
This commit is contained in:
@@ -2,6 +2,8 @@ package source
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -14,6 +16,7 @@ import (
|
||||
|
||||
type Options struct {
|
||||
Timeout time.Duration
|
||||
Debug bool
|
||||
}
|
||||
|
||||
type Client struct {
|
||||
@@ -27,6 +30,13 @@ func New(opt Options) *Client {
|
||||
return &Client{opt: opt}
|
||||
}
|
||||
|
||||
func (c *Client) Timeout() time.Duration {
|
||||
if c == nil {
|
||||
return 0
|
||||
}
|
||||
return c.opt.Timeout
|
||||
}
|
||||
|
||||
func (c *Client) Connect(address string, port int) (*info.ServerInfo, error) {
|
||||
return c.query(address, port, false)
|
||||
}
|
||||
@@ -93,14 +103,14 @@ func (c *Client) query(address string, port int, full bool) (*info.ServerInfo, e
|
||||
addr := normalizeAddress(address, port)
|
||||
client, err := a2s.NewClient(addr, a2s.TimeoutOption(c.opt.Timeout))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, wrapQueryError(addr, "connect", err, c.opt.Debug)
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
start := time.Now()
|
||||
infoResp, err := client.QueryInfo()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, wrapQueryError(addr, "info", err, c.opt.Debug)
|
||||
}
|
||||
|
||||
out := &info.ServerInfo{
|
||||
@@ -133,10 +143,14 @@ func (c *Client) query(address string, port int, full bool) (*info.ServerInfo, e
|
||||
}
|
||||
}
|
||||
out.Players = names
|
||||
} else if err != nil && c.opt.Debug {
|
||||
return nil, wrapQueryError(addr, "players", err, true)
|
||||
}
|
||||
rulesResp, err := client.QueryRules()
|
||||
if err == nil && rulesResp != nil {
|
||||
out.RawQuery = rulesResp.Rules
|
||||
} else if err != nil && c.opt.Debug {
|
||||
return nil, wrapQueryError(addr, "rules", err, true)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,6 +159,25 @@ func (c *Client) query(address string, port int, full bool) (*info.ServerInfo, e
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func wrapQueryError(addr, stage string, err error, debug bool) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
var netErr net.Error
|
||||
if errors.As(err, &netErr) && netErr.Timeout() {
|
||||
msg := fmt.Sprintf("no A2S response from %s", addr)
|
||||
if debug && strings.TrimSpace(stage) != "" {
|
||||
msg += fmt.Sprintf(" during %s", stage)
|
||||
}
|
||||
msg += " (server may have query disabled, blocked, or be using a different query port)"
|
||||
return errors.New(msg)
|
||||
}
|
||||
if debug && strings.TrimSpace(stage) != "" {
|
||||
return fmt.Errorf("source query %s failed for %s: %w", stage, addr, err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func normalizeAddress(host string, port int) string {
|
||||
if port == 0 {
|
||||
port = a2s.DefaultPort
|
||||
|
||||
Reference in New Issue
Block a user