Documentation
¶
Overview ¶
Package rcon is a Source RCON client.
It exists because the readily available Go clients read exactly one packet per command, and a response larger than about 4KB is split across several. That truncation is silent: a long response comes back looking like a short one, with no error to say otherwise. This client reassembles multi-packet responses and, when one is cut short anyway, says so explicitly while still handing back what did arrive.
The design assumes the far end is a game server running RCON on its game thread, so commands are bounded: one deadline covers a whole exchange, and callers past a configured concurrency limit fail fast rather than queue.
client := rcon.New("127.0.0.1:27015", password)
output, err := client.Execute(ctx, "status")
Index ¶
Constants ¶
const ( // DefaultTimeout bounds a whole exchange: connect, authenticate, send, receive. DefaultTimeout = 10 * time.Second // DefaultMaxConcurrent is deliberately small. Source servers handle RCON on // their main thread and cap or ban clients that pile on connections, so this // is headroom for a few callers at once, not a throughput setting. DefaultMaxConcurrent = 4 )
Defaults applied by New when the corresponding option is not given.
const MaxCommandLen = 1000
MaxCommandLen is the longest command a Source server will accept. Anything longer is rejected before dialling, so an over-long command reports itself as such instead of as whatever the connection happened to do.
Variables ¶
var ErrAuthFailed = errors.New("rcon: authentication failed, check the password")
ErrAuthFailed reports that the server rejected the password. Retrying cannot fix it, so callers should surface it rather than treat it as a transient.
var ErrBusy = errors.New("rcon: too many commands already in flight")
ErrBusy reports that every concurrent-command slot was taken. It is backpressure rather than a failure of the RCON server, and worth distinguishing: an ErrBusy is worth retrying in a moment, where most other errors mean something is actually wrong.
var ErrCommandTooLong = fmt.Errorf("rcon: command must be at most %d bytes", MaxCommandLen)
ErrCommandTooLong reports a command over MaxCommandLen bytes. It is returned before any connection is opened.
var ErrNotRCON = errors.New("rcon: the address is not an RCON server")
ErrNotRCON reports that something is listening and answering, but not with RCON. It is almost always a wrong port, and it is kept separate from ErrAuthFailed because the two send an operator to entirely different places.
var ErrProtocol = errors.New("rcon: malformed response")
ErrProtocol reports a response that is not valid Source RCON. It means the endpoint is not what we think it is, or the exchange has desynchronised; either way retrying the same way will not help.
var ErrTruncated = errors.New("rcon: response truncated before the end-of-response marker")
ErrTruncated reports that a response was cut short: the sentinel packet never arrived before the deadline, the response outgrew maxResponseBytes, or the game's own pagination could not be followed to the end because a page expired, stopped matching, or there were too many of them.
It is returned alongside the bytes that did arrive, because a partial response is still worth having. What must not happen is a truncated response being read as a complete one, so callers that can cross-check the result, against a count the server itself reported, for instance, should do so.
Functions ¶
This section is empty.
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client executes commands against a Source RCON server.
A fresh connection is opened per command. RCON connections do not survive a server restart and there is no state worth keeping warm, so reconnecting each time removes a whole class of stale-socket failures for the cost of one TCP handshake and auth round trip.
A Client is safe for concurrent use.
func (*Client) Execute ¶
Execute runs command on the RCON server and returns its response.
The entire exchange, connect, authenticate, send, receive, shares a single deadline, the smaller of ctx and the configured timeout. The socket deadline derived from that is the primary bound; the select below is what stops the caller waiting past it. The connection watches ctx itself from the moment it is dialled (see dialAndAuth) and closes on ctx.Done, so a goroutine abandoned here, whether to the deadline or to an early cancellation, has its blocked read fail immediately and releases its slot and socket promptly, rather than holding both against the game server for up to another full timeout after the caller already gave up.
A response cut short still returns the part that arrived, paired with ErrTruncated. Every other error returns an empty body.
type Option ¶
type Option func(*Client)
Option configures a Client.
func WithMaxConcurrent ¶
WithMaxConcurrent sets how many exchanges may be in flight at once. Callers past the limit get ErrBusy rather than being queued: waiting would spend the caller's deadline on the queue and then hand it a truncated budget for the exchange itself.
Values below 1 are raised to 1, because a zero-capacity limit would report ErrBusy for every command rather than meaning "unlimited".
func WithTimeout ¶
WithTimeout sets the deadline covering one complete exchange.
Values of zero or less are ignored, leaving DefaultTimeout in place: a client with no deadline at all hangs forever against a server that accepts a connection and then says nothing, which is a common way for a game server to fail.
type TimeoutError ¶
TimeoutError reports that an exchange did not finish within the deadline. Callers use errors.As to tell a slow or dead server apart from a server that answered with a failure:
var timeout *rcon.TimeoutError
if errors.As(err, &timeout) { ... }
It deliberately does not implement net.Error's Timeout() bool: that method name would collide with the Timeout field, and the field is the more useful of the two since it tells a caller what budget was actually exceeded.
func (*TimeoutError) Error ¶
func (e *TimeoutError) Error() string
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
rcon
command
Command rcon runs commands on a Source RCON server.
|
Command rcon runs commands on a Source RCON server. |
|
internal
|
|
|
cli
Package cli implements the rcon command-line tool.
|
Package cli implements the rcon command-line tool. |
|
config
Package config is the rcon command's configuration.
|
Package config is the rcon command's configuration. |
|
Package rcontest provides a scriptable Source RCON server for tests.
|
Package rcontest provides a scriptable Source RCON server for tests. |