WIP: Update struct decode and encode #2
@ -1,8 +1,6 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
@ -11,8 +9,6 @@ import (
|
||||
"net/netip"
|
||||
"time"
|
||||
|
||||
"github.com/sandertv/go-raknet"
|
||||
|
||||
"sirherobrine23.org/Minecraft-Server/go-pproxit/internal/pipe"
|
||||
"sirherobrine23.org/Minecraft-Server/go-pproxit/internal/structcode"
|
||||
"sirherobrine23.org/Minecraft-Server/go-pproxit/proto"
|
||||
@ -20,6 +16,7 @@ import (
|
||||
|
||||
var (
|
||||
ErrCannotConnect error = errors.New("cannot connect to controller")
|
||||
ErrUnathorized error = errors.New("cannot auth in controller")
|
||||
)
|
||||
|
||||
type NewClient struct {
|
||||
@ -28,17 +25,17 @@ type NewClient struct {
|
||||
}
|
||||
|
||||
type Client struct {
|
||||
Token [36]byte
|
||||
RemoteAdress []netip.AddrPort
|
||||
Token []byte
|
||||
RemoteAdress netip.AddrPort
|
||||
clientsTCP map[string]net.Conn
|
||||
clientsUDP map[string]net.Conn
|
||||
NewClient chan NewClient
|
||||
|
||||
Conn *raknet.Conn
|
||||
Conn net.Conn
|
||||
AgentInfo *proto.AgentInfo
|
||||
}
|
||||
|
||||
func CreateClient(Addres []netip.AddrPort, Token [36]byte) (*Client, error) {
|
||||
func CreateClient(Addres netip.AddrPort, Token []byte) (*Client, error) {
|
||||
cli := &Client{
|
||||
Token: Token,
|
||||
RemoteAdress: Addres,
|
||||
@ -52,48 +49,28 @@ func CreateClient(Addres []netip.AddrPort, Token [36]byte) (*Client, error) {
|
||||
return cli, nil
|
||||
}
|
||||
|
||||
func (client *Client) Send(req proto.Request) error {
|
||||
return structcode.NewEncode(client.Conn, req)
|
||||
}
|
||||
|
||||
func (client *Client) Setup() error {
|
||||
for _, addr := range client.RemoteAdress {
|
||||
var err error
|
||||
if client.Conn, err = raknet.Dial(addr.String()); err != nil {
|
||||
var err error
|
||||
if client.Conn, err = net.DialTCP("tcp", nil, net.TCPAddrFromAddrPort(client.RemoteAdress)); 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
|
||||
}
|
||||
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)
|
||||
n, err := client.Conn.Read(buff)
|
||||
if err != 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
|
||||
}
|
||||
client.AgentInfo = res.AgentInfo
|
||||
go client.handlers()
|
||||
return nil
|
||||
}
|
||||
return ErrCannotConnect
|
||||
}
|
||||
@ -105,7 +82,7 @@ type toWr struct {
|
||||
}
|
||||
|
||||
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{
|
||||
Client: proto.Client{
|
||||
Client: t.To,
|
||||
@ -126,16 +103,17 @@ func (tun *Client) GetTargetWrite(Proto uint8, To netip.AddrPort) io.Writer {
|
||||
}
|
||||
|
||||
func (client *Client) handlers() {
|
||||
bufioBuff := bufio.NewReader(client.Conn)
|
||||
var lastPing int64 = 0
|
||||
for {
|
||||
if time.Now().UnixMilli()-lastPing > 3_000 {
|
||||
var now = time.Now()
|
||||
go client.Send(proto.Request{Ping: &now})
|
||||
var req proto.Request
|
||||
req.Ping = new(time.Time)
|
||||
*req.Ping = time.Now()
|
||||
go structcode.NewEncode(client.Conn, req)
|
||||
}
|
||||
|
||||
var res proto.Response
|
||||
err := structcode.NewDecode(bufioBuff, &res)
|
||||
err := structcode.NewDecode(client.Conn, &res)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
if err == proto.ErrInvalidBody {
|
||||
@ -154,9 +132,9 @@ func (client *Client) handlers() {
|
||||
if res.Unauthorized || res.NotListened {
|
||||
panic(fmt.Errorf("cannot recive requests")) // TODO: Require fix to agent shutdown graced
|
||||
} else if res.SendAuth {
|
||||
var auth = proto.AgentAuth(client.Token)
|
||||
var auth = client.Token
|
||||
for {
|
||||
client.Send(proto.Request{AgentAuth: &auth})
|
||||
structcode.NewEncode(client.Conn, proto.Request{AgentAuth: &auth})
|
||||
var res proto.Response
|
||||
if err = structcode.NewDecode(client.Conn, &res); err != nil {
|
||||
panic(err) // TODO: Require fix to agent shutdown graced
|
||||
|
@ -28,14 +28,6 @@ var CmdClient = cli.Command{
|
||||
Required: true,
|
||||
Usage: "agent token",
|
||||
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{
|
||||
Name: "dial",
|
||||
@ -49,7 +41,8 @@ var CmdClient = cli.Command{
|
||||
if addr, err = netip.ParseAddrPort(ctx.String("url")); err != nil {
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
|
@ -25,12 +25,12 @@ type User struct {
|
||||
}
|
||||
|
||||
type Tun struct {
|
||||
ID int64 `xorm:"pk"` // Tunnel ID
|
||||
User int64 `xorm:"notnull"` // Agent ID
|
||||
Token [36]byte `xorm:"blob notnull unique"` // Tunnel Token
|
||||
Proto uint8 `xorm:"default 3"` // Proto accept
|
||||
TPCListen uint16 // Port listen TCP agent
|
||||
UDPListen uint16 // Port listen UDP agent
|
||||
ID int64 `xorm:"pk"` // Tunnel ID
|
||||
User int64 `xorm:"notnull"` // Agent ID
|
||||
Token []byte `xorm:"blob notnull unique"` // Tunnel Token
|
||||
Proto uint8 `xorm:"default 3"` // Proto accept
|
||||
TPCListen uint16 // Port listen TCP agent
|
||||
UDPListen uint16 // Port listen UDP agent
|
||||
}
|
||||
|
||||
type Ping struct {
|
||||
@ -104,7 +104,7 @@ func (tun *TunCallbcks) BlockedAddr(AddrPort string) bool {
|
||||
func (tun *TunCallbcks) AgentPing(agent, server time.Time) {
|
||||
c, _ := tun.XormEngine.Count(Ping{})
|
||||
tun.XormEngine.InsertOne(&Ping{
|
||||
ID: c,
|
||||
ID: c,
|
||||
TunID: tun.tunID,
|
||||
ServerTime: server,
|
||||
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}
|
||||
if ok, err := caller.XormEngine.Get(&tun); err != nil || !ok {
|
||||
if !ok {
|
||||
|
15
internal/structcode/bytes.go
Normal file
15
internal/structcode/bytes.go
Normal 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)
|
||||
}
|
107
internal/structcode/decode.go
Normal file
107
internal/structcode/decode.go
Normal 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
|
||||
}
|
73
internal/structcode/encode.go
Normal file
73
internal/structcode/encode.go
Normal 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
|
||||
}
|
@ -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
|
||||
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 -> int64 (Size) + data...
|
||||
map[any]any -> int64 (Size) + (key + data)...
|
||||
[]bytes Or String -> Int64 (Size) + []bytes
|
||||
map[any]any -> int64 (Size) + (key + data)...
|
||||
int64, uint64 -> int64
|
||||
int32, uint32 -> int32
|
||||
int16, uint16 -> int16
|
||||
int8, uint8 -> int8
|
||||
bool -> int8(0|1)
|
||||
*/
|
||||
package structcode
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
"time"
|
||||
)
|
||||
|
||||
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 {
|
||||
if target == nil {
|
||||
return binary.Write(w, binary.BigEndian, int8(0))
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
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 {
|
||||
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()
|
||||
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
|
||||
return decodeRecursive(r, reflect.ValueOf(target).Elem())
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package structcode
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
@ -12,58 +13,40 @@ type structTest struct {
|
||||
Int16 int16
|
||||
Int32 int32
|
||||
Int64 int64
|
||||
Date time.Time
|
||||
|
||||
Bytes []byte
|
||||
ArrayBytes [4]byte
|
||||
|
||||
Date time.Time
|
||||
Pointer *structTest
|
||||
Pointer2 any
|
||||
}
|
||||
|
||||
func TestSerelelize(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
|
||||
}
|
||||
func TestDeSerelelize(t *testing.T) {
|
||||
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 {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
d, _ := json.MarshalIndent(decodeTest, "", " ")
|
||||
t.Log(string(d))
|
||||
}
|
||||
|
@ -7,8 +7,8 @@ import (
|
||||
|
||||
const (
|
||||
ProtoBoth uint8 = iota // TCP+UDP Protocol
|
||||
ProtoTCP uint8 = iota // TCP Protocol
|
||||
ProtoUDP uint8 = iota // UDP Protocol
|
||||
ProtoTCP // TCP Protocol
|
||||
ProtoUDP // UDP Protocol
|
||||
|
||||
DataSize uint64 = 10_000 // Default listener data recive and send
|
||||
PacketSize uint64 = 800 // Packet to without data only requests and response headers
|
||||
|
@ -5,22 +5,11 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
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
|
||||
var ErrProtoBothNoSupported error = errors.New("protocol UDP+TCP not supported currently")
|
||||
|
||||
// Send request to agent and wait response
|
||||
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
|
||||
ClientClose *Client `json:",omitempty"` // Close client in controller
|
||||
DataTX *ClientData `json:",omitempty"` // Recive data from agent
|
||||
|
@ -5,17 +5,6 @@ import (
|
||||
"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 {
|
||||
Protocol uint8 // Proto supported (proto.ProtoTCP, proto.ProtoUDP or proto.ProtoBoth)
|
||||
UDPPort, TCPPort uint16 // Controller port listened
|
||||
|
@ -3,9 +3,10 @@ package server
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
|
||||
"github.com/sandertv/go-raknet"
|
||||
"net/netip"
|
||||
"os"
|
||||
|
||||
"sirherobrine23.org/Minecraft-Server/go-pproxit/internal/structcode"
|
||||
"sirherobrine23.org/Minecraft-Server/go-pproxit/proto"
|
||||
@ -17,18 +18,18 @@ var (
|
||||
|
||||
type ServerCall interface {
|
||||
// Authenticate agents
|
||||
AgentAuthentication(Token [36]byte) (TunnelInfo, error)
|
||||
AgentAuthentication(Token []byte) (TunnelInfo, error)
|
||||
}
|
||||
|
||||
type Server struct {
|
||||
ControllConn *raknet.Listener
|
||||
ControllConn net.Listener
|
||||
ProcessError chan error
|
||||
ControlCalls ServerCall
|
||||
Agents map[string]*Tunnel
|
||||
}
|
||||
|
||||
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 {
|
||||
return nil, err
|
||||
}
|
||||
@ -50,24 +51,26 @@ func (controller *Server) handler() {
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
fmt.Printf("New Client %q\n", conn.RemoteAddr())
|
||||
go controller.handlerConn(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 {
|
||||
var tunnelInfo TunnelInfo
|
||||
var err error
|
||||
var req proto.Request
|
||||
if err = structcode.NewDecode(conn, &req); err != nil {
|
||||
if err != io.EOF {
|
||||
fmt.Fprintf(os.Stderr, "Auth decode error: %s\n", err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if req.AgentAuth == nil {
|
||||
} else if req.AgentAuth == nil {
|
||||
structcode.NewEncode(conn, proto.Response{SendAuth: true})
|
||||
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 {
|
||||
structcode.NewEncode(conn, proto.Response{Unauthorized: true})
|
||||
return
|
||||
@ -75,17 +78,17 @@ func (controller *Server) handlerConn(conn net.Conn) {
|
||||
structcode.NewEncode(conn, proto.Response{BadRequest: true})
|
||||
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
|
||||
}
|
||||
|
||||
// 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))
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
@ -62,12 +61,7 @@ func (tun *Tunnel) Close() error {
|
||||
}
|
||||
|
||||
func (tun *Tunnel) send(res proto.Response) error {
|
||||
buff := new(bytes.Buffer)
|
||||
if err := structcode.NewEncode(buff, res); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err := tun.RootConn.Write(buff.Bytes())
|
||||
return err
|
||||
return structcode.NewEncode(tun.RootConn, res)
|
||||
}
|
||||
|
||||
type toWr struct {
|
||||
|
Reference in New Issue
Block a user