WIP: Update struct decode and encode #2
@@ -1,12 +1,13 @@
|
|||||||
package client
|
package gopproxit
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"maps"
|
||||||
"net"
|
"net"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"slices"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"sirherobrine23.com.br/Minecraft-Server/go-pproxit/internal/pipe"
|
"sirherobrine23.com.br/Minecraft-Server/go-pproxit/internal/pipe"
|
||||||
@@ -14,13 +15,6 @@ import (
|
|||||||
"sirherobrine23.com.br/Minecraft-Server/go-pproxit/proto"
|
"sirherobrine23.com.br/Minecraft-Server/go-pproxit/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrUnauthorized error = errors.New("cannot auth to controller")
|
|
||||||
|
|
||||||
type remoteClient struct {
|
|
||||||
Client proto.Client
|
|
||||||
Conn net.Conn
|
|
||||||
}
|
|
||||||
|
|
||||||
type toWr struct {
|
type toWr struct {
|
||||||
Proto proto.Protoc
|
Proto proto.Protoc
|
||||||
To netip.AddrPort
|
To netip.AddrPort
|
||||||
@@ -44,26 +38,32 @@ func (t toWr) Write(w []byte) (int, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
Token []byte // Token to auth in Controller if required
|
Token []byte // Token to auth in Controller if required
|
||||||
Conn net.Conn // Connection from Controller
|
Conn net.Conn // Connection from Controller
|
||||||
Agent *proto.AgentInfo // Agent info to show in UI and listened on controller
|
Agent *proto.AgentInfo // Agent info to show in UI and listened on controller
|
||||||
TCPConns map[string]*net.TCPConn // Clients connections to TCP
|
LastPong time.Time // Last Pong time
|
||||||
UDPConns map[string]*net.UDPConn // Clients connections to UDP
|
Latency int64 // Latency response in ms from last Pong
|
||||||
LastPong time.Time // Last Pong time
|
|
||||||
Latency int64 // Latency response in ms from last Pong
|
|
||||||
|
|
||||||
newListen chan remoteClient // new clients listener in Controller
|
TCPConns map[string]*net.TCPConn // Clients connections to TCP
|
||||||
errListen chan error // new clients listener in Controller
|
UDPConns map[string]*net.UDPConn // Clients connections to UDP
|
||||||
|
newListenTCP, newListenUDP chan net.Conn // Channel to accept new connections
|
||||||
|
|
||||||
|
errListen chan error // new clients listener in Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewClient(Address string, AuthToken []byte) (*Client, error) {
|
// Dial TCP Connection and return Client
|
||||||
var clientStr Client
|
func NewTCPClient(Address string, AuthToken []byte) (*Client, error) {
|
||||||
var err error
|
conn, err := net.Dial("tcp", Address)
|
||||||
|
if err != nil {
|
||||||
// Dial connection
|
|
||||||
if clientStr.Conn, err = net.Dial("tcp", Address); err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
return NewClient(conn, AuthToken)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup net.Conn and return client
|
||||||
|
func NewClient(conn net.Conn, AuthToken []byte) (*Client, error) {
|
||||||
|
var clientStr Client
|
||||||
|
clientStr.Conn = conn
|
||||||
|
|
||||||
var res proto.Response
|
var res proto.Response
|
||||||
if err := structcode.NewEncode(clientStr.Conn, proto.Request{Ping: proto.Point(time.Now())}); err != nil {
|
if err := structcode.NewEncode(clientStr.Conn, proto.Request{Ping: proto.Point(time.Now())}); err != nil {
|
||||||
@@ -71,7 +71,7 @@ func NewClient(Address string, AuthToken []byte) (*Client, error) {
|
|||||||
} else if err := structcode.NewDecode(clientStr.Conn, &res); err != nil {
|
} else if err := structcode.NewDecode(clientStr.Conn, &res); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else if res.SendAuth && len(AuthToken) == 0 {
|
} else if res.SendAuth && len(AuthToken) == 0 {
|
||||||
return nil, ErrUnauthorized
|
return nil, ErrAuthUnauthorized
|
||||||
}
|
}
|
||||||
|
|
||||||
// Auth Session
|
// Auth Session
|
||||||
@@ -82,52 +82,43 @@ func NewClient(Address string, AuthToken []byte) (*Client, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clientStr.newListenTCP, clientStr.newListenUDP = make(chan net.Conn), make(chan net.Conn)
|
||||||
|
clientStr.TCPConns, clientStr.UDPConns = make(map[string]*net.TCPConn), make(map[string]*net.UDPConn)
|
||||||
clientStr.errListen = make(chan error)
|
clientStr.errListen = make(chan error)
|
||||||
clientStr.newListen = make(chan remoteClient)
|
|
||||||
clientStr.TCPConns = make(map[string]*net.TCPConn)
|
|
||||||
clientStr.UDPConns = make(map[string]*net.UDPConn)
|
|
||||||
go clientStr.handle() // Process requests
|
go clientStr.handle() // Process requests
|
||||||
return &clientStr, nil
|
return &clientStr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for any error
|
// Return addr from Dial
|
||||||
func (client *Client) WaitError() error {
|
func (Client *Client) Addr() net.Addr { return Client.Conn.RemoteAddr() }
|
||||||
if err, ok := <-client.errListen; ok {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return io.EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for any error, if catch error close connection and return error
|
// Accept connection from Controller
|
||||||
func (client *Client) WaitCloseError() error {
|
func (client *Client) Accept() (net.Conn, error) {
|
||||||
err := client.WaitError()
|
select {
|
||||||
if err != nil && client.Conn != nil {
|
case v := <-client.newListenTCP:
|
||||||
client.Close()
|
return v, nil
|
||||||
|
case v := <-client.newListenUDP:
|
||||||
|
return v, nil
|
||||||
|
case err := <-client.errListen:
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close Clients and Controller connection
|
// Close Clients and Controller connection
|
||||||
func (client *Client) Close() error {
|
func (client *Client) Close() error {
|
||||||
for remoteClient := range client.TCPConns {
|
|
||||||
d := client.TCPConns[remoteClient]
|
|
||||||
if err := d.Close(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for remoteClient := range client.UDPConns {
|
|
||||||
d := client.UDPConns[remoteClient]
|
|
||||||
if err := d.Close(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if client.Conn != nil {
|
if client.Conn != nil {
|
||||||
if err := client.Conn.Close(); err != nil {
|
client.Conn.Close()
|
||||||
return err
|
|
||||||
}
|
|
||||||
client.Conn = nil
|
|
||||||
}
|
}
|
||||||
close(client.newListen)
|
|
||||||
|
for _, d := range slices.Collect(maps.Values(client.TCPConns)) {
|
||||||
|
d.Close()
|
||||||
|
}
|
||||||
|
for _, d := range slices.Collect(maps.Values(client.UDPConns)) {
|
||||||
|
d.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
close(client.newListenTCP)
|
||||||
|
close(client.newListenUDP)
|
||||||
close(client.errListen)
|
close(client.errListen)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -143,14 +134,14 @@ func (client *Client) sendErr(err error) {
|
|||||||
|
|
||||||
// Send auth to controller
|
// Send auth to controller
|
||||||
func (client *Client) Auth() error {
|
func (client *Client) Auth() error {
|
||||||
if err := structcode.NewEncode(client.Conn, proto.Request{AgentAuth: &client.Token}); err != nil {
|
if err := structcode.NewEncode(client.Conn, proto.Request{AgentAuth: client.Token}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
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 {
|
||||||
return err
|
return err
|
||||||
} else if res.BadRequest || res.Unauthorized {
|
} else if res.BadRequest || res.Unauthorized {
|
||||||
return ErrUnauthorized
|
return ErrAuthUnauthorized
|
||||||
} else if res.AgentInfo == nil {
|
} else if res.AgentInfo == nil {
|
||||||
return fmt.Errorf("cannot get agent info")
|
return fmt.Errorf("cannot get agent info")
|
||||||
}
|
}
|
||||||
@@ -176,7 +167,7 @@ func (client *Client) handle() {
|
|||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
} else if res.Unauthorized {
|
} else if res.Unauthorized {
|
||||||
client.sendErr(ErrUnauthorized) // Close connection
|
client.sendErr(ErrAuthUnauthorized) // Close connection
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,35 +182,6 @@ func (client *Client) handle() {
|
|||||||
client.LastPong = *res.Pong
|
client.LastPong = *res.Pong
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write data to Client
|
|
||||||
if data := res.DataRX; res.DataRX != nil {
|
|
||||||
var ok bool
|
|
||||||
var clientConn net.Conn
|
|
||||||
clientAddr := res.DataRX.Client.Client.String()
|
|
||||||
switch res.DataRX.Client.Proto {
|
|
||||||
case proto.ProtoTCP:
|
|
||||||
if clientConn, ok = client.TCPConns[clientAddr]; !ok {
|
|
||||||
toClient, toAgent := pipe.CreatePipe(data.Client.Client, data.Client.Client)
|
|
||||||
go io.Copy(&toWr{data.Client.Proto, data.Client.Client, client}, toAgent)
|
|
||||||
client.newListen <- remoteClient{res.DataRX.Client, toClient}
|
|
||||||
clientConn = client.TCPConns[clientAddr]
|
|
||||||
}
|
|
||||||
case proto.ProtoUDP:
|
|
||||||
if clientConn, ok = client.UDPConns[clientAddr]; !ok {
|
|
||||||
toClient, toAgent := pipe.CreatePipe(data.Client.Client, data.Client.Client)
|
|
||||||
go io.Copy(&toWr{data.Client.Proto, data.Client.Client, client}, toAgent)
|
|
||||||
client.newListen <- remoteClient{res.DataRX.Client, toClient}
|
|
||||||
clientConn = client.UDPConns[clientAddr]
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if _, err := clientConn.Write(res.DataRX.Data); err != nil {
|
|
||||||
client.sendErr(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if res.CloseClient != nil {
|
if res.CloseClient != nil {
|
||||||
clientAddr := res.DataRX.Client.Client.String()
|
clientAddr := res.DataRX.Client.Client.String()
|
||||||
switch res.DataRX.Client.Proto {
|
switch res.DataRX.Client.Proto {
|
||||||
@@ -239,13 +201,35 @@ func (client *Client) handle() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Accept connection from Controller
|
// Write data to Client
|
||||||
func (client *Client) Accept() (proto.Protoc, net.Conn, error) {
|
if data := res.DataRX; res.DataRX != nil {
|
||||||
if conn, ok := <-client.newListen; ok {
|
var ok bool
|
||||||
return conn.Client.Proto, conn.Conn, nil
|
var clientConn net.Conn
|
||||||
|
clientAddr := res.DataRX.Client.Client.String()
|
||||||
|
|
||||||
|
switch res.DataRX.Client.Proto {
|
||||||
|
case proto.ProtoTCP:
|
||||||
|
if clientConn, ok = client.TCPConns[clientAddr]; !ok {
|
||||||
|
toClient, toAgent := pipe.CreatePipe(data.Client.Client, data.Client.Client)
|
||||||
|
go io.Copy(&toWr{data.Client.Proto, data.Client.Client, client}, toAgent)
|
||||||
|
client.newListenTCP <- toClient
|
||||||
|
clientConn = client.TCPConns[clientAddr]
|
||||||
|
}
|
||||||
|
if _, err := clientConn.Write(res.DataRX.Data); err != nil {
|
||||||
|
client.sendErr(err)
|
||||||
|
}
|
||||||
|
case proto.ProtoUDP:
|
||||||
|
if clientConn, ok = client.UDPConns[clientAddr]; !ok {
|
||||||
|
toClient, toAgent := pipe.CreatePipe(data.Client.Client, data.Client.Client)
|
||||||
|
go io.Copy(&toWr{data.Client.Proto, data.Client.Client, client}, toAgent)
|
||||||
|
client.newListenUDP <- toClient
|
||||||
|
clientConn = client.UDPConns[clientAddr]
|
||||||
|
}
|
||||||
|
if _, err := clientConn.Write(res.DataRX.Data); err != nil {
|
||||||
|
client.sendErr(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0, nil, io.EOF
|
|
||||||
}
|
}
|
2
go.mod
2
go.mod
@@ -1,3 +1,3 @@
|
|||||||
module sirherobrine23.com.br/Minecraft-Server/go-pproxit
|
module sirherobrine23.com.br/Minecraft-Server/go-pproxit
|
||||||
|
|
||||||
go 1.22
|
go 1.23
|
||||||
|
@@ -1,30 +0,0 @@
|
|||||||
package gopproxit_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"sirherobrine23.com.br/Minecraft-Server/go-pproxit/client"
|
|
||||||
"sirherobrine23.com.br/Minecraft-Server/go-pproxit/server"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestClientServer(t *testing.T) {
|
|
||||||
calls, err := NewCall()
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
controller, err := server.NewController(calls, 8881)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer controller.ControllConn.Close()
|
|
||||||
token := calls.RegisterRandomUser()
|
|
||||||
|
|
||||||
clientConn, err := client.NewClient(controller.ControllConn.Addr().String(), token)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer clientConn.Close()
|
|
||||||
}
|
|
@@ -24,6 +24,9 @@ func decodeTypeof(r io.Reader, reflectValue reflect.Value) (bool, error) {
|
|||||||
switch {
|
switch {
|
||||||
default:
|
default:
|
||||||
return false, nil
|
return false, nil
|
||||||
|
case reflectValue.Type().Implements(typeofError), reflectValue.Type().ConvertibleTo(typeofError):
|
||||||
|
readBuff(r) // Read buff and ignore
|
||||||
|
return false, nil
|
||||||
case typeof.Implements(typeofBinUnmarshal), typeof.ConvertibleTo(typeofBinUnmarshal):
|
case typeof.Implements(typeofBinUnmarshal), typeof.ConvertibleTo(typeofBinUnmarshal):
|
||||||
buff, err := readBuff(r)
|
buff, err := readBuff(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@@ -25,6 +25,8 @@ func encodeTypeof(w io.Writer, reflectValue reflect.Value) (bool, error) {
|
|||||||
data, err = reflectValue.Interface().(encoding.BinaryMarshaler).MarshalBinary()
|
data, err = reflectValue.Interface().(encoding.BinaryMarshaler).MarshalBinary()
|
||||||
case reflectValue.Type().Implements(typeofTextMarshal), reflectValue.Type().ConvertibleTo(typeofTextMarshal):
|
case reflectValue.Type().Implements(typeofTextMarshal), reflectValue.Type().ConvertibleTo(typeofTextMarshal):
|
||||||
data, err = reflectValue.Interface().(encoding.TextMarshaler).MarshalText()
|
data, err = reflectValue.Interface().(encoding.TextMarshaler).MarshalText()
|
||||||
|
case reflectValue.Type().Implements(typeofError), reflectValue.Type().ConvertibleTo(typeofError):
|
||||||
|
data = []byte(reflectValue.Interface().(error).Error())
|
||||||
}
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
err = writeBuff(w, data)
|
err = writeBuff(w, data)
|
||||||
|
@@ -27,6 +27,7 @@ import (
|
|||||||
const selectorTagName = "ser"
|
const selectorTagName = "ser"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
typeofError = reflect.TypeFor[error]()
|
||||||
typeofBytes = reflect.TypeFor[[]byte]()
|
typeofBytes = reflect.TypeFor[[]byte]()
|
||||||
|
|
||||||
typeofTextUnmarshal = reflect.TypeFor[encoding.TextUnmarshaler]()
|
typeofTextUnmarshal = reflect.TypeFor[encoding.TextUnmarshaler]()
|
||||||
|
@@ -138,7 +138,7 @@ func TestSerelelize(t *testing.T) {
|
|||||||
t.Run("Request", func(t *testing.T) {
|
t.Run("Request", func(t *testing.T) {
|
||||||
var err error
|
var err error
|
||||||
var encodeRequest, decodeRequest proto.Request
|
var encodeRequest, decodeRequest proto.Request
|
||||||
encodeRequest.AgentAuth = &[]byte{0, 0, 1, 1, 1, 1, 1, 0, 255}
|
encodeRequest.AgentAuth = []byte{0, 0, 1, 1, 1, 1, 1, 0, 255}
|
||||||
encodeRequest.Ping = new(time.Time)
|
encodeRequest.Ping = new(time.Time)
|
||||||
*encodeRequest.Ping = time.Now()
|
*encodeRequest.Ping = time.Now()
|
||||||
|
|
||||||
@@ -165,8 +165,8 @@ func TestSerelelize(t *testing.T) {
|
|||||||
} else if decodeRequest.Ping.Unix() != encodeRequest.Ping.Unix() {
|
} else if decodeRequest.Ping.Unix() != encodeRequest.Ping.Unix() {
|
||||||
t.Errorf("cannot decode/encode Ping date, Decode %d, Encode: %d", decodeRequest.Ping.Unix(), encodeRequest.Ping.Unix())
|
t.Errorf("cannot decode/encode Ping date, Decode %d, Encode: %d", decodeRequest.Ping.Unix(), encodeRequest.Ping.Unix())
|
||||||
return
|
return
|
||||||
} else if !bytes.Equal(*decodeRequest.AgentAuth, *encodeRequest.AgentAuth) {
|
} else if !bytes.Equal(decodeRequest.AgentAuth, encodeRequest.AgentAuth) {
|
||||||
t.Errorf("cannot decode/encode auth data, Decode %q, Encode: %q", hex.EncodeToString(*decodeRequest.AgentAuth), hex.EncodeToString(*encodeRequest.AgentAuth))
|
t.Errorf("cannot decode/encode auth data, Decode %q, Encode: %q", hex.EncodeToString(decodeRequest.AgentAuth), hex.EncodeToString(encodeRequest.AgentAuth))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@@ -9,10 +9,6 @@ const (
|
|||||||
ProtoBoth Protoc = iota // TCP+UDP Protocol
|
ProtoBoth Protoc = iota // TCP+UDP Protocol
|
||||||
ProtoTCP // TCP Protocol
|
ProtoTCP // TCP Protocol
|
||||||
ProtoUDP // UDP 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
|
|
||||||
PacketDataSize uint64 = DataSize + PacketSize // Header and Data request/response
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrInvalidBody error = errors.New("invalid body, check request/response")
|
var ErrInvalidBody error = errors.New("invalid body, check request/response")
|
||||||
@@ -34,8 +30,8 @@ func (pr Protoc) String() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
Client netip.AddrPort // Client address and port
|
|
||||||
Proto Protoc // Protocol to close (proto.ProtoTCP, proto.ProtoUDP or proto.ProtoBoth)
|
Proto Protoc // Protocol to close (proto.ProtoTCP, proto.ProtoUDP or proto.ProtoBoth)
|
||||||
|
Client netip.AddrPort // Client address and port
|
||||||
}
|
}
|
||||||
|
|
||||||
type ClientData struct {
|
type ClientData struct {
|
||||||
|
@@ -9,8 +9,8 @@ var ErrProtoBothNoSupported error = errors.New("protocol UDP+TCP not supported c
|
|||||||
|
|
||||||
// Send request to agent and wait response
|
// Send request to agent and wait response
|
||||||
type Request struct {
|
type Request struct {
|
||||||
|
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
|
||||||
AgentAuth *[]byte `json:",omitempty"` // Send agent authentication to controller
|
|
||||||
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
|
||||||
}
|
}
|
||||||
|
@@ -8,19 +8,20 @@ import (
|
|||||||
type AgentInfo struct {
|
type AgentInfo struct {
|
||||||
Protocol Protoc // Proto supported (proto.ProtoTCP, proto.ProtoUDP or proto.ProtoBoth)
|
Protocol Protoc // Proto supported (proto.ProtoTCP, proto.ProtoUDP or proto.ProtoBoth)
|
||||||
UDPPort, TCPPort uint16 // Controller port listened
|
UDPPort, TCPPort uint16 // Controller port listened
|
||||||
AddrPort netip.AddrPort // request address and port
|
AddrPort netip.AddrPort // Address and port
|
||||||
|
ConnectToken []byte // Bytes to conenct
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reader data from Controller and process in agent
|
// Reader data from Controller and process in agent
|
||||||
type Response struct {
|
type Response struct {
|
||||||
Unauthorized bool `json:",omitempty"` // Controller reject connection
|
Unauthorized bool `json:",omitempty"` // Controller reject connection
|
||||||
BadRequest bool `json:",omitempty"` // Controller accepted packet so cannot process Request
|
SendAuth bool `json:",omitempty"` // Send Agent token
|
||||||
SendAuth bool `json:",omitempty"` // Send Agent token
|
BadRequest bool `json:",omitempty"` // Controller accepted packet so cannot process Request
|
||||||
NotListened bool `json:",omitempty"` // Controller cannot Listen port
|
NotListened bool `json:",omitempty"` // Controller cannot Listen port
|
||||||
|
AgentInfo *AgentInfo `json:",omitempty"` // Agent Info
|
||||||
AgentInfo *AgentInfo `json:",omitempty"` // Agent Info
|
Pong *time.Time `json:",omitempty"` // ping response
|
||||||
Pong *time.Time `json:",omitempty"` // ping response
|
ConnectTo *netip.AddrPort `json:",omitempty"` // Connect to dial and auth
|
||||||
|
CloseClient *Client `json:",omitempty"` // Controller end client
|
||||||
CloseClient *Client `json:",omitempty"` // Controller end client
|
DataRX *ClientData `json:",omitempty"` // Controller recive data from client
|
||||||
DataRX *ClientData `json:",omitempty"` // Controller recive data from client
|
Error error `json:",omitempty"` // Error
|
||||||
}
|
}
|
||||||
|
138
server.go
Normal file
138
server.go
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
package gopproxit
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/hex"
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"net/netip"
|
||||||
|
"reflect"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"sirherobrine23.com.br/Minecraft-Server/go-pproxit/internal/structcode"
|
||||||
|
"sirherobrine23.com.br/Minecraft-Server/go-pproxit/proto"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrAuthInvalidToken error = errors.New("invalid token authentication") // Token is bad
|
||||||
|
ErrAuthUnauthorized error = errors.New("unauthorized authentication") // Token not exists
|
||||||
|
)
|
||||||
|
|
||||||
|
type ServerServices interface {
|
||||||
|
Auth(token []byte) error // Authenticate client
|
||||||
|
Agent(token []byte) (*proto.AgentInfo, error) // Informations to agent
|
||||||
|
SkipAddress(addr netip.AddrPort) bool // Close/skip address process
|
||||||
|
}
|
||||||
|
|
||||||
|
type Server struct {
|
||||||
|
Controller net.Listener // Controller connection
|
||||||
|
Services ServerServices // Services to auth and another options
|
||||||
|
|
||||||
|
tunLock sync.Locker
|
||||||
|
Tuns map[string]*Tunnel
|
||||||
|
|
||||||
|
errChannel chan error
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewServer(addr string, service ServerServices) (*Server, error) {
|
||||||
|
var server Server
|
||||||
|
var err error
|
||||||
|
if server.Controller, err = net.Listen("tcp", addr); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
server.Services = service
|
||||||
|
server.errChannel = make(chan error)
|
||||||
|
server.tunLock = &sync.Mutex{}
|
||||||
|
|
||||||
|
go server.accepts()
|
||||||
|
return &server, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send error to WaitError, if closed catcher and ignored
|
||||||
|
func (server *Server) sendErr(err error) {
|
||||||
|
if reflect.ValueOf(server.errChannel).IsZero() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer func() { recover() }()
|
||||||
|
server.errChannel <- err
|
||||||
|
}
|
||||||
|
|
||||||
|
// process new connections
|
||||||
|
func (server *Server) accepts() {
|
||||||
|
for server.Controller != nil {
|
||||||
|
conn, err := server.Controller.Accept()
|
||||||
|
if err != nil {
|
||||||
|
server.sendErr(err)
|
||||||
|
return
|
||||||
|
} else if server.Services.SkipAddress(netip.MustParseAddrPort(conn.RemoteAddr().String())) {
|
||||||
|
conn.Close()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
go func(conn net.Conn) {
|
||||||
|
defer conn.Close()
|
||||||
|
var req proto.Request
|
||||||
|
i := 0
|
||||||
|
for {
|
||||||
|
if i++; i > 5 {
|
||||||
|
return
|
||||||
|
} else if err := structcode.NewDecode(conn, &req); err != nil {
|
||||||
|
if err == io.EOF {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
server.sendErr(err)
|
||||||
|
continue
|
||||||
|
} else if err := server.Services.Auth(req.AgentAuth); err != nil {
|
||||||
|
if err == ErrAuthUnauthorized {
|
||||||
|
structcode.NewEncode(conn, proto.Response{Unauthorized: true})
|
||||||
|
return
|
||||||
|
} else if err == ErrAuthInvalidToken {
|
||||||
|
structcode.NewEncode(conn, proto.Response{Unauthorized: true})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
structcode.NewEncode(conn, proto.Response{BadRequest: true})
|
||||||
|
server.sendErr(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
info, err := server.Services.Agent(req.AgentAuth)
|
||||||
|
if err != nil {
|
||||||
|
structcode.NewEncode(conn, proto.Response{Error: err})
|
||||||
|
server.sendErr(err)
|
||||||
|
conn.Close()
|
||||||
|
return
|
||||||
|
} else if err := structcode.NewEncode(conn, proto.Response{AgentInfo: info}); err != nil {
|
||||||
|
server.sendErr(err)
|
||||||
|
conn.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
tokenHex := hex.EncodeToString(req.AgentAuth)
|
||||||
|
|
||||||
|
server.tunLock.Lock()
|
||||||
|
defer conn.Close()
|
||||||
|
tun := NewTun(conn, info)
|
||||||
|
if oldTun, ok := server.Tuns[tokenHex]; ok {
|
||||||
|
oldTun.Close()
|
||||||
|
delete(server.Tuns, tokenHex)
|
||||||
|
}
|
||||||
|
|
||||||
|
server.Tuns[tokenHex] = tun
|
||||||
|
server.tunLock.Unlock()
|
||||||
|
defer func() {
|
||||||
|
server.tunLock.Lock()
|
||||||
|
defer server.tunLock.Unlock()
|
||||||
|
delete(server.Tuns, tokenHex)
|
||||||
|
}()
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case err := <-tun.TunErr:
|
||||||
|
server.sendErr(err)
|
||||||
|
case <-tun.Done:
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}(conn)
|
||||||
|
}
|
||||||
|
}
|
@@ -1,92 +0,0 @@
|
|||||||
package server
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"net"
|
|
||||||
"net/netip"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"sirherobrine23.com.br/Minecraft-Server/go-pproxit/internal/structcode"
|
|
||||||
"sirherobrine23.com.br/Minecraft-Server/go-pproxit/proto"
|
|
||||||
)
|
|
||||||
|
|
||||||
var ErrAuthAgentFail error = errors.New("cannot authenticate agent") // Send unathorized client and close new accepts from current port
|
|
||||||
|
|
||||||
type ServerCall interface {
|
|
||||||
// Authenticate agents
|
|
||||||
AgentAuthentication(Token []byte) (TunnelInfo, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type Server struct {
|
|
||||||
ControllConn net.Listener
|
|
||||||
ProcessError chan error
|
|
||||||
ControlCalls ServerCall
|
|
||||||
Agents map[string]*Tunnel
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewController(calls ServerCall, port uint16) (*Server, error) {
|
|
||||||
conn, err := net.ListenTCP("tcp", net.TCPAddrFromAddrPort(netip.AddrPortFrom(netip.IPv4Unspecified(), port)))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
fmt.Printf("Listen on %s\n", conn.Addr().String())
|
|
||||||
tuns := &Server{
|
|
||||||
ControllConn: conn,
|
|
||||||
ControlCalls: calls,
|
|
||||||
Agents: make(map[string]*Tunnel),
|
|
||||||
ProcessError: make(chan error),
|
|
||||||
}
|
|
||||||
go tuns.handler()
|
|
||||||
return tuns, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (controller *Server) handler() {
|
|
||||||
defer controller.ControllConn.Close()
|
|
||||||
for {
|
|
||||||
conn, err := controller.ControllConn.Accept()
|
|
||||||
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()
|
|
||||||
var tunnelInfo TunnelInfo
|
|
||||||
var err error
|
|
||||||
var req proto.Request
|
|
||||||
for {
|
|
||||||
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 tunnelInfo, err = controller.ControlCalls.AgentAuthentication(*req.AgentAuth); err != nil {
|
|
||||||
if err == ErrAuthAgentFail {
|
|
||||||
structcode.NewEncode(conn, proto.Response{Unauthorized: true})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
structcode.NewEncode(conn, proto.Response{BadRequest: true})
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
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))
|
|
||||||
}
|
|
212
server/tunnel.go
212
server/tunnel.go
@@ -1,212 +0,0 @@
|
|||||||
package server
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"net"
|
|
||||||
"net/netip"
|
|
||||||
"os"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"sirherobrine23.com.br/Minecraft-Server/go-pproxit/internal/structcode"
|
|
||||||
"sirherobrine23.com.br/Minecraft-Server/go-pproxit/internal/udplisterner"
|
|
||||||
"sirherobrine23.com.br/Minecraft-Server/go-pproxit/proto"
|
|
||||||
)
|
|
||||||
|
|
||||||
type TunnelCall interface {
|
|
||||||
BlockedAddr(AddrPort string) bool // Ignore request from this address
|
|
||||||
AgentPing(agent, server time.Time) // Register ping to Agent
|
|
||||||
AgentShutdown(onTime time.Time) // Agend end connection
|
|
||||||
RegisterRX(client netip.AddrPort, Size int, Proto proto.Protoc) // Register Recived data from client
|
|
||||||
RegisterTX(client netip.AddrPort, Size int, Proto proto.Protoc) // Register Transmitted data from client
|
|
||||||
}
|
|
||||||
|
|
||||||
type TunnelInfo struct {
|
|
||||||
Proto proto.Protoc // Protocol listen tunnel, use proto.ProtoTCP, proto.ProtoUDP or proto.ProtoBoth
|
|
||||||
UDPPort, TCPPort uint16 // Port to Listen UDP and TCP listeners
|
|
||||||
Callbacks TunnelCall // Tunnel Callbacks
|
|
||||||
}
|
|
||||||
|
|
||||||
type Tunnel struct {
|
|
||||||
RootConn net.Conn // Current client connection
|
|
||||||
TunInfo TunnelInfo // Tunnel info
|
|
||||||
|
|
||||||
connTCP *net.TCPListener
|
|
||||||
connUDP net.Listener
|
|
||||||
|
|
||||||
UDPClients map[string]net.Conn // Current clients connected
|
|
||||||
TCPClients map[string]net.Conn // Current clients connected
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tun *Tunnel) Close() error {
|
|
||||||
tun.connTCP.Close()
|
|
||||||
tun.connUDP.Close()
|
|
||||||
|
|
||||||
// Stop TCP Clients
|
|
||||||
for k := range tun.TCPClients {
|
|
||||||
tun.TCPClients[k].Close()
|
|
||||||
delete(tun.TCPClients, k)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stop UDP Clients
|
|
||||||
for k := range tun.UDPClients {
|
|
||||||
tun.UDPClients[k].Close()
|
|
||||||
delete(tun.UDPClients, k)
|
|
||||||
}
|
|
||||||
|
|
||||||
go tun.RootConn.Close() // End root conenction
|
|
||||||
go tun.TunInfo.Callbacks.AgentShutdown(time.Now()) // Register shutdown
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tun *Tunnel) send(res proto.Response) error {
|
|
||||||
return structcode.NewEncode(tun.RootConn, res)
|
|
||||||
}
|
|
||||||
|
|
||||||
type toWr struct {
|
|
||||||
Proto proto.Protoc
|
|
||||||
To netip.AddrPort
|
|
||||||
tun *Tunnel
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t toWr) Write(w []byte) (int, error) {
|
|
||||||
go t.tun.TunInfo.Callbacks.RegisterRX(t.To, len(w), t.Proto)
|
|
||||||
err := t.tun.send(proto.Response{
|
|
||||||
DataRX: &proto.ClientData{
|
|
||||||
Data: w,
|
|
||||||
Client: proto.Client{
|
|
||||||
Proto: t.Proto,
|
|
||||||
Client: t.To,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
if err == nil {
|
|
||||||
return len(w), nil
|
|
||||||
}
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tun *Tunnel) GetTargetWrite(Proto proto.Protoc, To netip.AddrPort) io.Writer {
|
|
||||||
return &toWr{Proto: Proto, To: To, tun: tun}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup connections and maneger connections from agent
|
|
||||||
func (tun *Tunnel) Setup() {
|
|
||||||
if proto.ProtoBoth == tun.TunInfo.Proto || proto.ProtoTCP == tun.TunInfo.Proto {
|
|
||||||
// Setup TCP Listerner
|
|
||||||
if err := tun.TCP(); err != nil {
|
|
||||||
tun.send(proto.Response{NotListened: true})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if proto.ProtoBoth == tun.TunInfo.Proto || proto.ProtoUDP == tun.TunInfo.Proto {
|
|
||||||
// Setup UDP Listerner
|
|
||||||
if err := tun.UDP(); err != nil {
|
|
||||||
tun.send(proto.Response{NotListened: true})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
defer tun.Close()
|
|
||||||
tun.send(proto.Response{
|
|
||||||
AgentInfo: &proto.AgentInfo{
|
|
||||||
Protocol: tun.TunInfo.Proto,
|
|
||||||
AddrPort: netip.MustParseAddrPort(tun.RootConn.RemoteAddr().String()),
|
|
||||||
UDPPort: tun.TunInfo.UDPPort,
|
|
||||||
TCPPort: tun.TunInfo.TCPPort,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
for {
|
|
||||||
var req proto.Request
|
|
||||||
if err := structcode.NewDecode(tun.RootConn, &req); err != nil {
|
|
||||||
fmt.Fprintln(os.Stderr, err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if req.AgentAuth != nil {
|
|
||||||
go tun.send(proto.Response{
|
|
||||||
AgentInfo: &proto.AgentInfo{
|
|
||||||
Protocol: tun.TunInfo.Proto,
|
|
||||||
AddrPort: netip.MustParseAddrPort(tun.RootConn.RemoteAddr().String()),
|
|
||||||
UDPPort: tun.TunInfo.UDPPort,
|
|
||||||
TCPPort: tun.TunInfo.TCPPort,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
continue
|
|
||||||
} else if ping := req.Ping; req.Ping != nil {
|
|
||||||
var now = time.Now()
|
|
||||||
tun.send(proto.Response{Pong: &now})
|
|
||||||
go tun.TunInfo.Callbacks.AgentPing(*ping, now) // backgroud process
|
|
||||||
} else if clClose := req.ClientClose; req.ClientClose != nil {
|
|
||||||
if clClose.Proto == proto.ProtoTCP {
|
|
||||||
if cl, ok := tun.TCPClients[clClose.Client.String()]; ok {
|
|
||||||
cl.Close()
|
|
||||||
}
|
|
||||||
} else if clClose.Proto == proto.ProtoUDP {
|
|
||||||
if cl, ok := tun.UDPClients[clClose.Client.String()]; ok {
|
|
||||||
cl.Close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if data := req.DataTX; req.DataTX != nil {
|
|
||||||
go tun.TunInfo.Callbacks.RegisterTX(data.Client.Client, len(data.Data), data.Client.Proto)
|
|
||||||
if data.Client.Proto == proto.ProtoTCP {
|
|
||||||
if cl, ok := tun.TCPClients[data.Client.Client.String()]; ok {
|
|
||||||
go cl.Write(data.Data) // Process in backgroud
|
|
||||||
}
|
|
||||||
} else if data.Client.Proto == proto.ProtoUDP {
|
|
||||||
if cl, ok := tun.UDPClients[data.Client.Client.String()]; ok {
|
|
||||||
go cl.Write(data.Data) // Process in backgroud
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Listen TCP
|
|
||||||
func (tun *Tunnel) TCP() (err error) {
|
|
||||||
if tun.connTCP, err = net.ListenTCP("tcp", net.TCPAddrFromAddrPort(netip.AddrPortFrom(netip.IPv4Unspecified(), tun.TunInfo.TCPPort))); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
go func() {
|
|
||||||
for {
|
|
||||||
conn, err := tun.connTCP.AcceptTCP()
|
|
||||||
if err != nil {
|
|
||||||
// panic(err) // TODO: fix accepts in future
|
|
||||||
return
|
|
||||||
}
|
|
||||||
remote := netip.MustParseAddrPort(conn.RemoteAddr().String())
|
|
||||||
if tun.TunInfo.Callbacks.BlockedAddr(remote.Addr().String()) {
|
|
||||||
conn.Close() // Close connection
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
tun.TCPClients[remote.String()] = conn
|
|
||||||
go io.Copy(tun.GetTargetWrite(proto.ProtoTCP, remote), conn)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Listen UDP
|
|
||||||
func (tun *Tunnel) UDP() (err error) {
|
|
||||||
if tun.connUDP, err = udplisterner.ListenAddrPort("udp", netip.AddrPortFrom(netip.IPv4Unspecified(), tun.TunInfo.UDPPort)); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
go func() {
|
|
||||||
for {
|
|
||||||
conn, err := tun.connUDP.Accept()
|
|
||||||
if err != nil {
|
|
||||||
// panic(err) // TODO: fix accepts in future
|
|
||||||
return
|
|
||||||
}
|
|
||||||
remote := netip.MustParseAddrPort(conn.RemoteAddr().String())
|
|
||||||
if tun.TunInfo.Callbacks.BlockedAddr(remote.Addr().String()) {
|
|
||||||
conn.Close() // Close connection
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
tun.UDPClients[remote.String()] = conn
|
|
||||||
go io.Copy(tun.GetTargetWrite(proto.ProtoUDP, remote), conn)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
return
|
|
||||||
}
|
|
@@ -1,107 +0,0 @@
|
|||||||
package gopproxit_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/netip"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"sirherobrine23.com.br/Minecraft-Server/go-pproxit/proto"
|
|
||||||
"sirherobrine23.com.br/Minecraft-Server/go-pproxit/server"
|
|
||||||
)
|
|
||||||
|
|
||||||
type serverCalls struct {
|
|
||||||
Locker sync.Locker
|
|
||||||
Tables map[string]map[int64]any
|
|
||||||
}
|
|
||||||
|
|
||||||
type User struct {
|
|
||||||
ID int64 // Client ID
|
|
||||||
Username string // Username
|
|
||||||
FullName string // Real name for user
|
|
||||||
AccountStatus int8 // Account Status
|
|
||||||
CreateAt time.Time // Create date
|
|
||||||
UpdateAt time.Time // Update date
|
|
||||||
}
|
|
||||||
|
|
||||||
type Tun struct {
|
|
||||||
ID int64 // Tunnel ID
|
|
||||||
User int64 // Agent ID
|
|
||||||
Token []byte // Tunnel Token
|
|
||||||
Proto proto.Protoc // Proto accept
|
|
||||||
TPCListen uint16 // Port listen TCP agent
|
|
||||||
UDPListen uint16 // Port listen UDP agent
|
|
||||||
}
|
|
||||||
|
|
||||||
type Ping struct {
|
|
||||||
ID int64 `json:"-"` // Tunnel ID
|
|
||||||
TunID int64 `json:"-"`
|
|
||||||
ServerTime time.Time `json:"server"`
|
|
||||||
AgentTime time.Time `json:"agent"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type AddrBlocked struct {
|
|
||||||
ID int64 `json:"-"` // Tunnel ID
|
|
||||||
TunID int64 `json:"-"`
|
|
||||||
Enabled bool
|
|
||||||
Address string
|
|
||||||
}
|
|
||||||
|
|
||||||
type RTX struct {
|
|
||||||
ID int64 `json:"-"` // Tunnel ID
|
|
||||||
TunID int64 `json:"-"`
|
|
||||||
Client netip.AddrPort
|
|
||||||
TXSize int
|
|
||||||
RXSize int
|
|
||||||
Proto proto.Protoc
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewCall() (call *serverCalls, err error) {
|
|
||||||
call = new(serverCalls)
|
|
||||||
call.Locker = &sync.Mutex{}
|
|
||||||
call.Tables = make(map[string]map[int64]any)
|
|
||||||
call.Tables["User"] = make(map[int64]any)
|
|
||||||
call.Tables["Tun"] = make(map[int64]any)
|
|
||||||
call.Tables["AddrBlocked"] = make(map[int64]any)
|
|
||||||
call.Tables["Ping"] = make(map[int64]any)
|
|
||||||
call.Tables["RTX"] = make(map[int64]any)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
type TunCallbcks struct {
|
|
||||||
tunID int64
|
|
||||||
Locker sync.Locker
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tun *TunCallbcks) BlockedAddr(AddrPort string) bool { return false }
|
|
||||||
func (*TunCallbcks) AgentShutdown(onTime time.Time) {}
|
|
||||||
func (tun *TunCallbcks) AgentPing(agent, server time.Time) {}
|
|
||||||
func (tun *TunCallbcks) RegisterRX(client netip.AddrPort, Size int, Proto proto.Protoc) {}
|
|
||||||
func (tun *TunCallbcks) RegisterTX(client netip.AddrPort, Size int, Proto proto.Protoc) {}
|
|
||||||
|
|
||||||
func (caller *serverCalls) AgentAuthentication(Token []byte) (server.TunnelInfo, error) {
|
|
||||||
for _, tunInfo := range caller.Tables["Tun"] {
|
|
||||||
return server.TunnelInfo{
|
|
||||||
Proto: tunInfo.(Tun).Proto,
|
|
||||||
TCPPort: tunInfo.(Tun).TPCListen,
|
|
||||||
UDPPort: tunInfo.(Tun).UDPListen,
|
|
||||||
Callbacks: &TunCallbcks{
|
|
||||||
Locker: caller.Locker,
|
|
||||||
tunID: tunInfo.(Tun).ID,
|
|
||||||
},
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
return server.TunnelInfo{}, server.ErrAuthAgentFail
|
|
||||||
}
|
|
||||||
|
|
||||||
func (caller *serverCalls) RegisterRandomUser() []byte {
|
|
||||||
token := []byte{0, 0, 12, 14, 22, 89, 255, 81}
|
|
||||||
caller.Tables["User"][0] = User{ID: 0, AccountStatus: 1, FullName: "Radon user", Username: "random"}
|
|
||||||
caller.Tables["Tun"][0] = Tun{
|
|
||||||
User: 0,
|
|
||||||
Token: token,
|
|
||||||
Proto: proto.ProtoBoth,
|
|
||||||
TPCListen: 5522,
|
|
||||||
UDPListen: 5522,
|
|
||||||
}
|
|
||||||
return token
|
|
||||||
}
|
|
86
tun.go
Normal file
86
tun.go
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
package gopproxit
|
||||||
|
|
||||||
|
import (
|
||||||
|
"maps"
|
||||||
|
"net"
|
||||||
|
"net/netip"
|
||||||
|
"reflect"
|
||||||
|
"slices"
|
||||||
|
|
||||||
|
"sirherobrine23.com.br/Minecraft-Server/go-pproxit/proto"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Tunnel struct {
|
||||||
|
Controller net.Conn // Tunnel client connection
|
||||||
|
Agent *proto.AgentInfo // Agent info
|
||||||
|
TunErr chan error // Return errors
|
||||||
|
Done chan struct{} // Closed connection
|
||||||
|
|
||||||
|
TCPServer *net.TCPListener
|
||||||
|
UDPServer *net.UDPConn
|
||||||
|
TCPConns map[string]net.Conn
|
||||||
|
UDPConns map[string]net.Conn
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewTun(conn net.Conn, Agent *proto.AgentInfo) *Tunnel {
|
||||||
|
var tun Tunnel
|
||||||
|
tun.Agent = Agent
|
||||||
|
tun.Controller = conn
|
||||||
|
|
||||||
|
// Listen clients
|
||||||
|
tun.TCPConns, tun.UDPConns = make(map[string]net.Conn), make(map[string]net.Conn)
|
||||||
|
tun.TunErr = make(chan error)
|
||||||
|
tun.Done = make(chan struct{})
|
||||||
|
|
||||||
|
if Agent.AddrPort.Compare(netip.AddrPortFrom(netip.IPv4Unspecified(), 0)) == 0 {
|
||||||
|
switch Agent.Protocol {
|
||||||
|
case proto.ProtoTCP:
|
||||||
|
go tun.TCPServerhandler()
|
||||||
|
case proto.ProtoUDP:
|
||||||
|
go tun.UDPServerhandler()
|
||||||
|
case proto.ProtoBoth:
|
||||||
|
go tun.TCPServerhandler()
|
||||||
|
go tun.UDPServerhandler()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &tun
|
||||||
|
}
|
||||||
|
func (tun *Tunnel) Close() error {
|
||||||
|
if tun.Controller != nil {
|
||||||
|
tun.Controller.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, d := range slices.Collect(maps.Values(tun.TCPConns)) {
|
||||||
|
d.Close()
|
||||||
|
}
|
||||||
|
for _, d := range slices.Collect(maps.Values(tun.UDPConns)) {
|
||||||
|
d.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
tun.Done <- struct{}{}
|
||||||
|
close(tun.Done)
|
||||||
|
close(tun.TunErr)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send error to WaitError, if closed catcher and ignored
|
||||||
|
func (tun *Tunnel) sendErr(err error) {
|
||||||
|
if reflect.ValueOf(tun.TunErr).IsZero() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer func() { recover() }()
|
||||||
|
tun.TunErr <- err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tun *Tunnel) Handler() {}
|
||||||
|
|
||||||
|
func (tun *Tunnel) TCPServerhandler() {
|
||||||
|
var err error
|
||||||
|
if tun.TCPServer, err = net.ListenTCP("tcp", net.TCPAddrFromAddrPort(netip.AddrPortFrom(netip.IPv4Unspecified(), tun.Agent.TCPPort))); err != nil {
|
||||||
|
tun.sendErr(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tun *Tunnel) UDPServerhandler() {}
|
Reference in New Issue
Block a user