mirror of
https://github.com/MetaCubeX/mihomo.git
synced 2026-03-04 12:57:31 +00:00
281 lines
7.7 KiB
Go
281 lines
7.7 KiB
Go
package trusttunnel
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"math"
|
|
"net"
|
|
|
|
"github.com/metacubex/sing/common"
|
|
"github.com/metacubex/sing/common/buf"
|
|
E "github.com/metacubex/sing/common/exceptions"
|
|
M "github.com/metacubex/sing/common/metadata"
|
|
N "github.com/metacubex/sing/common/network"
|
|
"github.com/metacubex/sing/common/rw"
|
|
)
|
|
|
|
type packetConn struct {
|
|
httpConn
|
|
readWaitOptions N.ReadWaitOptions
|
|
}
|
|
|
|
func (c *packetConn) InitializeReadWaiter(options N.ReadWaitOptions) (needCopy bool) {
|
|
c.readWaitOptions = options
|
|
return false
|
|
}
|
|
|
|
var (
|
|
_ N.NetPacketConn = (*clientPacketConn)(nil)
|
|
_ N.FrontHeadroom = (*clientPacketConn)(nil)
|
|
_ N.PacketReadWaiter = (*clientPacketConn)(nil)
|
|
)
|
|
|
|
type clientPacketConn struct {
|
|
packetConn
|
|
}
|
|
|
|
func (u *clientPacketConn) FrontHeadroom() int {
|
|
return 4 + 16 + 2 + 16 + 2 + 1 + math.MaxUint8
|
|
}
|
|
|
|
func (u *clientPacketConn) WaitReadPacket() (buffer *buf.Buffer, destination M.Socksaddr, err error) {
|
|
buffer = u.readWaitOptions.NewPacketBuffer()
|
|
destination, err = u.ReadPacket(buffer)
|
|
if err != nil {
|
|
buffer.Release()
|
|
return nil, M.Socksaddr{}, err
|
|
}
|
|
u.readWaitOptions.PostReturn(buffer)
|
|
return buffer, destination, nil
|
|
}
|
|
|
|
func (u *clientPacketConn) ReadPacket(buffer *buf.Buffer) (destination M.Socksaddr, err error) {
|
|
err = u.waitCreated()
|
|
if err != nil {
|
|
return M.Socksaddr{}, err
|
|
}
|
|
return u.readPacketFromServer(buffer)
|
|
}
|
|
|
|
func (u *clientPacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
|
|
buffer := buf.With(p)
|
|
destination, err := u.ReadPacket(buffer)
|
|
if err != nil {
|
|
return 0, nil, err
|
|
}
|
|
return buffer.Len(), destination.UDPAddr(), nil
|
|
}
|
|
|
|
func (u *clientPacketConn) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error {
|
|
return u.writePacketToServer(buffer, destination)
|
|
}
|
|
|
|
func (u *clientPacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
|
err = u.WritePacket(buf.As(p), M.SocksaddrFromNet(addr))
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return len(p), nil
|
|
}
|
|
|
|
func (u *clientPacketConn) readPacketFromServer(buffer *buf.Buffer) (destination M.Socksaddr, err error) {
|
|
header := buf.NewSize(4 + 16 + 2 + 16 + 2)
|
|
defer header.Release()
|
|
_, err = header.ReadFullFrom(u.body, header.Cap())
|
|
if err != nil {
|
|
return
|
|
}
|
|
var length uint32
|
|
common.Must(binary.Read(header, binary.BigEndian, &length))
|
|
var sourceAddressBuffer [16]byte
|
|
common.Must1(header.Read(sourceAddressBuffer[:]))
|
|
destination.Addr = parse16BytesIP(sourceAddressBuffer)
|
|
common.Must(binary.Read(header, binary.BigEndian, &destination.Port))
|
|
common.Must(rw.SkipN(header, 16+2)) // To local address:port
|
|
payloadLen := int(length) - (16 + 2 + 16 + 2)
|
|
if payloadLen < 0 {
|
|
return M.Socksaddr{}, E.New("invalid udp length: ", length)
|
|
}
|
|
_, err = buffer.ReadFullFrom(u.body, payloadLen)
|
|
return
|
|
}
|
|
|
|
func (u *clientPacketConn) writePacketToServer(buffer *buf.Buffer, source M.Socksaddr) error {
|
|
defer buffer.Release()
|
|
if !source.IsIP() {
|
|
return E.New("only support IP")
|
|
}
|
|
appName := AppName
|
|
if len(appName) > math.MaxUint8 {
|
|
appName = appName[:math.MaxUint8]
|
|
}
|
|
payloadLen := buffer.Len()
|
|
headerLen := 4 + 16 + 2 + 16 + 2 + 1 + len(appName)
|
|
lengthField := uint32(16 + 2 + 16 + 2 + 1 + len(appName) + payloadLen)
|
|
destinationAddress := buildPaddingIP(source.Addr)
|
|
|
|
var (
|
|
header *buf.Buffer
|
|
headerInBuffer bool
|
|
)
|
|
if buffer.Start() >= headerLen {
|
|
headerBytes := buffer.ExtendHeader(headerLen)
|
|
header = buf.With(headerBytes)
|
|
headerInBuffer = true
|
|
} else {
|
|
header = buf.NewSize(headerLen)
|
|
defer header.Release()
|
|
}
|
|
common.Must(binary.Write(header, binary.BigEndian, lengthField))
|
|
common.Must(header.WriteZeroN(16 + 2)) // Source address:port (unknown)
|
|
common.Must1(header.Write(destinationAddress[:]))
|
|
common.Must(binary.Write(header, binary.BigEndian, source.Port))
|
|
common.Must(binary.Write(header, binary.BigEndian, uint8(len(appName))))
|
|
common.Must1(header.WriteString(appName))
|
|
if !headerInBuffer {
|
|
_, err := u.writer.Write(header.Bytes())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
_, err := u.writer.Write(buffer.Bytes())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if u.flusher != nil {
|
|
u.flusher.Flush()
|
|
}
|
|
return nil
|
|
}
|
|
|
|
var (
|
|
_ N.NetPacketConn = (*serverPacketConn)(nil)
|
|
_ N.FrontHeadroom = (*serverPacketConn)(nil)
|
|
_ N.PacketReadWaiter = (*serverPacketConn)(nil)
|
|
)
|
|
|
|
type serverPacketConn struct {
|
|
packetConn
|
|
}
|
|
|
|
func (u *serverPacketConn) FrontHeadroom() int {
|
|
return 4 + 16 + 2 + 16 + 2
|
|
}
|
|
|
|
func (u *serverPacketConn) WaitReadPacket() (buffer *buf.Buffer, destination M.Socksaddr, err error) {
|
|
buffer = u.readWaitOptions.NewPacketBuffer()
|
|
destination, err = u.ReadPacket(buffer)
|
|
if err != nil {
|
|
buffer.Release()
|
|
return nil, M.Socksaddr{}, err
|
|
}
|
|
u.readWaitOptions.PostReturn(buffer)
|
|
return buffer, destination, nil
|
|
}
|
|
|
|
func (u *serverPacketConn) ReadPacket(buffer *buf.Buffer) (destination M.Socksaddr, err error) {
|
|
err = u.waitCreated()
|
|
if err != nil {
|
|
return M.Socksaddr{}, err
|
|
}
|
|
return u.readPacketFromClient(buffer)
|
|
}
|
|
|
|
func (u *serverPacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
|
|
buffer := buf.With(p)
|
|
destination, err := u.ReadPacket(buffer)
|
|
if err != nil {
|
|
return 0, nil, err
|
|
}
|
|
return buffer.Len(), destination.UDPAddr(), nil
|
|
}
|
|
|
|
func (u *serverPacketConn) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error {
|
|
return u.writePacketToClient(buffer, destination)
|
|
}
|
|
|
|
func (u *serverPacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
|
err = u.WritePacket(buf.As(p), M.SocksaddrFromNet(addr))
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return len(p), nil
|
|
}
|
|
|
|
func (u *serverPacketConn) readPacketFromClient(buffer *buf.Buffer) (destination M.Socksaddr, err error) {
|
|
header := buf.NewSize(4 + 16 + 2 + 16 + 2 + 1)
|
|
defer header.Release()
|
|
_, err = header.ReadFullFrom(u.body, header.Cap())
|
|
if err != nil {
|
|
return
|
|
}
|
|
var length uint32
|
|
common.Must(binary.Read(header, binary.BigEndian, &length))
|
|
var sourceAddressBuffer [16]byte
|
|
common.Must1(header.Read(sourceAddressBuffer[:]))
|
|
var sourcePort uint16
|
|
common.Must(binary.Read(header, binary.BigEndian, &sourcePort))
|
|
_ = sourcePort
|
|
var destinationAddressBuffer [16]byte
|
|
common.Must1(header.Read(destinationAddressBuffer[:]))
|
|
destination.Addr = parse16BytesIP(destinationAddressBuffer)
|
|
common.Must(binary.Read(header, binary.BigEndian, &destination.Port))
|
|
var appNameLen uint8
|
|
common.Must(binary.Read(header, binary.BigEndian, &appNameLen))
|
|
if appNameLen > 0 {
|
|
err = rw.SkipN(u.body, int(appNameLen))
|
|
if err != nil {
|
|
return M.Socksaddr{}, err
|
|
}
|
|
}
|
|
payloadLen := int(length) - (16 + 2 + 16 + 2 + 1 + int(appNameLen))
|
|
if payloadLen < 0 {
|
|
return M.Socksaddr{}, E.New("invalid udp length: ", length)
|
|
}
|
|
_, err = buffer.ReadFullFrom(u.body, payloadLen)
|
|
return
|
|
}
|
|
|
|
func (u *serverPacketConn) writePacketToClient(buffer *buf.Buffer, source M.Socksaddr) error {
|
|
defer buffer.Release()
|
|
if !source.IsIP() {
|
|
return E.New("only support IP")
|
|
}
|
|
payloadLen := buffer.Len()
|
|
headerLen := 4 + 16 + 2 + 16 + 2
|
|
lengthField := uint32(16 + 2 + 16 + 2 + payloadLen)
|
|
sourceAddress := buildPaddingIP(source.Addr)
|
|
var destinationAddress [16]byte
|
|
var destinationPort uint16
|
|
var (
|
|
header *buf.Buffer
|
|
headerInBuffer bool
|
|
)
|
|
if buffer.Start() >= headerLen {
|
|
headerBytes := buffer.ExtendHeader(headerLen)
|
|
header = buf.With(headerBytes)
|
|
headerInBuffer = true
|
|
} else {
|
|
header = buf.NewSize(headerLen)
|
|
defer header.Release()
|
|
}
|
|
common.Must(binary.Write(header, binary.BigEndian, lengthField))
|
|
common.Must1(header.Write(sourceAddress[:]))
|
|
common.Must(binary.Write(header, binary.BigEndian, source.Port))
|
|
common.Must1(header.Write(destinationAddress[:]))
|
|
common.Must(binary.Write(header, binary.BigEndian, destinationPort))
|
|
if !headerInBuffer {
|
|
_, err := u.writer.Write(header.Bytes())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
_, err := u.writer.Write(buffer.Bytes())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if u.flusher != nil {
|
|
u.flusher.Flush()
|
|
}
|
|
return nil
|
|
}
|