Fix live status on CS2: accept RCON output tagged with the end packet's id
CS2 tags a command's output with the id of the empty end packet when both arrive together, and replies to the end packet with a bare \x00\x01. The client dropped the output as stale, so the panel reported WebPanelBridge as missing. Also log each new kind of poll failure once, and recovery.
This commit is contained in:
parent
4f38daf0e6
commit
10694c69bc
3 changed files with 63 additions and 15 deletions
|
|
@ -2,8 +2,12 @@
|
|||
//
|
||||
// One connection is kept open and shared; commands are serialised with a mutex. A response can
|
||||
// span several packets, so every command is followed by an empty SERVERDATA_RESPONSE_VALUE packet:
|
||||
// the server answers packets in order, so seeing that packet's echo means the command's output is
|
||||
// complete. If the server never echoes it, reading stops after a short idle timeout instead.
|
||||
// the server answers packets in order, so its reply to that packet means the command's output is
|
||||
// complete. If the server never replies to it, reading stops after a short idle timeout instead.
|
||||
//
|
||||
// CS2 differs from older Source servers in two ways this handles: when both packets arrive
|
||||
// together it tags the command's output with the end packet's id, and it answers the end packet
|
||||
// with a single "\x00\x01" body rather than an empty packet followed by that one.
|
||||
package rcon
|
||||
|
||||
import (
|
||||
|
|
@ -25,6 +29,10 @@ const (
|
|||
typeAuth = 3
|
||||
|
||||
maxPacket = 4096 + 14
|
||||
|
||||
// The body a server sends in reply to an empty SERVERDATA_RESPONSE_VALUE packet (0x00 0x01
|
||||
// 0x00 0x00, less the trailing nulls read() trims).
|
||||
endMarker = "\x00\x01"
|
||||
)
|
||||
|
||||
// ErrAuth means the server rejected the RCON password.
|
||||
|
|
@ -112,15 +120,20 @@ func (c *Client) exec(cmd string) (string, error) {
|
|||
}
|
||||
return "", err
|
||||
}
|
||||
switch pid {
|
||||
case id:
|
||||
out.WriteString(body)
|
||||
got = true
|
||||
case endID:
|
||||
// Some servers answer the empty packet with a second, odd-looking packet. Drain it.
|
||||
if pid != id && pid != endID {
|
||||
continue // left over from an earlier command
|
||||
}
|
||||
switch {
|
||||
case pid == endID && body == endMarker:
|
||||
return out.String(), nil
|
||||
case pid == endID && body == "":
|
||||
// Older servers echo the empty packet, then send endMarker. Drain it.
|
||||
_ = c.conn.SetReadDeadline(time.Now().Add(50 * time.Millisecond))
|
||||
_, _, _, _ = c.read()
|
||||
return out.String(), nil
|
||||
default:
|
||||
out.WriteString(body)
|
||||
got = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue