Files
kubevpn/pkg/core/udpovertcp.go
naison 211c9309b2 feat: handle local conn with gvisor (#665)
* feat: handle local conn with gvisor

* feat: remove udp route map

* feat: optimize code

* feat: length

* feat: works

* feat: should works

* feat: optimize code

* feat: optimize code

* feat: gudp not set remark

* feat: ut

* feat: set to default value 0

* feat: send reset to gvisor tcp forward request if error

* feat: not need to create firewall rule on windows

* feat: typo
2025-07-05 21:43:44 +08:00

92 lines
2.0 KiB
Go

package core
import (
"context"
"encoding/binary"
"io"
"net"
"github.com/wencaiwulue/kubevpn/v2/pkg/config"
)
func NewUDPConnOverTCP(ctx context.Context, conn net.Conn) (net.Conn, error) {
return &UDPConnOverTCP{ctx: ctx, Conn: conn}, nil
}
var _ net.Conn = (*UDPConnOverTCP)(nil)
// UDPConnOverTCP fake udp connection over tcp connection
type UDPConnOverTCP struct {
// tcp connection
net.Conn
ctx context.Context
}
func (c *UDPConnOverTCP) Read(b []byte) (int, error) {
select {
case <-c.ctx.Done():
return 0, c.ctx.Err()
default:
datagram, err := readDatagramPacket(c.Conn, b)
if err != nil {
return 0, err
}
return int(datagram.DataLength), nil
}
}
func (c *UDPConnOverTCP) Write(b []byte) (int, error) {
buf := config.LPool.Get().([]byte)[:]
n := copy(buf, b)
defer config.LPool.Put(buf)
packet := newDatagramPacket(buf, n)
if err := packet.Write(c.Conn); err != nil {
return 0, err
}
return len(b), nil
}
func (c *UDPConnOverTCP) Close() error {
if cc, ok := c.Conn.(interface{ CloseRead() error }); ok {
_ = cc.CloseRead()
}
if cc, ok := c.Conn.(interface{ CloseWrite() error }); ok {
_ = cc.CloseWrite()
}
return c.Conn.Close()
}
type DatagramPacket struct {
DataLength uint16 // [2]byte
Data []byte // []byte
}
func newDatagramPacket(data []byte, length int) (r *DatagramPacket) {
return &DatagramPacket{
DataLength: uint16(length),
Data: data,
}
}
// this method will return all byte array in the way: b[:], len(DatagramPacket.Data)==64k
func readDatagramPacket(r io.Reader, b []byte) (*DatagramPacket, error) {
_, err := io.ReadFull(r, b[:2])
if err != nil {
return nil, err
}
dataLength := binary.BigEndian.Uint16(b[:2])
_, err = io.ReadFull(r, b[:dataLength])
if err != nil {
return nil, err
}
return &DatagramPacket{DataLength: dataLength, Data: b[:]}, nil
}
func (d *DatagramPacket) Write(w io.Writer) error {
n := copy(d.Data[2:], d.Data[:d.DataLength])
binary.BigEndian.PutUint16(d.Data[:2], d.DataLength)
_, err := w.Write(d.Data[:n+2])
return err
}