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
This commit is contained in:
@@ -21,7 +21,6 @@ import (
|
|||||||
"github.com/admin-else/strom/cmd/strom/print_replay"
|
"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_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/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_tmcpr"
|
||||||
"github.com/admin-else/strom/cmd/strom/serve_world"
|
"github.com/admin-else/strom/cmd/strom/serve_world"
|
||||||
"github.com/admin-else/strom/cmd/strom/status"
|
"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,
|
"print-replay": print_replay.Run,
|
||||||
// "raw-capture": raw_capture.Run, // removed: use tcpflow instead for raw TCP capture, then raw-to-tmcpr
|
// "raw-capture": raw_capture.Run, // removed: use tcpflow instead for raw TCP capture, then raw-to-tmcpr
|
||||||
"raw-to-tmcpr": raw_to_tmcpr.Run,
|
"raw-to-tmcpr": raw_to_tmcpr.Run,
|
||||||
"registry-data-hunter": registry_data_hunter.Run,
|
|
||||||
"serve-world": serve_world.Run,
|
"serve-world": serve_world.Run,
|
||||||
"mca-to-tmcpr": mca_to_tmcpr.Run,
|
"mca-to-tmcpr": mca_to_tmcpr.Run,
|
||||||
"serve-tmcpr": serve_tmcpr.Run,
|
"serve-tmcpr": serve_tmcpr.Run,
|
||||||
|
|||||||
@@ -212,6 +212,10 @@ func Run(args []string) (err error) {
|
|||||||
}
|
}
|
||||||
totalPackets++
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
|
||||||
}
|
|
||||||
+10
-9
@@ -23,7 +23,7 @@ type Timer struct {
|
|||||||
Interval []IntervalTask
|
Interval []IntervalTask
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Timer) Trigger(ch chan any) {
|
func (t *Timer) Trigger(ch chan any) (didWork bool) {
|
||||||
triggerAt := time.Time{}
|
triggerAt := time.Time{}
|
||||||
found := false
|
found := false
|
||||||
iOnce, iInterval := -1, -1
|
iOnce, iInterval := -1, -1
|
||||||
@@ -46,7 +46,7 @@ func (t *Timer) Trigger(ch chan any) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !found {
|
if !found {
|
||||||
return
|
return false
|
||||||
}
|
}
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
sleepFor := triggerAt.Sub(now)
|
sleepFor := triggerAt.Sub(now)
|
||||||
@@ -55,12 +55,12 @@ func (t *Timer) Trigger(ch chan any) {
|
|||||||
if iOnce >= 0 {
|
if iOnce >= 0 {
|
||||||
ch <- CallFunc{F: reflect.ValueOf(t.Once[iOnce].F), Args: []reflect.Value{}}
|
ch <- CallFunc{F: reflect.ValueOf(t.Once[iOnce].F), Args: []reflect.Value{}}
|
||||||
t.Once = slices.Delete(t.Once, iOnce, iOnce+1)
|
t.Once = slices.Delete(t.Once, iOnce, iOnce+1)
|
||||||
return
|
return true
|
||||||
}
|
}
|
||||||
if iInterval >= 0 {
|
if iInterval >= 0 {
|
||||||
t.Interval[iInterval].LastTrigger = triggerAt
|
t.Interval[iInterval].LastTrigger = triggerAt
|
||||||
ch <- CallFunc{F: reflect.ValueOf(t.Interval[iInterval].F), Args: []reflect.Value{}}
|
ch <- CallFunc{F: reflect.ValueOf(t.Interval[iInterval].F), Args: []reflect.Value{}}
|
||||||
return
|
return true
|
||||||
}
|
}
|
||||||
panic("unreachable")
|
panic("unreachable")
|
||||||
}
|
}
|
||||||
@@ -83,11 +83,12 @@ func (t *Timer) MakeEventSource(ctx context.Context) (chSending <-chan any) {
|
|||||||
ch := make(chan any)
|
ch := make(chan any)
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
select {
|
if !t.Trigger(ch) {
|
||||||
case <-ctx.Done():
|
select {
|
||||||
return
|
case <-ctx.Done():
|
||||||
default:
|
return
|
||||||
t.Trigger(ch)
|
case <-time.After(100 * time.Millisecond):
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"go/ast"
|
"go/ast"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -38,8 +39,14 @@ func GeneratePacketInfoFile(versions []string, packetInfos []PacketInfo) (err er
|
|||||||
typeExpr = Selector(vUnderscore, typeName)
|
typeExpr = Selector(vUnderscore, typeName)
|
||||||
}
|
}
|
||||||
|
|
||||||
packetId, _ := strconv.ParseInt(p.PacketId, 0, 32)
|
packetId, err := strconv.ParseInt(p.PacketId, 0, 32)
|
||||||
protocolVersion, _ := strconv.Atoi(p.ProtocolVersion)
|
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{
|
packetInfoExprs = append(packetInfoExprs, CompLit(nil, []ast.Expr{
|
||||||
KeyValueExpr(Ident("Type"), AddrOf(CompLit(typeExpr, nil))),
|
KeyValueExpr(Ident("Type"), AddrOf(CompLit(typeExpr, nil))),
|
||||||
|
|||||||
@@ -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")
|
s2, err := g.VisitEncoder(Index(varToSet, Ident(iName)), data.Type, name+"Inner")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
s2 = Stmts(ForRange(Ident(iName), Call(Ident("len"), varToSet), NewBlock(s2)))
|
s2 = Stmts(ForRange(Ident(iName), Call(Ident("len"), varToSet), NewBlock(s2)))
|
||||||
s = append(s1, s2...)
|
s = append(s1, s2...)
|
||||||
|
|||||||
+5
-3
@@ -3,6 +3,7 @@ package server
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"net"
|
"net"
|
||||||
|
"sync/atomic"
|
||||||
|
|
||||||
"github.com/admin-else/strom/mc/proto"
|
"github.com/admin-else/strom/mc/proto"
|
||||||
"github.com/admin-else/strom/mc/proto_base"
|
"github.com/admin-else/strom/mc/proto_base"
|
||||||
@@ -68,8 +69,9 @@ func StartServerWithOnConn(listenAddr string, onConn func(c *proto.Conn) (err er
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer l.Close()
|
defer l.Close()
|
||||||
running := true
|
running := atomic.Bool{}
|
||||||
for running {
|
running.Store(true)
|
||||||
|
for running.Load() {
|
||||||
var cNet net.Conn
|
var cNet net.Conn
|
||||||
cNet, err = l.Accept()
|
cNet, err = l.Accept()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -80,7 +82,7 @@ func StartServerWithOnConn(listenAddr string, onConn func(c *proto.Conn) (err er
|
|||||||
defer c.Close()
|
defer c.Close()
|
||||||
connErr := onConn(c)
|
connErr := onConn(c)
|
||||||
if errors.Is(connErr, ShutDownServerErr) {
|
if errors.Is(connErr, ShutDownServerErr) {
|
||||||
running = false
|
running.Store(false)
|
||||||
}
|
}
|
||||||
c.Log.Error("closing connection", "err", connErr)
|
c.Log.Error("closing connection", "err", connErr)
|
||||||
if connErr != nil {
|
if connErr != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user