Improve source query diagnostics

This commit is contained in:
2026-04-05 13:51:50 +03:00
parent cdf375ba80
commit 4c5dd0c5f4
3 changed files with 52 additions and 2 deletions

View File

@@ -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