WIP: Update struct decode and encode #2

Draft
Sirherobrine23 wants to merge 13 commits from struct-serealize into main
25 changed files with 1182 additions and 1494 deletions
Showing only changes of commit e320f3e44b - Show all commits

View File

@ -6,8 +6,8 @@ import (
"io"
"log"
"net"
"net/netip"
"sync"
"time"
"sirherobrine23.com.br/Minecraft-Server/go-pproxit/internal/pipe"
)
@ -25,6 +25,7 @@ type client struct {
fromAgent, toClient net.Conn
bufferCache *bytes.Buffer
bufioCache *bufio.Reader
LastPing time.Time
}
type UDPServer struct {
@ -37,6 +38,29 @@ type UDPServer struct {
rw sync.RWMutex
}
func ListenUDP(network string, laddr *net.UDPAddr) (*UDPServer, error) {
conn, err := net.ListenUDP(network, laddr)
if err != nil {
return nil, err
}
var root = &UDPServer{
rootUdp: conn,
peers: make(map[string]*client),
newPeer: make(chan net.Conn),
peerError: make(chan error),
}
go root.handler()
return root, nil
}
func Listen(Network, address string) (net.Listener, error) {
ip, err := net.ResolveUDPAddr(Network, address)
if err != nil {
return nil, err
}
return ListenUDP(Network, ip)
}
// Local address
func (udpListen *UDPServer) Addr() net.Addr {
return udpListen.rootUdp.LocalAddr()
@ -69,17 +93,23 @@ func (udpListen *UDPServer) Accept() (peer net.Conn, err error) {
}
func (udpListen *UDPServer) handler() {
buff := make([]byte, 32*1024)
for {
buff := make([]byte, 1480)
n, from, err := udpListen.rootUdp.ReadFromUDP(buff)
if err != nil {
return
}
udpListen.rw.Lock()
if nt, exist := udpListen.peers[from.String()]; exist {
if (time.Now().UnixMicro() - nt.LastPing.UnixMicro()) > 100_000_000 {
delete(udpListen.peers, from.String())
}
}
if _, exist := udpListen.peers[from.String()]; !exist {
c := new(client)
c.LastPing = time.Now()
c.bufferCache = new(bytes.Buffer)
c.bufioCache = bufio.NewReader(c.bufferCache)
@ -107,30 +137,3 @@ func (udpListen *UDPServer) handler() {
udpListen.rw.RUnlock()
}
}
func listenRoot(network string, laddr *net.UDPAddr) (net.Listener, error) {
conn, err := net.ListenUDP(network, laddr)
if err != nil {
return nil, err
}
var root = &UDPServer{
rootUdp: conn,
peers: make(map[string]*client),
newPeer: make(chan net.Conn),
peerError: make(chan error),
}
go root.handler()
return root, nil
}
func ListenAddrPort(Network string, address netip.AddrPort) (net.Listener, error) {
return listenRoot(Network, net.UDPAddrFromAddrPort(address))
}
func Listen(Network, address string) (net.Listener, error) {
ip, err := net.ResolveUDPAddr(Network, address)
if err != nil {
return nil, err
}
return listenRoot(Network, ip)
}

124
tun.go
View File

@ -1,12 +1,16 @@
package gopproxit
import (
"io"
"maps"
"net"
"net/netip"
"reflect"
"slices"
"sync"
"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"
)
@ -17,9 +21,11 @@ type Tunnel struct {
Done chan struct{} // Closed connection
TCPServer *net.TCPListener
UDPServer *net.UDPConn
TCPConns map[string]net.Conn
UDPConns map[string]net.Conn
UDPServer *udplisterner.UDPServer
TCPLocker, UDPLocker sync.Locker
TCPConns map[string]net.Conn
UDPConns map[string]net.Conn
}
func NewTun(conn net.Conn, Agent *proto.AgentInfo) *Tunnel {
@ -28,6 +34,7 @@ func NewTun(conn net.Conn, Agent *proto.AgentInfo) *Tunnel {
tun.Controller = conn
// Listen clients
tun.TCPLocker, tun.UDPLocker = &sync.Mutex{}, &sync.Mutex{}
tun.TCPConns, tun.UDPConns = make(map[string]net.Conn), make(map[string]net.Conn)
tun.TunErr = make(chan error)
tun.Done = make(chan struct{})
@ -50,6 +57,14 @@ func (tun *Tunnel) Close() error {
if tun.Controller != nil {
tun.Controller.Close()
}
if tun.TCPServer != nil {
tun.TCPServer.Close()
tun.TCPServer = nil
}
if tun.UDPServer != nil {
tun.UDPServer.Close()
tun.UDPServer = nil
}
for _, d := range slices.Collect(maps.Values(tun.TCPConns)) {
d.Close()
@ -73,7 +88,72 @@ func (tun *Tunnel) sendErr(err error) {
tun.TunErr <- err
}
func (tun *Tunnel) Handler() {}
func (tun *Tunnel) Handler() {
defer tun.Close()
for {
var req proto.Request
if err := structcode.NewDecode(tun.Controller, &req); err != nil {
if err == io.EOF {
return
}
continue
}
go func(req proto.Request) {
if data := *req.ClientClose; req.ClientClose != nil {
switch data.Proto {
case proto.ProtoTCP:
if client, ok := tun.TCPConns[data.Client.String()]; ok {
client.Close()
delete(tun.TCPConns, data.Client.String())
}
case proto.ProtoUDP:
if client, ok := tun.UDPConns[data.Client.String()]; ok {
client.Close()
delete(tun.UDPConns, data.Client.String())
}
}
}
if data := *req.DataTX; req.DataTX != nil {
var conn net.Conn
var ok bool
switch data.Client.Proto {
case proto.ProtoTCP:
if conn, ok = tun.TCPConns[data.Client.Client.String()]; !ok {
return
}
case proto.ProtoUDP:
if conn, ok = tun.UDPConns[data.Client.Client.String()]; !ok {
return
}
}
conn.Write(data.Data)
}
}(req)
}
}
type rx struct {
root net.Conn
proto proto.Protoc
}
func (t rx) Write(p []byte) (int, error) {
err := structcode.NewEncode(t.root, proto.Response{
DataRX: &proto.ClientData{
Data: p,
Client: proto.Client{
Proto: t.proto,
Client: netip.MustParseAddrPort(t.root.RemoteAddr().String()),
},
},
})
if err != nil {
return 0, err
}
return len(p), nil
}
func (tun *Tunnel) TCPServerhandler() {
var err error
@ -81,6 +161,40 @@ func (tun *Tunnel) TCPServerhandler() {
tun.sendErr(err)
return
}
defer tun.TCPServer.Close()
for {
conn, err := tun.TCPServer.Accept()
if err != nil {
tun.sendErr(err)
return
}
go func() {
tun.TCPLocker.Lock()
tun.TCPConns[conn.RemoteAddr().String()] = conn
tun.TCPLocker.Unlock()
io.Copy(&rx{root: conn, proto: proto.ProtoTCP}, conn)
}()
}
}
func (tun *Tunnel) UDPServerhandler() {}
func (tun *Tunnel) UDPServerhandler() {
var err error
if tun.UDPServer, err = udplisterner.ListenUDP("udp", net.UDPAddrFromAddrPort(netip.AddrPortFrom(netip.IPv4Unspecified(), tun.Agent.TCPPort))); err != nil {
tun.sendErr(err)
return
}
defer tun.UDPServer.Close()
for {
conn, err := tun.UDPServer.Accept()
if err != nil {
tun.sendErr(err)
return
}
go func() {
tun.UDPLocker.Lock()
tun.UDPConns[conn.RemoteAddr().String()] = conn
tun.UDPLocker.Unlock()
io.Copy(&rx{root: conn, proto: proto.ProtoUDP}, conn)
}()
}
}