128 lines
3 KiB
Go
128 lines
3 KiB
Go
|
|
package main
|
||
|
|
|
||
|
|
import (
|
||
|
|
"bytes"
|
||
|
|
"context"
|
||
|
|
"errors"
|
||
|
|
"net"
|
||
|
|
"testing"
|
||
|
|
"time"
|
||
|
|
|
||
|
|
"github.com/gorcon/rcon"
|
||
|
|
)
|
||
|
|
|
||
|
|
func TestMultipart(t *testing.T) {
|
||
|
|
listener, err := net.Listen("tcp", "127.0.0.1:0")
|
||
|
|
if err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
defer listener.Close()
|
||
|
|
done := make(chan error, 1)
|
||
|
|
go func() {
|
||
|
|
conn, err := listener.Accept()
|
||
|
|
if err != nil {
|
||
|
|
done <- err
|
||
|
|
return
|
||
|
|
}
|
||
|
|
defer conn.Close()
|
||
|
|
var packet rcon.Packet
|
||
|
|
if _, err := packet.ReadFrom(conn); err != nil {
|
||
|
|
done <- err
|
||
|
|
return
|
||
|
|
}
|
||
|
|
if _, err := rcon.NewPacket(2, packet.ID, "").WriteTo(conn); err != nil {
|
||
|
|
done <- err
|
||
|
|
return
|
||
|
|
}
|
||
|
|
if _, err := packet.ReadFrom(conn); err != nil {
|
||
|
|
done <- err
|
||
|
|
return
|
||
|
|
}
|
||
|
|
commandID := packet.ID
|
||
|
|
if _, err := rcon.NewPacket(0, commandID, "first packet\n").WriteTo(conn); err != nil {
|
||
|
|
done <- err
|
||
|
|
return
|
||
|
|
}
|
||
|
|
if _, err := packet.ReadFrom(conn); err != nil {
|
||
|
|
done <- err
|
||
|
|
return
|
||
|
|
}
|
||
|
|
markerID := packet.ID
|
||
|
|
for _, response := range []*rcon.Packet{
|
||
|
|
rcon.NewPacket(0, commandID, "second packet"),
|
||
|
|
rcon.NewPacket(0, markerID, "Unknown request 0"),
|
||
|
|
} {
|
||
|
|
if _, err := response.WriteTo(conn); err != nil {
|
||
|
|
done <- err
|
||
|
|
return
|
||
|
|
}
|
||
|
|
}
|
||
|
|
done <- nil
|
||
|
|
}()
|
||
|
|
output, err := execute(context.Background(), listener.Addr().String(), "synthetic", "help")
|
||
|
|
if err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
if output != "first packet\nsecond packet" {
|
||
|
|
t.Fatalf("output=%q", output)
|
||
|
|
}
|
||
|
|
if err := <-done; err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestSplitAuth(t *testing.T) {
|
||
|
|
client, server := net.Pipe()
|
||
|
|
defer client.Close()
|
||
|
|
defer server.Close()
|
||
|
|
_ = client.SetDeadline(time.Now().Add(time.Second))
|
||
|
|
done := make(chan error, 1)
|
||
|
|
go func() {
|
||
|
|
defer server.Close()
|
||
|
|
var request rcon.Packet
|
||
|
|
if _, err := request.ReadFrom(server); err != nil {
|
||
|
|
done <- err
|
||
|
|
return
|
||
|
|
}
|
||
|
|
var reply bytes.Buffer
|
||
|
|
_, _ = rcon.NewPacket(rcon.SERVERDATA_AUTH_RESPONSE, request.ID, "").WriteTo(&reply)
|
||
|
|
packet := reply.Bytes()
|
||
|
|
for _, part := range [][]byte{packet[:len(packet)-1], packet[len(packet)-1:]} {
|
||
|
|
if _, err := server.Write(part); err != nil {
|
||
|
|
done <- err
|
||
|
|
return
|
||
|
|
}
|
||
|
|
}
|
||
|
|
_, err := rcon.NewPacket(rcon.SERVERDATA_RESPONSE_VALUE, cmdID, "ok").WriteTo(server)
|
||
|
|
done <- err
|
||
|
|
}()
|
||
|
|
if err := authenticate(client, "synthetic-password"); err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
var response rcon.Packet
|
||
|
|
if _, err := response.ReadFrom(client); err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
if response.ID != cmdID || response.Body() != "ok" {
|
||
|
|
t.Fatalf("id=%d body=%q", response.ID, response.Body())
|
||
|
|
}
|
||
|
|
if err := <-done; err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestAuthFailure(t *testing.T) {
|
||
|
|
client, server := net.Pipe()
|
||
|
|
defer client.Close()
|
||
|
|
defer server.Close()
|
||
|
|
_ = client.SetDeadline(time.Now().Add(time.Second))
|
||
|
|
go func() {
|
||
|
|
defer server.Close()
|
||
|
|
var request rcon.Packet
|
||
|
|
_, _ = request.ReadFrom(server)
|
||
|
|
_, _ = rcon.NewPacket(rcon.SERVERDATA_AUTH_RESPONSE, -1, "").WriteTo(server)
|
||
|
|
}()
|
||
|
|
if err := authenticate(client, "wrong-password"); !errors.Is(err, rcon.ErrAuthFailed) {
|
||
|
|
t.Fatalf("error=%v", err)
|
||
|
|
}
|
||
|
|
}
|