2016-10-12 10:46:02 -04:00
package core
2015-09-05 11:48:38 -04:00
import (
2017-01-12 18:56:21 -05:00
"context"
2018-02-07 06:34:15 -05:00
"sync"
2017-01-12 18:56:21 -05:00
2017-02-10 10:54:51 -05:00
"v2ray.com/core/common"
2018-05-31 05:55:11 -04:00
"v2ray.com/core/common/serial"
2018-10-11 16:34:31 -04:00
"v2ray.com/core/features"
"v2ray.com/core/features/dns"
2018-10-11 15:14:53 -04:00
"v2ray.com/core/features/inbound"
2018-10-11 14:43:37 -04:00
"v2ray.com/core/features/outbound"
2018-10-11 16:34:31 -04:00
"v2ray.com/core/features/policy"
2018-10-11 14:43:37 -04:00
"v2ray.com/core/features/routing"
2015-09-05 11:48:38 -04:00
)
2017-02-10 10:25:54 -05:00
// Server is an instance of V2Ray. At any time, there must be at most one Server instance running.
type Server interface {
2018-01-10 06:22:37 -05:00
common . Runnable
2017-02-10 10:25:54 -05:00
}
2018-10-21 04:27:13 -04:00
// ServerType returns the type of the server.
func ServerType ( ) interface { } {
return ( * Instance ) ( nil )
}
type resolution struct {
deps [ ] interface { }
callback func ( [ ] features . Feature )
}
func getFeature ( allFeatures [ ] features . Feature , t interface { } ) features . Feature {
for _ , f := range allFeatures {
if f . Type ( ) == t {
return f
}
}
return nil
}
func ( r * resolution ) resolve ( allFeatures [ ] features . Feature ) bool {
var fs [ ] features . Feature
for _ , d := range r . deps {
f := getFeature ( allFeatures , d )
if f == nil {
return false
}
fs = append ( fs , f )
}
r . callback ( fs )
return true
}
2018-01-10 06:22:37 -05:00
// Instance combines all functionalities in V2Ray.
type Instance struct {
2018-10-21 04:27:13 -04:00
access sync . Mutex
features [ ] features . Feature
featureResolutions [ ] resolution
running bool
2017-02-10 10:25:54 -05:00
}
2018-10-21 13:41:12 -04:00
func addInboundHandlers ( server * Instance , configs [ ] * InboundHandlerConfig ) error {
if len ( configs ) == 0 {
return nil
}
inboundManager := server . GetFeature ( inbound . ManagerType ( ) ) . ( inbound . Manager )
for _ , inboundConfig := range configs {
rawHandler , err := CreateObject ( server , inboundConfig )
if err != nil {
return err
}
handler , ok := rawHandler . ( inbound . Handler )
if ! ok {
return newError ( "not an InboundHandler" )
}
if err := inboundManager . AddHandler ( context . Background ( ) , handler ) ; err != nil {
return err
}
}
return nil
}
func addOutboundHandlers ( server * Instance , configs [ ] * OutboundHandlerConfig ) error {
if len ( configs ) == 0 {
return nil
}
outboundManager := server . GetFeature ( outbound . ManagerType ( ) ) . ( outbound . Manager )
for _ , outboundConfig := range configs {
rawHandler , err := CreateObject ( server , outboundConfig )
if err != nil {
return err
}
handler , ok := rawHandler . ( outbound . Handler )
if ! ok {
return newError ( "not an OutboundHandler" )
}
if err := outboundManager . AddHandler ( context . Background ( ) , handler ) ; err != nil {
return err
}
}
return nil
}
2018-01-10 06:22:37 -05:00
// New returns a new V2Ray instance based on given configuration.
// The instance is not started at this point.
2018-04-03 05:11:54 -04:00
// To ensure V2Ray instance works properly, the config must contain one Dispatcher, one InboundHandlerManager and one OutboundHandlerManager. Other features are optional.
2018-01-10 06:22:37 -05:00
func New ( config * Config ) ( * Instance , error ) {
2018-10-21 04:27:13 -04:00
var server = & Instance { }
2015-09-12 05:51:42 -04:00
2018-09-21 10:54:06 -04:00
if config . Transport != nil {
2018-10-13 09:15:49 -04:00
features . PrintDeprecatedFeatureWarning ( "global transport settings" )
2018-09-21 10:54:06 -04:00
}
2017-02-01 17:05:27 -05:00
if err := config . Transport . Apply ( ) ; err != nil {
2016-10-14 16:21:45 -04:00
return nil , err
2016-06-01 19:49:25 -04:00
}
2017-02-01 17:05:27 -05:00
for _ , appSettings := range config . App {
2017-02-01 15:35:40 -05:00
settings , err := appSettings . GetInstance ( )
if err != nil {
return nil , err
}
2018-10-21 04:27:13 -04:00
obj , err := CreateObject ( server , settings )
if err != nil {
2017-02-01 15:35:40 -05:00
return nil , err
}
2018-10-21 04:27:13 -04:00
if feature , ok := obj . ( features . Feature ) ; ok {
server . AddFeature ( feature )
}
2017-02-01 15:35:40 -05:00
}
2018-10-21 04:27:13 -04:00
if server . GetFeature ( dns . ClientType ( ) ) == nil {
server . AddFeature ( dns . LocalClient { } )
}
if server . GetFeature ( policy . ManagerType ( ) ) == nil {
server . AddFeature ( policy . DefaultManager { } )
}
if server . GetFeature ( routing . RouterType ( ) ) == nil {
server . AddFeature ( routing . DefaultRouter { } )
}
2018-10-21 13:35:32 -04:00
// Add an empty instance at the end, for optional feature requirement.
2018-10-21 04:27:13 -04:00
server . AddFeature ( & Instance { } )
if server . featureResolutions != nil {
return nil , newError ( "not all dependency are resolved." )
2017-01-06 09:32:36 -05:00
}
2016-11-10 17:41:28 -05:00
2018-10-21 13:41:12 -04:00
if err := addInboundHandlers ( server , config . Inbound ) ; err != nil {
return nil , err
2018-10-21 04:27:13 -04:00
}
2018-10-21 13:41:12 -04:00
if err := addOutboundHandlers ( server , config . Outbound ) ; err != nil {
return nil , err
2016-12-16 09:39:47 -05:00
}
2015-12-05 16:55:45 -05:00
2018-01-10 06:22:37 -05:00
return server , nil
}
2018-10-21 04:27:13 -04:00
// Type implements common.HasType.
func ( s * Instance ) Type ( ) interface { } {
return ServerType ( )
2018-01-17 13:09:32 -05:00
}
2018-01-10 06:22:37 -05:00
// Close shutdown the V2Ray instance.
2018-02-08 09:39:46 -05:00
func ( s * Instance ) Close ( ) error {
2018-02-07 06:34:15 -05:00
s . access . Lock ( )
defer s . access . Unlock ( )
s . running = false
2018-05-31 05:55:11 -04:00
var errors [ ] interface { }
2018-10-21 04:27:13 -04:00
for _ , f := range s . features {
2018-05-31 05:55:11 -04:00
if err := f . Close ( ) ; err != nil {
errors = append ( errors , err )
}
}
if len ( errors ) > 0 {
return newError ( "failed to close all features" ) . Base ( newError ( serial . Concat ( errors ... ) ) )
2015-10-31 19:11:41 -04:00
}
2018-02-08 09:39:46 -05:00
return nil
2018-01-10 06:22:37 -05:00
}
2015-10-31 19:11:41 -04:00
2018-10-21 04:27:13 -04:00
// RequireFeatures registers a callback, which will be called when all dependent features are registered.
func ( s * Instance ) RequireFeatures ( featureTypes [ ] interface { } , callback func ( [ ] features . Feature ) ) {
r := resolution {
deps : featureTypes ,
callback : callback ,
2015-11-22 11:41:52 -05:00
}
2018-10-21 04:27:13 -04:00
if r . resolve ( s . features ) {
return
2018-02-07 06:34:15 -05:00
}
2018-10-21 04:27:13 -04:00
s . featureResolutions = append ( s . featureResolutions , r )
2018-01-10 06:22:37 -05:00
}
2016-05-18 11:12:04 -04:00
2018-10-21 04:27:13 -04:00
// AddFeature registers a feature into current Instance.
func ( s * Instance ) AddFeature ( feature features . Feature ) {
s . features = append ( s . features , feature )
2018-02-20 15:19:09 -05:00
2018-10-21 04:27:13 -04:00
if s . running {
if err := feature . Start ( ) ; err != nil {
newError ( "failed to start feature" ) . Base ( err ) . WriteToLog ( )
2018-02-14 11:35:09 -05:00
}
2018-10-21 04:27:13 -04:00
return
2018-02-14 11:35:09 -05:00
}
2018-10-21 04:27:13 -04:00
if s . featureResolutions == nil {
return
}
2015-09-05 11:48:38 -04:00
2018-10-21 04:27:13 -04:00
var pendingResolutions [ ] resolution
for _ , r := range s . featureResolutions {
if ! r . resolve ( s . features ) {
pendingResolutions = append ( pendingResolutions , r )
}
}
if len ( pendingResolutions ) == 0 {
s . featureResolutions = nil
} else if len ( pendingResolutions ) < len ( s . featureResolutions ) {
s . featureResolutions = pendingResolutions
}
2016-01-03 18:33:25 -05:00
}
2018-10-21 04:27:13 -04:00
// GetFeature returns a feature of the given type, or nil if such feature is not registered.
func ( s * Instance ) GetFeature ( featureType interface { } ) features . Feature {
return getFeature ( s . features , featureType )
2018-01-10 06:22:37 -05:00
}
2015-10-31 19:11:41 -04:00
2018-10-21 04:27:13 -04:00
// Start starts the V2Ray instance, including all registered features. When Start returns error, the state of the instance is unknown.
// A V2Ray instance can be started only once. Upon closing, the instance is not guaranteed to start again.
func ( s * Instance ) Start ( ) error {
s . access . Lock ( )
defer s . access . Unlock ( )
2018-01-10 06:22:37 -05:00
2018-10-21 04:27:13 -04:00
s . running = true
for _ , f := range s . features {
if err := f . Start ( ) ; err != nil {
return err
}
}
2018-01-10 06:22:37 -05:00
2018-10-21 04:27:13 -04:00
newError ( "V2Ray " , Version ( ) , " started" ) . AtWarning ( ) . WriteToLog ( )
2018-03-30 13:56:59 -04:00
2018-10-21 04:27:13 -04:00
return nil
2018-03-30 13:56:59 -04:00
}