feat: Add WebSocket RCON client to companion agent
All checks were successful
Test Asgard Runner / test (push) Successful in 3s

Wire gorilla/websocket into the Go companion agent to send arbitrary
console commands (e.g. oxide.reload BetterLoot) to the Rust Dedicated
Server's WebRCON endpoint. Adds RCON_PORT and RCON_PASSWORD env vars,
a new "command" action on the existing cmd.server NATS subject, and
the internal/rcon package that handles the JSON-over-WebSocket protocol.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Vantz Stockwell
2026-02-22 00:16:47 -05:00
parent f67b175d39
commit eb57c51a24
5 changed files with 113 additions and 1 deletions

View File

@@ -13,6 +13,7 @@ import (
"github.com/vigilcyber/corrosion-companion/internal/filemanager"
"github.com/vigilcyber/corrosion-companion/internal/files"
"github.com/vigilcyber/corrosion-companion/internal/process"
"github.com/vigilcyber/corrosion-companion/internal/rcon"
"github.com/vigilcyber/corrosion-companion/internal/update"
)
@@ -25,6 +26,8 @@ type DaemonConfig struct {
GameServerArgs string
Version string
InstallDir string
RconPort int
RconPassword string
}
// Daemon manages the companion agent's main operations
@@ -155,7 +158,8 @@ func (d *Daemon) subscribeServerCommands() error {
sub, err := d.nc.Subscribe(subject, func(msg *nats.Msg) {
var cmd struct {
Action string `json:"action"`
Action string `json:"action"`
Command string `json:"command"`
}
if err := json.Unmarshal(msg.Data, &cmd); err != nil {
@@ -174,6 +178,24 @@ func (d *Daemon) subscribeServerCommands() error {
err = d.gameServer.Stop()
case "restart":
err = d.gameServer.Restart()
case "command":
if cmd.Command == "" {
d.respondError(msg, "invalid_command", "command field is required")
return
}
result, rconErr := rcon.SendCommand(d.cfg.RconPort, d.cfg.RconPassword, cmd.Command)
if rconErr != nil {
log.Printf("RCON command failed: %v", rconErr)
d.respondError(msg, "rcon_failed", rconErr.Error())
} else {
d.respondSuccess(msg, map[string]interface{}{
"action": "command",
"command": cmd.Command,
"response": result,
"status": "success",
})
}
return
default:
err = fmt.Errorf("unknown action: %s", cmd.Action)
}