github.com/xraypb/Xray-core@v1.8.1/transport/internet/tcp/hub.go (about)

     1  package tcp
     2  
     3  import (
     4  	"context"
     5  	gotls "crypto/tls"
     6  	"strings"
     7  	"time"
     8  
     9  	"github.com/xraypb/Xray-core/common"
    10  	"github.com/xraypb/Xray-core/common/net"
    11  	"github.com/xraypb/Xray-core/common/session"
    12  	"github.com/xraypb/Xray-core/transport/internet"
    13  	"github.com/xraypb/Xray-core/transport/internet/reality"
    14  	"github.com/xraypb/Xray-core/transport/internet/stat"
    15  	"github.com/xraypb/Xray-core/transport/internet/tls"
    16  	goreality "github.com/xtls/reality"
    17  )
    18  
    19  // Listener is an internet.Listener that listens for TCP connections.
    20  type Listener struct {
    21  	listener      net.Listener
    22  	tlsConfig     *gotls.Config
    23  	realityConfig *goreality.Config
    24  	authConfig    internet.ConnectionAuthenticator
    25  	config        *Config
    26  	addConn       internet.ConnHandler
    27  	locker        *internet.FileLocker // for unix domain socket
    28  }
    29  
    30  // ListenTCP creates a new Listener based on configurations.
    31  func ListenTCP(ctx context.Context, address net.Address, port net.Port, streamSettings *internet.MemoryStreamConfig, handler internet.ConnHandler) (internet.Listener, error) {
    32  	l := &Listener{
    33  		addConn: handler,
    34  	}
    35  	tcpSettings := streamSettings.ProtocolSettings.(*Config)
    36  	l.config = tcpSettings
    37  	if l.config != nil {
    38  		if streamSettings.SocketSettings == nil {
    39  			streamSettings.SocketSettings = &internet.SocketConfig{}
    40  		}
    41  		streamSettings.SocketSettings.AcceptProxyProtocol = l.config.AcceptProxyProtocol || streamSettings.SocketSettings.AcceptProxyProtocol
    42  	}
    43  	var listener net.Listener
    44  	var err error
    45  	if port == net.Port(0) { // unix
    46  		listener, err = internet.ListenSystem(ctx, &net.UnixAddr{
    47  			Name: address.Domain(),
    48  			Net:  "unix",
    49  		}, streamSettings.SocketSettings)
    50  		if err != nil {
    51  			return nil, newError("failed to listen Unix Domain Socket on ", address).Base(err)
    52  		}
    53  		newError("listening Unix Domain Socket on ", address).WriteToLog(session.ExportIDToError(ctx))
    54  		locker := ctx.Value(address.Domain())
    55  		if locker != nil {
    56  			l.locker = locker.(*internet.FileLocker)
    57  		}
    58  	} else {
    59  		listener, err = internet.ListenSystem(ctx, &net.TCPAddr{
    60  			IP:   address.IP(),
    61  			Port: int(port),
    62  		}, streamSettings.SocketSettings)
    63  		if err != nil {
    64  			return nil, newError("failed to listen TCP on ", address, ":", port).Base(err)
    65  		}
    66  		newError("listening TCP on ", address, ":", port).WriteToLog(session.ExportIDToError(ctx))
    67  	}
    68  
    69  	if streamSettings.SocketSettings != nil && streamSettings.SocketSettings.AcceptProxyProtocol {
    70  		newError("accepting PROXY protocol").AtWarning().WriteToLog(session.ExportIDToError(ctx))
    71  	}
    72  
    73  	l.listener = listener
    74  
    75  	if config := tls.ConfigFromStreamSettings(streamSettings); config != nil {
    76  		l.tlsConfig = config.GetTLSConfig()
    77  	}
    78  	if config := reality.ConfigFromStreamSettings(streamSettings); config != nil {
    79  		l.realityConfig = config.GetREALITYConfig()
    80  	}
    81  
    82  	if tcpSettings.HeaderSettings != nil {
    83  		headerConfig, err := tcpSettings.HeaderSettings.GetInstance()
    84  		if err != nil {
    85  			return nil, newError("invalid header settings").Base(err).AtError()
    86  		}
    87  		auth, err := internet.CreateConnectionAuthenticator(headerConfig)
    88  		if err != nil {
    89  			return nil, newError("invalid header settings.").Base(err).AtError()
    90  		}
    91  		l.authConfig = auth
    92  	}
    93  
    94  	go l.keepAccepting()
    95  	return l, nil
    96  }
    97  
    98  func (v *Listener) keepAccepting() {
    99  	for {
   100  		conn, err := v.listener.Accept()
   101  		if err != nil {
   102  			errStr := err.Error()
   103  			if strings.Contains(errStr, "closed") {
   104  				break
   105  			}
   106  			newError("failed to accepted raw connections").Base(err).AtWarning().WriteToLog()
   107  			if strings.Contains(errStr, "too many") {
   108  				time.Sleep(time.Millisecond * 500)
   109  			}
   110  			continue
   111  		}
   112  		go func() {
   113  			if v.tlsConfig != nil {
   114  				conn = tls.Server(conn, v.tlsConfig)
   115  			} else if v.realityConfig != nil {
   116  				if conn, err = reality.Server(conn, v.realityConfig); err != nil {
   117  					newError(err).AtInfo().WriteToLog()
   118  					return
   119  				}
   120  			}
   121  			if v.authConfig != nil {
   122  				conn = v.authConfig.Server(conn)
   123  			}
   124  			v.addConn(stat.Connection(conn))
   125  		}()
   126  	}
   127  }
   128  
   129  // Addr implements internet.Listener.Addr.
   130  func (v *Listener) Addr() net.Addr {
   131  	return v.listener.Addr()
   132  }
   133  
   134  // Close implements internet.Listener.Close.
   135  func (v *Listener) Close() error {
   136  	if v.locker != nil {
   137  		v.locker.Release()
   138  	}
   139  	return v.listener.Close()
   140  }
   141  
   142  func init() {
   143  	common.Must(internet.RegisterTransportListener(protocolName, ListenTCP))
   144  }