WIP: Update struct decode and encode #2

Draft
Sirherobrine23 wants to merge 13 commits from struct-serealize into main
17 changed files with 389 additions and 543 deletions
Showing only changes of commit 115e9e9336 - Show all commits

View File

@ -1,8 +1,6 @@
package client package client
import ( import (
"bufio"
"bytes"
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
@ -11,8 +9,6 @@ import (
"net/netip" "net/netip"
"time" "time"
"github.com/sandertv/go-raknet"
"sirherobrine23.org/Minecraft-Server/go-pproxit/internal/pipe" "sirherobrine23.org/Minecraft-Server/go-pproxit/internal/pipe"
"sirherobrine23.org/Minecraft-Server/go-pproxit/internal/structcode" "sirherobrine23.org/Minecraft-Server/go-pproxit/internal/structcode"
"sirherobrine23.org/Minecraft-Server/go-pproxit/proto" "sirherobrine23.org/Minecraft-Server/go-pproxit/proto"
@ -20,6 +16,7 @@ import (
var ( var (
ErrCannotConnect error = errors.New("cannot connect to controller") ErrCannotConnect error = errors.New("cannot connect to controller")
ErrUnathorized error = errors.New("cannot auth in controller")
) )
type NewClient struct { type NewClient struct {
@ -28,17 +25,17 @@ type NewClient struct {
} }
type Client struct { type Client struct {
Token [36]byte Token []byte
RemoteAdress []netip.AddrPort RemoteAdress netip.AddrPort
clientsTCP map[string]net.Conn clientsTCP map[string]net.Conn
clientsUDP map[string]net.Conn clientsUDP map[string]net.Conn
NewClient chan NewClient NewClient chan NewClient
Conn *raknet.Conn Conn net.Conn
AgentInfo *proto.AgentInfo AgentInfo *proto.AgentInfo
} }
func CreateClient(Addres []netip.AddrPort, Token [36]byte) (*Client, error) { func CreateClient(Addres netip.AddrPort, Token []byte) (*Client, error) {
cli := &Client{ cli := &Client{
Token: Token, Token: Token,
RemoteAdress: Addres, RemoteAdress: Addres,
@ -52,48 +49,28 @@ func CreateClient(Addres []netip.AddrPort, Token [36]byte) (*Client, error) {
return cli, nil return cli, nil
} }
func (client *Client) Send(req proto.Request) error {
return structcode.NewEncode(client.Conn, req)
}
func (client *Client) Setup() error { func (client *Client) Setup() error {
for _, addr := range client.RemoteAdress { var err error
var err error if client.Conn, err = net.DialTCP("tcp", nil, net.TCPAddrFromAddrPort(client.RemoteAdress)); err != nil {
if client.Conn, err = raknet.Dial(addr.String()); err != nil { return err
}
for attemps := 0; attemps < 18; attemps++ {
if err := structcode.NewEncode(client.Conn, proto.Request{AgentAuth: &client.Token}); err != nil {
return err
}
var res proto.Response
if err = structcode.NewDecode(client.Conn, &res); err != nil {
return fmt.Errorf("decode status from server, error: %s", err.Error())
} else if res.Unauthorized {
return ErrUnathorized
} else if res.AgentInfo == nil {
continue continue
} }
client.Conn.SetReadDeadline(time.Now().Add(time.Second * 5))
var auth = proto.AgentAuth(client.Token)
for {
client.Send(proto.Request{AgentAuth: &auth})
buff := make([]byte, 1024) client.AgentInfo = res.AgentInfo
n, err := client.Conn.Read(buff) go client.handlers()
if err != nil { return nil
return err
}
var res proto.Response
if err = structcode.NewDecode(bytes.NewBuffer(buff[:n]), &res); err != nil {
if opt, isOpt := err.(*net.OpError); isOpt {
if opt.Timeout() {
<-time.After(time.Second * 3)
client.Send(proto.Request{AgentAuth: &auth})
continue
}
}
// return err
break
} else if res.Unauthorized {
return ErrCannotConnect
} else if res.AgentInfo == nil {
continue
}
client.AgentInfo = res.AgentInfo
client.Conn.SetReadDeadline(*new(time.Time)) // clear timeout
go client.handlers()
return nil
}
} }
return ErrCannotConnect return ErrCannotConnect
} }
@ -105,7 +82,7 @@ type toWr struct {
} }
func (t toWr) Write(w []byte) (int, error) { func (t toWr) Write(w []byte) (int, error) {
err := t.tun.Send(proto.Request{ err := structcode.NewEncode(t.tun.Conn, proto.Request{
DataTX: &proto.ClientData{ DataTX: &proto.ClientData{
Client: proto.Client{ Client: proto.Client{
Client: t.To, Client: t.To,
@ -126,16 +103,17 @@ func (tun *Client) GetTargetWrite(Proto uint8, To netip.AddrPort) io.Writer {
} }
func (client *Client) handlers() { func (client *Client) handlers() {
bufioBuff := bufio.NewReader(client.Conn)
var lastPing int64 = 0 var lastPing int64 = 0
for { for {
if time.Now().UnixMilli()-lastPing > 3_000 { if time.Now().UnixMilli()-lastPing > 3_000 {
var now = time.Now() var req proto.Request
go client.Send(proto.Request{Ping: &now}) req.Ping = new(time.Time)
*req.Ping = time.Now()
go structcode.NewEncode(client.Conn, req)
} }
var res proto.Response var res proto.Response
err := structcode.NewDecode(bufioBuff, &res) err := structcode.NewDecode(client.Conn, &res)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
if err == proto.ErrInvalidBody { if err == proto.ErrInvalidBody {
@ -154,9 +132,9 @@ func (client *Client) handlers() {
if res.Unauthorized || res.NotListened { if res.Unauthorized || res.NotListened {
panic(fmt.Errorf("cannot recive requests")) // TODO: Require fix to agent shutdown graced panic(fmt.Errorf("cannot recive requests")) // TODO: Require fix to agent shutdown graced
} else if res.SendAuth { } else if res.SendAuth {
var auth = proto.AgentAuth(client.Token) var auth = client.Token
for { for {
client.Send(proto.Request{AgentAuth: &auth}) structcode.NewEncode(client.Conn, proto.Request{AgentAuth: &auth})
var res proto.Response var res proto.Response
if err = structcode.NewDecode(client.Conn, &res); err != nil { if err = structcode.NewDecode(client.Conn, &res); err != nil {
panic(err) // TODO: Require fix to agent shutdown graced panic(err) // TODO: Require fix to agent shutdown graced

View File

@ -28,14 +28,6 @@ var CmdClient = cli.Command{
Required: true, Required: true,
Usage: "agent token", Usage: "agent token",
Aliases: []string{"t"}, Aliases: []string{"t"},
Action: func(ctx *cli.Context, s string) error {
if _, err := uuid.Parse(s); err == nil {
return nil
} else if len(s) == len(proto.AgentAuth{}) {
return nil
}
return fmt.Errorf("set valid token")
},
}, },
&cli.StringFlag{ &cli.StringFlag{
Name: "dial", Name: "dial",
@ -49,7 +41,8 @@ var CmdClient = cli.Command{
if addr, err = netip.ParseAddrPort(ctx.String("url")); err != nil { if addr, err = netip.ParseAddrPort(ctx.String("url")); err != nil {
return return
} }
client, err := client.CreateClient([]netip.AddrPort{addr}, [36]byte([]byte(ctx.String("token")))) key, _ := uuid.MustParse(ctx.String("token")).MarshalBinary()
client, err := client.CreateClient(addr, key)
if err != nil { if err != nil {
return err return err
} }

View File

@ -25,12 +25,12 @@ type User struct {
} }
type Tun struct { type Tun struct {
ID int64 `xorm:"pk"` // Tunnel ID ID int64 `xorm:"pk"` // Tunnel ID
User int64 `xorm:"notnull"` // Agent ID User int64 `xorm:"notnull"` // Agent ID
Token [36]byte `xorm:"blob notnull unique"` // Tunnel Token Token []byte `xorm:"blob notnull unique"` // Tunnel Token
Proto uint8 `xorm:"default 3"` // Proto accept Proto uint8 `xorm:"default 3"` // Proto accept
TPCListen uint16 // Port listen TCP agent TPCListen uint16 // Port listen TCP agent
UDPListen uint16 // Port listen UDP agent UDPListen uint16 // Port listen UDP agent
} }
type Ping struct { type Ping struct {
@ -104,7 +104,7 @@ func (tun *TunCallbcks) BlockedAddr(AddrPort string) bool {
func (tun *TunCallbcks) AgentPing(agent, server time.Time) { func (tun *TunCallbcks) AgentPing(agent, server time.Time) {
c, _ := tun.XormEngine.Count(Ping{}) c, _ := tun.XormEngine.Count(Ping{})
tun.XormEngine.InsertOne(&Ping{ tun.XormEngine.InsertOne(&Ping{
ID: c, ID: c,
TunID: tun.tunID, TunID: tun.tunID,
ServerTime: server, ServerTime: server,
AgentTime: agent, AgentTime: agent,
@ -130,7 +130,7 @@ func (tun *TunCallbcks) RegisterTX(client netip.AddrPort, Size int, Proto uint8)
}) })
} }
func (caller *serverCalls) AgentAuthentication(Token [36]byte) (server.TunnelInfo, error) { func (caller *serverCalls) AgentAuthentication(Token []byte) (server.TunnelInfo, error) {
var tun = Tun{Token: Token} var tun = Tun{Token: Token}
if ok, err := caller.XormEngine.Get(&tun); err != nil || !ok { if ok, err := caller.XormEngine.Get(&tun); err != nil || !ok {
if !ok { if !ok {

View File

@ -0,0 +1,15 @@
package structcode
import (
"bytes"
)
func Marshal(target any) ([]byte, error) {
buff := new(bytes.Buffer)
err := NewEncode(buff, target)
return buff.Bytes(), err
}
func Unmarshal(b []byte, target any) error {
return NewDecode(bytes.NewReader(b), target)
}

View File

@ -0,0 +1,107 @@
package structcode
import (
"encoding"
"encoding/binary"
"io"
"reflect"
"time"
)
func decodeRecursive(r io.Reader, reflectValue reflect.Value) error {
switch reflectValue.Type().Kind() {
case reflect.Interface:
case reflect.String:
size := int64(0)
if err := binary.Read(r, binary.BigEndian, &size); err != nil {
return err
}
buff := make([]byte, size)
if _, err := r.Read(buff); err != nil {
return err
}
reflectValue.SetString(string(buff))
case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
data := reflect.New(reflectValue.Type()).Interface()
if err := binary.Read(r, binary.BigEndian, data); err != nil {
return err
}
reflectValue.Set(reflect.ValueOf(data).Elem())
case reflect.Struct:
if reflectValue.Type().ConvertibleTo(typeofTimer) || reflectValue.Type().Implements(typeofBinUnmarshal) || reflectValue.Type().Implements(typeofTextUnmarshal) {
size := int64(0)
if err := binary.Read(r, binary.BigEndian, &size); err != nil {
return err
}
buff := make([]byte, size)
if _, err := r.Read(buff); err != nil {
return err
} else if reflectValue.Type().ConvertibleTo(typeofTimer) {
ttime := reflectValue.Interface().(time.Time)
if err := ttime.UnmarshalBinary(buff); err != nil {
return err
}
reflectValue.Set(reflect.ValueOf(ttime))
return nil
} else if reflectValue.Type().Implements(typeofBinUnmarshal) {
data := reflectValue.Interface().(encoding.BinaryUnmarshaler)
if err := data.UnmarshalBinary(buff); err != nil {
return err
}
reflectValue.Set(reflect.ValueOf(data))
return nil
}
data := reflectValue.Interface().(encoding.TextUnmarshaler)
if err := data.UnmarshalText(buff); err != nil {
return err
}
reflectValue.Set(reflect.ValueOf(data))
return nil
}
typeof := reflectValue.Type()
for fieldIndex := range typeof.NumField() {
if typeof.Field(fieldIndex).Tag.Get(selectorTagName) == "-" || !typeof.Field(fieldIndex).IsExported() {
continue
} else if err := decodeRecursive(r, reflectValue.Field(fieldIndex)); err != nil {
return err
}
}
case reflect.Pointer:
read := int8(0)
if err := binary.Read(r, binary.BigEndian, &read); err != nil {
return err
} else if read == 0 {
return nil
}
reflectValue.Set(reflect.New(reflectValue.Type().Elem()))
return decodeRecursive(r, reflectValue.Elem())
case reflect.Array:
for arrIndex := range reflectValue.Len() {
if err := decodeRecursive(r, reflectValue.Index(arrIndex)); err != nil {
return err
}
}
case reflect.Slice:
size := int64(0)
if err := binary.Read(r, binary.BigEndian, &size); err != nil {
return err
} else if reflectValue.Type().Elem().Kind() == typeofByte.Kind() {
buff := make([]byte, size)
if _, err = r.Read(buff); err != nil {
return err
}
reflectValue.SetBytes(buff)
} else {
typeof := reflectValue.Type().Elem()
for range size {
newData := reflect.New(typeof)
if err := decodeRecursive(r, newData); err != nil {
return err
}
reflectValue.Set(reflect.AppendSlice(reflectValue, newData.Elem()))
}
}
}
return nil
}

View File

@ -0,0 +1,73 @@
package structcode
import (
"encoding"
"encoding/binary"
"io"
"reflect"
)
func encodeRecursive(w io.Writer, reflectValue reflect.Value) error {
switch reflectValue.Type().Kind() {
case reflect.Interface:
case reflect.String:
str := reflectValue.String()
if err := binary.Write(w, binary.BigEndian, int64(len(str))); err != nil {
return err
} else if _, err := w.Write([]byte(str)); err != nil {
return err
}
case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return binary.Write(w, binary.BigEndian, reflectValue.Interface())
case reflect.Struct:
if reflectValue.Type().Implements(typeofBinMarshal) || reflectValue.Type().Implements(typeofTextMarshal) {
var err error
var data []byte
if reflectValue.Type().Implements(typeofBinMarshal) {
data, err = reflectValue.Interface().(encoding.BinaryMarshaler).MarshalBinary()
} else {
data, err = reflectValue.Interface().(encoding.TextMarshaler).MarshalText()
}
if err == nil {
if err = binary.Write(w, binary.BigEndian, int64(len(data))); err == nil {
_, err = w.Write(data)
}
}
return err
}
typeof := reflectValue.Type()
for fieldIndex := range typeof.NumField() {
if typeof.Field(fieldIndex).Tag.Get(selectorTagName) == "-" || !typeof.Field(fieldIndex).IsExported() {
continue
} else if err := encodeRecursive(w, reflectValue.Field(fieldIndex)); err != nil {
return err
}
}
case reflect.Pointer:
if reflectValue.IsNil() || reflectValue.IsZero() {
return binary.Write(w, binary.BigEndian, int8(0))
} else if err := binary.Write(w, binary.BigEndian, int8(1)); err != nil {
return err
}
return encodeRecursive(w, reflectValue.Elem())
case reflect.Array:
for arrIndex := range reflectValue.Len() {
if err := encodeRecursive(w, reflectValue.Index(arrIndex)); err != nil {
return err
}
}
case reflect.Slice:
if err := binary.Write(w, binary.BigEndian, int64(reflectValue.Len())); err != nil {
return err
} else if reflectValue.Type().Elem().Kind() == typeofByte.Kind() {
_, err = w.Write(reflectValue.Bytes())
return err
}
for sliceIndex := range reflectValue.Len() {
if err := encodeRecursive(w, reflectValue.Index(sliceIndex)); err != nil {
return err
}
}
}
return nil
}

View File

@ -1,13 +1,3 @@
package structcode
import (
"encoding"
"encoding/binary"
"fmt"
"io"
"reflect"
)
/* /*
Este bloco de codigo server apenas para facilitar minha vida no mundo do go Este bloco de codigo server apenas para facilitar minha vida no mundo do go
Definindo a estrutura de seguinte maneira, os dados estão fortemente ligado as structs go então qualquer merda aqui pode ferra com qualquer versão anterior, então isso não será recomendado para algumas coisa Definindo a estrutura de seguinte maneira, os dados estão fortemente ligado as structs go então qualquer merda aqui pode ferra com qualquer versão anterior, então isso não será recomendado para algumas coisa
@ -16,227 +6,54 @@ Os pointers serão verificados se são nil's para idicar para a sereliazação e
*any -> int8(0|1) + data... *any -> int8(0|1) + data...
[]any -> int64 (Size) + data... []any -> int64 (Size) + data...
map[any]any -> int64 (Size) + (key + data)...
[]bytes Or String -> Int64 (Size) + []bytes []bytes Or String -> Int64 (Size) + []bytes
map[any]any -> int64 (Size) + (key + data)...
int64, uint64 -> int64 int64, uint64 -> int64
int32, uint32 -> int32 int32, uint32 -> int32
int16, uint16 -> int16 int16, uint16 -> int16
int8, uint8 -> int8 int8, uint8 -> int8
bool -> int8(0|1) bool -> int8(0|1)
*/ */
package structcode
import (
"encoding"
"fmt"
"io"
"reflect"
"time"
)
const selectorTagName = "ser" const selectorTagName = "ser"
var typeofBytes = reflect.TypeOf([]byte{}) var (
typeofTimer = reflect.TypeFor[time.Time]()
typeofBytes = reflect.TypeOf([]byte{})
typeofByte = typeofBytes.Elem()
typeofBinMarshal = reflect.TypeFor[encoding.BinaryMarshaler]()
typeofTextMarshal = reflect.TypeFor[encoding.TextMarshaler]()
typeofBinUnmarshal = reflect.TypeFor[encoding.BinaryUnmarshaler]()
typeofTextUnmarshal = reflect.TypeFor[encoding.TextUnmarshaler]()
)
func NewEncode(w io.Writer, target any) error { func NewEncode(w io.Writer, target any) error {
if target == nil { if target == nil {
return binary.Write(w, binary.BigEndian, int8(0)) return nil
}
targetReflect := reflect.ValueOf(target)
switch targetReflect.Type().Kind() {
case reflect.Array, reflect.Slice:
if err := binary.Write(w, binary.BigEndian, int64(targetReflect.Len())); err != nil {
return err
}
switch targetReflect.Type().Elem().Kind() {
case typeofBytes.Elem().Kind(): // Check if the element is a byte type
buff := make([]byte, targetReflect.Len())
for i := range targetReflect.Len() {
buff[i] = targetReflect.Index(i).Interface().(byte)
}
_, err := w.Write(buff)
return err
default:
for i := range targetReflect.Len() {
if err := NewEncode(w, targetReflect.Index(i).Interface()); err != nil {
return err
}
}
}
case reflect.Pointer:
return NewEncode(w, targetReflect.Elem().Interface()) // Ignore point and reencode
case reflect.Struct:
BinaryMarshaler, isBinaryMarshaler := targetReflect.Interface().(encoding.BinaryMarshaler)
TextMarshaler, isTextMarshaler := targetReflect.Interface().(encoding.TextMarshaler)
if isBinaryMarshaler || isTextMarshaler {
var data []byte
var err error
if isBinaryMarshaler {
data, err = BinaryMarshaler.MarshalBinary()
} else {
data, err = TextMarshaler.MarshalText()
}
if err != nil {
return err
}
return NewEncode(w, data)
}
typeof := targetReflect.Type()
for i := range targetReflect.NumField() {
if tag := typeof.Field(i).Tag.Get(selectorTagName); tag == "-" || !targetReflect.Field(i).IsValid() {
continue
} else if targetReflect.Field(i).Type().Kind() == reflect.Pointer {
if targetReflect.IsZero() || !targetReflect.CanInterface() || targetReflect.Field(i).IsNil() {
return binary.Write(w, binary.BigEndian, int8(0))
} else if err := binary.Write(w, binary.BigEndian, int8(1)); err != nil {
return err
} else if err := NewEncode(w, targetReflect.Field(i).Elem().Interface()); err != nil {
return err
}
continue
}
if err := NewEncode(w, targetReflect.Field(i).Interface()); err != nil {
return err
}
}
case reflect.String:
if err := binary.Write(w, binary.BigEndian, int64(targetReflect.Len())); err != nil {
return err
}
_, err := w.Write([]byte(targetReflect.String()))
return err
case reflect.Bool:
if targetReflect.Bool() {
return binary.Write(w, binary.BigEndian, int8(1))
}
return binary.Write(w, binary.BigEndian, int8(0))
case reflect.Uint8, reflect.Int8, reflect.Int16, reflect.Uint16, reflect.Int32, reflect.Uint32, reflect.Int64, reflect.Uint64, reflect.Float32, reflect.Float64:
return binary.Write(w, binary.BigEndian, target)
default:
return fmt.Errorf("set valid struct or array/slice, or any primary values")
} }
return nil reflectValue := reflect.ValueOf(target)
if reflectValue.Type().Kind() == reflect.Pointer {
reflectValue = reflectValue.Elem()
}
return encodeRecursive(w, reflectValue)
} }
func NewDecode(r io.Reader, target any) error { func NewDecode(r io.Reader, target any) error {
if target == nil { if target == nil {
return binary.Read(r, binary.BigEndian, int8(0)) return fmt.Errorf("set target, not nil")
} else if reflect.TypeOf(target).Kind() != reflect.Pointer {
return fmt.Errorf("set pointer to struct")
} }
targetReflect := reflect.ValueOf(target).Elem() return decodeRecursive(r, reflect.ValueOf(target).Elem())
switch targetReflect.Type().Kind() {
case reflect.Slice:
var size int64
if err := binary.Read(r, binary.BigEndian, &size); err != nil {
return err
}
switch targetReflect.Type().Elem().Kind() {
case typeofBytes.Elem().Kind():
buff := make([]byte, size)
if _, err := r.Read(buff); err != nil {
return err
}
targetReflect.SetBytes(buff)
default:
for i := range int(size) {
data := reflect.New(targetReflect.Field(i).Type().Elem()).Interface()
if err := NewDecode(r, data); err != nil {
return err
}
targetReflect.Set(reflect.AppendSlice(targetReflect, reflect.ValueOf(data)))
}
}
return nil
case reflect.Array:
var size int64
if err := binary.Read(r, binary.BigEndian, &size); err != nil {
return err
} else if size != int64(targetReflect.Len()) {
return fmt.Errorf("size mismatch: expected %d, got %d", targetReflect.Len(), size)
}
switch targetReflect.Type().Elem().Kind() {
case typeofBytes.Elem().Kind(): // Check if the element is a byte type
buff := make([]byte, size)
if _, err := r.Read(buff); err != nil {
return err
}
for i, data := range buff {
targetReflect.Index(i).Set(reflect.ValueOf(data))
}
default:
for i := 0; i < int(size); i++ {
elem := reflect.New(targetReflect.Type().Elem()).Interface()
if err := NewDecode(r, elem); err != nil {
return err
}
targetReflect.Index(i).Set(reflect.ValueOf(elem).Elem())
}
}
return nil
case reflect.String:
var err error
var size int64
if err = binary.Read(r, binary.BigEndian, &size); err == nil {
buff := make([]byte, size)
if _, err = r.Read(buff); err == nil {
targetReflect.SetString(string(buff))
}
}
return err
case reflect.Bool:
var boolInt int8
if err := binary.Read(r, binary.BigEndian, &boolInt); err != nil {
return err
}
targetReflect.SetBool(boolInt == 1)
case reflect.Uint8, reflect.Int8, reflect.Int16, reflect.Uint16, reflect.Int32, reflect.Uint32, reflect.Int64, reflect.Uint64, reflect.Float32, reflect.Float64:
return binary.Read(r, binary.BigEndian, target)
case reflect.Struct:
BinaryMarshaler, isBinaryMarshaler := target.(encoding.BinaryUnmarshaler)
TextMarshaler, isTextMarshaler := target.(encoding.TextUnmarshaler)
if isBinaryMarshaler || isTextMarshaler {
var data []byte
var err error
if err = NewDecode(r, &data); err != nil {
return err
} else if isBinaryMarshaler {
return BinaryMarshaler.UnmarshalBinary(data)
}
return TextMarshaler.UnmarshalText(data)
}
for i := range targetReflect.NumField() {
if tag := targetReflect.Type().Field(i).Tag.Get(selectorTagName); tag == "-" || !targetReflect.Field(i).CanSet() {
continue
}
if targetReflect.Field(i).Type().Kind() == reflect.Pointer {
var ok bool
if err := NewDecode(r, &ok); err != nil {
return err
} else if ok {
data := reflect.New(targetReflect.Field(i).Type().Elem()).Interface()
if err := NewDecode(r, data); err != nil {
return err
}
targetReflect.Field(i).Set(reflect.ValueOf(data))
}
continue
}
data := reflect.New(targetReflect.Field(i).Type()).Interface()
if err := NewDecode(r, data); err != nil {
return err
}
targetReflect.Field(i).Set(reflect.ValueOf(data).Elem())
}
case reflect.Interface:
BinaryMarshaler, isBinaryMarshaler := target.(encoding.BinaryUnmarshaler)
TextMarshaler, isTextMarshaler := target.(encoding.TextUnmarshaler)
if isBinaryMarshaler || isTextMarshaler {
var data []byte
var err error
if err = NewDecode(r, &data); err != nil {
return err
} else if isBinaryMarshaler {
return BinaryMarshaler.UnmarshalBinary(data)
}
return TextMarshaler.UnmarshalText(data)
}
default:
return fmt.Errorf("set valid struct or array/slice, or any primary values, kind %s", targetReflect.Type().Kind())
}
return nil
} }

View File

@ -2,6 +2,7 @@ package structcode
import ( import (
"bytes" "bytes"
"encoding/json"
"testing" "testing"
"time" "time"
) )
@ -12,58 +13,40 @@ type structTest struct {
Int16 int16 Int16 int16
Int32 int32 Int32 int32
Int64 int64 Int64 int64
Date time.Time
Bytes []byte Bytes []byte
ArrayBytes [4]byte ArrayBytes [4]byte
Date time.Time
Pointer *structTest Pointer *structTest
Pointer2 any Pointer2 any
} }
func TestSerelelize(t *testing.T) { func TestDeSerelelize(t *testing.T) {
var testData structTest
testData.Text = "Golang is best"
testData.Int8 = 2
testData.Int16 = 200
testData.Int32 = 1_000_000
testData.Int64 = 1024 * 12 * 12
testData.Bytes = []byte("google maintener go")
testData.ArrayBytes = [4]byte{0, 1, 1, 1}
testData.Date = time.Now()
testData.Pointer = &structTest{
Text: "Golang",
}
buff := new(bytes.Buffer)
if err := NewEncode(buff, &testData); err != nil {
t.Error(err)
return
}
}
func TestDeserelelize(t *testing.T) {
var testData structTest
testData.Text = "Golang is best"
testData.Int8 = 2
testData.Int16 = 200
testData.Int32 = 1_000_000
testData.Int64 = 1024 * 12 * 12
testData.Bytes = []byte("google maintener go")
testData.ArrayBytes = [4]byte{0, 1, 1, 1}
testData.Date = time.Now()
testData.Pointer = &structTest{
Text: "Golang",
}
buff := new(bytes.Buffer)
if err := NewEncode(buff, &testData); err != nil {
t.Error(err)
return
}
var decodeTest structTest var decodeTest structTest
var testData structTest
testData.Text = "Golang is best"
testData.Int8 = 2
testData.Int16 = 200
testData.Int32 = 1_000_000
testData.Int64 = 1024 * 12 * 12
testData.Bytes = []byte("google maintener go")
testData.ArrayBytes = [4]byte{0, 1, 1, 1}
testData.Date = time.Now()
testData.Pointer = &structTest{
Text: "Golang",
}
buff := new(bytes.Buffer)
if err := NewEncode(buff, testData); err != nil {
t.Error(err)
return
}
t.Log(buff.Bytes())
if err := NewDecode(buff, &decodeTest); err != nil { if err := NewDecode(buff, &decodeTest); err != nil {
t.Error(err) t.Error(err)
return return
} }
d, _ := json.MarshalIndent(decodeTest, "", " ")
t.Log(string(d))
} }

View File

@ -7,8 +7,8 @@ import (
const ( const (
ProtoBoth uint8 = iota // TCP+UDP Protocol ProtoBoth uint8 = iota // TCP+UDP Protocol
ProtoTCP uint8 = iota // TCP Protocol ProtoTCP // TCP Protocol
ProtoUDP uint8 = iota // UDP Protocol ProtoUDP // UDP Protocol
DataSize uint64 = 10_000 // Default listener data recive and send DataSize uint64 = 10_000 // Default listener data recive and send
PacketSize uint64 = 800 // Packet to without data only requests and response headers PacketSize uint64 = 800 // Packet to without data only requests and response headers

View File

@ -5,22 +5,11 @@ import (
"time" "time"
) )
const ( var ErrProtoBothNoSupported error = errors.New("protocol UDP+TCP not supported currently")
ReqAuth uint64 = iota // Request Agent Auth
ReqPing uint64 = iota // Time ping
ReqCloseClient uint64 = iota // Close client
ReqClientData uint64 = iota // Send data
)
var (
ErrProtoBothNoSupported error = errors.New("protocol UDP+TCP not supported currently")
)
type AgentAuth [36]byte
// Send request to agent and wait response // Send request to agent and wait response
type Request struct { type Request struct {
AgentAuth *AgentAuth `json:",omitempty"` // Send agent authentication to controller AgentAuth *[]byte `json:",omitempty"` // Send agent authentication to controller
Ping *time.Time `json:",omitempty"` // Send ping time to controller in unix milliseconds Ping *time.Time `json:",omitempty"` // Send ping time to controller in unix milliseconds
ClientClose *Client `json:",omitempty"` // Close client in controller ClientClose *Client `json:",omitempty"` // Close client in controller
DataTX *ClientData `json:",omitempty"` // Recive data from agent DataTX *ClientData `json:",omitempty"` // Recive data from agent

View File

@ -5,17 +5,6 @@ import (
"time" "time"
) )
const (
ResUnauthorized uint64 = iota // Request not processed and ignored
ResBadRequest uint64 = iota // Request cannot process and ignored
ResCloseClient uint64 = iota // Controller closed connection
ResClientData uint64 = iota // Controller accepted data
ResSendAuth uint64 = iota // Send token to controller
ResAgentInfo uint64 = iota // Agent info
ResPong uint64 = iota // Ping response
ResNotListening uint64 = iota // Resize buffer size
)
type AgentInfo struct { type AgentInfo struct {
Protocol uint8 // Proto supported (proto.ProtoTCP, proto.ProtoUDP or proto.ProtoBoth) Protocol uint8 // Proto supported (proto.ProtoTCP, proto.ProtoUDP or proto.ProtoBoth)
UDPPort, TCPPort uint16 // Controller port listened UDPPort, TCPPort uint16 // Controller port listened

View File

@ -3,9 +3,10 @@ package server
import ( import (
"errors" "errors"
"fmt" "fmt"
"io"
"net" "net"
"net/netip"
"github.com/sandertv/go-raknet" "os"
"sirherobrine23.org/Minecraft-Server/go-pproxit/internal/structcode" "sirherobrine23.org/Minecraft-Server/go-pproxit/internal/structcode"
"sirherobrine23.org/Minecraft-Server/go-pproxit/proto" "sirherobrine23.org/Minecraft-Server/go-pproxit/proto"
@ -17,18 +18,18 @@ var (
type ServerCall interface { type ServerCall interface {
// Authenticate agents // Authenticate agents
AgentAuthentication(Token [36]byte) (TunnelInfo, error) AgentAuthentication(Token []byte) (TunnelInfo, error)
} }
type Server struct { type Server struct {
ControllConn *raknet.Listener ControllConn net.Listener
ProcessError chan error ProcessError chan error
ControlCalls ServerCall ControlCalls ServerCall
Agents map[string]*Tunnel Agents map[string]*Tunnel
} }
func NewController(calls ServerCall, local string) (*Server, error) { func NewController(calls ServerCall, local string) (*Server, error) {
conn, err := raknet.Listen(local) conn, err := net.ListenTCP("tcp", net.TCPAddrFromAddrPort(netip.MustParseAddrPort(local)))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -50,24 +51,26 @@ func (controller *Server) handler() {
if err != nil { if err != nil {
break break
} }
fmt.Printf("New Client %q\n", conn.RemoteAddr())
go controller.handlerConn(conn) go controller.handlerConn(conn)
} }
} }
func (controller *Server) handlerConn(conn net.Conn) { func (controller *Server) handlerConn(conn net.Conn) {
defer conn.Close() // End agent accepted defer conn.Close()
var tunnelInfo TunnelInfo
var err error
var req proto.Request
for { for {
var tunnelInfo TunnelInfo
var err error
var req proto.Request
if err = structcode.NewDecode(conn, &req); err != nil { if err = structcode.NewDecode(conn, &req); err != nil {
if err != io.EOF {
fmt.Fprintf(os.Stderr, "Auth decode error: %s\n", err.Error())
}
return return
} } else if req.AgentAuth == nil {
if req.AgentAuth == nil {
structcode.NewEncode(conn, proto.Response{SendAuth: true}) structcode.NewEncode(conn, proto.Response{SendAuth: true})
continue continue
} else if tunnelInfo, err = controller.ControlCalls.AgentAuthentication([36]byte(req.AgentAuth[:])); err != nil { } else if tunnelInfo, err = controller.ControlCalls.AgentAuthentication(*req.AgentAuth); err != nil {
if err == ErrAuthAgentFail { if err == ErrAuthAgentFail {
structcode.NewEncode(conn, proto.Response{Unauthorized: true}) structcode.NewEncode(conn, proto.Response{Unauthorized: true})
return return
@ -75,17 +78,17 @@ func (controller *Server) handlerConn(conn net.Conn) {
structcode.NewEncode(conn, proto.Response{BadRequest: true}) structcode.NewEncode(conn, proto.Response{BadRequest: true})
continue continue
} }
// Close current tunnel
if tun, ok := controller.Agents[string(req.AgentAuth[:])]; ok {
fmt.Println("closing old tunnel")
tun.Close() // Close connection
}
var tun = &Tunnel{RootConn: conn, TunInfo: tunnelInfo, UDPClients: make(map[string]net.Conn), TCPClients: make(map[string]net.Conn)}
controller.Agents[string(req.AgentAuth[:])] = tun
tun.Setup()
delete(controller.Agents, string(req.AgentAuth[:]))
break break
} }
// Close current tunnel
if tun, ok := controller.Agents[string(*req.AgentAuth)]; ok {
fmt.Println("closing old tunnel")
tun.Close() // Close connection
}
var tun = &Tunnel{RootConn: conn, TunInfo: tunnelInfo, UDPClients: make(map[string]net.Conn), TCPClients: make(map[string]net.Conn)}
controller.Agents[string(*req.AgentAuth)] = tun
tun.Setup()
delete(controller.Agents, string(*req.AgentAuth))
} }

View File

@ -1,7 +1,6 @@
package server package server
import ( import (
"bytes"
"fmt" "fmt"
"io" "io"
"log" "log"
@ -62,12 +61,7 @@ func (tun *Tunnel) Close() error {
} }
func (tun *Tunnel) send(res proto.Response) error { func (tun *Tunnel) send(res proto.Response) error {
buff := new(bytes.Buffer) return structcode.NewEncode(tun.RootConn, res)
if err := structcode.NewEncode(buff, res); err != nil {
return err
}
_, err := tun.RootConn.Write(buff.Bytes())
return err
} }
type toWr struct { type toWr struct {