github.com/sagernet/sing-box@v1.9.0-rc.20/inbound/default_tcp.go (about) 1 package inbound 2 3 import ( 4 "context" 5 "net" 6 7 "github.com/sagernet/sing-box/adapter" 8 C "github.com/sagernet/sing-box/constant" 9 "github.com/sagernet/sing-box/log" 10 "github.com/sagernet/sing/common/control" 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 // TODO: Add an option to customize the keep alive period 22 listenConfig.KeepAlive = C.TCPKeepAliveInitial 23 listenConfig.Control = control.Append(listenConfig.Control, control.SetKeepAlivePeriod(C.TCPKeepAliveInitial, C.TCPKeepAliveInterval)) 24 if a.listenOptions.TCPMultiPath { 25 if !go121Available { 26 return nil, E.New("MultiPath TCP requires go1.21, please recompile your binary.") 27 } 28 setMultiPathTCP(&listenConfig) 29 } 30 if a.listenOptions.TCPFastOpen { 31 if !go120Available { 32 return nil, E.New("TCP Fast Open requires go1.20, please recompile your binary.") 33 } 34 tcpListener, err = listenTFO(listenConfig, a.ctx, M.NetworkFromNetAddr(N.NetworkTCP, bindAddr.Addr), bindAddr.String()) 35 } else { 36 tcpListener, err = listenConfig.Listen(a.ctx, M.NetworkFromNetAddr(N.NetworkTCP, bindAddr.Addr), bindAddr.String()) 37 } 38 if err == nil { 39 a.logger.Info("tcp server started at ", tcpListener.Addr()) 40 } 41 if a.listenOptions.ProxyProtocol || a.listenOptions.ProxyProtocolAcceptNoHeader { 42 return nil, E.New("Proxy Protocol is deprecated and removed in sing-box 1.6.0") 43 } 44 a.tcpListener = tcpListener 45 return tcpListener, err 46 } 47 48 func (a *myInboundAdapter) loopTCPIn() { 49 tcpListener := a.tcpListener 50 for { 51 conn, err := tcpListener.Accept() 52 if err != nil { 53 //goland:noinspection GoDeprecation 54 //nolint:staticcheck 55 if netError, isNetError := err.(net.Error); isNetError && netError.Temporary() { 56 a.logger.Error(err) 57 continue 58 } 59 if a.inShutdown.Load() && E.IsClosed(err) { 60 return 61 } 62 a.tcpListener.Close() 63 a.logger.Error("serve error: ", err) 64 continue 65 } 66 go a.injectTCP(conn, adapter.InboundContext{}) 67 } 68 } 69 70 func (a *myInboundAdapter) injectTCP(conn net.Conn, metadata adapter.InboundContext) { 71 ctx := log.ContextWithNewID(a.ctx) 72 metadata = a.createMetadata(conn, metadata) 73 a.logger.InfoContext(ctx, "inbound connection from ", metadata.Source) 74 hErr := a.connHandler.NewConnection(ctx, conn, metadata) 75 if hErr != nil { 76 conn.Close() 77 a.NewError(ctx, E.Cause(hErr, "process connection from ", metadata.Source)) 78 } 79 } 80 81 func (a *myInboundAdapter) routeTCP(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) { 82 a.logger.InfoContext(ctx, "inbound connection from ", metadata.Source) 83 hErr := a.newConnection(ctx, conn, metadata) 84 if hErr != nil { 85 conn.Close() 86 a.NewError(ctx, E.Cause(hErr, "process connection from ", metadata.Source)) 87 } 88 }