WIP: replace the backend address related fields/API from udp config, move them to backend udp

This commit is contained in:
Suyono 2025-05-13 17:03:26 +10:00
parent 72745cf268
commit b645f2b6bd
5 changed files with 43 additions and 45 deletions

View File

@ -17,7 +17,6 @@ package abstract
*/ */
import ( import (
"net"
"time" "time"
) )
@ -47,5 +46,4 @@ type TCPConnectionConfig interface {
type UDPConnectionConfig interface { type UDPConnectionConfig interface {
ConnectionConfig ConnectionConfig
Timeout() time.Duration Timeout() time.Duration
BackendAddr() net.Addr
} }

View File

@ -27,6 +27,7 @@ type backendUDP struct {
cfg abstract.UDPConnectionConfig cfg abstract.UDPConnectionConfig
bufPool *BufPool bufPool *BufPool
msgChan chan udpMessage msgChan chan udpMessage
backendAddr *net.UDPAddr
} }
type udpMessage struct { type udpMessage struct {
@ -42,7 +43,16 @@ func (r udpRel) String() string {
return r.clientAddr return r.clientAddr
} }
func initUDP(wg *sync.WaitGroup, ctx context.Context, bp *BufPool, cfg abstract.UDPConnectionConfig, client net.PacketConn) *backendUDP { func initUDP(wg *sync.WaitGroup, ctx context.Context, bp *BufPool, cfg abstract.UDPConnectionConfig, client net.PacketConn) (*backendUDP, error) {
var (
addr *net.UDPAddr
err error
)
if addr, err = net.ResolveUDPAddr("udp", cfg.Backend()); err != nil {
return nil, fmt.Errorf("failed to resolve UDP address: %v", err)
}
backend := &backendUDP{ backend := &backendUDP{
relations: make(map[string]udpRel), relations: make(map[string]udpRel),
relMtx: new(sync.Mutex), relMtx: new(sync.Mutex),
@ -50,9 +60,11 @@ func initUDP(wg *sync.WaitGroup, ctx context.Context, bp *BufPool, cfg abstract.
client: client, client: client,
msgChan: make(chan udpMessage), msgChan: make(chan udpMessage),
bufPool: bp, bufPool: bp,
backendAddr: addr,
} }
defer wg.Done() defer wg.Done()
//TODO: make the number of handler spawn configurable
wg.Add(1) wg.Add(1)
handlerSpawn(wg, ctx, backend) handlerSpawn(wg, ctx, backend)
@ -65,7 +77,7 @@ func initUDP(wg *sync.WaitGroup, ctx context.Context, bp *BufPool, cfg abstract.
wg.Add(1) wg.Add(1)
handlerSpawn(wg, ctx, backend) handlerSpawn(wg, ctx, backend)
return backend return backend, nil
} }
func handlerSpawn(wg *sync.WaitGroup, ctx context.Context, backend *backendUDP) { func handlerSpawn(wg *sync.WaitGroup, ctx context.Context, backend *backendUDP) {
@ -115,7 +127,7 @@ func (b *backendUDP) addUpdateRel(clientAddr string, rel udpRel) {
func (b *backendUDP) createRelSend(clientAddr string, buf []byte) (udpRel, error) { func (b *backendUDP) createRelSend(clientAddr string, buf []byte) (udpRel, error) {
var ( var (
udpAddr *net.UDPAddr laddr *net.UDPAddr
udpConn *net.UDPConn udpConn *net.UDPConn
err error err error
) )
@ -124,15 +136,15 @@ func (b *backendUDP) createRelSend(clientAddr string, buf []byte) (udpRel, error
clientAddr: clientAddr, clientAddr: clientAddr,
} }
if udpAddr, err = net.ResolveUDPAddr("udp", b.cfg.Backend()); err != nil { if laddr, err = net.ResolveUDPAddr("udp", ""); err != nil {
return rel, fmt.Errorf("create udp relation and send message: resolve udp addr: %w", err) return rel, fmt.Errorf("create udp relation and send message: resolve local/self address for UDP: %w", err)
} }
if udpConn, err = net.DialUDP("udp", nil, udpAddr); err != nil { if udpConn, err = net.ListenUDP("udp", laddr); err != nil {
return rel, fmt.Errorf("create udp relation and send message: dial udp: %w", err) return rel, fmt.Errorf("create udp relation and send message: bind local/self address for UDP: %w", err)
} }
if _, err = udpConn.WriteTo(buf, b.cfg.BackendAddr()); err != nil { if _, err = udpConn.WriteTo(buf, b.backendAddr); err != nil {
if errors.Is(err, net.ErrClosed) { if errors.Is(err, net.ErrClosed) {
return rel, fmt.Errorf("create udp relation and send message: write udp: %w", err) return rel, fmt.Errorf("create udp relation and send message: write udp: %w", err)
} }
@ -152,7 +164,7 @@ func (b *backendUDP) relSend(rel udpRel, buf []byte) error {
err error err error
) )
if n, err = rel.backend.WriteTo(buf, b.cfg.BackendAddr()); err != nil && n == 0 { if n, err = rel.backend.WriteTo(buf, b.backendAddr); err != nil && n == 0 {
return fmt.Errorf("relSend: %w", err) return fmt.Errorf("relSend: %w", err)
} }
@ -199,7 +211,7 @@ func (b *backendUDP) Send(ctx context.Context, addr string, p []byte) error {
n int n int
) )
buf := b.bufPool.Get() // the buf will be released in handle buf := b.bufPool.Get() // the buf will be released in the handle
n = copy(buf, p) n = copy(buf, p)
if len(p) != n { if len(p) != n {
@ -261,8 +273,8 @@ udpBackendLoop:
} }
if wn, err = b.client.WriteTo(buf[:n], rel); err != nil { if wn, err = b.client.WriteTo(buf[:n], rel); err != nil {
// in case of error, never close b.client, it's a shared Packet Conn. // In case of error, never close b.client, it's a shared Packet Conn.
// All UDP relation use a shared connection/socket back to the client // All UDP relations use a shared connection/socket back to the client
if errors.Is(err, net.ErrClosed) { if errors.Is(err, net.ErrClosed) {
rel.ctxCancel() rel.ctxCancel()
break udpBackendLoop break udpBackendLoop

View File

@ -136,7 +136,7 @@ func RunTCP(wg *sync.WaitGroup, ctx context.Context, bp *BufPool, cfg abstract.T
) )
if l, err = net.Listen("tcp", cfg.Listen()); err != nil { if l, err = net.Listen("tcp", cfg.Listen()); err != nil {
panic(fmt.Errorf("failed to listen tcp: %w", err)) log.Panic().Caller().Err(err).Msg("listen tcp")
} }
accepted = make(chan net.Conn) accepted = make(chan net.Conn)
@ -365,11 +365,13 @@ func RunUDP(wg *sync.WaitGroup, ctx context.Context, bp *BufPool, cfg abstract.U
) )
if client, err = net.ListenPacket("udp", cfg.Listen()); err != nil { if client, err = net.ListenPacket("udp", cfg.Listen()); err != nil {
panic(fmt.Errorf("failed to bind for UDP %s: %w", cfg.Name(), err)) log.Panic().Err(err).Msgf("failed to bind for UDP %s", cfg.Listen())
} }
wg.Add(1) wg.Add(1)
backend = initUDP(wg, ctx, bp, cfg, client) if backend, err = initUDP(wg, ctx, bp, cfg, client); err != nil {
log.Panic().Caller().Err(err).Msg("failed to init UDP")
}
buf = bp.Get() buf = bp.Get()
defer bp.Put(buf) defer bp.Put(buf)

View File

@ -125,10 +125,9 @@ func sendUDP(ctx context.Context) {
if laddr, err = net.ResolveUDPAddr(UDP, ""); err != nil { if laddr, err = net.ResolveUDPAddr(UDP, ""); err != nil {
log.Fatal().Caller().Err(err).Str(SERVER, viper.GetString(SERVER)).Msg("udp resolve local/self address") log.Fatal().Caller().Err(err).Str(SERVER, viper.GetString(SERVER)).Msg("udp resolve local/self address")
} }
//TODO: log address to be bound by client log.Info().Str(SERVER, viper.GetString(SERVER)).Msgf("bound address %v", laddr)
//TODO: use un-connected socket of UDP, replace all net.DialUDP() with net.ListenUDP() // In Go, binding address and port for UDP use ListenUDP. Confusing!!
// In Go, binding for UDP using ListenUDP. Confusing!!
if conn, err = net.ListenUDP(UDP, laddr); err != nil { if conn, err = net.ListenUDP(UDP, laddr); err != nil {
log.Fatal().Caller().Err(err).Str(SERVER, viper.GetString(SERVER)).Msg("fail to bind local/self address") log.Fatal().Caller().Err(err).Str(SERVER, viper.GetString(SERVER)).Msg("fail to bind local/self address")
} }

View File

@ -18,7 +18,6 @@ package config
import ( import (
"fmt" "fmt"
"net"
"time" "time"
"gitea.suyono.dev/suyono/netbounce/abstract" "gitea.suyono.dev/suyono/netbounce/abstract"
@ -68,15 +67,3 @@ func (u udpModule) Backend() string {
func (u udpModule) Timeout() time.Duration { func (u udpModule) Timeout() time.Duration {
return u.config.Timeout return u.config.Timeout
} }
func (u udpModule) BackendAddr() net.Addr {
return udpBackendAddr(u)
}
func (a udpBackendAddr) Network() string {
return "udp"
}
func (a udpBackendAddr) String() string {
return a.config.Backend
}