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-10-22 05:26:22 -04:00
"reflect"
2022-09-06 15:22:10 -04:00
sync "sync"
2017-01-12 18:56:21 -05:00
2022-01-02 10:16:23 -05:00
"github.com/v2fly/v2ray-core/v5/common"
2022-02-10 18:20:39 -05:00
"github.com/v2fly/v2ray-core/v5/common/environment"
2022-09-06 15:22:10 -04:00
"github.com/v2fly/v2ray-core/v5/common/environment/systemnetworkimpl"
2022-02-10 18:20:39 -05:00
"github.com/v2fly/v2ray-core/v5/common/environment/transientstorageimpl"
2022-01-02 10:16:23 -05:00
"github.com/v2fly/v2ray-core/v5/common/serial"
"github.com/v2fly/v2ray-core/v5/features"
"github.com/v2fly/v2ray-core/v5/features/dns"
"github.com/v2fly/v2ray-core/v5/features/dns/localdns"
"github.com/v2fly/v2ray-core/v5/features/inbound"
"github.com/v2fly/v2ray-core/v5/features/outbound"
"github.com/v2fly/v2ray-core/v5/features/policy"
"github.com/v2fly/v2ray-core/v5/features/routing"
"github.com/v2fly/v2ray-core/v5/features/stats"
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 {
2018-10-22 05:26:22 -04:00
deps [ ] reflect . Type
callback interface { }
2018-10-21 04:27:13 -04:00
}
2018-10-22 05:26:22 -04:00
func getFeature ( allFeatures [ ] features . Feature , t reflect . Type ) features . Feature {
2018-10-21 04:27:13 -04:00
for _ , f := range allFeatures {
2018-10-22 05:26:22 -04:00
if reflect . TypeOf ( f . Type ( ) ) == t {
2018-10-21 04:27:13 -04:00
return f
}
}
return nil
}
2018-10-22 09:58:52 -04:00
func ( r * resolution ) resolve ( allFeatures [ ] features . Feature ) ( bool , error ) {
2018-10-21 04:27:13 -04:00
var fs [ ] features . Feature
for _ , d := range r . deps {
f := getFeature ( allFeatures , d )
if f == nil {
2018-10-22 09:58:52 -04:00
return false , nil
2018-10-21 04:27:13 -04:00
}
fs = append ( fs , f )
}
2018-10-22 05:26:22 -04:00
callback := reflect . ValueOf ( r . callback )
var input [ ] reflect . Value
callbackType := callback . Type ( )
for i := 0 ; i < callbackType . NumIn ( ) ; i ++ {
pt := callbackType . In ( i )
for _ , f := range fs {
if reflect . TypeOf ( f ) . AssignableTo ( pt ) {
input = append ( input , reflect . ValueOf ( f ) )
break
}
}
}
if len ( input ) != callbackType . NumIn ( ) {
panic ( "Can't get all input parameters" )
}
2018-10-22 09:58:52 -04:00
var err error
ret := callback . Call ( input )
errInterface := reflect . TypeOf ( ( * error ) ( nil ) ) . Elem ( )
for i := len ( ret ) - 1 ; i >= 0 ; i -- {
2018-10-22 15:25:25 -04:00
if ret [ i ] . Type ( ) == errInterface {
v := ret [ i ] . Interface ( )
if v != nil {
err = v . ( error )
}
break
2018-10-22 09:58:52 -04:00
}
}
2018-10-22 05:26:22 -04:00
2018-10-22 09:58:52 -04:00
return true , err
2018-10-21 04:27:13 -04:00
}
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
2022-02-10 18:20:39 -05:00
env environment . RootEnvironment
2020-06-17 23:19:05 -04:00
ctx context . Context
2017-02-10 10:25:54 -05:00
}
2018-10-21 15:27:05 -04:00
func AddInboundHandler ( server * Instance , config * InboundHandlerConfig ) error {
inboundManager := server . GetFeature ( inbound . ManagerType ( ) ) . ( inbound . Manager )
2022-02-10 18:20:39 -05:00
proxyEnv := server . env . ProxyEnvironment ( "i" + config . Tag )
rawHandler , err := CreateObjectWithEnvironment ( server , config , proxyEnv )
2018-10-21 15:27:05 -04:00
if err != nil {
return err
}
handler , ok := rawHandler . ( inbound . Handler )
if ! ok {
return newError ( "not an InboundHandler" )
2018-10-21 13:41:12 -04:00
}
2020-06-17 23:19:05 -04:00
if err := inboundManager . AddHandler ( server . ctx , handler ) ; err != nil {
2018-10-21 15:27:05 -04:00
return err
}
return nil
}
2018-10-21 13:41:12 -04:00
2018-10-21 15:27:05 -04:00
func addInboundHandlers ( server * Instance , configs [ ] * InboundHandlerConfig ) error {
2018-10-21 13:41:12 -04:00
for _ , inboundConfig := range configs {
2018-10-21 15:27:05 -04:00
if err := AddInboundHandler ( server , inboundConfig ) ; err != nil {
2018-10-21 13:41:12 -04:00
return err
}
}
return nil
}
2018-10-21 15:27:05 -04:00
func AddOutboundHandler ( server * Instance , config * OutboundHandlerConfig ) error {
outboundManager := server . GetFeature ( outbound . ManagerType ( ) ) . ( outbound . Manager )
2022-02-10 18:20:39 -05:00
proxyEnv := server . env . ProxyEnvironment ( "o" + config . Tag )
rawHandler , err := CreateObjectWithEnvironment ( server , config , proxyEnv )
2018-10-21 15:27:05 -04:00
if err != nil {
return err
}
handler , ok := rawHandler . ( outbound . Handler )
if ! ok {
return newError ( "not an OutboundHandler" )
2018-10-21 13:41:12 -04:00
}
2020-06-17 23:19:05 -04:00
if err := outboundManager . AddHandler ( server . ctx , handler ) ; err != nil {
2018-10-21 15:27:05 -04:00
return err
}
return nil
}
2018-10-21 13:41:12 -04:00
2018-10-21 15:27:05 -04:00
func addOutboundHandlers ( server * Instance , configs [ ] * OutboundHandlerConfig ) error {
2018-10-21 13:41:12 -04:00
for _ , outboundConfig := range configs {
2018-10-21 15:27:05 -04:00
if err := AddOutboundHandler ( server , outboundConfig ) ; err != nil {
2018-10-21 13:41:12 -04:00
return err
}
}
return nil
}
2018-10-22 05:26:22 -04:00
// RequireFeatures is a helper function to require features from Instance in context.
// See Instance.RequireFeatures for more information.
2018-10-22 09:58:52 -04:00
func RequireFeatures ( ctx context . Context , callback interface { } ) error {
2018-10-22 05:26:22 -04:00
v := MustFromContext ( ctx )
2018-10-22 09:58:52 -04:00
return v . RequireFeatures ( callback )
2018-10-22 05:26:22 -04:00
}
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 ) {
2021-05-19 17:28:52 -04:00
server := & Instance { ctx : context . Background ( ) }
2020-06-17 23:19:05 -04:00
2020-10-11 07:22:46 -04:00
done , err := initInstanceWithConfig ( config , server )
2020-06-17 23:19:05 -04:00
if done {
return nil , err
}
return server , nil
}
2020-10-11 07:22:46 -04:00
func NewWithContext ( ctx context . Context , config * Config ) ( * Instance , error ) {
2021-05-19 17:28:52 -04:00
server := & Instance { ctx : ctx }
2015-09-12 05:51:42 -04:00
2020-10-11 07:22:46 -04:00
done , err := initInstanceWithConfig ( config , server )
2020-06-17 23:19:05 -04:00
if done {
return nil , err
}
return server , nil
}
2020-10-11 07:22:46 -04:00
func initInstanceWithConfig ( config * Config , server * Instance ) ( bool , error ) {
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 {
2020-10-11 07:22:46 -04:00
return true , err
2016-06-01 19:49:25 -04:00
}
2022-09-06 15:22:10 -04:00
defaultNetworkImpl := systemnetworkimpl . NewSystemNetworkDefault ( )
server . env = environment . NewRootEnvImpl ( server . ctx , transientstorageimpl . NewScopedTransientStorageImpl ( ) , defaultNetworkImpl . Dialer ( ) , defaultNetworkImpl . Listener ( ) )
2022-02-10 18:20:39 -05:00
2017-02-01 17:05:27 -05:00
for _ , appSettings := range config . App {
2021-06-19 09:36:54 -04:00
settings , err := serial . GetInstanceOf ( appSettings )
2017-02-01 15:35:40 -05:00
if err != nil {
2020-10-11 07:22:46 -04:00
return true , err
2017-02-01 15:35:40 -05:00
}
2022-02-10 18:20:39 -05:00
key := appSettings . TypeUrl
appEnv := server . env . AppEnvironment ( key )
obj , err := CreateObjectWithEnvironment ( server , settings , appEnv )
2018-10-21 04:27:13 -04:00
if err != nil {
2020-10-11 07:22:46 -04:00
return true , err
2017-02-01 15:35:40 -05:00
}
2018-10-21 04:27:13 -04:00
if feature , ok := obj . ( features . Feature ) ; ok {
2018-10-22 09:58:52 -04:00
if err := server . AddFeature ( feature ) ; err != nil {
2020-10-11 07:22:46 -04:00
return true , err
2018-10-22 09:58:52 -04:00
}
2018-10-21 04:27:13 -04:00
}
2017-02-01 15:35:40 -05:00
}
2018-10-22 09:58:52 -04:00
essentialFeatures := [ ] struct {
Type interface { }
Instance features . Feature
} {
2018-11-19 14:42:02 -05:00
{ dns . ClientType ( ) , localdns . New ( ) } ,
2018-10-22 09:58:52 -04:00
{ policy . ManagerType ( ) , policy . DefaultManager { } } ,
{ routing . RouterType ( ) , routing . DefaultRouter { } } ,
{ stats . ManagerType ( ) , stats . NoopManager { } } ,
2018-10-21 04:27:13 -04:00
}
2018-10-22 09:58:52 -04:00
for _ , f := range essentialFeatures {
if server . GetFeature ( f . Type ) == nil {
if err := server . AddFeature ( f . Instance ) ; err != nil {
2020-10-11 07:22:46 -04:00
return true , err
2018-10-22 09:58:52 -04:00
}
}
2018-10-22 05:26:22 -04:00
}
2018-10-21 04:27:13 -04:00
if server . featureResolutions != nil {
2020-10-11 07:22:46 -04:00
return true , 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 {
2020-10-11 07:22:46 -04:00
return true , 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 {
2020-10-11 07:22:46 -04:00
return true , err
2016-12-16 09:39:47 -05:00
}
2020-10-11 07:22:46 -04:00
return false , nil
2018-01-10 06:22:37 -05:00
}
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.
2018-10-22 05:26:22 -04:00
// The callback must be a func(). All its parameters must be features.Feature.
2018-10-22 09:58:52 -04:00
func ( s * Instance ) RequireFeatures ( callback interface { } ) error {
2018-10-22 05:26:22 -04:00
callbackType := reflect . TypeOf ( callback )
if callbackType . Kind ( ) != reflect . Func {
panic ( "not a function" )
}
var featureTypes [ ] reflect . Type
for i := 0 ; i < callbackType . NumIn ( ) ; i ++ {
featureTypes = append ( featureTypes , reflect . PtrTo ( callbackType . In ( i ) ) )
}
2018-10-21 04:27:13 -04:00
r := resolution {
deps : featureTypes ,
callback : callback ,
2015-11-22 11:41:52 -05:00
}
2018-10-22 09:58:52 -04:00
if finished , err := r . resolve ( s . features ) ; finished {
return err
2018-02-07 06:34:15 -05:00
}
2018-10-21 04:27:13 -04:00
s . featureResolutions = append ( s . featureResolutions , r )
2018-10-22 09:58:52 -04:00
return nil
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.
2018-10-22 09:58:52 -04:00
func ( s * Instance ) AddFeature ( feature features . Feature ) error {
2018-10-21 04:27:13 -04:00
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-22 09:58:52 -04:00
return nil
2018-02-14 11:35:09 -05:00
}
2018-10-21 04:27:13 -04:00
if s . featureResolutions == nil {
2018-10-22 09:58:52 -04:00
return nil
2018-10-21 04:27:13 -04:00
}
2015-09-05 11:48:38 -04:00
2018-10-21 04:27:13 -04:00
var pendingResolutions [ ] resolution
for _ , r := range s . featureResolutions {
2018-10-22 09:58:52 -04:00
finished , err := r . resolve ( s . features )
if finished && err != nil {
return err
}
if ! finished {
2018-10-21 04:27:13 -04:00
pendingResolutions = append ( pendingResolutions , r )
}
}
if len ( pendingResolutions ) == 0 {
s . featureResolutions = nil
} else if len ( pendingResolutions ) < len ( s . featureResolutions ) {
s . featureResolutions = pendingResolutions
}
2018-10-22 09:58:52 -04:00
return nil
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 {
2018-10-22 05:26:22 -04:00
return getFeature ( s . features , reflect . TypeOf ( 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.
2018-12-03 16:44:42 -05:00
//
// v2ray:api:stable
2018-10-21 04:27:13 -04:00
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
}