github.com/eagleql/xray-core@v1.4.4/transport/internet/tcp/hub.go (about)

     1  package tcp
     2  
     3  import (
     4  	"context"
     5  	gotls "crypto/tls"
     6  	"strings"
     7  	"time"
     8  
     9  	goxtls "github.com/xtls/go"
    10  
    11  	"github.com/eagleql/xray-core/common"
    12  	"github.com/eagleql/xray-core/common/net"
    13  	"github.com/eagleql/xray-core/common/session"
    14  	"github.com/eagleql/xray-core/transport/internet"
    15  	"github.com/eagleql/xray-core/transport/internet/tls"
    16  	"github.com/eagleql/xray-core/transport/internet/xtls"
    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  	xtlsConfig *goxtls.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 =
    42  			l.config.AcceptProxyProtocol || streamSettings.SocketSettings.AcceptProxyProtocol
    43  	}
    44  	var listener net.Listener
    45  	var err error
    46  	if port == net.Port(0) { //unix
    47  		listener, err = internet.ListenSystem(ctx, &net.UnixAddr{
    48  			Name: address.Domain(),
    49  			Net:  "unix",
    50  		}, streamSettings.SocketSettings)
    51  		if err != nil {
    52  			return nil, newError("failed to listen Unix Domain Socket on ", address).Base(err)
    53  		}
    54  		newError("listening Unix Domain Socket on ", address).WriteToLog(session.ExportIDToError(ctx))
    55  		locker := ctx.Value(address.Domain())
    56  		if locker != nil {
    57  			l.locker = locker.(*internet.FileLocker)
    58  		}
    59  	} else {
    60  		listener, err = internet.ListenSystem(ctx, &net.TCPAddr{
    61  			IP:   address.IP(),
    62  			Port: int(port),
    63  		}, streamSettings.SocketSettings)
    64  		if err != nil {
    65  			return nil, newError("failed to listen TCP on ", address, ":", port).Base(err)
    66  		}
    67  		newError("listening TCP on ", address, ":", port).WriteToLog(session.ExportIDToError(ctx))
    68  	}
    69  
    70  	if streamSettings.SocketSettings != nil && streamSettings.SocketSettings.AcceptProxyProtocol {
    71  		newError("accepting PROXY protocol").AtWarning().WriteToLog(session.ExportIDToError(ctx))
    72  	}
    73  
    74  	l.listener = listener
    75  
    76  	if config := tls.ConfigFromStreamSettings(streamSettings); config != nil {
    77  		l.tlsConfig = config.GetTLSConfig()
    78  	}
    79  	if config := xtls.ConfigFromStreamSettings(streamSettings); config != nil {
    80  		l.xtlsConfig = config.GetXTLSConfig()
    81  	}
    82  
    83  	if tcpSettings.HeaderSettings != nil {
    84  		headerConfig, err := tcpSettings.HeaderSettings.GetInstance()
    85  		if err != nil {
    86  			return nil, newError("invalid header settings").Base(err).AtError()
    87  		}
    88  		auth, err := internet.CreateConnectionAuthenticator(headerConfig)
    89  		if err != nil {
    90  			return nil, newError("invalid header settings.").Base(err).AtError()
    91  		}
    92  		l.authConfig = auth
    93  	}
    94  
    95  	go l.keepAccepting()
    96  	return l, nil
    97  }
    98  
    99  func (v *Listener) keepAccepting() {
   100  	for {
   101  		conn, err := v.listener.Accept()
   102  		if err != nil {
   103  			errStr := err.Error()
   104  			if strings.Contains(errStr, "closed") {
   105  				break
   106  			}
   107  			newError("failed to accepted raw connections").Base(err).AtWarning().WriteToLog()
   108  			if strings.Contains(errStr, "too many") {
   109  				time.Sleep(time.Millisecond * 500)
   110  			}
   111  			continue
   112  		}
   113  
   114  		if v.tlsConfig != nil {
   115  			conn = tls.Server(conn, v.tlsConfig)
   116  		} else if v.xtlsConfig != nil {
   117  			conn = xtls.Server(conn, v.xtlsConfig)
   118  		}
   119  		if v.authConfig != nil {
   120  			conn = v.authConfig.Server(conn)
   121  		}
   122  
   123  		v.addConn(internet.Connection(conn))
   124  	}
   125  }
   126  
   127  // Addr implements internet.Listener.Addr.
   128  func (v *Listener) Addr() net.Addr {
   129  	return v.listener.Addr()
   130  }
   131  
   132  // Close implements internet.Listener.Close.
   133  func (v *Listener) Close() error {
   134  	if v.locker != nil {
   135  		v.locker.Release()
   136  	}
   137  	return v.listener.Close()
   138  }
   139  
   140  func init() {
   141  	common.Must(internet.RegisterTransportListener(protocolName, ListenTCP))
   142  }