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 }