github.com/inazumav/sing-box@v0.0.0-20230926072359-ab51429a14f1/inbound/default_tcp.go (about)

     1  package inbound
     2  
     3  import (
     4  	"context"
     5  	"net"
     6  	"time"
     7  
     8  	"github.com/inazumav/sing-box/adapter"
     9  	"github.com/inazumav/sing-box/common/proxyproto"
    10  	"github.com/inazumav/sing-box/log"
    11  	E "github.com/sagernet/sing/common/exceptions"
    12  	M "github.com/sagernet/sing/common/metadata"
    13  	N "github.com/sagernet/sing/common/network"
    14  )
    15  
    16  func (a *myInboundAdapter) ListenTCP() (net.Listener, error) {
    17  	var err error
    18  	bindAddr := M.SocksaddrFrom(a.listenOptions.Listen.Build(), a.listenOptions.ListenPort)
    19  	var tcpListener net.Listener
    20  	var listenConfig net.ListenConfig
    21  	if a.listenOptions.TCPMultiPath {
    22  		if !go121Available {
    23  			return nil, E.New("MultiPath TCP requires go1.21, please recompile your binary.")
    24  		}
    25  		setMultiPathTCP(&listenConfig)
    26  	}
    27  	if a.listenOptions.TCPFastOpen {
    28  		if !go120Available {
    29  			return nil, E.New("TCP Fast Open requires go1.20, please recompile your binary.")
    30  		}
    31  		tcpListener, err = listenTFO(listenConfig, a.ctx, M.NetworkFromNetAddr(N.NetworkTCP, bindAddr.Addr), bindAddr.String())
    32  	} else {
    33  		tcpListener, err = listenConfig.Listen(a.ctx, M.NetworkFromNetAddr(N.NetworkTCP, bindAddr.Addr), bindAddr.String())
    34  	}
    35  	if err == nil {
    36  		a.logger.Info("tcp server started at ", tcpListener.Addr())
    37  	}
    38  	if a.listenOptions.ProxyProtocol {
    39  		a.logger.Debug("proxy protocol enabled")
    40  		tcpListener = &proxyproto.Listener{Listener: tcpListener, AcceptNoHeader: a.listenOptions.ProxyProtocolAcceptNoHeader}
    41  	}
    42  	a.tcpListener = tcpListener
    43  	return tcpListener, err
    44  }
    45  
    46  func (a *myInboundAdapter) loopTCPIn() {
    47  	tcpListener := a.tcpListener
    48  	for {
    49  		conn, err := tcpListener.Accept()
    50  		if err != nil {
    51  			//goland:noinspection GoDeprecation
    52  			//nolint:staticcheck
    53  			if netError, isNetError := err.(net.Error); isNetError && netError.Temporary() {
    54  				a.logger.Error(err)
    55  				continue
    56  			}
    57  			if a.inShutdown.Load() && E.IsClosed(err) {
    58  				return
    59  			}
    60  			a.tcpListener.Close()
    61  			a.logger.Error("serve error: ", err)
    62  			continue
    63  		}
    64  		go a.injectTCP(conn, adapter.InboundContext{})
    65  	}
    66  }
    67  
    68  type DelayCloseConn struct {
    69  	time time.Duration
    70  	net.Conn
    71  }
    72  
    73  func (d *DelayCloseConn) Close() error {
    74  	time.Sleep(d.time)
    75  	return d.Conn.Close()
    76  }
    77  
    78  func (a *myInboundAdapter) injectTCP(conn net.Conn, metadata adapter.InboundContext) {
    79  	if a.listenOptions.DelayClose != 0 {
    80  		conn = &DelayCloseConn{
    81  			time: time.Second * time.Duration(a.listenOptions.DelayClose),
    82  			Conn: conn,
    83  		}
    84  	}
    85  	ctx := log.ContextWithNewID(a.ctx)
    86  	metadata = a.createMetadata(conn, metadata)
    87  	a.logger.InfoContext(ctx, "inbound connection from ", metadata.Source)
    88  	hErr := a.connHandler.NewConnection(ctx, conn, metadata)
    89  	if hErr != nil {
    90  		conn.Close()
    91  		a.NewError(ctx, E.Cause(hErr, "process connection from ", metadata.Source))
    92  	}
    93  }
    94  
    95  func (a *myInboundAdapter) routeTCP(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) {
    96  	a.logger.InfoContext(ctx, "inbound connection from ", metadata.Source)
    97  	hErr := a.newConnection(ctx, conn, metadata)
    98  	if hErr != nil {
    99  		conn.Close()
   100  		a.NewError(ctx, E.Cause(hErr, "process connection from ", metadata.Source))
   101  	}
   102  }