6 Commits
Author SHA1 Message Date
adman 8f771166a6 better unknown command text 2026-03-27 13:16:16 +01:00
adman 5d6a1a25ea fix packet spy 2026-03-27 13:09:07 +01:00
adman ca33185f20 fix LookupPacketInfoByType for undecoable 2026-03-27 12:59:10 +01:00
adman e921e9e9d2 fix routine thing 2026-03-27 00:03:01 +01:00
adman 7337068d86 more performance 2026-03-26 23:34:30 +01:00
adman 9983062522 fix timer 2026-03-26 22:39:48 +01:00
6 changed files with 65 additions and 23 deletions
+1 -1
View File
@@ -15,7 +15,7 @@ import (
) )
var ExpectedASubcommandErr = errors.New("expected a subcommand") var ExpectedASubcommandErr = errors.New("expected a subcommand")
var UnknownSubcommandErr = errors.New("unknown subcommand") var UnknownSubcommandErr = errors.New("unknown subcommand try 'strom help' for a list of subcommands")
var subcommands = map[string]func(args []string) error{ var subcommands = map[string]func(args []string) error{
"offline-uuid": offline_uuid.Run, "offline-uuid": offline_uuid.Run,
+12 -1
View File
@@ -93,6 +93,7 @@ func Run(args []string) (err error) {
slog.SetLogLoggerLevel(slog.LevelDebug) slog.SetLogLoggerLevel(slog.LevelDebug)
slog.Info("Starting packet inspector", "listen", *ListenAddr) slog.Info("Starting packet inspector", "listen", *ListenAddr)
err = server.StartServerWithOnConn(*ListenAddr, func(serveeConn *proto.Conn) (err error) { err = server.StartServerWithOnConn(*ListenAddr, func(serveeConn *proto.Conn) (err error) {
serveeConn.DecodeEvenIfUnused = true
p := &Proxy{Servee: serveeConn, Client: nil} p := &Proxy{Servee: serveeConn, Client: nil}
var acc = api.NewOfflineAccount(*OfflineNameFlag) var acc = api.NewOfflineAccount(*OfflineNameFlag)
if *Token != "" { if *Token != "" {
@@ -105,7 +106,17 @@ func Run(args []string) (err error) {
if err != nil { if err != nil {
return return
} }
c, err := client.Login(*TargetAddr, acc)
*TargetAddr, err = client.DoDnsSimple(*TargetAddr)
if err != nil {
return
}
c, err := client.Connect(*TargetAddr)
if err != nil {
return
}
c.DecodeEvenIfUnused = true
err = client.LoginRaw(c, acc, *TargetAddr)
if err != nil { if err != nil {
return return
} }
+5
View File
@@ -212,6 +212,11 @@ func (l *Loop) ContextDoneListener() (chSending <-chan any) {
return ch return ch
} }
func (l *Loop) IsTypeRegistered(t reflect.Type) bool {
_, ok := l.HandlerFunctions[t]
return ok
}
func (l *Loop) StartLoop() (err error) { func (l *Loop) StartLoop() (err error) {
_ = *l // exit early on nil loop _ = *l // exit early on nil loop
l.RegisterEventSource(l.ContextDoneListener()) l.RegisterEventSource(l.ContextDoneListener())
+8 -7
View File
@@ -54,22 +54,24 @@ func (t *Timer) Trigger(ch chan any) {
triggerAt := time.Time{} triggerAt := time.Time{}
found := false found := false
iOnce, iInterval := -1, -1 iOnce, iInterval := -1, -1
var oTask OnceTask
for iOnce, oTask = range t.Once { for i, oTask := range t.Once {
if oTask.Trigger.Before(triggerAt) || triggerAt.IsZero() { if oTask.Trigger.Before(triggerAt) || triggerAt.IsZero() {
found = true found = true
triggerAt = oTask.Trigger triggerAt = oTask.Trigger
break iOnce = i
} }
} }
var iTask IntervalTask
for iInterval, iTask = range t.Interval { for i, iTask := range t.Interval {
if iTask.LastTrigger.Add(iTask.Interval).Before(triggerAt) || triggerAt.IsZero() { if iTask.LastTrigger.Add(iTask.Interval).Before(triggerAt) || triggerAt.IsZero() {
found = true found = true
triggerAt = iTask.LastTrigger.Add(iTask.Interval) triggerAt = iTask.LastTrigger.Add(iTask.Interval)
break iOnce = -1
iInterval = i
} }
} }
if !found { if !found {
return return
} }
@@ -87,7 +89,6 @@ func (t *Timer) Trigger(ch chan any) {
} }
panic("unreachable") panic("unreachable")
} }
func (t *Timer) Every(interval time.Duration, f func() error) { func (t *Timer) Every(interval time.Duration, f func() error) {
t.Interval = append(t.Interval, IntervalTask{ t.Interval = append(t.Interval, IntervalTask{
F: f, F: f,
+14 -8
View File
@@ -27,6 +27,7 @@ var (
WrongDirectionErr = errors.New("wrong direction") WrongDirectionErr = errors.New("wrong direction")
CantTranslateErr = errors.New("cant translate packet") CantTranslateErr = errors.New("cant translate packet")
PacketDoesntExistInFutureVersionErr = errors.New("packet doesnt exist in future version") PacketDoesntExistInFutureVersionErr = errors.New("packet doesnt exist in future version")
NoHandlerRegisteredErr = errors.New("no handler registered")
) )
// LoginTick is used as a subsite for the old event system because it is very useful in login contexts // LoginTick is used as a subsite for the old event system because it is very useful in login contexts
@@ -54,19 +55,18 @@ func (u *UnCodablePacket) Decode(r io.Reader) (err error) {
type Conn struct { type Conn struct {
RawConn RawConn
*event.Loop *event.Loop
state proto_base.State state proto_base.State
stateMutex sync.RWMutex stateMutex sync.RWMutex
Actor proto_base.Actor Actor proto_base.Actor
Version string Version string
ProtocolVersion int32 ProtocolVersion int32
DecodeEvenIfUnused bool
sendTickAlways bool sendTickAlways bool
} }
func (c *Conn) StartConn() (err error) { func (c *Conn) StartConn() (err error) {
if c.State() != proto_base.Play { c.sendTickAlways = c.State() != proto_base.Play
c.sendTickAlways = true
}
c.RegisterEventSource(c.ActivateReceiveRoutine()) c.RegisterEventSource(c.ActivateReceiveRoutine())
c.RegisterCritical(c.OnLoginTick) c.RegisterCritical(c.OnLoginTick)
@@ -80,6 +80,7 @@ func (c *Conn) OnLoginTick(_ LoginTick) (err error) {
if err != nil { if err != nil {
return return
} }
slog.Debug("logintick recv", "actor", c.Actor, "packet", fmt.Sprintf("%#v", packet))
err = c.Fire(packet) err = c.Fire(packet)
return return
} }
@@ -135,6 +136,7 @@ func (c *Conn) ActivateReceiveRoutine() (chSending <-chan any) {
ch <- err ch <- err
return return
} }
slog.Debug("recv", "actor", c.Actor, "packet", fmt.Sprintf("%#v", packet))
ch <- packet ch <- packet
} }
} }
@@ -219,6 +221,10 @@ func (c *Conn) Receive() (packet proto_base.EncodeDecodeAble, err error) {
packet = &UnCodablePacket{Err: BadPacketIdErr, Data: packetBytes, Direction: c.Actor.ReceiveDirection()} packet = &UnCodablePacket{Err: BadPacketIdErr, Data: packetBytes, Direction: c.Actor.ReceiveDirection()}
return return
} }
if !c.DecodeEvenIfUnused && !c.IsTypeRegistered(reflect.TypeOf(packet)) {
packet = &UnCodablePacket{Err: NoHandlerRegisteredErr, Data: packetBytes, Direction: c.Actor.ReceiveDirection()}
return
}
err = packet.Decode(b) err = packet.Decode(b)
if err != nil { if err != nil {
packet = &UnCodablePacket{Err: err, Data: packetBytes, Direction: c.Actor.ReceiveDirection()} packet = &UnCodablePacket{Err: err, Data: packetBytes, Direction: c.Actor.ReceiveDirection()}
+25 -6
View File
@@ -7,15 +7,27 @@ import (
"github.com/admin-else/strom/proto_generated" "github.com/admin-else/strom/proto_generated"
) )
// I know this is in-performant and i dont care until it becomes a problem for somebody it will stay like this and it is pretty easy to make caches or similar to speed this up so yeah type PidEtc struct {
Direction proto_base.Direction
State proto_base.State
PacketId int32
ProtocolVersion int32
}
var pidMap = make(map[PidEtc]*proto_base.PacketInfo)
func init() {
for _, pin := range proto_generated.Packets {
pidMap[PidEtc{pin.Direction, pin.State, pin.PacketId, pin.ProtocolVersion}] = &pin
}
}
func LookUpTypeByPacketInfo(direction proto_base.Direction, state proto_base.State, pid, version int32) (p proto_base.PacketInfo, ok bool) { func LookUpTypeByPacketInfo(direction proto_base.Direction, state proto_base.State, pid, version int32) (p proto_base.PacketInfo, ok bool) {
for _, pin := range proto_generated.Packets { pP, ok := pidMap[PidEtc{direction, state, pid, version}]
if pin.Direction != direction || pin.State != state || pin.ProtocolVersion != version || pin.PacketId != pid { if !ok {
continue return
}
return pin, true
} }
p = *pP
return return
} }
@@ -29,6 +41,13 @@ func LookUpTypeByPacketInfoAndCopyType(direction proto_base.Direction, state pro
} }
func LookupPacketInfoByType(packet proto_base.EncodeDecodeAble) (p proto_base.PacketInfo, ok bool) { func LookupPacketInfoByType(packet proto_base.EncodeDecodeAble) (p proto_base.PacketInfo, ok bool) {
undecodedPacket, isUndecoable := packet.(*UnCodablePacket)
if isUndecoable {
p = proto_base.PacketInfo{Type: &UnCodablePacket{}, Name: "un_codable", Direction: undecodedPacket.Direction, State: proto_base.Handshaking, PacketId: -1, ProtocolVersion: -1}
ok = true
return
}
for _, p := range proto_generated.Packets { for _, p := range proto_generated.Packets {
if reflect.TypeOf(p.Type) == reflect.TypeOf(packet) { if reflect.TypeOf(p.Type) == reflect.TypeOf(packet) {
return p, true return p, true