Files
mc-god/internal/pkg/rcon/mockrcon.go

110 lines
2.2 KiB
Go
Raw Normal View History

2026-02-13 14:14:08 -08:00
package rcon
import (
"fmt"
"net"
"sync"
"github.com/gorcon/rcon"
)
// MockRCONServer simulates an RCON server for testing purposes
type MockRCONServer struct {
listener net.Listener
Commands []string
Errors []error
Messages []string
}
// Start starts the mock RCON server on a random available port
func (m *MockRCONServer) Start() (func() *RCONResults, error) {
listener, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
return nil, fmt.Errorf("failed to start mock server: %w", err)
}
m.listener = listener
results := &RCONResults{}
done := sync.WaitGroup{}
done.Go(func() {
for {
conn, err := listener.Accept()
if err != nil {
return
}
go m.handleConnection(conn, results)
}
})
return func() *RCONResults {
m.stop()
done.Wait()
return results
}, nil
}
// Stop stops the mock RCON server
func (m *MockRCONServer) stop() error {
if m.listener != nil {
return m.listener.Close()
}
return nil
}
// Address returns the address the mock server is listening on
func (m *MockRCONServer) Address() string {
if m.listener != nil {
return m.listener.Addr().String()
}
return ""
}
// handleConnection handles individual client connections
func (m *MockRCONServer) handleConnection(conn net.Conn, results *RCONResults) {
defer conn.Close()
for {
packet := &rcon.Packet{}
if _, err := packet.ReadFrom(conn); err != nil {
results.AppendError(err)
return
}
results.AppendMessage(packet.Body())
var respPacket *rcon.Packet
switch packet.Type {
case rcon.SERVERDATA_AUTH:
respPacket = rcon.NewPacket(rcon.SERVERDATA_AUTH_RESPONSE, packet.ID, "")
case rcon.SERVERDATA_EXECCOMMAND:
respPacket = rcon.NewPacket(rcon.SERVERDATA_RESPONSE_VALUE, packet.ID, "")
default:
results.AppendError(fmt.Errorf("unknown packet: %v", packet.Type))
return
}
if _, err := respPacket.WriteTo(conn); err != nil {
results.AppendError(err)
return
}
}
}
type RCONResults struct {
mu sync.Mutex
Messages []string
Errors []error
}
func (r *RCONResults) AppendError(err error) {
r.mu.Lock()
defer r.mu.Unlock()
r.Errors = append(r.Errors, err)
}
func (r *RCONResults) AppendMessage(msg string) {
r.mu.Lock()
defer r.mu.Unlock()
r.Messages = append(r.Messages, msg)
}