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