1
0
mirror of https://github.com/v2fly/v2ray-core.git synced 2024-06-18 13:35:23 +00:00

context'ize apps

This commit is contained in:
Darien Raymond 2017-01-13 13:41:40 +01:00
parent 148e4832eb
commit 17504d2aac
No known key found for this signature in database
GPG Key ID: 7251FFA14BB18169
15 changed files with 171 additions and 152 deletions

View File

@ -2,7 +2,6 @@ package dispatcher
import (
"v2ray.com/core/app"
"v2ray.com/core/common/serial"
"v2ray.com/core/proxy"
"v2ray.com/core/transport/ray"
)
@ -13,7 +12,7 @@ type PacketDispatcher interface {
}
func FromSpace(space app.Space) PacketDispatcher {
if app := space.(app.AppGetter).GetApp(serial.GetMessageType((*Config)(nil))); app != nil {
if app := space.GetApplication((*PacketDispatcher)(nil)); app != nil {
return app.(PacketDispatcher)
}
return nil

View File

@ -1,6 +1,7 @@
package impl
import (
"context"
"time"
"v2ray.com/core/app"
@ -21,7 +22,11 @@ type DefaultDispatcher struct {
router *router.Router
}
func NewDefaultDispatcher(space app.Space) *DefaultDispatcher {
func NewDefaultDispatcher(ctx context.Context, config *dispatcher.Config) (*DefaultDispatcher, error) {
space := app.SpaceFromContext(ctx)
if space == nil {
return nil, errors.New("DefaultDispatcher: No space in context.")
}
d := &DefaultDispatcher{}
space.OnInitialize(func() error {
d.ohm = proxyman.OutboundHandlerManagerFromSpace(space)
@ -31,7 +36,11 @@ func NewDefaultDispatcher(space app.Space) *DefaultDispatcher {
d.router = router.FromSpace(space)
return nil
})
return d
return d, nil
}
func (DefaultDispatcher) Interface() interface{} {
return (*dispatcher.PacketDispatcher)(nil)
}
func (v *DefaultDispatcher) DispatchToOutbound(session *proxy.SessionInfo) ray.InboundRay {
@ -79,14 +88,10 @@ func (v *DefaultDispatcher) waitAndDispatch(wait func() error, destination v2net
dispatcher.Dispatch(destination, link)
}
type DefaultDispatcherFactory struct{}
func (v DefaultDispatcherFactory) Create(space app.Space, config interface{}) (app.Application, error) {
return NewDefaultDispatcher(space), nil
}
func init() {
common.Must(app.RegisterApplicationFactory((*dispatcher.Config)(nil), DefaultDispatcherFactory{}))
common.Must(common.RegisterConfig((*dispatcher.Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
return NewDefaultDispatcher(ctx, config.(*dispatcher.Config))
}))
}
type waitDataInspector struct {

View File

@ -4,7 +4,6 @@ import (
"net"
"v2ray.com/core/app"
"v2ray.com/core/common/serial"
)
// A DnsCache is an internal cache of DNS resolutions.
@ -13,7 +12,7 @@ type Server interface {
}
func FromSpace(space app.Space) Server {
app := space.(app.AppGetter).GetApp(serial.GetMessageType((*Config)(nil)))
app := space.GetApplication((*Server)(nil))
if app == nil {
return nil
}

View File

@ -1,10 +1,12 @@
package server
import (
"context"
"net"
"sync"
"time"
dnsmsg "github.com/miekg/dns"
"v2ray.com/core/app"
"v2ray.com/core/app/dispatcher"
"v2ray.com/core/app/dns"
@ -12,8 +14,6 @@ import (
"v2ray.com/core/common/errors"
"v2ray.com/core/common/log"
v2net "v2ray.com/core/common/net"
dnsmsg "github.com/miekg/dns"
)
const (
@ -32,7 +32,11 @@ type CacheServer struct {
servers []NameServer
}
func NewCacheServer(space app.Space, config *dns.Config) *CacheServer {
func NewCacheServer(ctx context.Context, config *dns.Config) (*CacheServer, error) {
space := app.SpaceFromContext(ctx)
if space == nil {
return nil, errors.New("DNSCacheServer: No space in context.")
}
server := &CacheServer{
records: make(map[string]*DomainRecord),
servers: make([]NameServer, len(config.NameServers)),
@ -62,7 +66,11 @@ func NewCacheServer(space app.Space, config *dns.Config) *CacheServer {
}
return nil
})
return server
return server, nil
}
func (CacheServer) Interface() interface{} {
return (*dns.Server)(nil)
}
// Private: Visible for testing.
@ -109,13 +117,8 @@ func (v *CacheServer) Get(domain string) []net.IP {
return nil
}
type CacheServerFactory struct{}
func (v CacheServerFactory) Create(space app.Space, config interface{}) (app.Application, error) {
server := NewCacheServer(space, config.(*dns.Config))
return server, nil
}
func init() {
common.Must(app.RegisterApplicationFactory((*dns.Config)(nil), CacheServerFactory{}))
common.Must(common.RegisterConfig((*dns.Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
return NewCacheServer(ctx, config.(*dns.Config))
}))
}

View File

@ -5,6 +5,8 @@ import (
"net"
"time"
"context"
"v2ray.com/core/app"
"v2ray.com/core/app/proxyman"
"v2ray.com/core/common"
@ -12,7 +14,6 @@ import (
"v2ray.com/core/common/errors"
"v2ray.com/core/common/log"
v2net "v2ray.com/core/common/net"
"v2ray.com/core/common/serial"
"v2ray.com/core/transport/internet"
"v2ray.com/core/transport/ray"
)
@ -21,7 +22,11 @@ type OutboundProxy struct {
outboundManager proxyman.OutboundHandlerManager
}
func NewOutboundProxy(space app.Space) *OutboundProxy {
func NewOutboundProxy(ctx context.Context, config *Config) (*OutboundProxy, error) {
space := app.SpaceFromContext(ctx)
if space == nil {
return nil, errors.New("OutboundProxy: No space in context.")
}
proxy := new(OutboundProxy)
space.OnInitialize(func() error {
proxy.outboundManager = proxyman.OutboundHandlerManagerFromSpace(space)
@ -30,7 +35,11 @@ func NewOutboundProxy(space app.Space) *OutboundProxy {
}
return nil
})
return proxy
return proxy, nil
}
func (OutboundProxy) Interface() interface{} {
return (*OutboundProxy)(nil)
}
func (v *OutboundProxy) RegisterDialer() {
@ -132,14 +141,8 @@ func (v *Connection) SetReusable(bool) {
}
type OutboundProxyFactory struct{}
func (OutboundProxyFactory) Create(space app.Space, config interface{}) (app.Application, error) {
return NewOutboundProxy(space), nil
}
func OutboundProxyFromSpace(space app.Space) *OutboundProxy {
app := space.(app.AppGetter).GetApp(serial.GetMessageType((*Config)(nil)))
app := space.GetApplication((*OutboundProxy)(nil))
if app == nil {
return nil
}
@ -147,5 +150,7 @@ func OutboundProxyFromSpace(space app.Space) *OutboundProxy {
}
func init() {
common.Must(app.RegisterApplicationFactory((*Config)(nil), OutboundProxyFactory{}))
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
return NewOutboundProxy(ctx, config.(*Config))
}))
}

View File

@ -23,7 +23,7 @@ func TestProxyDial(t *testing.T) {
space := app.NewSpace()
ctx := app.ContextWithSpace(context.Background(), space)
assert.Error(space.AddApp(new(proxyman.OutboundConfig)))
assert.Error(app.AddApplicationToSpace(ctx, new(proxyman.OutboundConfig))).IsNil()
outboundManager := proxyman.OutboundHandlerManagerFromSpace(space)
freedom, err := freedom.New(proxy.ContextWithOutboundMeta(ctx, &proxy.OutboundHandlerMeta{
Tag: "tag",
@ -34,9 +34,8 @@ func TestProxyDial(t *testing.T) {
assert.Error(err).IsNil()
common.Must(outboundManager.SetHandler("tag", freedom))
assert.Error(space.AddApp(new(Config))).IsNil()
assert.Error(app.AddApplicationToSpace(ctx, new(Config))).IsNil()
proxy := OutboundProxyFromSpace(space)
assert.Error(space.Initialize()).IsNil()
xor := func(b []byte) []byte {

View File

@ -3,7 +3,8 @@ package outbound
import (
"sync"
"v2ray.com/core/app"
"context"
"v2ray.com/core/app/proxyman"
"v2ray.com/core/common"
"v2ray.com/core/proxy"
@ -15,10 +16,14 @@ type DefaultOutboundHandlerManager struct {
taggedHandler map[string]proxy.OutboundHandler
}
func New() *DefaultOutboundHandlerManager {
func New(ctx context.Context, config *proxyman.OutboundConfig) (*DefaultOutboundHandlerManager, error) {
return &DefaultOutboundHandlerManager{
taggedHandler: make(map[string]proxy.OutboundHandler),
}
}, nil
}
func (DefaultOutboundHandlerManager) Interface() interface{} {
return (*proxyman.OutboundHandlerManager)(nil)
}
func (v *DefaultOutboundHandlerManager) GetDefaultHandler() proxy.OutboundHandler {
@ -54,12 +59,8 @@ func (v *DefaultOutboundHandlerManager) SetHandler(tag string, handler proxy.Out
return nil
}
type OutboundHandlerManagerFactory struct{}
func (v OutboundHandlerManagerFactory) Create(space app.Space, config interface{}) (app.Application, error) {
return New(), nil
}
func init() {
common.Must(app.RegisterApplicationFactory((*proxyman.OutboundConfig)(nil), OutboundHandlerManagerFactory{}))
common.Must(common.RegisterConfig((*proxyman.OutboundConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
return New(ctx, config.(*proxyman.OutboundConfig))
}))
}

View File

@ -3,7 +3,6 @@ package proxyman
import (
"v2ray.com/core/app"
"v2ray.com/core/common/serial"
"v2ray.com/core/proxy"
)
@ -19,7 +18,7 @@ type OutboundHandlerManager interface {
}
func InboundHandlerManagerFromSpace(space app.Space) InboundHandlerManager {
app := space.(app.AppGetter).GetApp(serial.GetMessageType((*InboundConfig)(nil)))
app := space.GetApplication((*InboundHandlerManager)(nil))
if app == nil {
return nil
}
@ -27,7 +26,7 @@ func InboundHandlerManagerFromSpace(space app.Space) InboundHandlerManager {
}
func OutboundHandlerManagerFromSpace(space app.Space) OutboundHandlerManager {
app := space.(app.AppGetter).GetApp(serial.GetMessageType((*OutboundConfig)(nil)))
app := space.GetApplication((*OutboundHandlerManager)(nil))
if app == nil {
return nil
}

View File

@ -1,13 +1,14 @@
package router
import (
"context"
"v2ray.com/core/app"
"v2ray.com/core/app/dns"
"v2ray.com/core/common"
"v2ray.com/core/common/errors"
"v2ray.com/core/common/log"
v2net "v2ray.com/core/common/net"
"v2ray.com/core/common/serial"
"v2ray.com/core/proxy"
)
@ -23,7 +24,11 @@ type Router struct {
dnsServer dns.Server
}
func NewRouter(config *Config, space app.Space) *Router {
func NewRouter(ctx context.Context, config *Config) (*Router, error) {
space := app.SpaceFromContext(ctx)
if space == nil {
return nil, errors.New("Router: No space in context.")
}
r := &Router{
domainStrategy: config.DomainStrategy,
//cache: NewRoutingTable(),
@ -46,7 +51,7 @@ func NewRouter(config *Config, space app.Space) *Router {
}
return nil
})
return r
return r, nil
}
// Private: Visible for testing.
@ -106,15 +111,14 @@ func (v *Router) TakeDetour(session *proxy.SessionInfo) (string, error) {
//return tag, err
}
type RouterFactory struct{}
func (RouterFactory) Create(space app.Space, config interface{}) (app.Application, error) {
router := NewRouter(config.(*Config), space)
return router, nil
func (Router) Interface() interface{} {
return (*Router)(nil)
}
type RouterFactory struct{}
func FromSpace(space app.Space) *Router {
app := space.(app.AppGetter).GetApp(serial.GetMessageType((*Config)(nil)))
app := space.GetApplication((*Router)(nil))
if app == nil {
return nil
}
@ -122,5 +126,7 @@ func FromSpace(space app.Space) *Router {
}
func init() {
common.Must(app.RegisterApplicationFactory((*Config)(nil), RouterFactory{}))
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
return NewRouter(ctx, config.(*Config))
}))
}

View File

@ -1,6 +1,7 @@
package router_test
import (
"context"
"testing"
"v2ray.com/core/app"
@ -31,10 +32,11 @@ func TestSimpleRouter(t *testing.T) {
}
space := app.NewSpace()
assert.Error(space.AddApp(new(dns.Config))).IsNil()
assert.Error(space.AddApp(new(dispatcher.Config))).IsNil()
assert.Error(space.AddApp(new(proxyman.OutboundConfig))).IsNil()
assert.Error(space.AddApp(config)).IsNil()
ctx := app.ContextWithSpace(context.Background(), space)
assert.Error(app.AddApplicationToSpace(ctx, new(dns.Config))).IsNil()
assert.Error(app.AddApplicationToSpace(ctx, new(dispatcher.Config))).IsNil()
assert.Error(app.AddApplicationToSpace(ctx, new(proxyman.OutboundConfig))).IsNil()
assert.Error(app.AddApplicationToSpace(ctx, config)).IsNil()
assert.Error(space.Initialize()).IsNil()
r := FromSpace(space)

View File

@ -1,10 +1,11 @@
package sender
import (
"context"
"v2ray.com/core/app"
"v2ray.com/core/common"
"v2ray.com/core/common/net"
"v2ray.com/core/common/serial"
"v2ray.com/core/transport/internet"
)
@ -15,18 +16,16 @@ type Sender interface {
type SenderManager struct {
}
func New(space app.Space, config *Config) (*SenderManager, error) {
func New(ctx context.Context, config *Config) (*SenderManager, error) {
return &SenderManager{}, nil
}
type SenderManagerFactory struct{}
func (SenderManagerFactory) Create(space app.Space, config interface{}) (app.Application, error) {
return New(space, config.(*Config))
func (SenderManager) Interface() interface{} {
return (*SenderManager)(nil)
}
func FromSpace(space app.Space) *SenderManager {
app := space.(app.AppGetter).GetApp(serial.GetMessageType((*Config)(nil)))
app := space.GetApplication((*SenderManager)(nil))
if app == nil {
return nil
}
@ -34,5 +33,7 @@ func FromSpace(space app.Space) *SenderManager {
}
func init() {
common.Must(app.RegisterApplicationFactory((*Config)(nil), SenderManagerFactory{}))
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
return New(ctx, config.(*Config))
}))
}

View File

@ -2,60 +2,50 @@ package app
import (
"context"
"reflect"
"github.com/golang/protobuf/proto"
"v2ray.com/core/common"
"v2ray.com/core/common/errors"
"v2ray.com/core/common/log"
"v2ray.com/core/common/serial"
)
type Application interface {
Interface() interface{}
}
type InitializationCallback func() error
type ApplicationFactory interface {
Create(space Space, config interface{}) (Application, error)
}
type AppGetter interface {
GetApp(name string) Application
}
var (
applicationFactoryCache = make(map[string]ApplicationFactory)
)
func RegisterApplicationFactory(defaultConfig proto.Message, factory ApplicationFactory) error {
if defaultConfig == nil {
return errors.New("Space: config is nil.")
func CreateAppFromConfig(ctx context.Context, config interface{}) (Application, error) {
application, err := common.CreateObject(ctx, config)
if err != nil {
return nil, err
}
name := serial.GetMessageType(defaultConfig)
if len(name) == 0 {
return errors.New("Space: cannot get config type.")
switch a := application.(type) {
case Application:
return a, nil
default:
return nil, errors.New("App: Not an application.")
}
applicationFactoryCache[name] = factory
return nil
}
// A Space contains all apps that may be available in a V2Ray runtime.
// Caller must check the availability of an app by calling HasXXX before getting its instance.
type Space interface {
AddApp(config proto.Message) error
AddAppLegacy(name string, app Application)
GetApplication(appInterface interface{}) Application
AddApplication(application Application) error
Initialize() error
OnInitialize(InitializationCallback)
}
type spaceImpl struct {
initialized bool
cache map[string]Application
cache map[reflect.Type]Application
appInit []InitializationCallback
}
func NewSpace() Space {
return &spaceImpl{
cache: make(map[string]Application),
cache: make(map[reflect.Type]Application),
appInit: make([]InitializationCallback, 0, 32),
}
}
@ -81,38 +71,35 @@ func (v *spaceImpl) Initialize() error {
return nil
}
func (v *spaceImpl) GetApp(configType string) Application {
obj, found := v.cache[configType]
if !found {
return nil
}
return obj
func (v *spaceImpl) GetApplication(appInterface interface{}) Application {
appType := reflect.TypeOf(appInterface)
return v.cache[appType]
}
func (v *spaceImpl) AddApp(config proto.Message) error {
configName := serial.GetMessageType(config)
factory, found := applicationFactoryCache[configName]
if !found {
return errors.New("Space: app not registered: ", configName)
}
app, err := factory.Create(v, config)
if err != nil {
return err
}
v.cache[configName] = app
func (v *spaceImpl) AddApplication(app Application) error {
appType := reflect.TypeOf(app.Interface())
v.cache[appType] = app
return nil
}
func (v *spaceImpl) AddAppLegacy(name string, application Application) {
v.cache[name] = application
}
type contextKey int
const (
spaceKey = contextKey(0)
)
func AddApplicationToSpace(ctx context.Context, appConfig interface{}) error {
space := SpaceFromContext(ctx)
if space == nil {
return errors.New("App: No space in context.")
}
application, err := CreateAppFromConfig(ctx, appConfig)
if err != nil {
return err
}
return space.AddApplication(application)
}
func SpaceFromContext(ctx context.Context) Space {
return ctx.Value(spaceKey).(Space)
}

View File

@ -40,13 +40,11 @@ func TestDokodemoTCP(t *testing.T) {
defer tcpServer.Close()
space := app.NewSpace()
space.AddApp(new(dispatcher.Config))
space.AddApp(new(proxyman.OutboundConfig))
ctx := app.ContextWithSpace(context.Background(), space)
app.AddApplicationToSpace(ctx, new(dispatcher.Config))
app.AddApplicationToSpace(ctx, new(proxyman.OutboundConfig))
ohm := proxyman.OutboundHandlerManagerFromSpace(space)
ctx := context.Background()
ctx = app.ContextWithSpace(ctx, space)
freedom, err := freedom.New(proxy.ContextWithOutboundMeta(ctx, &proxy.OutboundHandlerMeta{
Address: v2net.LocalHostIP,
StreamSettings: &internet.StreamConfig{
@ -117,13 +115,11 @@ func TestDokodemoUDP(t *testing.T) {
defer udpServer.Close()
space := app.NewSpace()
space.AddApp(new(dispatcher.Config))
space.AddApp(new(proxyman.OutboundConfig))
ctx := app.ContextWithSpace(context.Background(), space)
app.AddApplicationToSpace(ctx, new(dispatcher.Config))
app.AddApplicationToSpace(ctx, new(proxyman.OutboundConfig))
ohm := proxyman.OutboundHandlerManagerFromSpace(space)
ctx := context.Background()
ctx = app.ContextWithSpace(ctx, space)
freedom, err := freedom.New(proxy.ContextWithOutboundMeta(ctx, &proxy.OutboundHandlerMeta{
Address: v2net.AnyIP,
StreamSettings: &internet.StreamConfig{

View File

@ -70,16 +70,16 @@ func TestIPResolution(t *testing.T) {
assert := assert.On(t)
space := app.NewSpace()
assert.Error(space.AddApp(new(proxyman.OutboundConfig))).IsNil()
assert.Error(space.AddApp(new(dispatcher.Config))).IsNil()
assert.Error(space.AddApp(new(router.Config))).IsNil()
assert.Error(space.AddApp(&dns.Config{
ctx := app.ContextWithSpace(context.Background(), space)
assert.Error(app.AddApplicationToSpace(ctx, new(proxyman.OutboundConfig))).IsNil()
assert.Error(app.AddApplicationToSpace(ctx, new(dispatcher.Config))).IsNil()
assert.Error(app.AddApplicationToSpace(ctx, new(router.Config))).IsNil()
assert.Error(app.AddApplicationToSpace(ctx, &dns.Config{
Hosts: map[string]*v2net.IPOrDomain{
"v2ray.com": v2net.NewIPOrDomain(v2net.LocalHostIP),
},
})).IsNil()
ctx := app.ContextWithSpace(context.Background(), space)
ctx = proxy.ContextWithOutboundMeta(ctx, &proxy.OutboundHandlerMeta{
Address: v2net.AnyIP,
StreamSettings: &internet.StreamConfig{

View File

@ -11,7 +11,6 @@ import (
"v2ray.com/core/common"
"v2ray.com/core/common/log"
v2net "v2ray.com/core/common/net"
"v2ray.com/core/common/serial"
"v2ray.com/core/proxy"
)
@ -43,29 +42,39 @@ func NewPoint(pConfig *Config) (*Point, error) {
ctx := app.ContextWithSpace(context.Background(), space)
vpoint.space = space
vpoint.space.AddAppLegacy(serial.GetMessageType((*proxyman.InboundConfig)(nil)), vpoint)
vpoint.space.AddApplication(vpoint)
outboundHandlerManager := proxyman.OutboundHandlerManagerFromSpace(space)
if outboundHandlerManager == nil {
if err := space.AddApp(new(proxyman.OutboundConfig)); err != nil {
o, err := app.CreateAppFromConfig(ctx, new(proxyman.OutboundConfig))
if err != nil {
return nil, err
}
outboundHandlerManager = proxyman.OutboundHandlerManagerFromSpace(space)
space.AddApplication(o)
outboundHandlerManager = o.(proxyman.OutboundHandlerManager)
}
proxyDialer := proxydialer.OutboundProxyFromSpace(space)
if proxyDialer == nil {
space.AddApp(new(proxydialer.Config))
proxyDialer = proxydialer.OutboundProxyFromSpace(space)
}
proxyDialer.RegisterDialer()
for _, app := range pConfig.App {
settings, err := app.GetInstance()
p, err := app.CreateAppFromConfig(ctx, new(proxydialer.Config))
if err != nil {
return nil, err
}
if err := space.AddApp(settings); err != nil {
space.AddApplication(p)
proxyDialer = p.(*proxydialer.OutboundProxy)
}
proxyDialer.RegisterDialer()
for _, appSettings := range pConfig.App {
settings, err := appSettings.GetInstance()
if err != nil {
return nil, err
}
application, err := app.CreateAppFromConfig(ctx, settings)
if err != nil {
return nil, err
}
if err := space.AddApplication(application); err != nil {
return nil, err
}
}
@ -77,18 +86,22 @@ func NewPoint(pConfig *Config) (*Point, error) {
Address: v2net.NewIPOrDomain(v2net.LocalHostDomain),
}},
}
if err := space.AddApp(dnsConfig); err != nil {
d, err := app.CreateAppFromConfig(ctx, dnsConfig)
if err != nil {
return nil, err
}
space.AddApplication(d)
dnsServer = d.(dns.Server)
}
disp := dispatcher.FromSpace(space)
if disp == nil {
dispatcherConfig := new(dispatcher.Config)
if err := vpoint.space.AddApp(dispatcherConfig); err != nil {
d, err := app.CreateAppFromConfig(ctx, new(dispatcher.Config))
if err != nil {
return nil, err
}
disp = dispatcher.FromSpace(space)
space.AddApplication(d)
disp = d.(dispatcher.PacketDispatcher)
}
vpoint.inboundHandlers = make([]InboundDetourHandler, 0, 8)
@ -156,6 +169,10 @@ func NewPoint(pConfig *Config) (*Point, error) {
return vpoint, nil
}
func (Point) Interface() interface{} {
return (*proxyman.InboundHandlerManager)(nil)
}
func (v *Point) Close() {
for _, inbound := range v.inboundHandlers {
inbound.Close()