WIP: Update struct decode and encode #2
@ -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
1
go.mod
@ -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
2
go.sum
@ -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=
|
||||
|
141
internal/structcode/structcode.go
Normal file
141
internal/structcode/structcode.go
Normal 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
|
||||
}
|
@ -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
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user