110 lines
2.2 KiB
Go
110 lines
2.2 KiB
Go
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)
|
|
}
|