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

     1  //go:build with_quic
     2  
     3  package inbound
     4  
     5  import (
     6  	"context"
     7  	"net"
     8  	"time"
     9  
    10  	"github.com/inazumav/sing-box/adapter"
    11  	"github.com/inazumav/sing-box/common/tls"
    12  	C "github.com/inazumav/sing-box/constant"
    13  	"github.com/inazumav/sing-box/log"
    14  	"github.com/inazumav/sing-box/option"
    15  	"github.com/inazumav/sing-box/transport/tuic"
    16  	"github.com/sagernet/sing/common"
    17  	"github.com/sagernet/sing/common/auth"
    18  	E "github.com/sagernet/sing/common/exceptions"
    19  	N "github.com/sagernet/sing/common/network"
    20  
    21  	"github.com/gofrs/uuid/v5"
    22  )
    23  
    24  var _ adapter.Inbound = (*TUIC)(nil)
    25  
    26  type TUIC struct {
    27  	myInboundAdapter
    28  	server    *tuic.Server
    29  	tlsConfig tls.ServerConfig
    30  }
    31  
    32  func NewTUIC(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.TUICInboundOptions) (*TUIC, error) {
    33  	options.UDPFragmentDefault = true
    34  	if options.TLS == nil || !options.TLS.Enabled {
    35  		return nil, C.ErrTLSRequired
    36  	}
    37  	tlsConfig, err := tls.NewServer(ctx, logger, common.PtrValueOrDefault(options.TLS))
    38  	if err != nil {
    39  		return nil, err
    40  	}
    41  	var users []tuic.User
    42  	for index, user := range options.Users {
    43  		if user.UUID == "" {
    44  			return nil, E.New("missing uuid for user ", index)
    45  		}
    46  		userUUID, err := uuid.FromString(user.UUID)
    47  		if err != nil {
    48  			return nil, E.Cause(err, "invalid uuid for user ", index)
    49  		}
    50  		users = append(users, tuic.User{Name: user.Name, UUID: userUUID, Password: user.Password})
    51  	}
    52  	inbound := &TUIC{
    53  		myInboundAdapter: myInboundAdapter{
    54  			protocol:      C.TypeTUIC,
    55  			network:       []string{N.NetworkUDP},
    56  			ctx:           ctx,
    57  			router:        router,
    58  			logger:        logger,
    59  			tag:           tag,
    60  			listenOptions: options.ListenOptions,
    61  		},
    62  	}
    63  	server, err := tuic.NewServer(tuic.ServerOptions{
    64  		Context:           ctx,
    65  		Logger:            logger,
    66  		TLSConfig:         tlsConfig,
    67  		Users:             users,
    68  		CongestionControl: options.CongestionControl,
    69  		AuthTimeout:       time.Duration(options.AuthTimeout),
    70  		ZeroRTTHandshake:  options.ZeroRTTHandshake,
    71  		Heartbeat:         time.Duration(options.Heartbeat),
    72  		Handler:           adapter.NewUpstreamHandler(adapter.InboundContext{}, inbound.newConnection, inbound.newPacketConnection, nil),
    73  	})
    74  	if err != nil {
    75  		return nil, err
    76  	}
    77  	inbound.server = server
    78  	return inbound, nil
    79  }
    80  
    81  func (h *TUIC) newConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
    82  	ctx = log.ContextWithNewID(ctx)
    83  	h.logger.InfoContext(ctx, "inbound connection to ", metadata.Destination)
    84  	metadata = h.createMetadata(conn, metadata)
    85  	metadata.User, _ = auth.UserFromContext[string](ctx)
    86  	return h.router.RouteConnection(ctx, conn, metadata)
    87  }
    88  
    89  func (h *TUIC) newPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
    90  	ctx = log.ContextWithNewID(ctx)
    91  	metadata = h.createPacketMetadata(conn, metadata)
    92  	metadata.User, _ = auth.UserFromContext[string](ctx)
    93  	h.logger.InfoContext(ctx, "inbound packet connection to ", metadata.Destination)
    94  	return h.router.RoutePacketConnection(ctx, conn, metadata)
    95  }
    96  
    97  func (h *TUIC) Start() error {
    98  	if h.tlsConfig != nil {
    99  		err := h.tlsConfig.Start()
   100  		if err != nil {
   101  			return err
   102  		}
   103  	}
   104  	packetConn, err := h.myInboundAdapter.ListenUDP()
   105  	if err != nil {
   106  		return err
   107  	}
   108  	return h.server.Start(packetConn)
   109  }
   110  
   111  func (h *TUIC) Close() error {
   112  	return common.Close(
   113  		&h.myInboundAdapter,
   114  		h.tlsConfig,
   115  		common.PtrOrNil(h.server),
   116  	)
   117  }
   118  
   119  func (h *TUIC) AddUsers(users []option.TUICUser) error {
   120  	return h.server.AddUsers(users)
   121  }
   122  
   123  func (h *TUIC) DelUsers(uuids []string) error {
   124  	return h.server.DelUsers(uuids)
   125  }