From 4b278b7ee3d1313a35cf654f4c3d79b35d6ddca8 Mon Sep 17 00:00:00 2001 From: OpenCode Date: Wed, 5 Aug 2026 14:50:10 +0200 Subject: [PATCH] fix: multiple bugfixes - Fix data race: use atomic.Bool for running in server.go - Fix busy loop in timer.go: use time.After when idle - Fix division by zero in print_replay - Fix silently swallowed errors in proto_generator - Fix suppressed error in native_encoder - Delete unused registry_data_hunter --- cmd/strom/main.go | 2 - cmd/strom/print_replay/main.go | 6 +- cmd/strom/registry_data_hunter/main.go | 152 ------------------------- mc/event/timer.go | 19 ++-- mc/proto_generator/helper_generator.go | 11 +- mc/proto_generator/native_encoder.go | 1 + mc/server/server.go | 8 +- 7 files changed, 30 insertions(+), 169 deletions(-) delete mode 100644 cmd/strom/registry_data_hunter/main.go diff --git a/cmd/strom/main.go b/cmd/strom/main.go index 173ef88..fa040c4 100644 --- a/cmd/strom/main.go +++ b/cmd/strom/main.go @@ -21,7 +21,6 @@ import ( "github.com/admin-else/strom/cmd/strom/print_replay" // "github.com/admin-else/strom/cmd/strom/raw_capture" // removed: use tcpflow instead for raw TCP capture "github.com/admin-else/strom/cmd/strom/raw_to_tmcpr" - "github.com/admin-else/strom/cmd/strom/registry_data_hunter" "github.com/admin-else/strom/cmd/strom/serve_tmcpr" "github.com/admin-else/strom/cmd/strom/serve_world" "github.com/admin-else/strom/cmd/strom/status" @@ -64,7 +63,6 @@ var subcommands = map[string]func(args []string) error{ "print-replay": print_replay.Run, // "raw-capture": raw_capture.Run, // removed: use tcpflow instead for raw TCP capture, then raw-to-tmcpr "raw-to-tmcpr": raw_to_tmcpr.Run, - "registry-data-hunter": registry_data_hunter.Run, "serve-world": serve_world.Run, "mca-to-tmcpr": mca_to_tmcpr.Run, "serve-tmcpr": serve_tmcpr.Run, diff --git a/cmd/strom/print_replay/main.go b/cmd/strom/print_replay/main.go index 36b85c4..2ece991 100644 --- a/cmd/strom/print_replay/main.go +++ b/cmd/strom/print_replay/main.go @@ -212,6 +212,10 @@ func Run(args []string) (err error) { } totalPackets++ } - fmt.Printf("Total packets: %d, failed packets: %d, %%failed: %.2f%%\n", totalPackets, failedPackets, float64(failedPackets)/float64(totalPackets)*100) + if totalPackets > 0 { + fmt.Printf("Total packets: %d, failed packets: %d, %%failed: %.2f%%\n", totalPackets, failedPackets, float64(failedPackets)/float64(totalPackets)*100) + } else { + fmt.Printf("Total packets: %d, failed packets: %d\n", totalPackets, failedPackets) + } return } diff --git a/cmd/strom/registry_data_hunter/main.go b/cmd/strom/registry_data_hunter/main.go deleted file mode 100644 index 90d06a7..0000000 --- a/cmd/strom/registry_data_hunter/main.go +++ /dev/null @@ -1,152 +0,0 @@ -package registry_data_hunter - -import ( - "encoding/json" - "errors" - "log/slog" - "os" - - "github.com/admin-else/strom/mc/api" - "github.com/admin-else/strom/mc/client" - "github.com/admin-else/strom/mc/data" - "github.com/admin-else/strom/mc/event" - "github.com/admin-else/strom/mc/nbt" - "github.com/admin-else/strom/mc/proto" - "github.com/admin-else/strom/mc/proto_base" - "github.com/admin-else/strom/mc/proto_generated/v1_21_8" - "github.com/admin-else/strom/mc/server" - "github.com/admin-else/strom/mc/text" -) - -func wontFail[T any](v T, err error) T { - if err != nil { - panic(err) - } - return v -} - -var ( - Version = "1.21.11" - SaveAs = "data/registry/" + Version + ".nbt" - - CompatibleProtocolVersion = wontFail(data.LookUpVersionByName(Version)).Version - FinishedConfigErr = errors.New("finished configuration") -) - -var Status = wontFail(json.Marshal(server.StatusResponse{ - Version: server.StatusResponseVersion{ - Name: nil, - Protocol: CompatibleProtocolVersion, - }, - Description: text.Pretty("Registry data hunter"), -})) - -type Proxy struct { - Client, Servee *proto.Conn - Data *nbt.Tag -} - -func (p *Proxy) OnAnything(e event.Anything) (err error) { - packet, ok := e.Val.(proto_base.EncodeDecodeAble) - if !ok { - return - } - packetInfo, ok := proto.LookupPacketInfoByType(packet) - if !ok { - return - } - switch packetInfo.Direction { - case proto_base.ToServer: - err = p.Client.Send(packet) - case proto_base.ToClient: - err = p.Servee.Send(packet) - } - return -} - -func (p *Proxy) OnFinishConfiguration(_ *v1_21_8.ConfigurationToClientPacketFinishConfiguration) (err error) { - err = FinishedConfigErr - return -} - -func (p *Proxy) OnSelectKnownPacks(data *v1_21_8.ConfigurationToClientPacketCommonSelectKnownPacks) (err error) { - var entries []any - for _, entry := range data.Packs { - e := map[string]any{"Namespace": entry.Namespace, "Id": entry.Id, "Version": entry.Version} - entries = append(entries, e) - } - p.Data.Value.(map[string]any)["KnownPacks"] = entries - return -} - -func (p *Proxy) OnData(data *v1_21_8.ConfigurationToClientPacketRegistryData) (err error) { - d := p.Data.Value.(map[string]any)["Registries"].([]any) - var entries []any - for _, entry := range data.Entries { - if entry.Value != nil { - entries = append(entries, map[string]any{"TagType": entry.Key, "Value": entry.Value.Value}) - } else { - entries = append(entries, map[string]any{"TagType": entry.Key}) - } - } - d = append(d, map[string]any{"Id": data.Id, "Entries": entries}) - p.Data.Value.(map[string]any)["Registries"] = d - return -} - -func (p *Proxy) OnTags(data *v1_21_8.ConfigurationToClientPacketTags) (err error) { - var tags []any - for _, tag := range data.Tags { - var entries []any - for _, entry := range tag.Tags.Val { - entries = append(entries, map[string]any{"TagName": entry.TagName, "Entries": entry.Entries}) - } - tags = append(tags, map[string]any{"TagType": tag.TagType, "Entries": entries}) - } - p.Data.Value.(map[string]any)["Tags"] = tags - return -} - -func handleClient(c *proto.Conn) (err error) { - acc := api.NewOfflineAccount("RegistryHunter") - - _, err = server.ServeLogin(c, server.WithOtherAccount(acc), server.WithCompatibleVersions(CompatibleProtocolVersion), server.WithRawStatus(Status)) - if err != nil { - return - } - sockPuppet, err := client.Login(":25565", acc) - if err != nil { - return - } - defer sockPuppet.Close() - errChan := make(chan error) - p := &Proxy{Client: sockPuppet, Servee: c} - p.Data.Value = map[string]any{"Registries": []any{}} - p.Client.RegisterCritical(p.OnAnything) - p.Servee.RegisterCritical(p.OnAnything) - p.Client.RegisterCriticalUntilLatest(p.OnData) - p.Client.RegisterCriticalUntilLatest(p.OnTags) - p.Client.RegisterCriticalUntilLatest(p.OnSelectKnownPacks) - p.Client.RegisterCriticalUntilLatest(p.OnFinishConfiguration) - - go func() { - errChan <- p.Client.StartConn() - }() - go func() { - errChan <- p.Servee.StartConn() - }() - err = <-errChan - f, err := os.Create(SaveAs) - if err != nil { - return - } - defer f.Close() - err = nbt.WriteUnstructuredFile(f, p.Data) - slog.Info("saved", "file", SaveAs) - return -} - -func Run(args []string) error { - slog.SetLogLoggerLevel(slog.LevelDebug) - return server.StartServerWithOnConn(":25566", handleClient) -} diff --git a/mc/event/timer.go b/mc/event/timer.go index 427eefa..e76b0bf 100644 --- a/mc/event/timer.go +++ b/mc/event/timer.go @@ -23,7 +23,7 @@ type Timer struct { Interval []IntervalTask } -func (t *Timer) Trigger(ch chan any) { +func (t *Timer) Trigger(ch chan any) (didWork bool) { triggerAt := time.Time{} found := false iOnce, iInterval := -1, -1 @@ -46,7 +46,7 @@ func (t *Timer) Trigger(ch chan any) { } if !found { - return + return false } now := time.Now() sleepFor := triggerAt.Sub(now) @@ -55,12 +55,12 @@ func (t *Timer) Trigger(ch chan any) { if iOnce >= 0 { ch <- CallFunc{F: reflect.ValueOf(t.Once[iOnce].F), Args: []reflect.Value{}} t.Once = slices.Delete(t.Once, iOnce, iOnce+1) - return + return true } if iInterval >= 0 { t.Interval[iInterval].LastTrigger = triggerAt ch <- CallFunc{F: reflect.ValueOf(t.Interval[iInterval].F), Args: []reflect.Value{}} - return + return true } panic("unreachable") } @@ -83,11 +83,12 @@ func (t *Timer) MakeEventSource(ctx context.Context) (chSending <-chan any) { ch := make(chan any) go func() { for { - select { - case <-ctx.Done(): - return - default: - t.Trigger(ch) + if !t.Trigger(ch) { + select { + case <-ctx.Done(): + return + case <-time.After(100 * time.Millisecond): + } } } }() diff --git a/mc/proto_generator/helper_generator.go b/mc/proto_generator/helper_generator.go index ee8a8e0..0b68494 100644 --- a/mc/proto_generator/helper_generator.go +++ b/mc/proto_generator/helper_generator.go @@ -1,6 +1,7 @@ package main import ( + "fmt" "go/ast" "os" "strconv" @@ -38,8 +39,14 @@ func GeneratePacketInfoFile(versions []string, packetInfos []PacketInfo) (err er typeExpr = Selector(vUnderscore, typeName) } - packetId, _ := strconv.ParseInt(p.PacketId, 0, 32) - protocolVersion, _ := strconv.Atoi(p.ProtocolVersion) + packetId, err := strconv.ParseInt(p.PacketId, 0, 32) + if err != nil { + panic(fmt.Errorf("failed to parse packet ID %q: %w", p.PacketId, err)) + } + protocolVersion, err := strconv.Atoi(p.ProtocolVersion) + if err != nil { + panic(fmt.Errorf("failed to parse protocol version %q: %w", p.ProtocolVersion, err)) + } packetInfoExprs = append(packetInfoExprs, CompLit(nil, []ast.Expr{ KeyValueExpr(Ident("Type"), AddrOf(CompLit(typeExpr, nil))), diff --git a/mc/proto_generator/native_encoder.go b/mc/proto_generator/native_encoder.go index a298dab..f73e122 100644 --- a/mc/proto_generator/native_encoder.go +++ b/mc/proto_generator/native_encoder.go @@ -87,6 +87,7 @@ func ArrayEncoder(g *Generator, varToSet ast.Expr, dataRaw any, name string) (s } s2, err := g.VisitEncoder(Index(varToSet, Ident(iName)), data.Type, name+"Inner") if err != nil { + return } s2 = Stmts(ForRange(Ident(iName), Call(Ident("len"), varToSet), NewBlock(s2))) s = append(s1, s2...) diff --git a/mc/server/server.go b/mc/server/server.go index 6998b70..762b3dd 100644 --- a/mc/server/server.go +++ b/mc/server/server.go @@ -3,6 +3,7 @@ package server import ( "errors" "net" + "sync/atomic" "github.com/admin-else/strom/mc/proto" "github.com/admin-else/strom/mc/proto_base" @@ -68,8 +69,9 @@ func StartServerWithOnConn(listenAddr string, onConn func(c *proto.Conn) (err er return } defer l.Close() - running := true - for running { + running := atomic.Bool{} + running.Store(true) + for running.Load() { var cNet net.Conn cNet, err = l.Accept() if err != nil { @@ -80,7 +82,7 @@ func StartServerWithOnConn(listenAddr string, onConn func(c *proto.Conn) (err er defer c.Close() connErr := onConn(c) if errors.Is(connErr, ShutDownServerErr) { - running = false + running.Store(false) } c.Log.Error("closing connection", "err", connErr) if connErr != nil {