github.com/v2fly/v2ray-core/v5@v5.16.2-0.20240507031116-8191faa6e095/v2ray.go (about) 1 package core 2 3 import ( 4 "context" 5 "reflect" 6 sync "sync" 7 8 "github.com/v2fly/v2ray-core/v5/common" 9 "github.com/v2fly/v2ray-core/v5/common/environment" 10 "github.com/v2fly/v2ray-core/v5/common/environment/systemnetworkimpl" 11 "github.com/v2fly/v2ray-core/v5/common/environment/transientstorageimpl" 12 "github.com/v2fly/v2ray-core/v5/common/serial" 13 "github.com/v2fly/v2ray-core/v5/features" 14 "github.com/v2fly/v2ray-core/v5/features/dns" 15 "github.com/v2fly/v2ray-core/v5/features/dns/localdns" 16 "github.com/v2fly/v2ray-core/v5/features/inbound" 17 "github.com/v2fly/v2ray-core/v5/features/outbound" 18 "github.com/v2fly/v2ray-core/v5/features/policy" 19 "github.com/v2fly/v2ray-core/v5/features/routing" 20 "github.com/v2fly/v2ray-core/v5/features/stats" 21 ) 22 23 // Server is an instance of V2Ray. At any time, there must be at most one Server instance running. 24 type Server interface { 25 common.Runnable 26 } 27 28 // ServerType returns the type of the server. 29 func ServerType() interface{} { 30 return (*Instance)(nil) 31 } 32 33 type resolution struct { 34 deps []reflect.Type 35 callback interface{} 36 } 37 38 func getFeature(allFeatures []features.Feature, t reflect.Type) features.Feature { 39 for _, f := range allFeatures { 40 if reflect.TypeOf(f.Type()) == t { 41 return f 42 } 43 } 44 return nil 45 } 46 47 func (r *resolution) resolve(allFeatures []features.Feature) (bool, error) { 48 var fs []features.Feature 49 for _, d := range r.deps { 50 f := getFeature(allFeatures, d) 51 if f == nil { 52 return false, nil 53 } 54 fs = append(fs, f) 55 } 56 57 callback := reflect.ValueOf(r.callback) 58 var input []reflect.Value 59 callbackType := callback.Type() 60 for i := 0; i < callbackType.NumIn(); i++ { 61 pt := callbackType.In(i) 62 for _, f := range fs { 63 if reflect.TypeOf(f).AssignableTo(pt) { 64 input = append(input, reflect.ValueOf(f)) 65 break 66 } 67 } 68 } 69 70 if len(input) != callbackType.NumIn() { 71 panic("Can't get all input parameters") 72 } 73 74 var err error 75 ret := callback.Call(input) 76 errInterface := reflect.TypeOf((*error)(nil)).Elem() 77 for i := len(ret) - 1; i >= 0; i-- { 78 if ret[i].Type() == errInterface { 79 v := ret[i].Interface() 80 if v != nil { 81 err = v.(error) 82 } 83 break 84 } 85 } 86 87 return true, err 88 } 89 90 // Instance combines all functionalities in V2Ray. 91 type Instance struct { 92 access sync.Mutex 93 features []features.Feature 94 featureResolutions []resolution 95 running bool 96 env environment.RootEnvironment 97 98 ctx context.Context 99 } 100 101 func AddInboundHandler(server *Instance, config *InboundHandlerConfig) error { 102 inboundManager := server.GetFeature(inbound.ManagerType()).(inbound.Manager) 103 proxyEnv := server.env.ProxyEnvironment("i" + config.Tag) 104 rawHandler, err := CreateObjectWithEnvironment(server, config, proxyEnv) 105 if err != nil { 106 return err 107 } 108 handler, ok := rawHandler.(inbound.Handler) 109 if !ok { 110 return newError("not an InboundHandler") 111 } 112 if err := inboundManager.AddHandler(server.ctx, handler); err != nil { 113 return err 114 } 115 return nil 116 } 117 118 func addInboundHandlers(server *Instance, configs []*InboundHandlerConfig) error { 119 for _, inboundConfig := range configs { 120 if err := AddInboundHandler(server, inboundConfig); err != nil { 121 return err 122 } 123 } 124 125 return nil 126 } 127 128 func AddOutboundHandler(server *Instance, config *OutboundHandlerConfig) error { 129 outboundManager := server.GetFeature(outbound.ManagerType()).(outbound.Manager) 130 proxyEnv := server.env.ProxyEnvironment("o" + config.Tag) 131 rawHandler, err := CreateObjectWithEnvironment(server, config, proxyEnv) 132 if err != nil { 133 return err 134 } 135 handler, ok := rawHandler.(outbound.Handler) 136 if !ok { 137 return newError("not an OutboundHandler") 138 } 139 if err := outboundManager.AddHandler(server.ctx, handler); err != nil { 140 return err 141 } 142 return nil 143 } 144 145 func RemoveOutboundHandler(server *Instance, tag string) error { 146 outboundManager := server.GetFeature(outbound.ManagerType()).(outbound.Manager) 147 if err := outboundManager.RemoveHandler(server.ctx, tag); err != nil { 148 return err 149 } 150 151 if err := server.env.DropProxyEnvironment("o" + tag); err != nil { 152 return err 153 } 154 return nil 155 } 156 157 func addOutboundHandlers(server *Instance, configs []*OutboundHandlerConfig) error { 158 for _, outboundConfig := range configs { 159 if err := AddOutboundHandler(server, outboundConfig); err != nil { 160 return err 161 } 162 } 163 164 return nil 165 } 166 167 // RequireFeatures is a helper function to require features from Instance in context. 168 // See Instance.RequireFeatures for more information. 169 func RequireFeatures(ctx context.Context, callback interface{}) error { 170 v := MustFromContext(ctx) 171 return v.RequireFeatures(callback) 172 } 173 174 // New returns a new V2Ray instance based on given configuration. 175 // The instance is not started at this point. 176 // To ensure V2Ray instance works properly, the config must contain one Dispatcher, one InboundHandlerManager and one OutboundHandlerManager. Other features are optional. 177 func New(config *Config) (*Instance, error) { 178 server := &Instance{ctx: context.Background()} 179 180 done, err := initInstanceWithConfig(config, server) 181 if done { 182 return nil, err 183 } 184 185 return server, nil 186 } 187 188 func NewWithContext(ctx context.Context, config *Config) (*Instance, error) { 189 server := &Instance{ctx: ctx} 190 191 done, err := initInstanceWithConfig(config, server) 192 if done { 193 return nil, err 194 } 195 196 return server, nil 197 } 198 199 func initInstanceWithConfig(config *Config, server *Instance) (bool, error) { 200 if config.Transport != nil { 201 features.PrintDeprecatedFeatureWarning("global transport settings") 202 } 203 if err := config.Transport.Apply(); err != nil { 204 return true, err 205 } 206 207 defaultNetworkImpl := systemnetworkimpl.NewSystemNetworkDefault() 208 server.env = environment.NewRootEnvImpl(server.ctx, transientstorageimpl.NewScopedTransientStorageImpl(), defaultNetworkImpl.Dialer(), defaultNetworkImpl.Listener()) 209 210 for _, appSettings := range config.App { 211 settings, err := serial.GetInstanceOf(appSettings) 212 if err != nil { 213 return true, err 214 } 215 key := appSettings.TypeUrl 216 appEnv := server.env.AppEnvironment(key) 217 obj, err := CreateObjectWithEnvironment(server, settings, appEnv) 218 if err != nil { 219 return true, err 220 } 221 if feature, ok := obj.(features.Feature); ok { 222 if err := server.AddFeature(feature); err != nil { 223 return true, err 224 } 225 } 226 } 227 228 essentialFeatures := []struct { 229 Type interface{} 230 Instance features.Feature 231 }{ 232 {dns.ClientType(), localdns.New()}, 233 {policy.ManagerType(), policy.DefaultManager{}}, 234 {routing.RouterType(), routing.DefaultRouter{}}, 235 {stats.ManagerType(), stats.NoopManager{}}, 236 } 237 238 for _, f := range essentialFeatures { 239 if server.GetFeature(f.Type) == nil { 240 if err := server.AddFeature(f.Instance); err != nil { 241 return true, err 242 } 243 } 244 } 245 246 if server.featureResolutions != nil { 247 return true, newError("not all dependency are resolved.") 248 } 249 250 if err := addInboundHandlers(server, config.Inbound); err != nil { 251 return true, err 252 } 253 254 if err := addOutboundHandlers(server, config.Outbound); err != nil { 255 return true, err 256 } 257 return false, nil 258 } 259 260 // Type implements common.HasType. 261 func (s *Instance) Type() interface{} { 262 return ServerType() 263 } 264 265 // Close shutdown the V2Ray instance. 266 func (s *Instance) Close() error { 267 s.access.Lock() 268 defer s.access.Unlock() 269 270 s.running = false 271 272 var errors []interface{} 273 for _, f := range s.features { 274 if err := f.Close(); err != nil { 275 errors = append(errors, err) 276 } 277 } 278 if len(errors) > 0 { 279 return newError("failed to close all features").Base(newError(serial.Concat(errors...))) 280 } 281 282 return nil 283 } 284 285 // RequireFeatures registers a callback, which will be called when all dependent features are registered. 286 // The callback must be a func(). All its parameters must be features.Feature. 287 func (s *Instance) RequireFeatures(callback interface{}) error { 288 callbackType := reflect.TypeOf(callback) 289 if callbackType.Kind() != reflect.Func { 290 panic("not a function") 291 } 292 293 var featureTypes []reflect.Type 294 for i := 0; i < callbackType.NumIn(); i++ { 295 featureTypes = append(featureTypes, reflect.PtrTo(callbackType.In(i))) 296 } 297 298 r := resolution{ 299 deps: featureTypes, 300 callback: callback, 301 } 302 if finished, err := r.resolve(s.features); finished { 303 return err 304 } 305 s.featureResolutions = append(s.featureResolutions, r) 306 return nil 307 } 308 309 // AddFeature registers a feature into current Instance. 310 func (s *Instance) AddFeature(feature features.Feature) error { 311 s.features = append(s.features, feature) 312 313 if s.running { 314 if err := feature.Start(); err != nil { 315 newError("failed to start feature").Base(err).WriteToLog() 316 } 317 return nil 318 } 319 320 if s.featureResolutions == nil { 321 return nil 322 } 323 324 var pendingResolutions []resolution 325 for _, r := range s.featureResolutions { 326 finished, err := r.resolve(s.features) 327 if finished && err != nil { 328 return err 329 } 330 if !finished { 331 pendingResolutions = append(pendingResolutions, r) 332 } 333 } 334 if len(pendingResolutions) == 0 { 335 s.featureResolutions = nil 336 } else if len(pendingResolutions) < len(s.featureResolutions) { 337 s.featureResolutions = pendingResolutions 338 } 339 340 return nil 341 } 342 343 // GetFeature returns a feature of the given type, or nil if such feature is not registered. 344 func (s *Instance) GetFeature(featureType interface{}) features.Feature { 345 return getFeature(s.features, reflect.TypeOf(featureType)) 346 } 347 348 // Start starts the V2Ray instance, including all registered features. When Start returns error, the state of the instance is unknown. 349 // A V2Ray instance can be started only once. Upon closing, the instance is not guaranteed to start again. 350 // 351 // v2ray:api:stable 352 func (s *Instance) Start() error { 353 s.access.Lock() 354 defer s.access.Unlock() 355 356 s.running = true 357 for _, f := range s.features { 358 if err := f.Start(); err != nil { 359 return err 360 } 361 } 362 363 newError("V2Ray ", Version(), " started").AtWarning().WriteToLog() 364 365 return nil 366 }