78 lines
1.8 KiB
Go
78 lines
1.8 KiB
Go
package tunnel
|
|
|
|
import (
|
|
"net"
|
|
"time"
|
|
|
|
cN "github.com/Dreamacro/clash/common/net"
|
|
"github.com/Dreamacro/clash/component/resolver"
|
|
C "github.com/Dreamacro/clash/constant"
|
|
"github.com/sagernet/sing/common"
|
|
"github.com/sagernet/sing/common/buf"
|
|
M "github.com/sagernet/sing/common/metadata"
|
|
N "github.com/sagernet/sing/common/network"
|
|
)
|
|
|
|
func handleUDPToRemote(packet C.UDPPacket, pc C.PacketConn, metadata *C.Metadata) error {
|
|
defer packet.Data().Release()
|
|
// local resolve UDP dns
|
|
if !metadata.Resolved() {
|
|
ip, err := resolver.ResolveIP(metadata.Host)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
metadata.DstIP = ip
|
|
}
|
|
|
|
if err := pc.WritePacket(packet.Data(), metadata.Socksaddr()); err != nil {
|
|
return err
|
|
}
|
|
// reset timeout
|
|
pc.SetReadDeadline(time.Now().Add(udpTimeout))
|
|
|
|
return nil
|
|
}
|
|
|
|
func handleUDPToLocal(packet C.UDPPacket, pc C.PacketConn, key string, fAddr net.Addr) {
|
|
defer natTable.Delete(key)
|
|
defer pc.Close()
|
|
var fSocksaddr M.Socksaddr
|
|
if fAddr != nil {
|
|
fSocksaddr = M.SocksaddrFromNet(fAddr)
|
|
}
|
|
_, _ = copyPacketTimeout(packet, pc, udpTimeout, fSocksaddr, fAddr != nil)
|
|
}
|
|
|
|
func handleSocket(ctx C.ConnContext, outbound net.Conn) {
|
|
cN.Relay(ctx.Conn(), outbound)
|
|
}
|
|
|
|
func copyPacketTimeout(dst N.PacketWriter, src N.TimeoutPacketReader, timeout time.Duration, fAddr M.Socksaddr, fOverride bool) (n int64, err error) {
|
|
_buffer := buf.StackNewPacket()
|
|
defer common.KeepAlive(_buffer)
|
|
buffer := common.Dup(_buffer)
|
|
buffer.IncRef()
|
|
defer buffer.DecRef()
|
|
var destination M.Socksaddr
|
|
for {
|
|
buffer.Reset()
|
|
err = src.SetReadDeadline(time.Now().Add(timeout))
|
|
if err != nil {
|
|
return
|
|
}
|
|
destination, err = src.ReadPacket(buffer)
|
|
if err != nil {
|
|
return
|
|
}
|
|
if fOverride {
|
|
destination = fAddr
|
|
}
|
|
dataLen := buffer.Len()
|
|
err = dst.WritePacket(buffer, destination)
|
|
if err != nil {
|
|
return
|
|
}
|
|
n += int64(dataLen)
|
|
}
|
|
}
|