bedrocktool/utils/packet_logger.go

196 lines
4.2 KiB
Go
Raw Normal View History

2022-09-04 14:26:32 +00:00
package utils
import (
"bytes"
"encoding/json"
"fmt"
"io"
2022-09-04 14:26:32 +00:00
"net"
"reflect"
"strings"
"sync"
2022-09-04 14:26:32 +00:00
"github.com/bedrock-tool/bedrocktool/locale"
2022-09-04 23:40:55 +00:00
"github.com/fatih/color"
2022-09-04 14:26:32 +00:00
"github.com/sandertv/gophertunnel/minecraft/protocol"
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
"github.com/sirupsen/logrus"
"golang.org/x/exp/slices"
)
var pool = packet.NewPool()
2022-09-04 14:26:32 +00:00
2022-09-05 11:13:43 +00:00
var MutedPackets = []string{
2022-09-04 23:40:55 +00:00
"packet.UpdateBlock",
"packet.MoveActorAbsolute",
"packet.SetActorMotion",
"packet.SetTime",
"packet.RemoveActor",
"packet.AddActor",
"packet.UpdateAttributes",
"packet.Interact",
"packet.LevelEvent",
"packet.SetActorData",
"packet.MoveActorDelta",
"packet.MovePlayer",
"packet.BlockActorData",
"packet.PlayerAuthInput",
"packet.LevelChunk",
"packet.LevelSoundEvent",
"packet.ActorEvent",
"packet.NetworkChunkPublisherUpdate",
"packet.UpdateSubChunkBlocks",
"packet.SubChunk",
"packet.SubChunkRequest",
"packet.Animate",
"packet.NetworkStackLatency",
"packet.InventoryTransaction",
2022-09-05 11:35:18 +00:00
"packet.PlaySound",
2022-09-04 14:26:32 +00:00
}
2023-01-29 21:20:13 +00:00
var (
ExtraVerbose []string
2023-02-18 19:39:45 +00:00
FLog io.Writer
dmpLock sync.Mutex
2023-01-29 21:20:13 +00:00
)
2023-03-11 18:50:13 +00:00
func dmpStruct(level int, inputStruct any, withType bool, isInList bool) (s string) {
2023-01-29 21:20:13 +00:00
tBase := strings.Repeat("\t", level)
2023-03-11 18:50:13 +00:00
ii := reflect.Indirect(reflect.ValueOf(inputStruct))
typeName := reflect.TypeOf(inputStruct).String()
typeString := ""
if withType {
if slices.Contains([]string{"bool", "string"}, typeName) {
} else {
typeString = typeName + " "
}
}
if ii.Kind() == reflect.Struct {
2023-03-11 18:50:13 +00:00
if ii.NumField() == 0 {
s += typeName + "{}"
} else {
s += typeName + "{\n"
for i := 0; i < ii.NumField(); i++ {
fieldType := ii.Type().Field(i)
if fieldType.IsExported() {
field := ii.Field(i).Interface()
d := dmpStruct(level+1, field, true, false)
s += tBase + fmt.Sprintf("\t%s = %s\n", fieldType.Name, d)
} else {
s += tBase + " " + fieldType.Name + " (unexported)"
}
}
2023-03-11 18:50:13 +00:00
s += tBase + "}"
}
} else if ii.Kind() == reflect.Slice {
var t reflect.Type
2023-03-11 18:50:13 +00:00
is_elem_struct := false
if ii.Len() > 0 {
e := ii.Index(0)
t = reflect.TypeOf(e.Interface())
2023-03-11 18:50:13 +00:00
is_elem_struct = t.Kind() == reflect.Struct
}
2023-03-11 18:50:13 +00:00
if ii.Len() > 1000 {
2023-03-11 18:50:13 +00:00
s += "[<slice too long>]"
} else if ii.Len() == 0 {
s += typeString + "[]"
} else {
s += typeString + "["
if is_elem_struct {
s += "\n"
}
for i := 0; i < ii.Len(); i++ {
2023-03-11 18:50:13 +00:00
if is_elem_struct {
s += tBase + "\t"
}
s += dmpStruct(level+1, ii.Index(i).Interface(), false, true)
if is_elem_struct {
s += "\n"
} else {
s += " "
}
}
if is_elem_struct {
2023-01-29 21:20:13 +00:00
s += tBase
}
2023-03-11 18:50:13 +00:00
s += "]"
}
} else if ii.Kind() == reflect.Map {
2023-01-29 21:20:13 +00:00
j, err := json.MarshalIndent(ii.Interface(), tBase, "\t")
if err != nil {
s += err.Error()
}
s += string(j)
} else {
2023-03-11 18:50:13 +00:00
if !isInList {
s += typeString
}
s += fmt.Sprintf("%#v", ii.Interface())
}
return s
}
2022-09-05 11:13:43 +00:00
2022-09-04 14:26:32 +00:00
func PacketLogger(header packet.Header, payload []byte, src, dst net.Addr) {
var pk packet.Packet
if pkFunc, ok := pool[header.PacketID]; ok {
2022-09-04 14:26:32 +00:00
pk = pkFunc()
2022-09-04 23:40:55 +00:00
} else {
pk = &packet.Unknown{PacketID: header.PacketID}
2022-09-04 14:26:32 +00:00
}
2022-09-05 11:35:18 +00:00
2023-03-09 13:58:54 +00:00
if pk.ID() == packet.IDRequestNetworkSettings {
ClientAddr = src
}
2022-09-05 11:35:18 +00:00
defer func() {
if recoveredErr := recover(); recoveredErr != nil {
logrus.Errorf("%T: %w", pk, recoveredErr)
2022-09-05 11:35:18 +00:00
}
}()
2022-09-04 23:40:55 +00:00
pk.Unmarshal(protocol.NewReader(bytes.NewBuffer(payload), 0))
2022-09-04 14:26:32 +00:00
2023-01-29 21:20:13 +00:00
if FLog != nil {
dmpLock.Lock()
defer dmpLock.Unlock()
2023-03-11 18:50:13 +00:00
FLog.Write([]byte(dmpStruct(0, pk, true, false)))
FLog.Write([]byte("\n\n\n"))
}
2023-01-29 21:20:13 +00:00
pkName := reflect.TypeOf(pk).String()[1:]
if slices.Contains(MutedPackets, pkName) {
2022-09-04 14:26:32 +00:00
return
}
2022-09-04 23:40:55 +00:00
2022-09-04 14:26:32 +00:00
switch pk := pk.(type) {
case *packet.Disconnect:
logrus.Infof(locale.Loc("disconnect", locale.Strmap{"Pk": pk}))
2022-09-04 14:26:32 +00:00
}
2022-09-04 23:40:55 +00:00
2023-01-29 21:20:13 +00:00
dirS2C := color.GreenString("S") + "->" + color.CyanString("C")
dirC2S := color.CyanString("C") + "->" + color.GreenString("S")
var dir string = dirS2C
2022-09-07 12:07:33 +00:00
2023-01-29 21:20:13 +00:00
if ClientAddr != nil {
if src == ClientAddr {
dir = dirC2S
2022-09-07 12:07:33 +00:00
}
} else {
2023-01-29 21:20:13 +00:00
srcAddr, _, _ := net.SplitHostPort(src.String())
if IPPrivate(net.ParseIP(srcAddr)) {
dir = dirS2C
2022-09-07 12:07:33 +00:00
}
2022-09-04 23:40:55 +00:00
}
2023-01-29 21:20:13 +00:00
logrus.Debugf("%s 0x%02x, %s", dir, pk.ID(), pkName)
2022-09-05 11:13:43 +00:00
2023-01-29 21:20:13 +00:00
if slices.Contains(ExtraVerbose, pkName) {
2022-09-07 12:07:33 +00:00
logrus.Debugf("%+v", pk)
2022-09-05 11:13:43 +00:00
}
2022-09-04 14:26:32 +00:00
}