1
0
mirror of https://github.com/v2fly/v2ray-core.git synced 2025-02-20 23:47:21 -05:00

simplify app design

This commit is contained in:
Darien Raymond 2017-01-06 15:32:36 +01:00
parent 13e4506781
commit b11d48d73f
No known key found for this signature in database
GPG Key ID: 7251FFA14BB18169
27 changed files with 286 additions and 283 deletions

View File

@ -1,12 +1,4 @@
package api package api
import (
"v2ray.com/core/app"
)
const (
APP_ID = app.ID(5)
)
type ApiServer struct { type ApiServer struct {
} }

View File

@ -2,15 +2,19 @@ package dispatcher
import ( import (
"v2ray.com/core/app" "v2ray.com/core/app"
"v2ray.com/core/common/serial"
"v2ray.com/core/proxy" "v2ray.com/core/proxy"
"v2ray.com/core/transport/ray" "v2ray.com/core/transport/ray"
) )
const (
APP_ID = app.ID(1)
)
// PacketDispatcher dispatch a packet and possibly further network payload to its destination. // PacketDispatcher dispatch a packet and possibly further network payload to its destination.
type PacketDispatcher interface { type PacketDispatcher interface {
DispatchToOutbound(session *proxy.SessionInfo) ray.InboundRay DispatchToOutbound(session *proxy.SessionInfo) ray.InboundRay
} }
func FromSpace(space app.Space) PacketDispatcher {
if app := space.(app.AppGetter).GetApp(serial.GetMessageType((*Config)(nil))); app != nil {
return app.(PacketDispatcher)
}
return nil
}

View File

@ -7,11 +7,11 @@ import (
"v2ray.com/core/app/dispatcher" "v2ray.com/core/app/dispatcher"
"v2ray.com/core/app/proxyman" "v2ray.com/core/app/proxyman"
"v2ray.com/core/app/router" "v2ray.com/core/app/router"
"v2ray.com/core/common"
"v2ray.com/core/common/buf" "v2ray.com/core/common/buf"
"v2ray.com/core/common/errors" "v2ray.com/core/common/errors"
"v2ray.com/core/common/log" "v2ray.com/core/common/log"
v2net "v2ray.com/core/common/net" v2net "v2ray.com/core/common/net"
"v2ray.com/core/common/serial"
"v2ray.com/core/proxy" "v2ray.com/core/proxy"
"v2ray.com/core/transport/ray" "v2ray.com/core/transport/ray"
) )
@ -23,27 +23,17 @@ type DefaultDispatcher struct {
func NewDefaultDispatcher(space app.Space) *DefaultDispatcher { func NewDefaultDispatcher(space app.Space) *DefaultDispatcher {
d := &DefaultDispatcher{} d := &DefaultDispatcher{}
space.InitializeApplication(func() error { space.OnInitialize(func() error {
return d.Initialize(space) d.ohm = proxyman.OutboundHandlerManagerFromSpace(space)
if d.ohm == nil {
return errors.New("DefaultDispatcher: OutboundHandlerManager is not found in the space.")
}
d.router = router.FromSpace(space)
return nil
}) })
return d return d
} }
// Initialize initializes the dispatcher.
// Private: Used by app.Space only.
func (v *DefaultDispatcher) Initialize(space app.Space) error {
if !space.HasApp(proxyman.APP_ID_OUTBOUND_MANAGER) {
return errors.New("DefaultDispatcher: OutboundHandlerManager is not found in the space.")
}
v.ohm = space.GetApp(proxyman.APP_ID_OUTBOUND_MANAGER).(proxyman.OutboundHandlerManager)
if space.HasApp(router.APP_ID) {
v.router = space.GetApp(router.APP_ID).(*router.Router)
}
return nil
}
func (v *DefaultDispatcher) DispatchToOutbound(session *proxy.SessionInfo) ray.InboundRay { func (v *DefaultDispatcher) DispatchToOutbound(session *proxy.SessionInfo) ray.InboundRay {
dispatcher := v.ohm.GetDefaultHandler() dispatcher := v.ohm.GetDefaultHandler()
destination := session.Destination destination := session.Destination
@ -95,12 +85,8 @@ func (v DefaultDispatcherFactory) Create(space app.Space, config interface{}) (a
return NewDefaultDispatcher(space), nil return NewDefaultDispatcher(space), nil
} }
func (v DefaultDispatcherFactory) AppId() app.ID {
return dispatcher.APP_ID
}
func init() { func init() {
app.RegisterApplicationFactory(serial.GetMessageType(new(dispatcher.Config)), DefaultDispatcherFactory{}) common.Must(app.RegisterApplicationFactory((*dispatcher.Config)(nil), DefaultDispatcherFactory{}))
} }
type waitDataInspector struct { type waitDataInspector struct {

View File

@ -1,44 +0,0 @@
package testing
import (
"v2ray.com/core/common/buf"
v2net "v2ray.com/core/common/net"
"v2ray.com/core/proxy"
"v2ray.com/core/transport/ray"
)
type TestPacketDispatcher struct {
Destination chan v2net.Destination
Handler func(destination v2net.Destination, traffic ray.OutboundRay)
}
func NewTestPacketDispatcher(handler func(destination v2net.Destination, traffic ray.OutboundRay)) *TestPacketDispatcher {
if handler == nil {
handler = func(destination v2net.Destination, traffic ray.OutboundRay) {
for {
payload, err := traffic.OutboundInput().Read()
if err != nil {
break
}
output := buf.New()
output.Append([]byte("Processed: "))
output.Append(payload.Bytes())
payload.Release()
traffic.OutboundOutput().Write(output)
}
traffic.OutboundOutput().Close()
}
}
return &TestPacketDispatcher{
Destination: make(chan v2net.Destination),
Handler: handler,
}
}
func (v *TestPacketDispatcher) DispatchToOutbound(session *proxy.SessionInfo) ray.InboundRay {
traffic := ray.NewRay()
v.Destination <- session.Destination
go v.Handler(session.Destination, traffic)
return traffic
}

View File

@ -4,13 +4,18 @@ import (
"net" "net"
"v2ray.com/core/app" "v2ray.com/core/app"
) "v2ray.com/core/common/serial"
const (
APP_ID = app.ID(2)
) )
// A DnsCache is an internal cache of DNS resolutions. // A DnsCache is an internal cache of DNS resolutions.
type Server interface { type Server interface {
Get(domain string) []net.IP Get(domain string) []net.IP
} }
func FromSpace(space app.Space) Server {
app := space.(app.AppGetter).GetApp(serial.GetMessageType((*Config)(nil)))
if app == nil {
return nil
}
return app.(Server)
}

View File

@ -8,10 +8,10 @@ import (
"v2ray.com/core/app" "v2ray.com/core/app"
"v2ray.com/core/app/dispatcher" "v2ray.com/core/app/dispatcher"
"v2ray.com/core/app/dns" "v2ray.com/core/app/dns"
"v2ray.com/core/common"
"v2ray.com/core/common/errors" "v2ray.com/core/common/errors"
"v2ray.com/core/common/log" "v2ray.com/core/common/log"
v2net "v2ray.com/core/common/net" v2net "v2ray.com/core/common/net"
"v2ray.com/core/common/serial"
dnsmsg "github.com/miekg/dns" dnsmsg "github.com/miekg/dns"
) )
@ -38,12 +38,11 @@ func NewCacheServer(space app.Space, config *dns.Config) *CacheServer {
servers: make([]NameServer, len(config.NameServers)), servers: make([]NameServer, len(config.NameServers)),
hosts: config.GetInternalHosts(), hosts: config.GetInternalHosts(),
} }
space.InitializeApplication(func() error { space.OnInitialize(func() error {
if !space.HasApp(dispatcher.APP_ID) { disp := dispatcher.FromSpace(space)
if disp == nil {
return errors.New("DNS: Dispatcher is not found in the space.") return errors.New("DNS: Dispatcher is not found in the space.")
} }
dispatcher := space.GetApp(dispatcher.APP_ID).(dispatcher.PacketDispatcher)
for idx, destPB := range config.NameServers { for idx, destPB := range config.NameServers {
address := destPB.Address.AsAddress() address := destPB.Address.AsAddress()
if address.Family().IsDomain() && address.Domain() == "localhost" { if address.Family().IsDomain() && address.Domain() == "localhost" {
@ -54,7 +53,7 @@ func NewCacheServer(space app.Space, config *dns.Config) *CacheServer {
dest.Network = v2net.Network_UDP dest.Network = v2net.Network_UDP
} }
if dest.Network == v2net.Network_UDP { if dest.Network == v2net.Network_UDP {
server.servers[idx] = NewUDPNameServer(dest, dispatcher) server.servers[idx] = NewUDPNameServer(dest, disp)
} }
} }
} }
@ -117,10 +116,6 @@ func (v CacheServerFactory) Create(space app.Space, config interface{}) (app.App
return server, nil return server, nil
} }
func (v CacheServerFactory) AppId() app.ID {
return dns.APP_ID
}
func init() { func init() {
app.RegisterApplicationFactory(serial.GetMessageType(new(dns.Config)), CacheServerFactory{}) common.Must(app.RegisterApplicationFactory((*dns.Config)(nil), CacheServerFactory{}))
} }

42
app/proxy/config.pb.go Normal file
View File

@ -0,0 +1,42 @@
package proxy
import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
type Config struct {
}
func (m *Config) Reset() { *m = Config{} }
func (m *Config) String() string { return proto.CompactTextString(m) }
func (*Config) ProtoMessage() {}
func (*Config) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
func init() {
proto.RegisterType((*Config)(nil), "v2ray.core.app.proxy.Config")
}
func init() { proto.RegisterFile("v2ray.com/core/app/proxy/config.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 128 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0x52, 0x2d, 0x33, 0x2a, 0x4a,
0xac, 0xd4, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xce, 0x2f, 0x4a, 0xd5, 0x4f, 0x2c, 0x28, 0xd0, 0x2f,
0x28, 0xca, 0xaf, 0xa8, 0xd4, 0x4f, 0xce, 0xcf, 0x4b, 0xcb, 0x4c, 0xd7, 0x2b, 0x28, 0xca, 0x2f,
0xc9, 0x17, 0x12, 0x81, 0x29, 0x2b, 0x4a, 0xd5, 0x4b, 0x2c, 0x28, 0xd0, 0x03, 0x2b, 0x51, 0xe2,
0xe0, 0x62, 0x73, 0x06, 0xab, 0x72, 0x72, 0xe5, 0x92, 0x48, 0xce, 0xcf, 0xd5, 0xc3, 0xa6, 0xca,
0x89, 0x1b, 0xa2, 0x26, 0x00, 0x64, 0x50, 0x14, 0x2b, 0x58, 0x6c, 0x15, 0x93, 0x48, 0x98, 0x51,
0x50, 0x62, 0xa5, 0x9e, 0x33, 0x48, 0xa9, 0x63, 0x41, 0x81, 0x5e, 0x00, 0x48, 0x38, 0x89, 0x0d,
0x6c, 0x9b, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0x16, 0xbe, 0x54, 0x50, 0x96, 0x00, 0x00, 0x00,
}

10
app/proxy/config.proto Normal file
View File

@ -0,0 +1,10 @@
syntax = "proto3";
package v2ray.core.app.proxy;
option csharp_namespace = "V2Ray.Core.App.Proxy";
option go_package = "proxy";
option java_package = "com.v2ray.core.app.proxy";
option java_outer_classname = "ConfigProto";
message Config {
}

View File

@ -7,29 +7,27 @@ import (
"v2ray.com/core/app" "v2ray.com/core/app"
"v2ray.com/core/app/proxyman" "v2ray.com/core/app/proxyman"
"v2ray.com/core/common"
"v2ray.com/core/common/buf" "v2ray.com/core/common/buf"
"v2ray.com/core/common/errors" "v2ray.com/core/common/errors"
"v2ray.com/core/common/log" "v2ray.com/core/common/log"
v2net "v2ray.com/core/common/net" v2net "v2ray.com/core/common/net"
"v2ray.com/core/common/serial"
"v2ray.com/core/transport/internet" "v2ray.com/core/transport/internet"
"v2ray.com/core/transport/ray" "v2ray.com/core/transport/ray"
) )
const (
APP_ID = 7
)
type OutboundProxy struct { type OutboundProxy struct {
outboundManager proxyman.OutboundHandlerManager outboundManager proxyman.OutboundHandlerManager
} }
func NewOutboundProxy(space app.Space) *OutboundProxy { func NewOutboundProxy(space app.Space) *OutboundProxy {
proxy := new(OutboundProxy) proxy := new(OutboundProxy)
space.InitializeApplication(func() error { space.OnInitialize(func() error {
if !space.HasApp(proxyman.APP_ID_OUTBOUND_MANAGER) { proxy.outboundManager = proxyman.OutboundHandlerManagerFromSpace(space)
return errors.New("Proxy: Outbound handler manager not found.") if proxy.outboundManager == nil {
return errors.New("Proxy: Outbound handler manager not found in space.")
} }
proxy.outboundManager = space.GetApp(proxyman.APP_ID_OUTBOUND_MANAGER).(proxyman.OutboundHandlerManager)
return nil return nil
}) })
return proxy return proxy
@ -133,3 +131,21 @@ func (v *Connection) Reusable() bool {
func (v *Connection) SetReusable(bool) { 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)))
if app == nil {
return nil
}
return app.(*OutboundProxy)
}
func init() {
common.Must(app.RegisterApplicationFactory((*Config)(nil), OutboundProxyFactory{}))
}

View File

@ -6,7 +6,7 @@ import (
"v2ray.com/core/app" "v2ray.com/core/app"
. "v2ray.com/core/app/proxy" . "v2ray.com/core/app/proxy"
"v2ray.com/core/app/proxyman" "v2ray.com/core/app/proxyman"
"v2ray.com/core/app/proxyman/outbound" _ "v2ray.com/core/app/proxyman/outbound"
"v2ray.com/core/common" "v2ray.com/core/common"
v2net "v2ray.com/core/common/net" v2net "v2ray.com/core/common/net"
"v2ray.com/core/proxy" "v2ray.com/core/proxy"
@ -21,17 +21,17 @@ func TestProxyDial(t *testing.T) {
assert := assert.On(t) assert := assert.On(t)
space := app.NewSpace() space := app.NewSpace()
outboundManager := outbound.New() assert.Error(space.AddApp(new(proxyman.OutboundConfig)))
outboundManager := proxyman.OutboundHandlerManagerFromSpace(space)
common.Must(outboundManager.SetHandler("tag", freedom.New(&freedom.Config{}, space, &proxy.OutboundHandlerMeta{ common.Must(outboundManager.SetHandler("tag", freedom.New(&freedom.Config{}, space, &proxy.OutboundHandlerMeta{
Tag: "tag", Tag: "tag",
StreamSettings: &internet.StreamConfig{ StreamSettings: &internet.StreamConfig{
Network: v2net.Network_TCP, Network: v2net.Network_TCP,
}, },
}))) })))
space.BindApp(proxyman.APP_ID_OUTBOUND_MANAGER, outboundManager)
proxy := NewOutboundProxy(space) assert.Error(space.AddApp(new(Config))).IsNil()
space.BindApp(APP_ID, proxy) proxy := OutboundProxyFromSpace(space)
assert.Error(space.Initialize()).IsNil() assert.Error(space.Initialize()).IsNil()

View File

@ -5,7 +5,7 @@ import (
"v2ray.com/core/app" "v2ray.com/core/app"
"v2ray.com/core/app/proxyman" "v2ray.com/core/app/proxyman"
"v2ray.com/core/common/serial" "v2ray.com/core/common"
"v2ray.com/core/proxy" "v2ray.com/core/proxy"
) )
@ -60,10 +60,6 @@ func (v OutboundHandlerManagerFactory) Create(space app.Space, config interface{
return New(), nil return New(), nil
} }
func (v OutboundHandlerManagerFactory) AppId() app.ID {
return proxyman.APP_ID_OUTBOUND_MANAGER
}
func init() { func init() {
app.RegisterApplicationFactory(serial.GetMessageType(new(proxyman.OutboundConfig)), OutboundHandlerManagerFactory{}) common.Must(app.RegisterApplicationFactory((*proxyman.OutboundConfig)(nil), OutboundHandlerManagerFactory{}))
} }

View File

@ -3,14 +3,10 @@ package proxyman
import ( import (
"v2ray.com/core/app" "v2ray.com/core/app"
"v2ray.com/core/common/serial"
"v2ray.com/core/proxy" "v2ray.com/core/proxy"
) )
const (
APP_ID_INBOUND_MANAGER = app.ID(4)
APP_ID_OUTBOUND_MANAGER = app.ID(6)
)
type InboundHandlerManager interface { type InboundHandlerManager interface {
GetHandler(tag string) (proxy.InboundHandler, int) GetHandler(tag string) (proxy.InboundHandler, int)
} }
@ -21,3 +17,19 @@ type OutboundHandlerManager interface {
SetDefaultHandler(handler proxy.OutboundHandler) error SetDefaultHandler(handler proxy.OutboundHandler) error
SetHandler(tag string, handler proxy.OutboundHandler) error SetHandler(tag string, handler proxy.OutboundHandler) error
} }
func InboundHandlerManagerFromSpace(space app.Space) InboundHandlerManager {
app := space.(app.AppGetter).GetApp(serial.GetMessageType((*InboundConfig)(nil)))
if app == nil {
return nil
}
return app.(InboundHandlerManager)
}
func OutboundHandlerManagerFromSpace(space app.Space) OutboundHandlerManager {
app := space.(app.AppGetter).GetApp(serial.GetMessageType((*OutboundConfig)(nil)))
if app == nil {
return nil
}
return app.(OutboundHandlerManager)
}

View File

@ -3,6 +3,7 @@ package router
import ( import (
"v2ray.com/core/app" "v2ray.com/core/app"
"v2ray.com/core/app/dns" "v2ray.com/core/app/dns"
"v2ray.com/core/common"
"v2ray.com/core/common/errors" "v2ray.com/core/common/errors"
"v2ray.com/core/common/log" "v2ray.com/core/common/log"
v2net "v2ray.com/core/common/net" v2net "v2ray.com/core/common/net"
@ -10,10 +11,6 @@ import (
"v2ray.com/core/proxy" "v2ray.com/core/proxy"
) )
const (
APP_ID = app.ID(3)
)
var ( var (
ErrInvalidRule = errors.New("Invalid Rule") ErrInvalidRule = errors.New("Invalid Rule")
ErrNoRuleApplicable = errors.New("No rule applicable") ErrNoRuleApplicable = errors.New("No rule applicable")
@ -33,7 +30,7 @@ func NewRouter(config *Config, space app.Space) *Router {
rules: make([]Rule, len(config.Rule)), rules: make([]Rule, len(config.Rule)),
} }
space.InitializeApplication(func() error { space.OnInitialize(func() error {
for idx, rule := range config.Rule { for idx, rule := range config.Rule {
r.rules[idx].Tag = rule.Tag r.rules[idx].Tag = rule.Tag
cond, err := rule.BuildCondition() cond, err := rule.BuildCondition()
@ -43,10 +40,10 @@ func NewRouter(config *Config, space app.Space) *Router {
r.rules[idx].Condition = cond r.rules[idx].Condition = cond
} }
if !space.HasApp(dns.APP_ID) { r.dnsServer = dns.FromSpace(space)
if r.dnsServer == nil {
return errors.New("Router: DNS is not found in the space.") return errors.New("Router: DNS is not found in the space.")
} }
r.dnsServer = space.GetApp(dns.APP_ID).(dns.Server)
return nil return nil
}) })
return r return r
@ -116,10 +113,14 @@ func (RouterFactory) Create(space app.Space, config interface{}) (app.Applicatio
return router, nil return router, nil
} }
func (RouterFactory) AppId() app.ID { func FromSpace(space app.Space) *Router {
return APP_ID app := space.(app.AppGetter).GetApp(serial.GetMessageType((*Config)(nil)))
if app == nil {
return nil
}
return app.(*Router)
} }
func init() { func init() {
app.RegisterApplicationFactory(serial.GetMessageType(new(Config)), RouterFactory{}) common.Must(app.RegisterApplicationFactory((*Config)(nil), RouterFactory{}))
} }

View File

@ -5,11 +5,11 @@ import (
"v2ray.com/core/app" "v2ray.com/core/app"
"v2ray.com/core/app/dispatcher" "v2ray.com/core/app/dispatcher"
dispatchers "v2ray.com/core/app/dispatcher/impl" _ "v2ray.com/core/app/dispatcher/impl"
"v2ray.com/core/app/dns" "v2ray.com/core/app/dns"
dnsserver "v2ray.com/core/app/dns/server" _ "v2ray.com/core/app/dns/server"
"v2ray.com/core/app/proxyman" "v2ray.com/core/app/proxyman"
"v2ray.com/core/app/proxyman/outbound" _ "v2ray.com/core/app/proxyman/outbound"
. "v2ray.com/core/app/router" . "v2ray.com/core/app/router"
v2net "v2ray.com/core/common/net" v2net "v2ray.com/core/common/net"
"v2ray.com/core/proxy" "v2ray.com/core/proxy"
@ -31,13 +31,14 @@ func TestSimpleRouter(t *testing.T) {
} }
space := app.NewSpace() space := app.NewSpace()
space.BindApp(dns.APP_ID, dnsserver.NewCacheServer(space, &dns.Config{})) assert.Error(space.AddApp(new(dns.Config))).IsNil()
space.BindApp(dispatcher.APP_ID, dispatchers.NewDefaultDispatcher(space)) assert.Error(space.AddApp(new(dispatcher.Config))).IsNil()
space.BindApp(proxyman.APP_ID_OUTBOUND_MANAGER, outbound.New()) assert.Error(space.AddApp(new(proxyman.OutboundConfig))).IsNil()
r := NewRouter(config, space) assert.Error(space.AddApp(config)).IsNil()
space.BindApp(APP_ID, r)
assert.Error(space.Initialize()).IsNil() assert.Error(space.Initialize()).IsNil()
r := FromSpace(space)
tag, err := r.TakeDetour(&proxy.SessionInfo{Destination: v2net.TCPDestination(v2net.DomainAddress("v2ray.com"), 80)}) tag, err := r.TakeDetour(&proxy.SessionInfo{Destination: v2net.TCPDestination(v2net.DomainAddress("v2ray.com"), 80)})
assert.Error(err).IsNil() assert.Error(err).IsNil()
assert.String(tag).Equals("test") assert.String(tag).Equals("test")

View File

@ -1,23 +1,37 @@
package app package app
import "v2ray.com/core/common/errors" import (
"github.com/golang/protobuf/proto"
type ID int "v2ray.com/core/common/errors"
"v2ray.com/core/common/log"
"v2ray.com/core/common/serial"
)
type Application interface { type Application interface {
} }
type ApplicationInitializer func() error type InitializationCallback func() error
type ApplicationFactory interface { type ApplicationFactory interface {
Create(space Space, config interface{}) (Application, error) Create(space Space, config interface{}) (Application, error)
AppId() ID }
type AppGetter interface {
GetApp(name string) Application
} }
var ( var (
applicationFactoryCache = make(map[string]ApplicationFactory) applicationFactoryCache = make(map[string]ApplicationFactory)
) )
func RegisterApplicationFactory(name string, factory ApplicationFactory) error { func RegisterApplicationFactory(defaultConfig proto.Message, factory ApplicationFactory) error {
if defaultConfig == nil {
return errors.New("Space: config is nil.")
}
name := serial.GetMessageType(defaultConfig)
if len(name) == 0 {
return errors.New("Space: cannot get config type.")
}
applicationFactoryCache[name] = factory applicationFactoryCache[name] = factory
return nil return nil
} }
@ -25,67 +39,67 @@ func RegisterApplicationFactory(name string, factory ApplicationFactory) error {
// A Space contains all apps that may be available in a V2Ray runtime. // 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. // Caller must check the availability of an app by calling HasXXX before getting its instance.
type Space interface { type Space interface {
AddApp(config proto.Message) error
AddAppLegacy(name string, app Application)
Initialize() error Initialize() error
InitializeApplication(ApplicationInitializer) OnInitialize(InitializationCallback)
HasApp(ID) bool
GetApp(ID) Application
BindApp(ID, Application)
BindFromConfig(name string, config interface{}) error
} }
type spaceImpl struct { type spaceImpl struct {
cache map[ID]Application initialized bool
appInit []ApplicationInitializer cache map[string]Application
appInit []InitializationCallback
} }
func NewSpace() Space { func NewSpace() Space {
return &spaceImpl{ return &spaceImpl{
cache: make(map[ID]Application), cache: make(map[string]Application),
appInit: make([]ApplicationInitializer, 0, 32), appInit: make([]InitializationCallback, 0, 32),
} }
} }
func (v *spaceImpl) InitializeApplication(f ApplicationInitializer) { func (v *spaceImpl) OnInitialize(f InitializationCallback) {
v.appInit = append(v.appInit, f) if v.initialized {
if err := f(); err != nil {
log.Error("Space: error after space initialization: ", err)
}
} else {
v.appInit = append(v.appInit, f)
}
} }
func (v *spaceImpl) Initialize() error { func (v *spaceImpl) Initialize() error {
for _, f := range v.appInit { for _, f := range v.appInit {
err := f() if err := f(); err != nil {
if err != nil {
return err return err
} }
} }
v.initialized = true
return nil return nil
} }
func (v *spaceImpl) HasApp(id ID) bool { func (v *spaceImpl) GetApp(configType string) Application {
_, found := v.cache[id] obj, found := v.cache[configType]
return found
}
func (v *spaceImpl) GetApp(id ID) Application {
obj, found := v.cache[id]
if !found { if !found {
return nil return nil
} }
return obj return obj
} }
func (v *spaceImpl) BindApp(id ID, application Application) { func (v *spaceImpl) AddApp(config proto.Message) error {
v.cache[id] = application configName := serial.GetMessageType(config)
} factory, found := applicationFactoryCache[configName]
func (v *spaceImpl) BindFromConfig(name string, config interface{}) error {
factory, found := applicationFactoryCache[name]
if !found { if !found {
return errors.New("Space: app not registered: ", name) return errors.New("Space: app not registered: ", configName)
} }
app, err := factory.Create(v, config) app, err := factory.Create(v, config)
if err != nil { if err != nil {
return err return err
} }
v.BindApp(factory.AppId(), app) v.cache[configName] = app
return nil return nil
} }
func (v *spaceImpl) AddAppLegacy(name string, application Application) {
v.cache[name] = application
}

View File

@ -1,11 +1,5 @@
package web package web
import "v2ray.com/core/app"
const (
APP_ID = app.ID(8)
)
type WebServer interface { type WebServer interface {
Handle() Handle()
} }

View File

@ -30,13 +30,14 @@ func GetInstance(messageType string) (interface{}, error) {
return reflect.New(mType.Elem()).Interface(), nil return reflect.New(mType.Elem()).Interface(), nil
} }
func (v *TypedMessage) GetInstance() (interface{}, error) { func (v *TypedMessage) GetInstance() (proto.Message, error) {
instance, err := GetInstance(v.Type) instance, err := GetInstance(v.Type)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if err := proto.Unmarshal(v.Value, instance.(proto.Message)); err != nil { protoMessage := instance.(proto.Message)
if err := proto.Unmarshal(v.Value, protoMessage); err != nil {
return nil, err return nil, err
} }
return instance, nil return protoMessage, nil
} }

View File

@ -38,11 +38,11 @@ func NewDokodemoDoor(config *Config, space app.Space, meta *proxy.InboundHandler
port: v2net.Port(config.Port), port: v2net.Port(config.Port),
meta: meta, meta: meta,
} }
space.InitializeApplication(func() error { space.OnInitialize(func() error {
if !space.HasApp(dispatcher.APP_ID) { d.packetDispatcher = dispatcher.FromSpace(space)
if d.packetDispatcher == nil {
return errors.New("Dokodemo: Dispatcher is not found in the space.") return errors.New("Dokodemo: Dispatcher is not found in the space.")
} }
d.packetDispatcher = space.GetApp(dispatcher.APP_ID).(dispatcher.PacketDispatcher)
return nil return nil
}) })
return d return d

View File

@ -6,9 +6,9 @@ import (
"v2ray.com/core/app" "v2ray.com/core/app"
"v2ray.com/core/app/dispatcher" "v2ray.com/core/app/dispatcher"
dispatchers "v2ray.com/core/app/dispatcher/impl" _ "v2ray.com/core/app/dispatcher/impl"
"v2ray.com/core/app/proxyman" "v2ray.com/core/app/proxyman"
"v2ray.com/core/app/proxyman/outbound" _ "v2ray.com/core/app/proxyman/outbound"
"v2ray.com/core/common/dice" "v2ray.com/core/common/dice"
v2net "v2ray.com/core/common/net" v2net "v2ray.com/core/common/net"
"v2ray.com/core/proxy" "v2ray.com/core/proxy"
@ -38,8 +38,10 @@ func TestDokodemoTCP(t *testing.T) {
defer tcpServer.Close() defer tcpServer.Close()
space := app.NewSpace() space := app.NewSpace()
space.BindApp(dispatcher.APP_ID, dispatchers.NewDefaultDispatcher(space)) space.AddApp(new(dispatcher.Config))
ohm := outbound.New() space.AddApp(new(proxyman.OutboundConfig))
ohm := proxyman.OutboundHandlerManagerFromSpace(space)
ohm.SetDefaultHandler( ohm.SetDefaultHandler(
freedom.New( freedom.New(
&freedom.Config{}, &freedom.Config{},
@ -50,7 +52,6 @@ func TestDokodemoTCP(t *testing.T) {
Network: v2net.Network_TCP, Network: v2net.Network_TCP,
}, },
})) }))
space.BindApp(proxyman.APP_ID_OUTBOUND_MANAGER, ohm)
data2Send := "Data to be sent to remote." data2Send := "Data to be sent to remote."
@ -109,8 +110,10 @@ func TestDokodemoUDP(t *testing.T) {
defer udpServer.Close() defer udpServer.Close()
space := app.NewSpace() space := app.NewSpace()
space.BindApp(dispatcher.APP_ID, dispatchers.NewDefaultDispatcher(space)) space.AddApp(new(dispatcher.Config))
ohm := outbound.New() space.AddApp(new(proxyman.OutboundConfig))
ohm := proxyman.OutboundHandlerManagerFromSpace(space)
ohm.SetDefaultHandler( ohm.SetDefaultHandler(
freedom.New( freedom.New(
&freedom.Config{}, &freedom.Config{},
@ -120,7 +123,6 @@ func TestDokodemoUDP(t *testing.T) {
StreamSettings: &internet.StreamConfig{ StreamSettings: &internet.StreamConfig{
Network: v2net.Network_TCP, Network: v2net.Network_TCP,
}})) }}))
space.BindApp(proxyman.APP_ID_OUTBOUND_MANAGER, ohm)
data2Send := "Data to be sent to remote." data2Send := "Data to be sent to remote."

View File

@ -32,12 +32,12 @@ func New(config *Config, space app.Space, meta *proxy.OutboundHandlerMeta) *Hand
timeout: config.Timeout, timeout: config.Timeout,
meta: meta, meta: meta,
} }
space.InitializeApplication(func() error { space.OnInitialize(func() error {
if config.DomainStrategy == Config_USE_IP { if config.DomainStrategy == Config_USE_IP {
if !space.HasApp(dns.APP_ID) { f.dns = dns.FromSpace(space)
if f.dns == nil {
return errors.New("Freedom: DNS server is not found in the space.") return errors.New("Freedom: DNS server is not found in the space.")
} }
f.dns = space.GetApp(dns.APP_ID).(dns.Server)
} }
return nil return nil
}) })

View File

@ -6,11 +6,11 @@ import (
"v2ray.com/core/app" "v2ray.com/core/app"
"v2ray.com/core/app/dispatcher" "v2ray.com/core/app/dispatcher"
dispatchers "v2ray.com/core/app/dispatcher/impl" _ "v2ray.com/core/app/dispatcher/impl"
"v2ray.com/core/app/dns" "v2ray.com/core/app/dns"
dnsserver "v2ray.com/core/app/dns/server" _ "v2ray.com/core/app/dns/server"
"v2ray.com/core/app/proxyman" "v2ray.com/core/app/proxyman"
"v2ray.com/core/app/proxyman/outbound" _ "v2ray.com/core/app/proxyman/outbound"
"v2ray.com/core/app/router" "v2ray.com/core/app/router"
"v2ray.com/core/common/buf" "v2ray.com/core/common/buf"
v2net "v2ray.com/core/common/net" v2net "v2ray.com/core/common/net"
@ -70,16 +70,14 @@ func TestIPResolution(t *testing.T) {
assert := assert.On(t) assert := assert.On(t)
space := app.NewSpace() space := app.NewSpace()
space.BindApp(proxyman.APP_ID_OUTBOUND_MANAGER, outbound.New()) assert.Error(space.AddApp(new(proxyman.OutboundConfig))).IsNil()
space.BindApp(dispatcher.APP_ID, dispatchers.NewDefaultDispatcher(space)) assert.Error(space.AddApp(new(dispatcher.Config))).IsNil()
r := router.NewRouter(&router.Config{}, space) assert.Error(space.AddApp(new(router.Config))).IsNil()
space.BindApp(router.APP_ID, r) assert.Error(space.AddApp(&dns.Config{
dnsServer := dnsserver.NewCacheServer(space, &dns.Config{
Hosts: map[string]*v2net.IPOrDomain{ Hosts: map[string]*v2net.IPOrDomain{
"v2ray.com": v2net.NewIPOrDomain(v2net.LocalHostIP), "v2ray.com": v2net.NewIPOrDomain(v2net.LocalHostIP),
}, },
}) })).IsNil()
space.BindApp(dns.APP_ID, dnsServer)
freedom := New( freedom := New(
&Config{DomainStrategy: Config_USE_IP}, &Config{DomainStrategy: Config_USE_IP},

View File

@ -33,12 +33,19 @@ type Server struct {
} }
// NewServer creates a new HTTP inbound handler. // NewServer creates a new HTTP inbound handler.
func NewServer(config *ServerConfig, packetDispatcher dispatcher.PacketDispatcher, meta *proxy.InboundHandlerMeta) *Server { func NewServer(config *ServerConfig, space app.Space, meta *proxy.InboundHandlerMeta) *Server {
return &Server{ s := &Server{
packetDispatcher: packetDispatcher, config: config,
config: config, meta: meta,
meta: meta,
} }
space.OnInitialize(func() error {
s.packetDispatcher = dispatcher.FromSpace(space)
if s.packetDispatcher == nil {
return errors.New("HTTP|Server: Dispatcher not found in space.")
}
return nil
})
return s
} }
// Port implements InboundHandler.Port(). // Port implements InboundHandler.Port().
@ -291,13 +298,7 @@ func (v *ServerFactory) StreamCapability() v2net.NetworkList {
// Create implements InboundHandlerFactory.Create(). // Create implements InboundHandlerFactory.Create().
func (v *ServerFactory) Create(space app.Space, rawConfig interface{}, meta *proxy.InboundHandlerMeta) (proxy.InboundHandler, error) { func (v *ServerFactory) Create(space app.Space, rawConfig interface{}, meta *proxy.InboundHandlerMeta) (proxy.InboundHandler, error) {
if !space.HasApp(dispatcher.APP_ID) { return NewServer(rawConfig.(*ServerConfig), space, meta), nil
return nil, common.ErrBadConfiguration
}
return NewServer(
rawConfig.(*ServerConfig),
space.GetApp(dispatcher.APP_ID).(dispatcher.PacketDispatcher),
meta), nil
} }
func init() { func init() {

View File

@ -6,13 +6,8 @@ import (
"strings" "strings"
"testing" "testing"
testdispatcher "v2ray.com/core/app/dispatcher/testing"
"v2ray.com/core/common/dice"
v2net "v2ray.com/core/common/net"
"v2ray.com/core/proxy"
. "v2ray.com/core/proxy/http" . "v2ray.com/core/proxy/http"
"v2ray.com/core/testing/assert" "v2ray.com/core/testing/assert"
"v2ray.com/core/transport/internet"
_ "v2ray.com/core/transport/internet/tcp" _ "v2ray.com/core/transport/internet/tcp"
) )
@ -50,30 +45,3 @@ Accept-Language: de,en;q=0.7,en-us;q=0.3
assert.String(req.Header.Get("Proxy-Connection")).Equals("") assert.String(req.Header.Get("Proxy-Connection")).Equals("")
assert.String(req.Header.Get("Proxy-Authenticate")).Equals("") assert.String(req.Header.Get("Proxy-Authenticate")).Equals("")
} }
func TestNormalGetRequest(t *testing.T) {
assert := assert.On(t)
testPacketDispatcher := testdispatcher.NewTestPacketDispatcher(nil)
port := v2net.Port(dice.Roll(20000) + 10000)
httpProxy := NewServer(
&ServerConfig{},
testPacketDispatcher,
&proxy.InboundHandlerMeta{
Address: v2net.LocalHostIP,
Port: port,
StreamSettings: &internet.StreamConfig{
Network: v2net.Network_TCP,
}})
defer httpProxy.Close()
err := httpProxy.Start()
assert.Error(err).IsNil()
assert.Port(port).Equals(httpProxy.Port())
httpClient := &http.Client{}
resp, err := httpClient.Get("http://127.0.0.1:" + port.String() + "/")
assert.Error(err).IsNil()
assert.Int(resp.StatusCode).Equals(400)
}

View File

@ -3,7 +3,6 @@ package shadowsocks
import ( import (
"v2ray.com/core/app" "v2ray.com/core/app"
"v2ray.com/core/app/dispatcher" "v2ray.com/core/app/dispatcher"
"v2ray.com/core/common"
"v2ray.com/core/common/buf" "v2ray.com/core/common/buf"
"v2ray.com/core/common/bufio" "v2ray.com/core/common/bufio"
"v2ray.com/core/common/errors" "v2ray.com/core/common/errors"
@ -46,11 +45,11 @@ func NewServer(config *ServerConfig, space app.Space, meta *proxy.InboundHandler
account: account, account: account,
} }
space.InitializeApplication(func() error { space.OnInitialize(func() error {
if !space.HasApp(dispatcher.APP_ID) { s.packetDispatcher = dispatcher.FromSpace(space)
if s.packetDispatcher == nil {
return errors.New("Shadowsocks|Server: Dispatcher is not found in space.") return errors.New("Shadowsocks|Server: Dispatcher is not found in space.")
} }
s.packetDispatcher = space.GetApp(dispatcher.APP_ID).(dispatcher.PacketDispatcher)
return nil return nil
}) })
@ -228,8 +227,5 @@ func (v *ServerFactory) StreamCapability() v2net.NetworkList {
} }
func (v *ServerFactory) Create(space app.Space, rawConfig interface{}, meta *proxy.InboundHandlerMeta) (proxy.InboundHandler, error) { func (v *ServerFactory) Create(space app.Space, rawConfig interface{}, meta *proxy.InboundHandlerMeta) (proxy.InboundHandler, error) {
if !space.HasApp(dispatcher.APP_ID) {
return nil, common.ErrBadConfiguration
}
return NewServer(rawConfig.(*ServerConfig), space, meta) return NewServer(rawConfig.(*ServerConfig), space, meta)
} }

View File

@ -41,11 +41,11 @@ func NewServer(config *ServerConfig, space app.Space, meta *proxy.InboundHandler
config: config, config: config,
meta: meta, meta: meta,
} }
space.InitializeApplication(func() error { space.OnInitialize(func() error {
if !space.HasApp(dispatcher.APP_ID) { s.packetDispatcher = dispatcher.FromSpace(space)
if s.packetDispatcher == nil {
return errors.New("Socks|Server: Dispatcher is not found in the space.") return errors.New("Socks|Server: Dispatcher is not found in the space.")
} }
s.packetDispatcher = space.GetApp(dispatcher.APP_ID).(dispatcher.PacketDispatcher)
return nil return nil
}) })
return s return s

View File

@ -261,9 +261,6 @@ func (v *Factory) StreamCapability() v2net.NetworkList {
} }
func (v *Factory) Create(space app.Space, rawConfig interface{}, meta *proxy.InboundHandlerMeta) (proxy.InboundHandler, error) { func (v *Factory) Create(space app.Space, rawConfig interface{}, meta *proxy.InboundHandlerMeta) (proxy.InboundHandler, error) {
if !space.HasApp(dispatcher.APP_ID) {
return nil, common.ErrBadConfiguration
}
config := rawConfig.(*Config) config := rawConfig.(*Config)
allowedClients := vmess.NewTimedUserValidator(protocol.DefaultIDHash) allowedClients := vmess.NewTimedUserValidator(protocol.DefaultIDHash)
@ -272,16 +269,23 @@ func (v *Factory) Create(space app.Space, rawConfig interface{}, meta *proxy.Inb
} }
handler := &VMessInboundHandler{ handler := &VMessInboundHandler{
packetDispatcher: space.GetApp(dispatcher.APP_ID).(dispatcher.PacketDispatcher), clients: allowedClients,
clients: allowedClients, detours: config.Detour,
detours: config.Detour, usersByEmail: NewUserByEmail(config.User, config.GetDefaultValue()),
usersByEmail: NewUserByEmail(config.User, config.GetDefaultValue()), meta: meta,
meta: meta,
} }
if space.HasApp(proxyman.APP_ID_INBOUND_MANAGER) { space.OnInitialize(func() error {
handler.inboundHandlerManager = space.GetApp(proxyman.APP_ID_INBOUND_MANAGER).(proxyman.InboundHandlerManager) handler.packetDispatcher = dispatcher.FromSpace(space)
} if handler.packetDispatcher == nil {
return errors.New("VMess|Inbound: Dispatcher is not found in space.")
}
handler.inboundHandlerManager = proxyman.InboundHandlerManagerFromSpace(space)
if handler.inboundHandlerManager == nil {
return errors.New("VMess|Inbound: InboundHandlerManager is not found is space.")
}
return nil
})
return handler, nil return handler, nil
} }

View File

@ -39,43 +39,52 @@ func NewPoint(pConfig *Config) (*Point, error) {
space := app.NewSpace() space := app.NewSpace()
vpoint.space = space vpoint.space = space
vpoint.space.BindApp(proxyman.APP_ID_INBOUND_MANAGER, vpoint) vpoint.space.AddAppLegacy(serial.GetMessageType((*proxyman.InboundConfig)(nil)), vpoint)
outboundManagerConfig := new(proxyman.OutboundConfig) outboundHandlerManager := proxyman.OutboundHandlerManagerFromSpace(space)
if err := space.BindFromConfig(serial.GetMessageType(outboundManagerConfig), outboundManagerConfig); err != nil { if outboundHandlerManager == nil {
return nil, err if err := space.AddApp(new(proxyman.OutboundConfig)); err != nil {
return nil, err
}
outboundHandlerManager = proxyman.OutboundHandlerManagerFromSpace(space)
} }
outboundHandlerManager := space.GetApp(proxyman.APP_ID_OUTBOUND_MANAGER).(proxyman.OutboundHandlerManager) proxyDialer := proxydialer.OutboundProxyFromSpace(space)
if proxyDialer == nil {
proxyDialer := proxydialer.NewOutboundProxy(space) space.AddApp(new(proxydialer.Config))
proxyDialer = proxydialer.OutboundProxyFromSpace(space)
}
proxyDialer.RegisterDialer() proxyDialer.RegisterDialer()
space.BindApp(proxydialer.APP_ID, proxyDialer)
for _, app := range pConfig.App { for _, app := range pConfig.App {
settings, err := app.GetInstance() settings, err := app.GetInstance()
if err != nil { if err != nil {
return nil, err return nil, err
} }
if err := space.BindFromConfig(app.Type, settings); err != nil { if err := space.AddApp(settings); err != nil {
return nil, err return nil, err
} }
} }
if !space.HasApp(dns.APP_ID) { dnsServer := dns.FromSpace(space)
if dnsServer == nil {
dnsConfig := &dns.Config{ dnsConfig := &dns.Config{
NameServers: []*v2net.Endpoint{{ NameServers: []*v2net.Endpoint{{
Address: v2net.NewIPOrDomain(v2net.LocalHostDomain), Address: v2net.NewIPOrDomain(v2net.LocalHostDomain),
}}, }},
} }
if err := space.BindFromConfig(serial.GetMessageType(dnsConfig), dnsConfig); err != nil { if err := space.AddApp(dnsConfig); err != nil {
return nil, err return nil, err
} }
} }
dispatcherConfig := new(dispatcher.Config) disp := dispatcher.FromSpace(space)
if err := vpoint.space.BindFromConfig(serial.GetMessageType(dispatcherConfig), dispatcherConfig); err != nil { if disp == nil {
return nil, err dispatcherConfig := new(dispatcher.Config)
if err := vpoint.space.AddApp(dispatcherConfig); err != nil {
return nil, err
}
disp = dispatcher.FromSpace(space)
} }
vpoint.inboundHandlers = make([]InboundDetourHandler, 0, 8) vpoint.inboundHandlers = make([]InboundDetourHandler, 0, 8)