github.com/sagernet/sing-box@v1.9.0-rc.20/inbound/default_udp.go (about)

     1  package inbound
     2  
     3  import (
     4  	"net"
     5  	"os"
     6  	"time"
     7  
     8  	"github.com/sagernet/sing-box/adapter"
     9  	"github.com/sagernet/sing/common"
    10  	"github.com/sagernet/sing/common/buf"
    11  	"github.com/sagernet/sing/common/control"
    12  	E "github.com/sagernet/sing/common/exceptions"
    13  	M "github.com/sagernet/sing/common/metadata"
    14  	N "github.com/sagernet/sing/common/network"
    15  )
    16  
    17  func (a *myInboundAdapter) ListenUDP() (net.PacketConn, error) {
    18  	bindAddr := M.SocksaddrFrom(a.listenOptions.Listen.Build(), a.listenOptions.ListenPort)
    19  	var lc net.ListenConfig
    20  	var udpFragment bool
    21  	if a.listenOptions.UDPFragment != nil {
    22  		udpFragment = *a.listenOptions.UDPFragment
    23  	} else {
    24  		udpFragment = a.listenOptions.UDPFragmentDefault
    25  	}
    26  	if !udpFragment {
    27  		lc.Control = control.Append(lc.Control, control.DisableUDPFragment())
    28  	}
    29  	udpConn, err := lc.ListenPacket(a.ctx, M.NetworkFromNetAddr(N.NetworkUDP, bindAddr.Addr), bindAddr.String())
    30  	if err != nil {
    31  		return nil, err
    32  	}
    33  	a.udpConn = udpConn.(*net.UDPConn)
    34  	a.udpAddr = bindAddr
    35  	a.logger.Info("udp server started at ", udpConn.LocalAddr())
    36  	return udpConn, err
    37  }
    38  
    39  func (a *myInboundAdapter) loopUDPIn() {
    40  	defer close(a.packetOutboundClosed)
    41  	buffer := buf.NewPacket()
    42  	defer buffer.Release()
    43  	buffer.IncRef()
    44  	defer buffer.DecRef()
    45  	packetService := (*myInboundPacketAdapter)(a)
    46  	for {
    47  		buffer.Reset()
    48  		n, addr, err := a.udpConn.ReadFromUDPAddrPort(buffer.FreeBytes())
    49  		if err != nil {
    50  			return
    51  		}
    52  		buffer.Truncate(n)
    53  		var metadata adapter.InboundContext
    54  		metadata.Inbound = a.tag
    55  		metadata.InboundType = a.protocol
    56  		metadata.InboundOptions = a.listenOptions.InboundOptions
    57  		metadata.Source = M.SocksaddrFromNetIP(addr).Unwrap()
    58  		metadata.OriginDestination = a.udpAddr
    59  		err = a.packetHandler.NewPacket(a.ctx, packetService, buffer, metadata)
    60  		if err != nil {
    61  			a.newError(E.Cause(err, "process packet from ", metadata.Source))
    62  		}
    63  	}
    64  }
    65  
    66  func (a *myInboundAdapter) loopUDPOOBIn() {
    67  	defer close(a.packetOutboundClosed)
    68  	buffer := buf.NewPacket()
    69  	defer buffer.Release()
    70  	buffer.IncRef()
    71  	defer buffer.DecRef()
    72  	packetService := (*myInboundPacketAdapter)(a)
    73  	oob := make([]byte, 1024)
    74  	for {
    75  		buffer.Reset()
    76  		n, oobN, _, addr, err := a.udpConn.ReadMsgUDPAddrPort(buffer.FreeBytes(), oob)
    77  		if err != nil {
    78  			return
    79  		}
    80  		buffer.Truncate(n)
    81  		var metadata adapter.InboundContext
    82  		metadata.Inbound = a.tag
    83  		metadata.InboundType = a.protocol
    84  		metadata.InboundOptions = a.listenOptions.InboundOptions
    85  		metadata.Source = M.SocksaddrFromNetIP(addr).Unwrap()
    86  		metadata.OriginDestination = a.udpAddr
    87  		err = a.oobPacketHandler.NewPacket(a.ctx, packetService, buffer, oob[:oobN], metadata)
    88  		if err != nil {
    89  			a.newError(E.Cause(err, "process packet from ", metadata.Source))
    90  		}
    91  	}
    92  }
    93  
    94  func (a *myInboundAdapter) loopUDPInThreadSafe() {
    95  	defer close(a.packetOutboundClosed)
    96  	packetService := (*myInboundPacketAdapter)(a)
    97  	for {
    98  		buffer := buf.NewPacket()
    99  		n, addr, err := a.udpConn.ReadFromUDPAddrPort(buffer.FreeBytes())
   100  		if err != nil {
   101  			buffer.Release()
   102  			return
   103  		}
   104  		buffer.Truncate(n)
   105  		var metadata adapter.InboundContext
   106  		metadata.Inbound = a.tag
   107  		metadata.InboundType = a.protocol
   108  		metadata.InboundOptions = a.listenOptions.InboundOptions
   109  		metadata.Source = M.SocksaddrFromNetIP(addr).Unwrap()
   110  		metadata.OriginDestination = a.udpAddr
   111  		err = a.packetHandler.NewPacket(a.ctx, packetService, buffer, metadata)
   112  		if err != nil {
   113  			buffer.Release()
   114  			a.newError(E.Cause(err, "process packet from ", metadata.Source))
   115  		}
   116  	}
   117  }
   118  
   119  func (a *myInboundAdapter) loopUDPOOBInThreadSafe() {
   120  	defer close(a.packetOutboundClosed)
   121  	packetService := (*myInboundPacketAdapter)(a)
   122  	oob := make([]byte, 1024)
   123  	for {
   124  		buffer := buf.NewPacket()
   125  		n, oobN, _, addr, err := a.udpConn.ReadMsgUDPAddrPort(buffer.FreeBytes(), oob)
   126  		if err != nil {
   127  			buffer.Release()
   128  			return
   129  		}
   130  		buffer.Truncate(n)
   131  		var metadata adapter.InboundContext
   132  		metadata.Inbound = a.tag
   133  		metadata.InboundType = a.protocol
   134  		metadata.InboundOptions = a.listenOptions.InboundOptions
   135  		metadata.Source = M.SocksaddrFromNetIP(addr).Unwrap()
   136  		metadata.OriginDestination = a.udpAddr
   137  		err = a.oobPacketHandler.NewPacket(a.ctx, packetService, buffer, oob[:oobN], metadata)
   138  		if err != nil {
   139  			buffer.Release()
   140  			a.newError(E.Cause(err, "process packet from ", metadata.Source))
   141  		}
   142  	}
   143  }
   144  
   145  func (a *myInboundAdapter) loopUDPOut() {
   146  	for {
   147  		select {
   148  		case packet := <-a.packetOutbound:
   149  			err := a.writePacket(packet.buffer, packet.destination)
   150  			if err != nil && !E.IsClosed(err) {
   151  				a.newError(E.New("write back udp: ", err))
   152  			}
   153  			continue
   154  		case <-a.packetOutboundClosed:
   155  		}
   156  		for {
   157  			select {
   158  			case packet := <-a.packetOutbound:
   159  				packet.buffer.Release()
   160  			default:
   161  				return
   162  			}
   163  		}
   164  	}
   165  }
   166  
   167  func (a *myInboundAdapter) writePacket(buffer *buf.Buffer, destination M.Socksaddr) error {
   168  	defer buffer.Release()
   169  	if destination.IsFqdn() {
   170  		udpAddr, err := net.ResolveUDPAddr(N.NetworkUDP, destination.String())
   171  		if err != nil {
   172  			return err
   173  		}
   174  		return common.Error(a.udpConn.WriteTo(buffer.Bytes(), udpAddr))
   175  	}
   176  	return common.Error(a.udpConn.WriteToUDPAddrPort(buffer.Bytes(), destination.AddrPort()))
   177  }
   178  
   179  type myInboundPacketAdapter myInboundAdapter
   180  
   181  func (s *myInboundPacketAdapter) ReadPacket(buffer *buf.Buffer) (M.Socksaddr, error) {
   182  	n, addr, err := s.udpConn.ReadFromUDPAddrPort(buffer.FreeBytes())
   183  	if err != nil {
   184  		return M.Socksaddr{}, err
   185  	}
   186  	buffer.Truncate(n)
   187  	return M.SocksaddrFromNetIP(addr), nil
   188  }
   189  
   190  func (s *myInboundPacketAdapter) WriteIsThreadUnsafe() {
   191  }
   192  
   193  type myInboundPacket struct {
   194  	buffer      *buf.Buffer
   195  	destination M.Socksaddr
   196  }
   197  
   198  func (s *myInboundPacketAdapter) Upstream() any {
   199  	return s.udpConn
   200  }
   201  
   202  func (s *myInboundPacketAdapter) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error {
   203  	select {
   204  	case s.packetOutbound <- &myInboundPacket{buffer, destination}:
   205  		return nil
   206  	case <-s.packetOutboundClosed:
   207  		return os.ErrClosed
   208  	}
   209  }
   210  
   211  func (s *myInboundPacketAdapter) Close() error {
   212  	return s.udpConn.Close()
   213  }
   214  
   215  func (s *myInboundPacketAdapter) LocalAddr() net.Addr {
   216  	return s.udpConn.LocalAddr()
   217  }
   218  
   219  func (s *myInboundPacketAdapter) SetDeadline(t time.Time) error {
   220  	return s.udpConn.SetDeadline(t)
   221  }
   222  
   223  func (s *myInboundPacketAdapter) SetReadDeadline(t time.Time) error {
   224  	return s.udpConn.SetReadDeadline(t)
   225  }
   226  
   227  func (s *myInboundPacketAdapter) SetWriteDeadline(t time.Time) error {
   228  	return s.udpConn.SetWriteDeadline(t)
   229  }