github.com/sagernet/sing-box@v1.9.0-rc.20/inbound/http.go (about)

     1  package inbound
     2  
     3  import (
     4  	std_bufio "bufio"
     5  	"context"
     6  	"net"
     7  	"os"
     8  
     9  	"github.com/sagernet/sing-box/adapter"
    10  	"github.com/sagernet/sing-box/common/tls"
    11  	"github.com/sagernet/sing-box/common/uot"
    12  	C "github.com/sagernet/sing-box/constant"
    13  	"github.com/sagernet/sing-box/log"
    14  	"github.com/sagernet/sing-box/option"
    15  	"github.com/sagernet/sing/common"
    16  	"github.com/sagernet/sing/common/auth"
    17  	E "github.com/sagernet/sing/common/exceptions"
    18  	N "github.com/sagernet/sing/common/network"
    19  	"github.com/sagernet/sing/protocol/http"
    20  )
    21  
    22  var (
    23  	_ adapter.Inbound           = (*HTTP)(nil)
    24  	_ adapter.InjectableInbound = (*HTTP)(nil)
    25  )
    26  
    27  type HTTP struct {
    28  	myInboundAdapter
    29  	authenticator *auth.Authenticator
    30  	tlsConfig     tls.ServerConfig
    31  }
    32  
    33  func NewHTTP(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.HTTPMixedInboundOptions) (*HTTP, error) {
    34  	inbound := &HTTP{
    35  		myInboundAdapter: myInboundAdapter{
    36  			protocol:       C.TypeHTTP,
    37  			network:        []string{N.NetworkTCP},
    38  			ctx:            ctx,
    39  			router:         uot.NewRouter(router, logger),
    40  			logger:         logger,
    41  			tag:            tag,
    42  			listenOptions:  options.ListenOptions,
    43  			setSystemProxy: options.SetSystemProxy,
    44  		},
    45  		authenticator: auth.NewAuthenticator(options.Users),
    46  	}
    47  	if options.TLS != nil {
    48  		tlsConfig, err := tls.NewServer(ctx, logger, common.PtrValueOrDefault(options.TLS))
    49  		if err != nil {
    50  			return nil, err
    51  		}
    52  		inbound.tlsConfig = tlsConfig
    53  	}
    54  	inbound.connHandler = inbound
    55  	return inbound, nil
    56  }
    57  
    58  func (h *HTTP) Start() error {
    59  	if h.tlsConfig != nil {
    60  		err := h.tlsConfig.Start()
    61  		if err != nil {
    62  			return E.Cause(err, "create TLS config")
    63  		}
    64  	}
    65  	return h.myInboundAdapter.Start()
    66  }
    67  
    68  func (h *HTTP) Close() error {
    69  	return common.Close(
    70  		&h.myInboundAdapter,
    71  		h.tlsConfig,
    72  	)
    73  }
    74  
    75  func (h *HTTP) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
    76  	var err error
    77  	if h.tlsConfig != nil {
    78  		conn, err = tls.ServerHandshake(ctx, conn, h.tlsConfig)
    79  		if err != nil {
    80  			return err
    81  		}
    82  	}
    83  	return http.HandleConnection(ctx, conn, std_bufio.NewReader(conn), h.authenticator, h.upstreamUserHandler(metadata), adapter.UpstreamMetadata(metadata))
    84  }
    85  
    86  func (h *HTTP) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
    87  	return os.ErrInvalid
    88  }
    89  
    90  func (a *myInboundAdapter) upstreamUserHandler(metadata adapter.InboundContext) adapter.UpstreamHandlerAdapter {
    91  	return adapter.NewUpstreamHandler(metadata, a.newUserConnection, a.streamUserPacketConnection, a)
    92  }
    93  
    94  func (a *myInboundAdapter) newUserConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
    95  	user, loaded := auth.UserFromContext[string](ctx)
    96  	if !loaded {
    97  		a.logger.InfoContext(ctx, "inbound connection to ", metadata.Destination)
    98  		return a.router.RouteConnection(ctx, conn, metadata)
    99  	}
   100  	metadata.User = user
   101  	a.logger.InfoContext(ctx, "[", user, "] inbound connection to ", metadata.Destination)
   102  	return a.router.RouteConnection(ctx, conn, metadata)
   103  }
   104  
   105  func (a *myInboundAdapter) streamUserPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
   106  	user, loaded := auth.UserFromContext[string](ctx)
   107  	if !loaded {
   108  		a.logger.InfoContext(ctx, "inbound packet connection to ", metadata.Destination)
   109  		return a.router.RoutePacketConnection(ctx, conn, metadata)
   110  	}
   111  	metadata.User = user
   112  	a.logger.InfoContext(ctx, "[", user, "] inbound packet connection to ", metadata.Destination)
   113  	return a.router.RoutePacketConnection(ctx, conn, metadata)
   114  }