WIP: Update struct decode and encode #2

Draft
Sirherobrine23 wants to merge 13 commits from struct-serealize into main
5 changed files with 152 additions and 6 deletions
Showing only changes of commit 9017c8a9d2 - Show all commits

View File

@ -11,6 +11,8 @@ import (
"net/netip"
"time"
"github.com/sandertv/go-raknet"
"sirherobrine23.org/Minecraft-Server/go-pproxit/internal/pipe"
"sirherobrine23.org/Minecraft-Server/go-pproxit/proto"
)
@ -31,7 +33,7 @@ type Client struct {
clientsUDP map[string]net.Conn
NewClient chan NewClient
Conn *net.UDPConn
Conn *raknet.Conn
AgentInfo *proto.AgentInfo
}
@ -56,7 +58,7 @@ func (client *Client) Send(req proto.Request) error {
func (client *Client) Setup() error {
for _, addr := range client.RemoteAdress {
var err error
if client.Conn, err = net.DialUDP("udp", nil, net.UDPAddrFromAddrPort(addr)); err != nil {
if client.Conn, err = raknet.Dial(addr.String()); err != nil {
continue
}
client.Conn.SetReadDeadline(time.Now().Add(time.Second * 5))

1
go.mod
View File

@ -22,6 +22,7 @@ require (
github.com/ncruces/go-strftime v0.1.9 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/sandertv/go-raknet v1.14.1 // indirect
github.com/syndtr/goleveldb v1.0.0 // indirect
github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 // indirect
golang.org/x/sys v0.19.0 // indirect

2
go.sum
View File

@ -48,6 +48,8 @@ github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sandertv/go-raknet v1.14.1 h1:V2Gslo+0x4jfj+p0PM48mWxmMbYkxSlgeKy//y3ZrzI=
github.com/sandertv/go-raknet v1.14.1/go.mod h1:/yysjwfCXm2+2OY8mBazLzcxJ3irnylKCyG3FLgUPVU=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=

View File

@ -0,0 +1,141 @@
package structcode
import (
"encoding/binary"
"fmt"
"io"
"reflect"
)
func NewDecode(r io.Reader, body any) error {
if body == nil {
return nil
}
structType := reflect.TypeOf(body)
if structType.Kind() != reflect.Ptr {
return fmt.Errorf("must pass a pointer")
}
elem := structType.Elem()
kind := elem.Kind()
value := reflect.ValueOf(body)
if kind == reflect.Struct {
structurePointer := value.Elem()
for i := range structurePointer.NumField() {
field := elem.Field(i)
fieldPointer := structurePointer.FieldByName(field.Name)
kind := field.Type.Kind()
switch kind {
default:
newValue := reflect.New(fieldPointer.Type()).Interface()
if err := NewDecode(r, newValue); err != nil {
fmt.Printf("unable to convert value to [%s][%s]\n", fieldPointer.Type().Kind(), field.Name)
break
}
fieldPointer.Set(reflect.ValueOf(newValue).Elem())
case reflect.Struct:
nestedStruct := reflect.New(fieldPointer.Type()).Interface()
if err := NewDecode(r, nestedStruct); err != nil {
return err
}
fieldPointer.Set(reflect.ValueOf(nestedStruct).Elem())
}
}
}
valuePtr := value.Elem()
switch kind {
default:
break
case reflect.String:
var size int64
if err := binary.Read(r, binary.BigEndian, &size); err != nil {
return err
}
buff := make([]byte, size)
if err := binary.Read(r, binary.BigEndian, buff); err != nil {
return err
}
valuePtr.Set(reflect.ValueOf(string(buff)).Elem())
case reflect.Slice:
if data, ok := reflect.New(valuePtr.Type()).Interface().([]byte); ok {
size := int64(len(data))
if size == 0 {
if err := binary.Read(r, binary.BigEndian, &size); err != nil {
return err
}
}
if _, err := r.Read(data); err != nil {
return err
}
valuePtr.Set(reflect.ValueOf(data).Elem())
return nil
}
case
reflect.Float32, reflect.Float64,
reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
newValue := reflect.New(valuePtr.Type()).Interface()
if err := binary.Read(r, binary.BigEndian, newValue); err != nil {
return err
}
valuePtr.Set(reflect.ValueOf(newValue).Elem())
}
return nil
}
func NewEncode(w io.Writer, body any) error {
if body == nil {
return nil
}
structType := reflect.TypeOf(body)
if structType.Kind() != reflect.Ptr {
return fmt.Errorf("must pass a pointer")
}
elem := structType.Elem()
kind := elem.Kind()
value := reflect.ValueOf(body)
if kind == reflect.Struct {
structurePointer := value.Elem()
for i := range structurePointer.NumField() {
field := elem.Field(i)
fieldPointer := structurePointer.FieldByName(field.Name)
kind := field.Type.Kind()
switch kind {
default:
if err := NewEncode(w, fieldPointer.Interface()); err != nil {
fmt.Printf("unable to convert value to [%s][%s]\n", fieldPointer.Type().Kind(), field.Name)
}
case reflect.Struct:
if err := NewEncode(w, fieldPointer.Interface()); err != nil {
return err
}
}
}
}
valuePtr := value.Elem()
switch kind {
default:
break
case reflect.String, reflect.Slice:
content := valuePtr.Bytes()
if err := binary.Write(w, binary.BigEndian, int64(len(content))); err != nil {
return err
} else if err := binary.Write(w, binary.BigEndian, content); err != nil {
return err
}
case
reflect.Float32, reflect.Float64,
reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
if err := binary.Write(w, binary.BigEndian, valuePtr.Interface()); err != nil {
return err
}
}
return nil
}

View File

@ -6,7 +6,8 @@ import (
"net"
"net/netip"
"sirherobrine23.org/Minecraft-Server/go-pproxit/internal/udplisterner"
"github.com/sandertv/go-raknet"
"sirherobrine23.org/Minecraft-Server/go-pproxit/proto"
)
@ -20,14 +21,14 @@ type ServerCall interface {
}
type Server struct {
ControllConn net.Listener
ControllConn *raknet.Listener
ProcessError chan error
ControlCalls ServerCall
Agents map[string]*Tunnel
}
func NewController(calls ServerCall, local netip.AddrPort) (*Server, error) {
conn, err := udplisterner.ListenAddrPort("udp", local)
conn, err := raknet.Listen(local.String())
if err != nil {
return nil, err
}
@ -59,7 +60,6 @@ func (controller *Server) handlerConn(conn net.Conn) {
var err error
for {
if req, err = proto.ReaderRequest(conn); err != nil {
panic(err)
return
}