github.com/kelleygo/clashcore@v1.0.2/tunnel/connection.go (about)

     1  package tunnel
     2  
     3  import (
     4  	"errors"
     5  	"net"
     6  	"net/netip"
     7  	"time"
     8  
     9  	N "github.com/kelleygo/clashcore/common/net"
    10  	C "github.com/kelleygo/clashcore/constant"
    11  	"github.com/kelleygo/clashcore/log"
    12  )
    13  
    14  func handleUDPToRemote(packet C.UDPPacket, pc C.PacketConn, metadata *C.Metadata) error {
    15  	addr := metadata.UDPAddr()
    16  	if addr == nil {
    17  		return errors.New("udp addr invalid")
    18  	}
    19  
    20  	if _, err := pc.WriteTo(packet.Data(), addr); err != nil {
    21  		return err
    22  	}
    23  	// reset timeout
    24  	_ = pc.SetReadDeadline(time.Now().Add(udpTimeout))
    25  
    26  	return nil
    27  }
    28  
    29  func handleUDPToLocal(writeBack C.WriteBack, pc N.EnhancePacketConn, key string, oAddrPort netip.AddrPort, fAddr netip.Addr) {
    30  	defer func() {
    31  		_ = pc.Close()
    32  		closeAllLocalCoon(key)
    33  		natTable.Delete(key)
    34  	}()
    35  
    36  	for {
    37  		_ = pc.SetReadDeadline(time.Now().Add(udpTimeout))
    38  		data, put, from, err := pc.WaitReadFrom()
    39  		if err != nil {
    40  			return
    41  		}
    42  
    43  		fromUDPAddr, isUDPAddr := from.(*net.UDPAddr)
    44  		if !isUDPAddr {
    45  			fromUDPAddr = net.UDPAddrFromAddrPort(oAddrPort) // oAddrPort was Unmapped
    46  			log.Warnln("server return a [%T](%s) which isn't a *net.UDPAddr, force replace to (%s), this may be caused by a wrongly implemented server", from, from, oAddrPort)
    47  		} else if fromUDPAddr == nil {
    48  			fromUDPAddr = net.UDPAddrFromAddrPort(oAddrPort) // oAddrPort was Unmapped
    49  			log.Warnln("server return a nil *net.UDPAddr, force replace to (%s), this may be caused by a wrongly implemented server", oAddrPort)
    50  		} else {
    51  			_fromUDPAddr := *fromUDPAddr
    52  			fromUDPAddr = &_fromUDPAddr // make a copy
    53  			if fromAddr, ok := netip.AddrFromSlice(fromUDPAddr.IP); ok {
    54  				fromAddr = fromAddr.Unmap()
    55  				if fAddr.IsValid() && (oAddrPort.Addr() == fromAddr) { // oAddrPort was Unmapped
    56  					fromAddr = fAddr.Unmap()
    57  				}
    58  				fromUDPAddr.IP = fromAddr.AsSlice()
    59  				if fromAddr.Is4() {
    60  					fromUDPAddr.Zone = "" // only ipv6 can have the zone
    61  				}
    62  			}
    63  		}
    64  
    65  		_, err = writeBack.WriteBack(data, fromUDPAddr)
    66  		if put != nil {
    67  			put()
    68  		}
    69  		if err != nil {
    70  			return
    71  		}
    72  	}
    73  }
    74  
    75  func closeAllLocalCoon(lAddr string) {
    76  	natTable.RangeForLocalConn(lAddr, func(key string, value *net.UDPConn) bool {
    77  		conn := value
    78  
    79  		conn.Close()
    80  		log.Debugln("Closing TProxy local conn... lAddr=%s rAddr=%s", lAddr, key)
    81  		return true
    82  	})
    83  }
    84  
    85  func handleSocket(inbound, outbound net.Conn) {
    86  	N.Relay(inbound, outbound)
    87  }