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
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,49 +49,29 @@ 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 {
continue
if client.Conn, err = net.DialTCP("tcp", nil, net.TCPAddrFromAddrPort(client.RemoteAdress)); err != nil {
return err
}
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 {
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(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
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 ErrCannotConnect
return ErrUnathorized
} 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
}
@ -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

View File

@ -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
}

View File

@ -27,7 +27,7 @@ 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
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
@ -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 {

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
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
}
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())
}

View File

@ -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))
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
for {
defer conn.Close()
var tunnelInfo TunnelInfo
var err error
var req proto.Request
for {
if err = structcode.NewDecode(conn, &req); err != nil {
return
if err != io.EOF {
fmt.Fprintf(os.Stderr, "Auth decode error: %s\n", err.Error())
}
if req.AgentAuth == nil {
return
} 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
}
break
}
// Close current tunnel
if tun, ok := controller.Agents[string(req.AgentAuth[:])]; ok {
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
controller.Agents[string(*req.AgentAuth)] = tun
tun.Setup()
delete(controller.Agents, string(req.AgentAuth[:]))
break
}
delete(controller.Agents, string(*req.AgentAuth))
}

View File

@ -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 {