Skip to content

GoFurry/a2s-go

Repository files navigation

a2s-go

中文文档

License Release Go Version Go Report Card

a2s-go is a focused Go SDK for Steam/Source A2S UDP queries.

It is intentionally split into three layers:

  • a2s: query a known game server with A2S_INFO, A2S_PLAYER, and A2S_RULES
  • master: discover server addresses from Valve master server pagination
  • scanner: turn address lists or discovery streams into batched probe results

Install

go get github.com/GoFurry/a2s-go@latest

Quick Start

Query One Server

package main

import (
	"context"
	"log"
	"time"

	"github.com/GoFurry/a2s-go"
)

func main() {
	client, err := a2s.NewClient(
		"1.2.3.4:27015",
		a2s.WithTimeout(3*time.Second),
	)
	if err != nil {
		log.Fatal(err)
	}
	defer client.Close()

	info, err := client.QueryInfo(context.Background())
	if err != nil {
		log.Fatal(err)
	}

	log.Printf("name=%s map=%s players=%d/%d", info.Name, info.Map, info.Players, info.MaxPlayers)
}

Discover Servers From Master

package main

import (
	"context"
	"log"
	"time"

	"github.com/GoFurry/a2s-go/master"
)

func main() {
	client, err := master.NewClient(
		master.WithTimeout(5*time.Second),
	)
	if err != nil {
		log.Fatal(err)
	}
	defer client.Close()

	req := master.Request{
		Region: master.RegionAsia,
		Filter: "\\secure\\1",
	}

	page, err := client.Query(context.Background(), req)
	if err != nil {
		log.Fatal(err)
	}

	log.Printf("servers=%d done=%v next=%s", len(page.Servers), page.Done, page.NextCursor.String())
}

Query fetches one page. Stream keeps turning pages until discovery is done.

Batch Probe Servers

package main

import (
	"context"
	"log"

	"github.com/GoFurry/a2s-go/scanner"
)

func main() {
	client, err := scanner.NewClient(
		scanner.WithConcurrency(32),
	)
	if err != nil {
		log.Fatal(err)
	}

	servers, err := scanner.ParseAddresses([]string{
		"127.0.0.1:27015",
		"127.0.0.2", // defaults to 27015
	})
	if err != nil {
		log.Fatal(err)
	}

	results, err := client.CollectInfo(context.Background(), scanner.Request{
		Servers: servers,
	})
	if err != nil {
		log.Fatal(err)
	}

	for _, result := range results {
		if result.Err != nil {
			log.Printf("probe error: %v", result.Err)
			continue
		}
		log.Printf("%s -> %s", result.Server.String(), result.Info.Name)
	}
}

The scanner also supports:

  • direct []string address input via scanner.Request{Addresses: ...}
  • explicit address normalization via scanner.ParseAddress(...) / scanner.ParseAddresses(...)
  • ProbePlayers / CollectPlayers
  • ProbeRules / CollectRules
  • master.Stream style discovery input

Scanner input rules:

  • exactly one of Addresses, Servers, or Discovery must be non-nil
  • Addresses accepts host:port or host and defaults missing ports to 27015
  • empty Addresses / Servers lists are valid and produce zero probe results
  • scanner currently supports IPv4 targets only

Examples

  • go run ./examples/basic
  • go run ./examples/live-regression -servers=1.2.3.4:27015,5.6.7.8
  • go run ./examples/master
  • go run ./examples/master/fake-master
  • go run ./examples/scanner

Manual Regression

For release-time live validation, use the manual regression example:

go run ./examples/live-regression -servers=1.2.3.4:27015,5.6.7.8 -mode=all -scanner=true

It runs single-server probes first, then verifies the same targets through scanner. See release-checklist.md for the recommended release gate.

References

Protocol behavior follows Valve documentation first:

About

A lightweight and extensible Go client for A2S server queries.

Topics

Resources

License

Stars

Watchers

Forks

Contributors

Languages