package main import ( "crypto/sha256" "fmt" "log/slog" "os" "github.com/admin-else/strom/api" "github.com/admin-else/strom/client" "github.com/admin-else/strom/event" "github.com/admin-else/strom/proto" "github.com/admin-else/strom/proto_base" "github.com/admin-else/strom/proto_generated/v1_21_8" "github.com/admin-else/strom/server" "github.com/admin-else/strom/text" ) type ProxyClient struct { *proto.Conn Server *Proxy } func (p *ProxyClient) OnDefault(event event.Unhandled) (err error) { packet, isPacket := event.Val.(proto_base.EncodeDecodeAble) if !isPacket { return } err = p.Server.Send(packet) return } func (p *ProxyClient) OnCycle(_ event.Tick) (err error) { return } func (p *ProxyClient) OnStart() (err error) { return } func (p *ProxyClient) OnUnCodeAble(packet *proto.UnCodablePacket) (err error) { err = p.OnDefault(event.Unhandled{Val: packet}) if err != nil { return } SaveUnCodeAbleAsTest(proto_base.ToServer, packet) return } type Proxy struct { *proto.Conn Client *ProxyClient } func (p *Proxy) OnDefault(event event.Unhandled) (err error) { packet, isPacket := event.Val.(proto_base.EncodeDecodeAble) if !isPacket { return } err = p.Client.Send(packet) return } func (p *Proxy) OnCycle(_ event.Tick) (err error) { return } func (p *Proxy) OnStart() (err error) { return } func (p *Proxy) OnFinishConfiguration(packet *v1_21_8.ConfigurationToServerPacketFinishConfiguration) (err error) { err = p.OnDefault(event.Unhandled{Val: packet}) if err != nil { return } p.SetState(proto_base.Play) p.Client.SetState(proto_base.Play) return } func (p *Proxy) OnUnCodeAble(packet *proto.UnCodablePacket) (err error) { err = p.OnDefault(event.Unhandled{Val: packet}) if err != nil { return } SaveUnCodeAbleAsTest(proto_base.ToClient, packet) return } const TestSrcF = `package failed_packets_test import ( "bytes" "testing" "github.com/admin-else/strom/proto_generated/v1_21_8" ) // Error: %v func TestFailedPacket%10X(t *testing.T) { p := v1_21_8.Play%vPacket{} b := bytes.NewBuffer(%#v) err := p.Decode(b) if err != nil { t.Fatal(err) } } ` func SaveUnCodeAbleAsTest(d proto_base.Direction, packet *proto.UnCodablePacket) { hUntrimmed := sha256.Sum256(packet.Data) h := hUntrimmed[:8] f, err := os.Create(fmt.Sprintf(".failed_packets/%v_%10x_test.go", len(packet.Data), h)) if err != nil { panic(err) } //goland:noinspection GoUnhandledErrorResult defer f.Close() _, err = fmt.Fprintf(f, TestSrcF, packet.Err, h, d.Opposite(), packet.Data) if err != nil { panic(err) } slog.Info("Packet failed to parse", "error", packet.Err, "saved", f.Name(), "data", fmt.Sprintf("%q", packet.Data)) } var StatusResponse = server.StatusResponse{ Version: server.StatusResponseVersion{ Name: text.Pretty("STROM"), Protocol: 772, }, Players: server.StatusResponsePlayers{}, Description: text.Pretty("Hunt the uncodeable packets"), Favicon: "", EnforcesSecureChat: false, } func main() { slog.SetLogLoggerLevel(slog.LevelDebug) err := server.StartServerWithOnConn(":25565", func(serveeConn *proto.Conn) (err error) { p := &Proxy{Conn: serveeConn, Client: nil} acc := api.NewOfflineAccount("sigma") _, err = server.ServeLogin(serveeConn, server.WithOtherAccount(acc), server.WithStatus(StatusResponse)) if err != nil { return } c, err := client.ConnectAndLogin("127.0.0.1:25566", acc) if err != nil { return } pc := &ProxyClient{Conn: c, Server: p} p.Client = pc errChan := make(chan error) defer pc.Close() go func() { errChan <- pc.Start(pc) }() go func() { errChan <- p.Start(p) }() err = <-errChan return }) if err != nil { panic(err) } }