github.com/yaling888/clash@v1.53.0/tunnel/connection.go (about) 1 package tunnel 2 3 import ( 4 "errors" 5 "net" 6 "net/netip" 7 "time" 8 9 N "github.com/yaling888/clash/common/net" 10 "github.com/yaling888/clash/common/pool" 11 C "github.com/yaling888/clash/constant" 12 ) 13 14 func handleUDPToRemote(packet C.UDPPacket, pc C.PacketConn, metadata *C.Metadata) error { 15 if packet.Data() == nil { 16 return errors.New("invalid udp payload") 17 } 18 19 addr := metadata.UDPAddr() 20 if addr == nil { 21 return errors.New("invalid udp addr") 22 } 23 24 if _, err := pc.WriteTo(*packet.Data(), addr); err != nil { 25 return err 26 } 27 // reset timeout 28 _ = pc.SetReadDeadline(time.Now().Add(udpTimeout)) 29 30 return nil 31 } 32 33 func handleUDPToLocal(packet C.UDPPacket, pc net.PacketConn, key, rKey string, oAddr, fAddr netip.Addr) { 34 bufP := pool.GetNetBuf() 35 defer func() { 36 _ = pc.Close() 37 natTable.Delete(key) 38 pool.PutNetBuf(bufP) 39 40 if rKey != "" { 41 addrTable.Delete(rKey) 42 } 43 }() 44 45 for { 46 _ = pc.SetReadDeadline(time.Now().Add(udpTimeout)) 47 n, from, err := pc.ReadFrom(*bufP) 48 if err != nil { 49 return 50 } 51 52 fromUDPAddr := *(from.(*net.UDPAddr)) 53 if fAddr.IsValid() { 54 fromAddr, _ := netip.AddrFromSlice(fromUDPAddr.IP) 55 fromAddr = fromAddr.Unmap() 56 if oAddr == fromAddr { 57 fromUDPAddr.IP = fAddr.AsSlice() 58 fromUDPAddr.Zone = fAddr.Zone() 59 } 60 } 61 62 _, err = packet.WriteBack((*bufP)[:n], &fromUDPAddr) 63 if err != nil { 64 return 65 } 66 } 67 } 68 69 func handleSocket(ctx C.ConnContext, outbound net.Conn) { 70 N.Relay(ctx.Conn(), outbound) 71 }