github.com/sagernet/sing-box@v1.2.7/inbound/direct.go (about)

     1  package inbound
     2  
     3  import (
     4  	"context"
     5  	"net"
     6  	"net/netip"
     7  
     8  	"github.com/sagernet/sing-box/adapter"
     9  	C "github.com/sagernet/sing-box/constant"
    10  	"github.com/sagernet/sing-box/log"
    11  	"github.com/sagernet/sing-box/option"
    12  	"github.com/sagernet/sing/common/buf"
    13  	M "github.com/sagernet/sing/common/metadata"
    14  	N "github.com/sagernet/sing/common/network"
    15  	"github.com/sagernet/sing/common/udpnat"
    16  )
    17  
    18  var _ adapter.Inbound = (*Direct)(nil)
    19  
    20  type Direct struct {
    21  	myInboundAdapter
    22  	udpNat              *udpnat.Service[netip.AddrPort]
    23  	overrideOption      int
    24  	overrideDestination M.Socksaddr
    25  }
    26  
    27  func NewDirect(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.DirectInboundOptions) *Direct {
    28  	options.UDPFragmentDefault = true
    29  	inbound := &Direct{
    30  		myInboundAdapter: myInboundAdapter{
    31  			protocol:      C.TypeDirect,
    32  			network:       options.Network.Build(),
    33  			ctx:           ctx,
    34  			router:        router,
    35  			logger:        logger,
    36  			tag:           tag,
    37  			listenOptions: options.ListenOptions,
    38  		},
    39  	}
    40  	if options.OverrideAddress != "" && options.OverridePort != 0 {
    41  		inbound.overrideOption = 1
    42  		inbound.overrideDestination = M.ParseSocksaddrHostPort(options.OverrideAddress, options.OverridePort)
    43  	} else if options.OverrideAddress != "" {
    44  		inbound.overrideOption = 2
    45  		inbound.overrideDestination = M.ParseSocksaddrHostPort(options.OverrideAddress, options.OverridePort)
    46  	} else if options.OverridePort != 0 {
    47  		inbound.overrideOption = 3
    48  		inbound.overrideDestination = M.Socksaddr{Port: options.OverridePort}
    49  	}
    50  	var udpTimeout int64
    51  	if options.UDPTimeout != 0 {
    52  		udpTimeout = options.UDPTimeout
    53  	} else {
    54  		udpTimeout = int64(C.UDPTimeout.Seconds())
    55  	}
    56  	inbound.udpNat = udpnat.New[netip.AddrPort](udpTimeout, adapter.NewUpstreamContextHandler(inbound.newConnection, inbound.newPacketConnection, inbound))
    57  	inbound.connHandler = inbound
    58  	inbound.packetHandler = inbound
    59  	inbound.packetUpstream = inbound.udpNat
    60  	return inbound
    61  }
    62  
    63  func (d *Direct) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
    64  	switch d.overrideOption {
    65  	case 1:
    66  		metadata.Destination = d.overrideDestination
    67  	case 2:
    68  		destination := d.overrideDestination
    69  		destination.Port = metadata.Destination.Port
    70  		metadata.Destination = destination
    71  	case 3:
    72  		metadata.Destination.Port = d.overrideDestination.Port
    73  	}
    74  	d.logger.InfoContext(ctx, "inbound connection to ", metadata.Destination)
    75  	return d.router.RouteConnection(ctx, conn, metadata)
    76  }
    77  
    78  func (d *Direct) NewPacket(ctx context.Context, conn N.PacketConn, buffer *buf.Buffer, metadata adapter.InboundContext) error {
    79  	switch d.overrideOption {
    80  	case 1:
    81  		metadata.Destination = d.overrideDestination
    82  	case 2:
    83  		destination := d.overrideDestination
    84  		destination.Port = metadata.Destination.Port
    85  		metadata.Destination = destination
    86  	case 3:
    87  		metadata.Destination.Port = d.overrideDestination.Port
    88  	}
    89  	d.udpNat.NewContextPacket(ctx, metadata.Source.AddrPort(), buffer, adapter.UpstreamMetadata(metadata), func(natConn N.PacketConn) (context.Context, N.PacketWriter) {
    90  		return adapter.WithContext(log.ContextWithNewID(ctx), &metadata), &udpnat.DirectBackWriter{Source: conn, Nat: natConn}
    91  	})
    92  	return nil
    93  }
    94  
    95  func (d *Direct) newConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
    96  	return d.router.RouteConnection(ctx, conn, metadata)
    97  }
    98  
    99  func (d *Direct) newPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
   100  	ctx = log.ContextWithNewID(ctx)
   101  	d.logger.InfoContext(ctx, "inbound packet connection from ", metadata.Source)
   102  	return d.router.RoutePacketConnection(ctx, conn, metadata)
   103  }