mirror of https://github.com/v2ray/v2ray-core
support using specific address
parent
6c31ff91e6
commit
a4d76dc394
|
@ -20,7 +20,7 @@ func TestDnsAdd(t *testing.T) {
|
||||||
space := app.NewSpace()
|
space := app.NewSpace()
|
||||||
|
|
||||||
outboundHandlerManager := proxyman.NewDefaultOutboundHandlerManager()
|
outboundHandlerManager := proxyman.NewDefaultOutboundHandlerManager()
|
||||||
outboundHandlerManager.SetDefaultHandler(freedom.NewFreedomConnection(&freedom.Config{}, space))
|
outboundHandlerManager.SetDefaultHandler(freedom.NewFreedomConnection(&freedom.Config{}, space, v2net.AnyIP))
|
||||||
space.BindApp(proxyman.APP_ID_OUTBOUND_MANAGER, outboundHandlerManager)
|
space.BindApp(proxyman.APP_ID_OUTBOUND_MANAGER, outboundHandlerManager)
|
||||||
space.BindApp(dispatcher.APP_ID, dispatchers.NewDefaultDispatcher(space))
|
space.BindApp(dispatcher.APP_ID, dispatchers.NewDefaultDispatcher(space))
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,10 @@ func (this Network) AsList() *NetworkList {
|
||||||
return &list
|
return &list
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this Network) String() string {
|
||||||
|
return string(this)
|
||||||
|
}
|
||||||
|
|
||||||
// NetworkList is a list of Networks.
|
// NetworkList is a list of Networks.
|
||||||
type NetworkList []Network
|
type NetworkList []Network
|
||||||
|
|
||||||
|
|
|
@ -6,5 +6,5 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func PickPort() v2net.Port {
|
func PickPort() v2net.Port {
|
||||||
return v2net.Port(30000 + dice.Roll(5000))
|
return v2net.Port(30000 + dice.Roll(20000))
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ func NewTimedUserValidator(hasher IDHash) UserValidator {
|
||||||
hasher: hasher,
|
hasher: hasher,
|
||||||
cancel: signal.NewCloseSignal(),
|
cancel: signal.NewCloseSignal(),
|
||||||
}
|
}
|
||||||
go tus.updateUserHash(time.Tick(updateIntervalSec*time.Second), tus.cancel)
|
go tus.updateUserHash(updateIntervalSec*time.Second, tus.cancel)
|
||||||
return tus
|
return tus
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,11 +88,11 @@ func (this *TimedUserValidator) generateNewHashes(nowSec Timestamp, idx int, ent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *TimedUserValidator) updateUserHash(tick <-chan time.Time, cancel *signal.CancelSignal) {
|
func (this *TimedUserValidator) updateUserHash(interval time.Duration, cancel *signal.CancelSignal) {
|
||||||
L:
|
L:
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case now := <-tick:
|
case now := <-time.After(interval):
|
||||||
nowSec := Timestamp(now.Unix() + cacheDurationSec)
|
nowSec := Timestamp(now.Unix() + cacheDurationSec)
|
||||||
for _, entry := range this.ids {
|
for _, entry := range this.ids {
|
||||||
this.generateNewHashes(nowSec, entry.userIdx, entry)
|
this.generateNewHashes(nowSec, entry.userIdx, entry)
|
||||||
|
|
|
@ -31,7 +31,7 @@ func (this *BlackHole) Dispatch(destination v2net.Destination, payload *alloc.Bu
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
internal.MustRegisterOutboundHandlerCreator("blackhole",
|
internal.MustRegisterOutboundHandlerCreator("blackhole",
|
||||||
func(space app.Space, config interface{}) (proxy.OutboundHandler, error) {
|
func(space app.Space, config interface{}, sendThrough v2net.Address) (proxy.OutboundHandler, error) {
|
||||||
return NewBlackHole(), nil
|
return NewBlackHole(), nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,11 +29,13 @@ type DokodemoDoor struct {
|
||||||
listeningAddress v2net.Address
|
listeningAddress v2net.Address
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDokodemoDoor(config *Config, space app.Space) *DokodemoDoor {
|
func NewDokodemoDoor(config *Config, space app.Space, listen v2net.Address, port v2net.Port) *DokodemoDoor {
|
||||||
d := &DokodemoDoor{
|
d := &DokodemoDoor{
|
||||||
config: config,
|
config: config,
|
||||||
address: config.Address,
|
address: config.Address,
|
||||||
port: config.Port,
|
port: config.Port,
|
||||||
|
listeningAddress: listen,
|
||||||
|
listeningPort: port,
|
||||||
}
|
}
|
||||||
space.InitializeApplication(func() error {
|
space.InitializeApplication(func() error {
|
||||||
if !space.HasApp(dispatcher.APP_ID) {
|
if !space.HasApp(dispatcher.APP_ID) {
|
||||||
|
@ -66,26 +68,20 @@ func (this *DokodemoDoor) Close() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *DokodemoDoor) Listen(address v2net.Address, port v2net.Port) error {
|
func (this *DokodemoDoor) Start() error {
|
||||||
if this.accepting {
|
if this.accepting {
|
||||||
if this.listeningPort == port && this.listeningAddress.Equals(address) {
|
return nil
|
||||||
return nil
|
|
||||||
} else {
|
|
||||||
return proxy.ErrorAlreadyListening
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
this.listeningPort = port
|
|
||||||
this.listeningAddress = address
|
|
||||||
this.accepting = true
|
this.accepting = true
|
||||||
|
|
||||||
if this.config.Network.HasNetwork(v2net.TCPNetwork) {
|
if this.config.Network.HasNetwork(v2net.TCPNetwork) {
|
||||||
err := this.ListenTCP(address, port)
|
err := this.ListenTCP(this.listeningAddress, this.listeningPort)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if this.config.Network.HasNetwork(v2net.UDPNetwork) {
|
if this.config.Network.HasNetwork(v2net.UDPNetwork) {
|
||||||
err := this.ListenUDP(address, port)
|
err := this.ListenUDP(this.listeningAddress, this.listeningPort)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -168,7 +164,7 @@ func (this *DokodemoDoor) HandleTCPConnection(conn *hub.Connection) {
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
internal.MustRegisterInboundHandlerCreator("dokodemo-door",
|
internal.MustRegisterInboundHandlerCreator("dokodemo-door",
|
||||||
func(space app.Space, rawConfig interface{}) (proxy.InboundHandler, error) {
|
func(space app.Space, rawConfig interface{}, listen v2net.Address, port v2net.Port) (proxy.InboundHandler, error) {
|
||||||
return NewDokodemoDoor(rawConfig.(*Config), space), nil
|
return NewDokodemoDoor(rawConfig.(*Config), space, listen, port), nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,23 +37,23 @@ func TestDokodemoTCP(t *testing.T) {
|
||||||
space := app.NewSpace()
|
space := app.NewSpace()
|
||||||
space.BindApp(dispatcher.APP_ID, dispatchers.NewDefaultDispatcher(space))
|
space.BindApp(dispatcher.APP_ID, dispatchers.NewDefaultDispatcher(space))
|
||||||
ohm := proxyman.NewDefaultOutboundHandlerManager()
|
ohm := proxyman.NewDefaultOutboundHandlerManager()
|
||||||
ohm.SetDefaultHandler(freedom.NewFreedomConnection(&freedom.Config{}, space))
|
ohm.SetDefaultHandler(freedom.NewFreedomConnection(&freedom.Config{}, space, v2net.LocalHostIP))
|
||||||
space.BindApp(proxyman.APP_ID_OUTBOUND_MANAGER, ohm)
|
space.BindApp(proxyman.APP_ID_OUTBOUND_MANAGER, ohm)
|
||||||
|
|
||||||
data2Send := "Data to be sent to remote."
|
data2Send := "Data to be sent to remote."
|
||||||
|
|
||||||
|
port := v2nettesting.PickPort()
|
||||||
dokodemo := NewDokodemoDoor(&Config{
|
dokodemo := NewDokodemoDoor(&Config{
|
||||||
Address: v2net.LocalHostIP,
|
Address: v2net.LocalHostIP,
|
||||||
Port: tcpServer.Port,
|
Port: tcpServer.Port,
|
||||||
Network: v2net.TCPNetwork.AsList(),
|
Network: v2net.TCPNetwork.AsList(),
|
||||||
Timeout: 600,
|
Timeout: 600,
|
||||||
}, space)
|
}, space, v2net.LocalHostIP, port)
|
||||||
defer dokodemo.Close()
|
defer dokodemo.Close()
|
||||||
|
|
||||||
assert.Error(space.Initialize()).IsNil()
|
assert.Error(space.Initialize()).IsNil()
|
||||||
|
|
||||||
port := v2nettesting.PickPort()
|
err = dokodemo.Start()
|
||||||
err = dokodemo.Listen(v2net.LocalHostIP, port)
|
|
||||||
assert.Error(err).IsNil()
|
assert.Error(err).IsNil()
|
||||||
assert.Port(port).Equals(dokodemo.Port())
|
assert.Port(port).Equals(dokodemo.Port())
|
||||||
|
|
||||||
|
@ -95,23 +95,23 @@ func TestDokodemoUDP(t *testing.T) {
|
||||||
space := app.NewSpace()
|
space := app.NewSpace()
|
||||||
space.BindApp(dispatcher.APP_ID, dispatchers.NewDefaultDispatcher(space))
|
space.BindApp(dispatcher.APP_ID, dispatchers.NewDefaultDispatcher(space))
|
||||||
ohm := proxyman.NewDefaultOutboundHandlerManager()
|
ohm := proxyman.NewDefaultOutboundHandlerManager()
|
||||||
ohm.SetDefaultHandler(freedom.NewFreedomConnection(&freedom.Config{}, space))
|
ohm.SetDefaultHandler(freedom.NewFreedomConnection(&freedom.Config{}, space, v2net.AnyIP))
|
||||||
space.BindApp(proxyman.APP_ID_OUTBOUND_MANAGER, ohm)
|
space.BindApp(proxyman.APP_ID_OUTBOUND_MANAGER, ohm)
|
||||||
|
|
||||||
data2Send := "Data to be sent to remote."
|
data2Send := "Data to be sent to remote."
|
||||||
|
|
||||||
|
port := v2nettesting.PickPort()
|
||||||
dokodemo := NewDokodemoDoor(&Config{
|
dokodemo := NewDokodemoDoor(&Config{
|
||||||
Address: v2net.LocalHostIP,
|
Address: v2net.LocalHostIP,
|
||||||
Port: udpServer.Port,
|
Port: udpServer.Port,
|
||||||
Network: v2net.UDPNetwork.AsList(),
|
Network: v2net.UDPNetwork.AsList(),
|
||||||
Timeout: 600,
|
Timeout: 600,
|
||||||
}, space)
|
}, space, v2net.LocalHostIP, port)
|
||||||
defer dokodemo.Close()
|
defer dokodemo.Close()
|
||||||
|
|
||||||
assert.Error(space.Initialize()).IsNil()
|
assert.Error(space.Initialize()).IsNil()
|
||||||
|
|
||||||
port := v2nettesting.PickPort()
|
err = dokodemo.Start()
|
||||||
err = dokodemo.Listen(v2net.LocalHostIP, port)
|
|
||||||
assert.Error(err).IsNil()
|
assert.Error(err).IsNil()
|
||||||
assert.Port(port).Equals(dokodemo.Port())
|
assert.Port(port).Equals(dokodemo.Port())
|
||||||
|
|
||||||
|
|
|
@ -23,12 +23,14 @@ type FreedomConnection struct {
|
||||||
domainStrategy DomainStrategy
|
domainStrategy DomainStrategy
|
||||||
timeout uint32
|
timeout uint32
|
||||||
dns dns.Server
|
dns dns.Server
|
||||||
|
sendThrough v2net.Address
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewFreedomConnection(config *Config, space app.Space) *FreedomConnection {
|
func NewFreedomConnection(config *Config, space app.Space, sendThrough v2net.Address) *FreedomConnection {
|
||||||
f := &FreedomConnection{
|
f := &FreedomConnection{
|
||||||
domainStrategy: config.DomainStrategy,
|
domainStrategy: config.DomainStrategy,
|
||||||
timeout: config.Timeout,
|
timeout: config.Timeout,
|
||||||
|
sendThrough: sendThrough,
|
||||||
}
|
}
|
||||||
space.InitializeApplication(func() error {
|
space.InitializeApplication(func() error {
|
||||||
if config.DomainStrategy == DomainStrategyUseIP {
|
if config.DomainStrategy == DomainStrategyUseIP {
|
||||||
|
@ -78,7 +80,7 @@ func (this *FreedomConnection) Dispatch(destination v2net.Destination, payload *
|
||||||
destination = this.ResolveIP(destination)
|
destination = this.ResolveIP(destination)
|
||||||
}
|
}
|
||||||
err := retry.Timed(5, 100).On(func() error {
|
err := retry.Timed(5, 100).On(func() error {
|
||||||
rawConn, err := hub.DialWithoutCache(destination)
|
rawConn, err := hub.DialWithoutCache(this.sendThrough, destination)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -138,7 +140,7 @@ func (this *FreedomConnection) Dispatch(destination v2net.Destination, payload *
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
internal.MustRegisterOutboundHandlerCreator("freedom",
|
internal.MustRegisterOutboundHandlerCreator("freedom",
|
||||||
func(space app.Space, config interface{}) (proxy.OutboundHandler, error) {
|
func(space app.Space, config interface{}, sendThrough v2net.Address) (proxy.OutboundHandler, error) {
|
||||||
return NewFreedomConnection(config.(*Config), space), nil
|
return NewFreedomConnection(config.(*Config), space, sendThrough), nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ func TestSinglePacket(t *testing.T) {
|
||||||
assert.Error(err).IsNil()
|
assert.Error(err).IsNil()
|
||||||
|
|
||||||
space := app.NewSpace()
|
space := app.NewSpace()
|
||||||
freedom := NewFreedomConnection(&Config{}, space)
|
freedom := NewFreedomConnection(&Config{}, space, v2net.AnyIP)
|
||||||
space.Initialize()
|
space.Initialize()
|
||||||
|
|
||||||
traffic := ray.NewRay()
|
traffic := ray.NewRay()
|
||||||
|
@ -57,7 +57,7 @@ func TestSinglePacket(t *testing.T) {
|
||||||
func TestUnreachableDestination(t *testing.T) {
|
func TestUnreachableDestination(t *testing.T) {
|
||||||
assert := assert.On(t)
|
assert := assert.On(t)
|
||||||
|
|
||||||
freedom := NewFreedomConnection(&Config{}, app.NewSpace())
|
freedom := NewFreedomConnection(&Config{}, app.NewSpace(), v2net.AnyIP)
|
||||||
traffic := ray.NewRay()
|
traffic := ray.NewRay()
|
||||||
data2Send := "Data to be sent to remote"
|
data2Send := "Data to be sent to remote"
|
||||||
payload := alloc.NewSmallBuffer().Clear().Append([]byte(data2Send))
|
payload := alloc.NewSmallBuffer().Clear().Append([]byte(data2Send))
|
||||||
|
@ -81,7 +81,7 @@ func TestIPResolution(t *testing.T) {
|
||||||
})
|
})
|
||||||
space.BindApp(dns.APP_ID, dnsServer)
|
space.BindApp(dns.APP_ID, dnsServer)
|
||||||
|
|
||||||
freedom := NewFreedomConnection(&Config{DomainStrategy: DomainStrategyUseIP}, space)
|
freedom := NewFreedomConnection(&Config{DomainStrategy: DomainStrategyUseIP}, space, v2net.AnyIP)
|
||||||
|
|
||||||
space.Initialize()
|
space.Initialize()
|
||||||
|
|
||||||
|
|
|
@ -33,10 +33,12 @@ type Server struct {
|
||||||
listeningAddress v2net.Address
|
listeningAddress v2net.Address
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewServer(config *Config, packetDispatcher dispatcher.PacketDispatcher) *Server {
|
func NewServer(config *Config, packetDispatcher dispatcher.PacketDispatcher, listen v2net.Address, port v2net.Port) *Server {
|
||||||
return &Server{
|
return &Server{
|
||||||
packetDispatcher: packetDispatcher,
|
packetDispatcher: packetDispatcher,
|
||||||
config: config,
|
config: config,
|
||||||
|
listeningAddress: listen,
|
||||||
|
listeningPort: port,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,24 +56,18 @@ func (this *Server) Close() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *Server) Listen(address v2net.Address, port v2net.Port) error {
|
func (this *Server) Start() error {
|
||||||
if this.accepting {
|
if this.accepting {
|
||||||
if this.listeningPort == port && this.listeningAddress.Equals(address) {
|
return nil
|
||||||
return nil
|
|
||||||
} else {
|
|
||||||
return proxy.ErrorAlreadyListening
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
this.listeningPort = port
|
|
||||||
this.listeningAddress = address
|
|
||||||
|
|
||||||
var tlsConfig *tls.Config
|
var tlsConfig *tls.Config
|
||||||
if this.config.TLSConfig != nil {
|
if this.config.TLSConfig != nil {
|
||||||
tlsConfig = this.config.TLSConfig.GetConfig()
|
tlsConfig = this.config.TLSConfig.GetConfig()
|
||||||
}
|
}
|
||||||
tcpListener, err := hub.ListenTCP(address, port, this.handleConnection, tlsConfig)
|
tcpListener, err := hub.ListenTCP(this.listeningAddress, this.listeningPort, this.handleConnection, tlsConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("HTTP: Failed listen on port ", port, ": ", err)
|
log.Error("HTTP: Failed listen on port ", this.listeningPort, ": ", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
this.Lock()
|
this.Lock()
|
||||||
|
@ -276,12 +272,14 @@ func (this *Server) handlePlainHTTP(request *http.Request, dest v2net.Destinatio
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
internal.MustRegisterInboundHandlerCreator("http",
|
internal.MustRegisterInboundHandlerCreator("http",
|
||||||
func(space app.Space, rawConfig interface{}) (proxy.InboundHandler, error) {
|
func(space app.Space, rawConfig interface{}, listen v2net.Address, port v2net.Port) (proxy.InboundHandler, error) {
|
||||||
if !space.HasApp(dispatcher.APP_ID) {
|
if !space.HasApp(dispatcher.APP_ID) {
|
||||||
return nil, internal.ErrorBadConfiguration
|
return nil, internal.ErrorBadConfiguration
|
||||||
}
|
}
|
||||||
return NewServer(
|
return NewServer(
|
||||||
rawConfig.(*Config),
|
rawConfig.(*Config),
|
||||||
space.GetApp(dispatcher.APP_ID).(dispatcher.PacketDispatcher)), nil
|
space.GetApp(dispatcher.APP_ID).(dispatcher.PacketDispatcher),
|
||||||
|
listen,
|
||||||
|
port), nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,11 +52,11 @@ func TestNormalGetRequest(t *testing.T) {
|
||||||
|
|
||||||
testPacketDispatcher := testdispatcher.NewTestPacketDispatcher(nil)
|
testPacketDispatcher := testdispatcher.NewTestPacketDispatcher(nil)
|
||||||
|
|
||||||
httpProxy := NewServer(&Config{}, testPacketDispatcher)
|
port := v2nettesting.PickPort()
|
||||||
|
httpProxy := NewServer(&Config{}, testPacketDispatcher, v2net.LocalHostIP, port)
|
||||||
defer httpProxy.Close()
|
defer httpProxy.Close()
|
||||||
|
|
||||||
port := v2nettesting.PickPort()
|
err := httpProxy.Start()
|
||||||
err := httpProxy.Listen(v2net.LocalHostIP, port)
|
|
||||||
assert.Error(err).IsNil()
|
assert.Error(err).IsNil()
|
||||||
assert.Port(port).Equals(httpProxy.Port())
|
assert.Port(port).Equals(httpProxy.Port())
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,9 @@ package internal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/v2ray/v2ray-core/app"
|
"github.com/v2ray/v2ray-core/app"
|
||||||
|
v2net "github.com/v2ray/v2ray-core/common/net"
|
||||||
"github.com/v2ray/v2ray-core/proxy"
|
"github.com/v2ray/v2ray-core/proxy"
|
||||||
)
|
)
|
||||||
|
|
||||||
type InboundHandlerCreator func(space app.Space, config interface{}) (proxy.InboundHandler, error)
|
type InboundHandlerCreator func(space app.Space, config interface{}, listenOn v2net.Address, port v2net.Port) (proxy.InboundHandler, error)
|
||||||
type OutboundHandlerCreator func(space app.Space, config interface{}) (proxy.OutboundHandler, error)
|
type OutboundHandlerCreator func(space app.Space, config interface{}, sendThrough v2net.Address) (proxy.OutboundHandler, error)
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"github.com/v2ray/v2ray-core/app"
|
"github.com/v2ray/v2ray-core/app"
|
||||||
|
v2net "github.com/v2ray/v2ray-core/common/net"
|
||||||
"github.com/v2ray/v2ray-core/proxy"
|
"github.com/v2ray/v2ray-core/proxy"
|
||||||
"github.com/v2ray/v2ray-core/proxy/internal/config"
|
"github.com/v2ray/v2ray-core/proxy/internal/config"
|
||||||
)
|
)
|
||||||
|
@ -45,7 +46,7 @@ func MustRegisterOutboundHandlerCreator(name string, creator OutboundHandlerCrea
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateInboundHandler(name string, space app.Space, rawConfig []byte) (proxy.InboundHandler, error) {
|
func CreateInboundHandler(name string, space app.Space, rawConfig []byte, listen v2net.Address, port v2net.Port) (proxy.InboundHandler, error) {
|
||||||
creator, found := inboundFactories[name]
|
creator, found := inboundFactories[name]
|
||||||
if !found {
|
if !found {
|
||||||
return nil, ErrorProxyNotFound
|
return nil, ErrorProxyNotFound
|
||||||
|
@ -55,12 +56,12 @@ func CreateInboundHandler(name string, space app.Space, rawConfig []byte) (proxy
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return creator(space, proxyConfig)
|
return creator(space, proxyConfig, listen, port)
|
||||||
}
|
}
|
||||||
return creator(space, nil)
|
return creator(space, nil, listen, port)
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateOutboundHandler(name string, space app.Space, rawConfig []byte) (proxy.OutboundHandler, error) {
|
func CreateOutboundHandler(name string, space app.Space, rawConfig []byte, sendThrough v2net.Address) (proxy.OutboundHandler, error) {
|
||||||
creator, found := outboundFactories[name]
|
creator, found := outboundFactories[name]
|
||||||
if !found {
|
if !found {
|
||||||
return nil, ErrorNameExists
|
return nil, ErrorNameExists
|
||||||
|
@ -71,8 +72,8 @@ func CreateOutboundHandler(name string, space app.Space, rawConfig []byte) (prox
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return creator(space, proxyConfig)
|
return creator(space, proxyConfig, sendThrough)
|
||||||
}
|
}
|
||||||
|
|
||||||
return creator(space, nil)
|
return creator(space, nil, sendThrough)
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,8 +16,8 @@ const (
|
||||||
|
|
||||||
// An InboundHandler handles inbound network connections to V2Ray.
|
// An InboundHandler handles inbound network connections to V2Ray.
|
||||||
type InboundHandler interface {
|
type InboundHandler interface {
|
||||||
// Listen starts a InboundHandler by listen on a specific port.
|
// Listen starts a InboundHandler.
|
||||||
Listen(on v2net.Address, port v2net.Port) error
|
Start() error
|
||||||
// Close stops the handler to accepting anymore inbound connections.
|
// Close stops the handler to accepting anymore inbound connections.
|
||||||
Close()
|
Close()
|
||||||
// Port returns the port that the handler is listening on.
|
// Port returns the port that the handler is listening on.
|
||||||
|
|
|
@ -2,14 +2,15 @@ package repo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/v2ray/v2ray-core/app"
|
"github.com/v2ray/v2ray-core/app"
|
||||||
|
v2net "github.com/v2ray/v2ray-core/common/net"
|
||||||
"github.com/v2ray/v2ray-core/proxy"
|
"github.com/v2ray/v2ray-core/proxy"
|
||||||
"github.com/v2ray/v2ray-core/proxy/internal"
|
"github.com/v2ray/v2ray-core/proxy/internal"
|
||||||
)
|
)
|
||||||
|
|
||||||
func CreateInboundHandler(name string, space app.Space, rawConfig []byte) (proxy.InboundHandler, error) {
|
func CreateInboundHandler(name string, space app.Space, rawConfig []byte, listen v2net.Address, port v2net.Port) (proxy.InboundHandler, error) {
|
||||||
return internal.CreateInboundHandler(name, space, rawConfig)
|
return internal.CreateInboundHandler(name, space, rawConfig, listen, port)
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateOutboundHandler(name string, space app.Space, rawConfig []byte) (proxy.OutboundHandler, error) {
|
func CreateOutboundHandler(name string, space app.Space, rawConfig []byte, sendThrough v2net.Address) (proxy.OutboundHandler, error) {
|
||||||
return internal.CreateOutboundHandler(name, space, rawConfig)
|
return internal.CreateOutboundHandler(name, space, rawConfig, sendThrough)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package shadowsocks_test
|
package shadowsocks_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/v2ray/v2ray-core/common/alloc"
|
"github.com/v2ray/v2ray-core/common/alloc"
|
||||||
|
@ -29,7 +30,7 @@ func TestEmptyPayload(t *testing.T) {
|
||||||
|
|
||||||
buffer := alloc.NewSmallBuffer().Clear()
|
buffer := alloc.NewSmallBuffer().Clear()
|
||||||
_, err := ReadRequest(buffer, nil, false)
|
_, err := ReadRequest(buffer, nil, false)
|
||||||
assert.Error(err).Equals(transport.ErrorCorruptedPacket)
|
assert.Error(err).Equals(io.EOF)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSingleBytePayload(t *testing.T) {
|
func TestSingleBytePayload(t *testing.T) {
|
||||||
|
|
|
@ -30,10 +30,12 @@ type Server struct {
|
||||||
udpServer *hub.UDPServer
|
udpServer *hub.UDPServer
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewServer(config *Config, packetDispatcher dispatcher.PacketDispatcher) *Server {
|
func NewServer(config *Config, packetDispatcher dispatcher.PacketDispatcher, listen v2net.Address, port v2net.Port) *Server {
|
||||||
return &Server{
|
return &Server{
|
||||||
config: config,
|
config: config,
|
||||||
packetDispatcher: packetDispatcher,
|
packetDispatcher: packetDispatcher,
|
||||||
|
address: listen,
|
||||||
|
port: port,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,34 +58,28 @@ func (this *Server) Close() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *Server) Listen(address v2net.Address, port v2net.Port) error {
|
func (this *Server) Start() error {
|
||||||
if this.accepting {
|
if this.accepting {
|
||||||
if this.port == port && this.address.Equals(address) {
|
return nil
|
||||||
return nil
|
|
||||||
} else {
|
|
||||||
return proxy.ErrorAlreadyListening
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tcpHub, err := hub.ListenTCP(address, port, this.handleConnection, nil)
|
tcpHub, err := hub.ListenTCP(this.address, this.port, this.handleConnection, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Shadowsocks: Failed to listen TCP on port ", port, ": ", err)
|
log.Error("Shadowsocks: Failed to listen TCP on port ", this.port, ": ", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
this.tcpHub = tcpHub
|
this.tcpHub = tcpHub
|
||||||
|
|
||||||
if this.config.UDP {
|
if this.config.UDP {
|
||||||
this.udpServer = hub.NewUDPServer(this.packetDispatcher)
|
this.udpServer = hub.NewUDPServer(this.packetDispatcher)
|
||||||
udpHub, err := hub.ListenUDP(address, port, this.handlerUDPPayload)
|
udpHub, err := hub.ListenUDP(this.address, this.port, this.handlerUDPPayload)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Shadowsocks: Failed to listen UDP on port ", port, ": ", err)
|
log.Error("Shadowsocks: Failed to listen UDP on port ", this.port, ": ", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
this.udpHub = udpHub
|
this.udpHub = udpHub
|
||||||
}
|
}
|
||||||
|
|
||||||
this.port = port
|
|
||||||
this.address = address
|
|
||||||
this.accepting = true
|
this.accepting = true
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -256,12 +252,14 @@ func (this *Server) handleConnection(conn *hub.Connection) {
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
internal.MustRegisterInboundHandlerCreator("shadowsocks",
|
internal.MustRegisterInboundHandlerCreator("shadowsocks",
|
||||||
func(space app.Space, rawConfig interface{}) (proxy.InboundHandler, error) {
|
func(space app.Space, rawConfig interface{}, listen v2net.Address, port v2net.Port) (proxy.InboundHandler, error) {
|
||||||
if !space.HasApp(dispatcher.APP_ID) {
|
if !space.HasApp(dispatcher.APP_ID) {
|
||||||
return nil, internal.ErrorBadConfiguration
|
return nil, internal.ErrorBadConfiguration
|
||||||
}
|
}
|
||||||
return NewServer(
|
return NewServer(
|
||||||
rawConfig.(*Config),
|
rawConfig.(*Config),
|
||||||
space.GetApp(dispatcher.APP_ID).(dispatcher.PacketDispatcher)), nil
|
space.GetApp(dispatcher.APP_ID).(dispatcher.PacketDispatcher),
|
||||||
|
listen,
|
||||||
|
port), nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,10 +38,12 @@ type Server struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewServer creates a new Server object.
|
// NewServer creates a new Server object.
|
||||||
func NewServer(config *Config, packetDispatcher dispatcher.PacketDispatcher) *Server {
|
func NewServer(config *Config, packetDispatcher dispatcher.PacketDispatcher, listen v2net.Address, port v2net.Port) *Server {
|
||||||
return &Server{
|
return &Server{
|
||||||
config: config,
|
config: config,
|
||||||
packetDispatcher: packetDispatcher,
|
packetDispatcher: packetDispatcher,
|
||||||
|
listeningAddress: listen,
|
||||||
|
listeningPort: port,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,20 +70,18 @@ func (this *Server) Close() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Listen implements InboundHandler.Listen().
|
// Listen implements InboundHandler.Listen().
|
||||||
func (this *Server) Listen(address v2net.Address, port v2net.Port) error {
|
func (this *Server) Start() error {
|
||||||
if this.accepting {
|
if this.accepting {
|
||||||
if this.listeningPort == port && this.listeningAddress.Equals(address) {
|
return nil
|
||||||
return nil
|
|
||||||
} else {
|
|
||||||
return proxy.ErrorAlreadyListening
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
this.listeningPort = port
|
|
||||||
this.listeningAddress = address
|
|
||||||
|
|
||||||
listener, err := hub.ListenTCP(address, port, this.handleConnection, nil)
|
listener, err := hub.ListenTCP(
|
||||||
|
this.listeningAddress,
|
||||||
|
this.listeningPort,
|
||||||
|
this.handleConnection,
|
||||||
|
nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Socks: failed to listen on port ", port, ": ", err)
|
log.Error("Socks: failed to listen on port ", this.listeningPort, ": ", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
this.accepting = true
|
this.accepting = true
|
||||||
|
@ -89,7 +89,7 @@ func (this *Server) Listen(address v2net.Address, port v2net.Port) error {
|
||||||
this.tcpListener = listener
|
this.tcpListener = listener
|
||||||
this.tcpMutex.Unlock()
|
this.tcpMutex.Unlock()
|
||||||
if this.config.UDPEnabled {
|
if this.config.UDPEnabled {
|
||||||
this.listenUDP(address, port)
|
this.listenUDP(this.listeningAddress, this.listeningPort)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -301,12 +301,14 @@ func (this *Server) transport(reader io.Reader, writer io.Writer, destination v2
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
internal.MustRegisterInboundHandlerCreator("socks",
|
internal.MustRegisterInboundHandlerCreator("socks",
|
||||||
func(space app.Space, rawConfig interface{}) (proxy.InboundHandler, error) {
|
func(space app.Space, rawConfig interface{}, listen v2net.Address, port v2net.Port) (proxy.InboundHandler, error) {
|
||||||
if !space.HasApp(dispatcher.APP_ID) {
|
if !space.HasApp(dispatcher.APP_ID) {
|
||||||
return nil, internal.ErrorBadConfiguration
|
return nil, internal.ErrorBadConfiguration
|
||||||
}
|
}
|
||||||
return NewServer(
|
return NewServer(
|
||||||
rawConfig.(*Config),
|
rawConfig.(*Config),
|
||||||
space.GetApp(dispatcher.APP_ID).(dispatcher.PacketDispatcher)), nil
|
space.GetApp(dispatcher.APP_ID).(dispatcher.PacketDispatcher),
|
||||||
|
listen,
|
||||||
|
port), nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,16 +31,17 @@ func TestSocksTcpConnect(t *testing.T) {
|
||||||
ConnInput: bytes.NewReader(connInput),
|
ConnInput: bytes.NewReader(connInput),
|
||||||
}
|
}
|
||||||
|
|
||||||
protocol, err := proxytesting.RegisterOutboundConnectionHandlerCreator("mock_och", func(space app.Space, config interface{}) (v2proxy.OutboundHandler, error) {
|
protocol, err := proxytesting.RegisterOutboundConnectionHandlerCreator("mock_och",
|
||||||
return och, nil
|
func(space app.Space, config interface{}, sendThrough v2net.Address) (v2proxy.OutboundHandler, error) {
|
||||||
})
|
return och, nil
|
||||||
|
})
|
||||||
assert.Error(err).IsNil()
|
assert.Error(err).IsNil()
|
||||||
|
|
||||||
config := &point.Config{
|
config := &point.Config{
|
||||||
Port: port,
|
Port: port,
|
||||||
ListenOn: v2net.LocalHostIP,
|
InboundConfig: &point.InboundConnectionConfig{
|
||||||
InboundConfig: &point.ConnectionConfig{
|
|
||||||
Protocol: "socks",
|
Protocol: "socks",
|
||||||
|
ListenOn: v2net.LocalHostIP,
|
||||||
Settings: []byte(`
|
Settings: []byte(`
|
||||||
{
|
{
|
||||||
"auth": "noauth"
|
"auth": "noauth"
|
||||||
|
@ -51,7 +52,7 @@ func TestSocksTcpConnect(t *testing.T) {
|
||||||
v2net.UDPDestination(v2net.DomainAddress("localhost"), v2net.Port(53)),
|
v2net.UDPDestination(v2net.DomainAddress("localhost"), v2net.Port(53)),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
OutboundConfig: &point.ConnectionConfig{
|
OutboundConfig: &point.OutboundConnectionConfig{
|
||||||
Protocol: protocol,
|
Protocol: protocol,
|
||||||
Settings: nil,
|
Settings: nil,
|
||||||
},
|
},
|
||||||
|
@ -96,16 +97,17 @@ func TestSocksTcpConnectWithUserPass(t *testing.T) {
|
||||||
ConnOutput: connOutput,
|
ConnOutput: connOutput,
|
||||||
}
|
}
|
||||||
|
|
||||||
protocol, err := proxytesting.RegisterOutboundConnectionHandlerCreator("mock_och", func(space app.Space, config interface{}) (v2proxy.OutboundHandler, error) {
|
protocol, err := proxytesting.RegisterOutboundConnectionHandlerCreator("mock_och",
|
||||||
return och, nil
|
func(space app.Space, config interface{}, sendThrough v2net.Address) (v2proxy.OutboundHandler, error) {
|
||||||
})
|
return och, nil
|
||||||
|
})
|
||||||
assert.Error(err).IsNil()
|
assert.Error(err).IsNil()
|
||||||
|
|
||||||
config := &point.Config{
|
config := &point.Config{
|
||||||
Port: port,
|
Port: port,
|
||||||
ListenOn: v2net.LocalHostIP,
|
InboundConfig: &point.InboundConnectionConfig{
|
||||||
InboundConfig: &point.ConnectionConfig{
|
|
||||||
Protocol: "socks",
|
Protocol: "socks",
|
||||||
|
ListenOn: v2net.LocalHostIP,
|
||||||
Settings: []byte(`
|
Settings: []byte(`
|
||||||
{
|
{
|
||||||
"auth": "password",
|
"auth": "password",
|
||||||
|
@ -119,7 +121,7 @@ func TestSocksTcpConnectWithUserPass(t *testing.T) {
|
||||||
v2net.UDPDestination(v2net.DomainAddress("localhost"), v2net.Port(53)),
|
v2net.UDPDestination(v2net.DomainAddress("localhost"), v2net.Port(53)),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
OutboundConfig: &point.ConnectionConfig{
|
OutboundConfig: &point.OutboundConnectionConfig{
|
||||||
Protocol: protocol,
|
Protocol: protocol,
|
||||||
Settings: nil,
|
Settings: nil,
|
||||||
},
|
},
|
||||||
|
@ -164,16 +166,17 @@ func TestSocksTcpConnectWithWrongUserPass(t *testing.T) {
|
||||||
ConnOutput: connOutput,
|
ConnOutput: connOutput,
|
||||||
}
|
}
|
||||||
|
|
||||||
protocol, err := proxytesting.RegisterOutboundConnectionHandlerCreator("mock_och", func(space app.Space, config interface{}) (v2proxy.OutboundHandler, error) {
|
protocol, err := proxytesting.RegisterOutboundConnectionHandlerCreator("mock_och",
|
||||||
return och, nil
|
func(space app.Space, config interface{}, sendThrough v2net.Address) (v2proxy.OutboundHandler, error) {
|
||||||
})
|
return och, nil
|
||||||
|
})
|
||||||
assert.Error(err).IsNil()
|
assert.Error(err).IsNil()
|
||||||
|
|
||||||
config := &point.Config{
|
config := &point.Config{
|
||||||
Port: port,
|
Port: port,
|
||||||
ListenOn: v2net.LocalHostIP,
|
InboundConfig: &point.InboundConnectionConfig{
|
||||||
InboundConfig: &point.ConnectionConfig{
|
|
||||||
Protocol: "socks",
|
Protocol: "socks",
|
||||||
|
ListenOn: v2net.LocalHostIP,
|
||||||
Settings: []byte(`
|
Settings: []byte(`
|
||||||
{
|
{
|
||||||
"auth": "password",
|
"auth": "password",
|
||||||
|
@ -187,7 +190,7 @@ func TestSocksTcpConnectWithWrongUserPass(t *testing.T) {
|
||||||
v2net.UDPDestination(v2net.DomainAddress("localhost"), v2net.Port(53)),
|
v2net.UDPDestination(v2net.DomainAddress("localhost"), v2net.Port(53)),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
OutboundConfig: &point.ConnectionConfig{
|
OutboundConfig: &point.OutboundConnectionConfig{
|
||||||
Protocol: protocol,
|
Protocol: protocol,
|
||||||
Settings: nil,
|
Settings: nil,
|
||||||
},
|
},
|
||||||
|
@ -218,15 +221,16 @@ func TestSocksTcpConnectWithWrongAuthMethod(t *testing.T) {
|
||||||
ConnOutput: connOutput,
|
ConnOutput: connOutput,
|
||||||
}
|
}
|
||||||
|
|
||||||
protocol, err := proxytesting.RegisterOutboundConnectionHandlerCreator("mock_och", func(space app.Space, config interface{}) (v2proxy.OutboundHandler, error) {
|
protocol, err := proxytesting.RegisterOutboundConnectionHandlerCreator("mock_och",
|
||||||
return och, nil
|
func(space app.Space, config interface{}, sendThrough v2net.Address) (v2proxy.OutboundHandler, error) {
|
||||||
})
|
return och, nil
|
||||||
|
})
|
||||||
assert.Error(err).IsNil()
|
assert.Error(err).IsNil()
|
||||||
|
|
||||||
config := &point.Config{
|
config := &point.Config{
|
||||||
Port: port,
|
Port: port,
|
||||||
ListenOn: v2net.LocalHostIP,
|
InboundConfig: &point.InboundConnectionConfig{
|
||||||
InboundConfig: &point.ConnectionConfig{
|
ListenOn: v2net.LocalHostIP,
|
||||||
Protocol: "socks",
|
Protocol: "socks",
|
||||||
Settings: []byte(`
|
Settings: []byte(`
|
||||||
{
|
{
|
||||||
|
@ -241,7 +245,7 @@ func TestSocksTcpConnectWithWrongAuthMethod(t *testing.T) {
|
||||||
v2net.UDPDestination(v2net.DomainAddress("localhost"), v2net.Port(53)),
|
v2net.UDPDestination(v2net.DomainAddress("localhost"), v2net.Port(53)),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
OutboundConfig: &point.ConnectionConfig{
|
OutboundConfig: &point.OutboundConnectionConfig{
|
||||||
Protocol: protocol,
|
Protocol: protocol,
|
||||||
Settings: nil,
|
Settings: nil,
|
||||||
},
|
},
|
||||||
|
|
|
@ -10,21 +10,19 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type InboundConnectionHandler struct {
|
type InboundConnectionHandler struct {
|
||||||
port v2net.Port
|
ListeningPort v2net.Port
|
||||||
address v2net.Address
|
ListeningAddress v2net.Address
|
||||||
PacketDispatcher dispatcher.PacketDispatcher
|
PacketDispatcher dispatcher.PacketDispatcher
|
||||||
ConnInput io.Reader
|
ConnInput io.Reader
|
||||||
ConnOutput io.Writer
|
ConnOutput io.Writer
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *InboundConnectionHandler) Listen(address v2net.Address, port v2net.Port) error {
|
func (this *InboundConnectionHandler) Start() error {
|
||||||
this.port = port
|
|
||||||
this.address = address
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *InboundConnectionHandler) Port() v2net.Port {
|
func (this *InboundConnectionHandler) Port() v2net.Port {
|
||||||
return this.port
|
return this.ListeningPort
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *InboundConnectionHandler) Close() {
|
func (this *InboundConnectionHandler) Close() {
|
||||||
|
|
|
@ -50,6 +50,6 @@ func (this *OutboundConnectionHandler) Dispatch(destination v2net.Destination, p
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *OutboundConnectionHandler) Create(space app.Space, config interface{}) (proxy.OutboundHandler, error) {
|
func (this *OutboundConnectionHandler) Create(space app.Space, config interface{}, sendThrough v2net.Address) (proxy.OutboundHandler, error) {
|
||||||
return this, nil
|
return this, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,6 +88,8 @@ func (this *VMessInboundHandler) Close() {
|
||||||
this.Lock()
|
this.Lock()
|
||||||
this.listener.Close()
|
this.listener.Close()
|
||||||
this.listener = nil
|
this.listener = nil
|
||||||
|
this.clients.Release()
|
||||||
|
this.clients = nil
|
||||||
this.Unlock()
|
this.Unlock()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -100,20 +102,14 @@ func (this *VMessInboundHandler) GetUser(email string) *protocol.User {
|
||||||
return user
|
return user
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *VMessInboundHandler) Listen(address v2net.Address, port v2net.Port) error {
|
func (this *VMessInboundHandler) Start() error {
|
||||||
if this.accepting {
|
if this.accepting {
|
||||||
if this.listeningPort == port && this.listeningAddress.Equals(address) {
|
return nil
|
||||||
return nil
|
|
||||||
} else {
|
|
||||||
return proxy.ErrorAlreadyListening
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
this.listeningPort = port
|
|
||||||
this.listeningAddress = address
|
|
||||||
|
|
||||||
tcpListener, err := hub.ListenTCP(address, port, this.HandleConnection, nil)
|
tcpListener, err := hub.ListenTCP(this.listeningAddress, this.listeningPort, this.HandleConnection, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Unable to listen tcp port ", port, ": ", err)
|
log.Error("Unable to listen tcp port ", this.listeningPort, ": ", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
this.accepting = true
|
this.accepting = true
|
||||||
|
@ -224,7 +220,7 @@ func (this *VMessInboundHandler) HandleConnection(connection *hub.Connection) {
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
internal.MustRegisterInboundHandlerCreator("vmess",
|
internal.MustRegisterInboundHandlerCreator("vmess",
|
||||||
func(space app.Space, rawConfig interface{}) (proxy.InboundHandler, error) {
|
func(space app.Space, rawConfig interface{}, listen v2net.Address, port v2net.Port) (proxy.InboundHandler, error) {
|
||||||
if !space.HasApp(dispatcher.APP_ID) {
|
if !space.HasApp(dispatcher.APP_ID) {
|
||||||
return nil, internal.ErrorBadConfiguration
|
return nil, internal.ErrorBadConfiguration
|
||||||
}
|
}
|
||||||
|
@ -240,6 +236,8 @@ func init() {
|
||||||
clients: allowedClients,
|
clients: allowedClients,
|
||||||
detours: config.DetourConfig,
|
detours: config.DetourConfig,
|
||||||
usersByEmail: NewUserByEmail(config.AllowedUsers, config.Defaults),
|
usersByEmail: NewUserByEmail(config.AllowedUsers, config.Defaults),
|
||||||
|
listeningAddress: listen,
|
||||||
|
listeningPort: port,
|
||||||
}
|
}
|
||||||
|
|
||||||
if space.HasApp(proxyman.APP_ID_INBOUND_MANAGER) {
|
if space.HasApp(proxyman.APP_ID_INBOUND_MANAGER) {
|
||||||
|
|
|
@ -21,6 +21,7 @@ import (
|
||||||
|
|
||||||
type VMessOutboundHandler struct {
|
type VMessOutboundHandler struct {
|
||||||
receiverManager *ReceiverManager
|
receiverManager *ReceiverManager
|
||||||
|
sendThrough v2net.Address
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *VMessOutboundHandler) Dispatch(target v2net.Destination, payload *alloc.Buffer, ray ray.OutboundRay) error {
|
func (this *VMessOutboundHandler) Dispatch(target v2net.Destination, payload *alloc.Buffer, ray ray.OutboundRay) error {
|
||||||
|
@ -42,7 +43,7 @@ func (this *VMessOutboundHandler) Dispatch(target v2net.Destination, payload *al
|
||||||
Option: protocol.RequestOptionChunkStream,
|
Option: protocol.RequestOptionChunkStream,
|
||||||
}
|
}
|
||||||
|
|
||||||
conn, err := hub.Dial(destination)
|
conn, err := hub.Dial(this.sendThrough, destination)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Failed to open ", destination, ": ", err)
|
log.Error("Failed to open ", destination, ": ", err)
|
||||||
return err
|
return err
|
||||||
|
@ -142,10 +143,11 @@ func (this *VMessOutboundHandler) handleResponse(session *raw.ClientSession, con
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
internal.MustRegisterOutboundHandlerCreator("vmess",
|
internal.MustRegisterOutboundHandlerCreator("vmess",
|
||||||
func(space app.Space, rawConfig interface{}) (proxy.OutboundHandler, error) {
|
func(space app.Space, rawConfig interface{}, sendThrough v2net.Address) (proxy.OutboundHandler, error) {
|
||||||
vOutConfig := rawConfig.(*Config)
|
vOutConfig := rawConfig.(*Config)
|
||||||
return &VMessOutboundHandler{
|
return &VMessOutboundHandler{
|
||||||
receiverManager: NewReceiverManager(vOutConfig.Receivers),
|
receiverManager: NewReceiverManager(vOutConfig.Receivers),
|
||||||
|
sendThrough: sendThrough,
|
||||||
}, nil
|
}, nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,25 +38,28 @@ func TestVMessInAndOut(t *testing.T) {
|
||||||
ConnOutput: ichConnOutput,
|
ConnOutput: ichConnOutput,
|
||||||
}
|
}
|
||||||
|
|
||||||
protocol, err := proxytesting.RegisterInboundConnectionHandlerCreator("mock_och", func(space app.Space, config interface{}) (proxy.InboundHandler, error) {
|
protocol, err := proxytesting.RegisterInboundConnectionHandlerCreator("mock_ich",
|
||||||
ich.PacketDispatcher = space.GetApp(dispatcher.APP_ID).(dispatcher.PacketDispatcher)
|
func(space app.Space, config interface{}, listen v2net.Address, port v2net.Port) (proxy.InboundHandler, error) {
|
||||||
return ich, nil
|
ich.ListeningAddress = listen
|
||||||
})
|
ich.ListeningPort = port
|
||||||
|
ich.PacketDispatcher = space.GetApp(dispatcher.APP_ID).(dispatcher.PacketDispatcher)
|
||||||
|
return ich, nil
|
||||||
|
})
|
||||||
assert.Error(err).IsNil()
|
assert.Error(err).IsNil()
|
||||||
|
|
||||||
configA := &point.Config{
|
configA := &point.Config{
|
||||||
Port: portA,
|
Port: portA,
|
||||||
ListenOn: v2net.LocalHostIP,
|
|
||||||
DNSConfig: &dns.Config{
|
DNSConfig: &dns.Config{
|
||||||
NameServers: []v2net.Destination{
|
NameServers: []v2net.Destination{
|
||||||
v2net.UDPDestination(v2net.DomainAddress("localhost"), v2net.Port(53)),
|
v2net.UDPDestination(v2net.DomainAddress("localhost"), v2net.Port(53)),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
InboundConfig: &point.ConnectionConfig{
|
InboundConfig: &point.InboundConnectionConfig{
|
||||||
Protocol: protocol,
|
Protocol: protocol,
|
||||||
|
ListenOn: v2net.LocalHostIP,
|
||||||
Settings: nil,
|
Settings: nil,
|
||||||
},
|
},
|
||||||
OutboundConfig: &point.ConnectionConfig{
|
OutboundConfig: &point.OutboundConnectionConfig{
|
||||||
Protocol: "vmess",
|
Protocol: "vmess",
|
||||||
Settings: []byte(`{
|
Settings: []byte(`{
|
||||||
"vnext": [
|
"vnext": [
|
||||||
|
@ -85,28 +88,29 @@ func TestVMessInAndOut(t *testing.T) {
|
||||||
ConnOutput: ochConnOutput,
|
ConnOutput: ochConnOutput,
|
||||||
}
|
}
|
||||||
|
|
||||||
protocol, err = proxytesting.RegisterOutboundConnectionHandlerCreator("mock_och", func(space app.Space, config interface{}) (proxy.OutboundHandler, error) {
|
protocol, err = proxytesting.RegisterOutboundConnectionHandlerCreator("mock_och",
|
||||||
return och, nil
|
func(space app.Space, config interface{}, sendThrough v2net.Address) (proxy.OutboundHandler, error) {
|
||||||
})
|
return och, nil
|
||||||
|
})
|
||||||
assert.Error(err).IsNil()
|
assert.Error(err).IsNil()
|
||||||
|
|
||||||
configB := &point.Config{
|
configB := &point.Config{
|
||||||
Port: portB,
|
Port: portB,
|
||||||
ListenOn: v2net.LocalHostIP,
|
|
||||||
DNSConfig: &dns.Config{
|
DNSConfig: &dns.Config{
|
||||||
NameServers: []v2net.Destination{
|
NameServers: []v2net.Destination{
|
||||||
v2net.UDPDestination(v2net.DomainAddress("localhost"), v2net.Port(53)),
|
v2net.UDPDestination(v2net.DomainAddress("localhost"), v2net.Port(53)),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
InboundConfig: &point.ConnectionConfig{
|
InboundConfig: &point.InboundConnectionConfig{
|
||||||
Protocol: "vmess",
|
Protocol: "vmess",
|
||||||
|
ListenOn: v2net.LocalHostIP,
|
||||||
Settings: []byte(`{
|
Settings: []byte(`{
|
||||||
"clients": [
|
"clients": [
|
||||||
{"id": "` + testAccount.String() + `"}
|
{"id": "` + testAccount.String() + `"}
|
||||||
]
|
]
|
||||||
}`),
|
}`),
|
||||||
},
|
},
|
||||||
OutboundConfig: &point.ConnectionConfig{
|
OutboundConfig: &point.OutboundConnectionConfig{
|
||||||
Protocol: protocol,
|
Protocol: protocol,
|
||||||
Settings: nil,
|
Settings: nil,
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
{
|
{
|
||||||
"port": 1080,
|
|
||||||
"log": {
|
"log": {
|
||||||
"access": ""
|
"loglevel": "warning"
|
||||||
},
|
},
|
||||||
"inbound": {
|
"inbound": {
|
||||||
|
"port": 1080,
|
||||||
|
"listen": "127.0.0.1",
|
||||||
"protocol": "socks",
|
"protocol": "socks",
|
||||||
"settings": {
|
"settings": {
|
||||||
"auth": "noauth",
|
"auth": "noauth",
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
{
|
{
|
||||||
"port": 10086,
|
|
||||||
"log" : {
|
"log" : {
|
||||||
"access": "/var/log/v2ray/access.log",
|
"access": "/var/log/v2ray/access.log",
|
||||||
"error": "/var/log/v2ray/error.log",
|
"error": "/var/log/v2ray/error.log",
|
||||||
"loglevel": "warning"
|
"loglevel": "warning"
|
||||||
},
|
},
|
||||||
"inbound": {
|
"inbound": {
|
||||||
|
"port": 10086,
|
||||||
"protocol": "vmess",
|
"protocol": "vmess",
|
||||||
"settings": {
|
"settings": {
|
||||||
"clients": [
|
"clients": [
|
||||||
|
|
|
@ -8,11 +8,19 @@ import (
|
||||||
"github.com/v2ray/v2ray-core/transport"
|
"github.com/v2ray/v2ray-core/transport"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ConnectionConfig struct {
|
type InboundConnectionConfig struct {
|
||||||
|
Port v2net.Port
|
||||||
|
ListenOn v2net.Address
|
||||||
Protocol string
|
Protocol string
|
||||||
Settings []byte
|
Settings []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type OutboundConnectionConfig struct {
|
||||||
|
Protocol string
|
||||||
|
SendThrough v2net.Address
|
||||||
|
Settings []byte
|
||||||
|
}
|
||||||
|
|
||||||
type LogConfig struct {
|
type LogConfig struct {
|
||||||
AccessLog string
|
AccessLog string
|
||||||
ErrorLog string
|
ErrorLog string
|
||||||
|
@ -41,19 +49,19 @@ type InboundDetourConfig struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type OutboundDetourConfig struct {
|
type OutboundDetourConfig struct {
|
||||||
Protocol string
|
Protocol string
|
||||||
Tag string
|
SendThrough v2net.Address
|
||||||
Settings []byte
|
Tag string
|
||||||
|
Settings []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Port v2net.Port
|
Port v2net.Port
|
||||||
ListenOn v2net.Address
|
|
||||||
LogConfig *LogConfig
|
LogConfig *LogConfig
|
||||||
RouterConfig *router.Config
|
RouterConfig *router.Config
|
||||||
DNSConfig *dns.Config
|
DNSConfig *dns.Config
|
||||||
InboundConfig *ConnectionConfig
|
InboundConfig *InboundConnectionConfig
|
||||||
OutboundConfig *ConnectionConfig
|
OutboundConfig *OutboundConnectionConfig
|
||||||
InboundDetours []*InboundDetourConfig
|
InboundDetours []*InboundDetourConfig
|
||||||
OutboundDetours []*OutboundDetourConfig
|
OutboundDetours []*OutboundDetourConfig
|
||||||
TransportConfig *transport.Config
|
TransportConfig *transport.Config
|
||||||
|
|
|
@ -22,29 +22,21 @@ const (
|
||||||
|
|
||||||
func (this *Config) UnmarshalJSON(data []byte) error {
|
func (this *Config) UnmarshalJSON(data []byte) error {
|
||||||
type JsonConfig struct {
|
type JsonConfig struct {
|
||||||
Port v2net.Port `json:"port"` // Port of this Point server.
|
Port v2net.Port `json:"port"` // Port of this Point server.
|
||||||
ListenOn *v2net.AddressJson `json:"listen"`
|
LogConfig *LogConfig `json:"log"`
|
||||||
LogConfig *LogConfig `json:"log"`
|
RouterConfig *router.Config `json:"routing"`
|
||||||
RouterConfig *router.Config `json:"routing"`
|
DNSConfig *dns.Config `json:"dns"`
|
||||||
DNSConfig *dns.Config `json:"dns"`
|
InboundConfig *InboundConnectionConfig `json:"inbound"`
|
||||||
InboundConfig *ConnectionConfig `json:"inbound"`
|
OutboundConfig *OutboundConnectionConfig `json:"outbound"`
|
||||||
OutboundConfig *ConnectionConfig `json:"outbound"`
|
InboundDetours []*InboundDetourConfig `json:"inboundDetour"`
|
||||||
InboundDetours []*InboundDetourConfig `json:"inboundDetour"`
|
OutboundDetours []*OutboundDetourConfig `json:"outboundDetour"`
|
||||||
OutboundDetours []*OutboundDetourConfig `json:"outboundDetour"`
|
Transport *transport.Config `json:"transport"`
|
||||||
Transport *transport.Config `json:"transport"`
|
|
||||||
}
|
}
|
||||||
jsonConfig := new(JsonConfig)
|
jsonConfig := new(JsonConfig)
|
||||||
if err := json.Unmarshal(data, jsonConfig); err != nil {
|
if err := json.Unmarshal(data, jsonConfig); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
this.Port = jsonConfig.Port
|
this.Port = jsonConfig.Port
|
||||||
this.ListenOn = v2net.AnyIP
|
|
||||||
if jsonConfig.ListenOn != nil {
|
|
||||||
if jsonConfig.ListenOn.Address.IsDomain() {
|
|
||||||
return errors.New("Point: Unable to listen on domain address: " + jsonConfig.ListenOn.Address.Domain())
|
|
||||||
}
|
|
||||||
this.ListenOn = jsonConfig.ListenOn.Address
|
|
||||||
}
|
|
||||||
this.LogConfig = jsonConfig.LogConfig
|
this.LogConfig = jsonConfig.LogConfig
|
||||||
this.RouterConfig = jsonConfig.RouterConfig
|
this.RouterConfig = jsonConfig.RouterConfig
|
||||||
this.InboundConfig = jsonConfig.InboundConfig
|
this.InboundConfig = jsonConfig.InboundConfig
|
||||||
|
@ -63,10 +55,37 @@ func (this *Config) UnmarshalJSON(data []byte) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *ConnectionConfig) UnmarshalJSON(data []byte) error {
|
func (this *InboundConnectionConfig) UnmarshalJSON(data []byte) error {
|
||||||
|
type JsonConfig struct {
|
||||||
|
Port uint16 `json:"port"`
|
||||||
|
Listen *v2net.AddressJson `json:"listen"`
|
||||||
|
Protocol string `json:"protocol"`
|
||||||
|
Settings json.RawMessage `json:"settings"`
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonConfig := new(JsonConfig)
|
||||||
|
if err := json.Unmarshal(data, jsonConfig); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
this.Port = v2net.Port(jsonConfig.Port)
|
||||||
|
this.ListenOn = v2net.AnyIP
|
||||||
|
if jsonConfig.Listen != nil {
|
||||||
|
if jsonConfig.Listen.Address.IsDomain() {
|
||||||
|
return errors.New("Point: Unable to listen on domain address: " + jsonConfig.Listen.Address.Domain())
|
||||||
|
}
|
||||||
|
this.ListenOn = jsonConfig.Listen.Address
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Protocol = jsonConfig.Protocol
|
||||||
|
this.Settings = jsonConfig.Settings
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *OutboundConnectionConfig) UnmarshalJSON(data []byte) error {
|
||||||
type JsonConnectionConfig struct {
|
type JsonConnectionConfig struct {
|
||||||
Protocol string `json:"protocol"`
|
Protocol string `json:"protocol"`
|
||||||
Settings json.RawMessage `json:"settings"`
|
SendThrough *v2net.AddressJson `json:"sendThrough"`
|
||||||
|
Settings json.RawMessage `json:"settings"`
|
||||||
}
|
}
|
||||||
jsonConfig := new(JsonConnectionConfig)
|
jsonConfig := new(JsonConnectionConfig)
|
||||||
if err := json.Unmarshal(data, jsonConfig); err != nil {
|
if err := json.Unmarshal(data, jsonConfig); err != nil {
|
||||||
|
@ -74,6 +93,14 @@ func (this *ConnectionConfig) UnmarshalJSON(data []byte) error {
|
||||||
}
|
}
|
||||||
this.Protocol = jsonConfig.Protocol
|
this.Protocol = jsonConfig.Protocol
|
||||||
this.Settings = jsonConfig.Settings
|
this.Settings = jsonConfig.Settings
|
||||||
|
|
||||||
|
if jsonConfig.SendThrough != nil {
|
||||||
|
address := jsonConfig.SendThrough.Address
|
||||||
|
if address.IsDomain() {
|
||||||
|
return errors.New("Point: Unable to send through: " + address.String())
|
||||||
|
}
|
||||||
|
this.SendThrough = address
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,9 +200,10 @@ func (this *InboundDetourConfig) UnmarshalJSON(data []byte) error {
|
||||||
|
|
||||||
func (this *OutboundDetourConfig) UnmarshalJSON(data []byte) error {
|
func (this *OutboundDetourConfig) UnmarshalJSON(data []byte) error {
|
||||||
type JsonOutboundDetourConfig struct {
|
type JsonOutboundDetourConfig struct {
|
||||||
Protocol string `json:"protocol"`
|
Protocol string `json:"protocol"`
|
||||||
Tag string `json:"tag"`
|
SendThrough *v2net.AddressJson `json:"sendThrough"`
|
||||||
Settings json.RawMessage `json:"settings"`
|
Tag string `json:"tag"`
|
||||||
|
Settings json.RawMessage `json:"settings"`
|
||||||
}
|
}
|
||||||
jsonConfig := new(JsonOutboundDetourConfig)
|
jsonConfig := new(JsonOutboundDetourConfig)
|
||||||
if err := json.Unmarshal(data, jsonConfig); err != nil {
|
if err := json.Unmarshal(data, jsonConfig); err != nil {
|
||||||
|
@ -184,6 +212,14 @@ func (this *OutboundDetourConfig) UnmarshalJSON(data []byte) error {
|
||||||
this.Protocol = jsonConfig.Protocol
|
this.Protocol = jsonConfig.Protocol
|
||||||
this.Tag = jsonConfig.Tag
|
this.Tag = jsonConfig.Tag
|
||||||
this.Settings = jsonConfig.Settings
|
this.Settings = jsonConfig.Settings
|
||||||
|
|
||||||
|
if jsonConfig.SendThrough != nil {
|
||||||
|
address := jsonConfig.SendThrough.Address
|
||||||
|
if address.IsDomain() {
|
||||||
|
return errors.New("Point: Unable to send through: " + address.String())
|
||||||
|
}
|
||||||
|
this.SendThrough = address
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,8 +23,8 @@ func TestClientSampleConfig(t *testing.T) {
|
||||||
pointConfig, err := LoadConfig(filepath.Join(baseDir, "vpoint_socks_vmess.json"))
|
pointConfig, err := LoadConfig(filepath.Join(baseDir, "vpoint_socks_vmess.json"))
|
||||||
assert.Error(err).IsNil()
|
assert.Error(err).IsNil()
|
||||||
|
|
||||||
assert.Port(pointConfig.Port).IsValid()
|
|
||||||
assert.Pointer(pointConfig.InboundConfig).IsNotNil()
|
assert.Pointer(pointConfig.InboundConfig).IsNotNil()
|
||||||
|
assert.Port(pointConfig.InboundConfig.Port).IsValid()
|
||||||
assert.Pointer(pointConfig.OutboundConfig).IsNotNil()
|
assert.Pointer(pointConfig.OutboundConfig).IsNotNil()
|
||||||
|
|
||||||
assert.String(pointConfig.InboundConfig.Protocol).Equals("socks")
|
assert.String(pointConfig.InboundConfig.Protocol).Equals("socks")
|
||||||
|
@ -43,8 +43,8 @@ func TestServerSampleConfig(t *testing.T) {
|
||||||
pointConfig, err := LoadConfig(filepath.Join(baseDir, "vpoint_vmess_freedom.json"))
|
pointConfig, err := LoadConfig(filepath.Join(baseDir, "vpoint_vmess_freedom.json"))
|
||||||
assert.Error(err).IsNil()
|
assert.Error(err).IsNil()
|
||||||
|
|
||||||
assert.Port(pointConfig.Port).IsValid()
|
|
||||||
assert.Pointer(pointConfig.InboundConfig).IsNotNil()
|
assert.Pointer(pointConfig.InboundConfig).IsNotNil()
|
||||||
|
assert.Port(pointConfig.InboundConfig.Port).IsValid()
|
||||||
assert.Pointer(pointConfig.OutboundConfig).IsNotNil()
|
assert.Pointer(pointConfig.OutboundConfig).IsNotNil()
|
||||||
|
|
||||||
assert.String(pointConfig.InboundConfig.Protocol).Equals("vmess")
|
assert.String(pointConfig.InboundConfig.Protocol).Equals("vmess")
|
||||||
|
|
|
@ -32,7 +32,7 @@ func NewInboundDetourHandlerAlways(space app.Space, config *InboundDetourConfig)
|
||||||
handler.ich = make([]*InboundConnectionHandlerWithPort, 0, ports.To-ports.From+1)
|
handler.ich = make([]*InboundConnectionHandlerWithPort, 0, ports.To-ports.From+1)
|
||||||
for i := ports.From; i <= ports.To; i++ {
|
for i := ports.From; i <= ports.To; i++ {
|
||||||
ichConfig := config.Settings
|
ichConfig := config.Settings
|
||||||
ich, err := proxyrepo.CreateInboundHandler(config.Protocol, space, ichConfig)
|
ich, err := proxyrepo.CreateInboundHandler(config.Protocol, space, ichConfig, config.ListenOn, i)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Failed to create inbound connection handler: ", err)
|
log.Error("Failed to create inbound connection handler: ", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -61,7 +61,7 @@ func (this *InboundDetourHandlerAlways) Close() {
|
||||||
func (this *InboundDetourHandlerAlways) Start() error {
|
func (this *InboundDetourHandlerAlways) Start() error {
|
||||||
for _, ich := range this.ich {
|
for _, ich := range this.ich {
|
||||||
err := retry.Timed(100 /* times */, 100 /* ms */).On(func() error {
|
err := retry.Timed(100 /* times */, 100 /* ms */).On(func() error {
|
||||||
err := ich.handler.Listen(ich.listen, ich.port)
|
err := ich.handler.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Failed to start inbound detour on port ", ich.port, ": ", err)
|
log.Error("Failed to start inbound detour on port ", ich.port, ": ", err)
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -8,7 +8,6 @@ import (
|
||||||
"github.com/v2ray/v2ray-core/common/dice"
|
"github.com/v2ray/v2ray-core/common/dice"
|
||||||
"github.com/v2ray/v2ray-core/common/log"
|
"github.com/v2ray/v2ray-core/common/log"
|
||||||
v2net "github.com/v2ray/v2ray-core/common/net"
|
v2net "github.com/v2ray/v2ray-core/common/net"
|
||||||
"github.com/v2ray/v2ray-core/common/retry"
|
|
||||||
"github.com/v2ray/v2ray-core/proxy"
|
"github.com/v2ray/v2ray-core/proxy"
|
||||||
proxyrepo "github.com/v2ray/v2ray-core/proxy/repo"
|
proxyrepo "github.com/v2ray/v2ray-core/proxy/repo"
|
||||||
)
|
)
|
||||||
|
@ -18,8 +17,7 @@ type InboundDetourHandlerDynamic struct {
|
||||||
space app.Space
|
space app.Space
|
||||||
config *InboundDetourConfig
|
config *InboundDetourConfig
|
||||||
portsInUse map[v2net.Port]bool
|
portsInUse map[v2net.Port]bool
|
||||||
ichInUse []proxy.InboundHandler
|
ichs []proxy.InboundHandler
|
||||||
ich2Recycle []proxy.InboundHandler
|
|
||||||
lastRefresh time.Time
|
lastRefresh time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,18 +27,16 @@ func NewInboundDetourHandlerDynamic(space app.Space, config *InboundDetourConfig
|
||||||
config: config,
|
config: config,
|
||||||
portsInUse: make(map[v2net.Port]bool),
|
portsInUse: make(map[v2net.Port]bool),
|
||||||
}
|
}
|
||||||
ichCount := config.Allocation.Concurrency
|
handler.ichs = make([]proxy.InboundHandler, config.Allocation.Concurrency)
|
||||||
ichArray := make([]proxy.InboundHandler, ichCount*2)
|
|
||||||
for idx := range ichArray {
|
// To test configuration
|
||||||
ich, err := proxyrepo.CreateInboundHandler(config.Protocol, space, config.Settings)
|
ich, err := proxyrepo.CreateInboundHandler(config.Protocol, space, config.Settings, config.ListenOn, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Point: Failed to create inbound connection handler: ", err)
|
log.Error("Point: Failed to create inbound connection handler: ", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
|
||||||
ichArray[idx] = ich
|
|
||||||
}
|
}
|
||||||
handler.ichInUse = ichArray[:ichCount]
|
ich.Close()
|
||||||
handler.ich2Recycle = ichArray[ichCount:]
|
|
||||||
return handler, nil
|
return handler, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,7 +55,7 @@ func (this *InboundDetourHandlerDynamic) pickUnusedPort() v2net.Port {
|
||||||
func (this *InboundDetourHandlerDynamic) GetConnectionHandler() (proxy.InboundHandler, int) {
|
func (this *InboundDetourHandlerDynamic) GetConnectionHandler() (proxy.InboundHandler, int) {
|
||||||
this.RLock()
|
this.RLock()
|
||||||
defer this.RUnlock()
|
defer this.RUnlock()
|
||||||
ich := this.ichInUse[dice.Roll(len(this.ichInUse))]
|
ich := this.ichs[dice.Roll(len(this.ichs))]
|
||||||
until := this.config.Allocation.Refresh - int((time.Now().Unix()-this.lastRefresh.Unix())/60/1000)
|
until := this.config.Allocation.Refresh - int((time.Now().Unix()-this.lastRefresh.Unix())/60/1000)
|
||||||
if until < 0 {
|
if until < 0 {
|
||||||
until = 0
|
until = 0
|
||||||
|
@ -70,58 +66,68 @@ func (this *InboundDetourHandlerDynamic) GetConnectionHandler() (proxy.InboundHa
|
||||||
func (this *InboundDetourHandlerDynamic) Close() {
|
func (this *InboundDetourHandlerDynamic) Close() {
|
||||||
this.Lock()
|
this.Lock()
|
||||||
defer this.Unlock()
|
defer this.Unlock()
|
||||||
for _, ich := range this.ichInUse {
|
for _, ich := range this.ichs {
|
||||||
ich.Close()
|
ich.Close()
|
||||||
}
|
}
|
||||||
if this.ich2Recycle != nil {
|
|
||||||
for _, ich := range this.ich2Recycle {
|
|
||||||
if ich != nil {
|
|
||||||
ich.Close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *InboundDetourHandlerDynamic) refresh() error {
|
func (this *InboundDetourHandlerDynamic) refresh() error {
|
||||||
this.lastRefresh = time.Now()
|
this.lastRefresh = time.Now()
|
||||||
|
|
||||||
for _, ich := range this.ich2Recycle {
|
config := this.config
|
||||||
port2Delete := ich.Port()
|
ich2Recycle := this.ichs
|
||||||
|
newIchs := make([]proxy.InboundHandler, config.Allocation.Concurrency)
|
||||||
|
|
||||||
ich.Close()
|
for idx, _ := range newIchs {
|
||||||
err := retry.Timed(100 /* times */, 1000 /* ms */).On(func() error {
|
port := this.pickUnusedPort()
|
||||||
port := this.pickUnusedPort()
|
ich, err := proxyrepo.CreateInboundHandler(config.Protocol, this.space, config.Settings, config.ListenOn, port)
|
||||||
err := ich.Listen(this.config.ListenOn, port)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("Point: Failed to start inbound detour on port ", port, ": ", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
this.portsInUse[port] = true
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
log.Error("Point: Failed to create inbound connection handler: ", err)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
err = ich.Start()
|
||||||
delete(this.portsInUse, port2Delete)
|
if err != nil {
|
||||||
|
log.Error("Point: Failed to start inbound connection handler: ", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
this.portsInUse[port] = true
|
||||||
|
newIchs[idx] = ich
|
||||||
}
|
}
|
||||||
|
|
||||||
this.Lock()
|
this.Lock()
|
||||||
this.ich2Recycle, this.ichInUse = this.ichInUse, this.ich2Recycle
|
this.ichs = newIchs
|
||||||
this.Unlock()
|
this.Unlock()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
time.Sleep(time.Minute)
|
||||||
|
for _, ich := range ich2Recycle {
|
||||||
|
if ich == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
port := ich.Port()
|
||||||
|
ich.Close()
|
||||||
|
delete(this.portsInUse, port)
|
||||||
|
}
|
||||||
|
ich2Recycle = nil
|
||||||
|
}()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *InboundDetourHandlerDynamic) Start() error {
|
func (this *InboundDetourHandlerDynamic) Start() error {
|
||||||
err := this.refresh()
|
err := this.refresh()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Error("Point: Failed to refresh dynamic allocations: ", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
for range time.Tick(time.Duration(this.config.Allocation.Refresh) * time.Minute) {
|
for {
|
||||||
this.refresh()
|
time.Sleep(time.Duration(this.config.Allocation.Refresh) * time.Minute)
|
||||||
|
err := this.refresh()
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Point: Failed to refresh dynamic allocations: ", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|
|
@ -35,8 +35,12 @@ type Point struct {
|
||||||
// The server is not started at this point.
|
// The server is not started at this point.
|
||||||
func NewPoint(pConfig *Config) (*Point, error) {
|
func NewPoint(pConfig *Config) (*Point, error) {
|
||||||
var vpoint = new(Point)
|
var vpoint = new(Point)
|
||||||
vpoint.port = pConfig.Port
|
vpoint.port = pConfig.InboundConfig.Port
|
||||||
vpoint.listen = pConfig.ListenOn
|
if vpoint.port == 0 {
|
||||||
|
vpoint.port = pConfig.Port // Backward compatibility
|
||||||
|
}
|
||||||
|
|
||||||
|
vpoint.listen = pConfig.InboundConfig.ListenOn
|
||||||
|
|
||||||
if pConfig.TransportConfig != nil {
|
if pConfig.TransportConfig != nil {
|
||||||
pConfig.TransportConfig.Apply()
|
pConfig.TransportConfig.Apply()
|
||||||
|
@ -87,7 +91,7 @@ func NewPoint(pConfig *Config) (*Point, error) {
|
||||||
vpoint.space.BindApp(dispatcher.APP_ID, dispatchers.NewDefaultDispatcher(vpoint.space))
|
vpoint.space.BindApp(dispatcher.APP_ID, dispatchers.NewDefaultDispatcher(vpoint.space))
|
||||||
|
|
||||||
ichConfig := pConfig.InboundConfig.Settings
|
ichConfig := pConfig.InboundConfig.Settings
|
||||||
ich, err := proxyrepo.CreateInboundHandler(pConfig.InboundConfig.Protocol, vpoint.space, ichConfig)
|
ich, err := proxyrepo.CreateInboundHandler(pConfig.InboundConfig.Protocol, vpoint.space, ichConfig, pConfig.InboundConfig.ListenOn, vpoint.port)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Failed to create inbound connection handler: ", err)
|
log.Error("Failed to create inbound connection handler: ", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -95,7 +99,7 @@ func NewPoint(pConfig *Config) (*Point, error) {
|
||||||
vpoint.ich = ich
|
vpoint.ich = ich
|
||||||
|
|
||||||
ochConfig := pConfig.OutboundConfig.Settings
|
ochConfig := pConfig.OutboundConfig.Settings
|
||||||
och, err := proxyrepo.CreateOutboundHandler(pConfig.OutboundConfig.Protocol, vpoint.space, ochConfig)
|
och, err := proxyrepo.CreateOutboundHandler(pConfig.OutboundConfig.Protocol, vpoint.space, ochConfig, pConfig.OutboundConfig.SendThrough)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Failed to create outbound connection handler: ", err)
|
log.Error("Failed to create outbound connection handler: ", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -140,7 +144,7 @@ func NewPoint(pConfig *Config) (*Point, error) {
|
||||||
if len(outboundDetours) > 0 {
|
if len(outboundDetours) > 0 {
|
||||||
vpoint.odh = make(map[string]proxy.OutboundHandler)
|
vpoint.odh = make(map[string]proxy.OutboundHandler)
|
||||||
for _, detourConfig := range outboundDetours {
|
for _, detourConfig := range outboundDetours {
|
||||||
detourHandler, err := proxyrepo.CreateOutboundHandler(detourConfig.Protocol, vpoint.space, detourConfig.Settings)
|
detourHandler, err := proxyrepo.CreateOutboundHandler(detourConfig.Protocol, vpoint.space, detourConfig.Settings, detourConfig.SendThrough)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Point: Failed to create detour outbound connection handler: ", err)
|
log.Error("Point: Failed to create detour outbound connection handler: ", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -173,7 +177,7 @@ func (this *Point) Start() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
err := retry.Timed(100 /* times */, 100 /* ms */).On(func() error {
|
err := retry.Timed(100 /* times */, 100 /* ms */).On(func() error {
|
||||||
err := this.ich.Listen(this.listen, this.port)
|
err := this.ich.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"port": 50000,
|
|
||||||
"listen": "127.0.0.1",
|
|
||||||
"inbound": {
|
"inbound": {
|
||||||
|
"port": 50000,
|
||||||
|
"listen": "127.0.0.1",
|
||||||
"protocol": "socks",
|
"protocol": "socks",
|
||||||
"settings": {
|
"settings": {
|
||||||
"auth": "noauth",
|
"auth": "noauth",
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
{
|
{
|
||||||
"port": 50001,
|
"port": 50001,
|
||||||
"listen": "127.0.0.1",
|
|
||||||
"log": {
|
"log": {
|
||||||
"loglevel": "none"
|
"loglevel": "none"
|
||||||
},
|
},
|
||||||
"inbound": {
|
"inbound": {
|
||||||
|
"listen": "127.0.0.1",
|
||||||
"protocol": "vmess",
|
"protocol": "vmess",
|
||||||
"settings": {
|
"settings": {
|
||||||
"clients": [
|
"clients": [
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"port": 50010,
|
"port": 50010,
|
||||||
"listen": "127.0.0.1",
|
|
||||||
"inbound": {
|
"inbound": {
|
||||||
|
"listen": "127.0.0.1",
|
||||||
"protocol": "socks",
|
"protocol": "socks",
|
||||||
"settings": {
|
"settings": {
|
||||||
"auth": "noauth",
|
"auth": "noauth",
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
{
|
{
|
||||||
"port": 50017,
|
"port": 50017,
|
||||||
"listen": "127.0.0.1",
|
|
||||||
"log": {
|
"log": {
|
||||||
"loglevel": "none"
|
"loglevel": "none"
|
||||||
},
|
},
|
||||||
"inbound": {
|
"inbound": {
|
||||||
|
"listen": "127.0.0.1",
|
||||||
"protocol": "vmess",
|
"protocol": "vmess",
|
||||||
"settings": {
|
"settings": {
|
||||||
"clients": [
|
"clients": [
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
{
|
{
|
||||||
"port": 50020,
|
"port": 50020,
|
||||||
"listen": "127.0.0.1",
|
|
||||||
"log": {
|
"log": {
|
||||||
"loglevel": "none"
|
"loglevel": "none"
|
||||||
},
|
},
|
||||||
"inbound": {
|
"inbound": {
|
||||||
|
"listen": "127.0.0.1",
|
||||||
"protocol": "dokodemo-door",
|
"protocol": "dokodemo-door",
|
||||||
"settings": {
|
"settings": {
|
||||||
"address": "127.0.0.1",
|
"address": "127.0.0.1",
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"port": 50021,
|
"port": 50021,
|
||||||
"listen": "127.0.0.1",
|
|
||||||
"inbound": {
|
"inbound": {
|
||||||
|
"listen": "127.0.0.1",
|
||||||
"protocol": "vmess",
|
"protocol": "vmess",
|
||||||
"settings": {
|
"settings": {
|
||||||
"clients": [
|
"clients": [
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
{
|
{
|
||||||
"port": 50030,
|
"port": 50030,
|
||||||
"listen": "127.0.0.1",
|
|
||||||
"log": {
|
"log": {
|
||||||
"loglevel": "debug"
|
"loglevel": "debug"
|
||||||
},
|
},
|
||||||
"inbound": {
|
"inbound": {
|
||||||
|
"listen": "127.0.0.1",
|
||||||
"protocol": "dokodemo-door",
|
"protocol": "dokodemo-door",
|
||||||
"settings": {
|
"settings": {
|
||||||
"address": "127.0.0.1",
|
"address": "127.0.0.1",
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
{
|
{
|
||||||
"port": 50031,
|
"port": 50031,
|
||||||
"listen": "127.0.0.1",
|
|
||||||
"log": {
|
"log": {
|
||||||
"loglevel": "debug"
|
"loglevel": "debug"
|
||||||
},
|
},
|
||||||
"inbound": {
|
"inbound": {
|
||||||
|
"listen": "127.0.0.1",
|
||||||
"protocol": "vmess",
|
"protocol": "vmess",
|
||||||
"settings": {
|
"settings": {
|
||||||
"clients": [
|
"clients": [
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"port": 50040,
|
"port": 50040,
|
||||||
"listen": "127.0.0.1",
|
|
||||||
"inbound": {
|
"inbound": {
|
||||||
|
"listen": "127.0.0.1",
|
||||||
"protocol": "http",
|
"protocol": "http",
|
||||||
"settings": {}
|
"settings": {}
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"port": 50041,
|
"port": 50041,
|
||||||
"listen": "127.0.0.1",
|
|
||||||
"inbound": {
|
"inbound": {
|
||||||
|
"listen": "127.0.0.1",
|
||||||
"protocol": "vmess",
|
"protocol": "vmess",
|
||||||
"settings": {
|
"settings": {
|
||||||
"clients": [
|
"clients": [
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"port": 50051,
|
"port": 50051,
|
||||||
"listen": "127.0.0.1",
|
|
||||||
"inbound": {
|
"inbound": {
|
||||||
|
"listen": "127.0.0.1",
|
||||||
"protocol": "shadowsocks",
|
"protocol": "shadowsocks",
|
||||||
"settings": {
|
"settings": {
|
||||||
"method": "aes-256-cfb",
|
"method": "aes-256-cfb",
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
package scenarios
|
package scenarios
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
_ "github.com/v2ray/v2ray-core/app/router/rules"
|
_ "github.com/v2ray/v2ray-core/app/router/rules"
|
||||||
"github.com/v2ray/v2ray-core/common/log"
|
"github.com/v2ray/v2ray-core/common/log"
|
||||||
"github.com/v2ray/v2ray-core/shell/point"
|
|
||||||
|
|
||||||
// The following are necessary as they register handlers in their init functions.
|
// The following are necessary as they register handlers in their init functions.
|
||||||
_ "github.com/v2ray/v2ray-core/proxy/blackhole"
|
_ "github.com/v2ray/v2ray-core/proxy/blackhole"
|
||||||
|
@ -20,9 +21,25 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
runningServers = make([]*point.Point, 0, 10)
|
runningServers = make([]*exec.Cmd, 0, 10)
|
||||||
|
|
||||||
|
binaryPath string
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func BuildV2Ray() error {
|
||||||
|
if len(binaryPath) > 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
dir, err := ioutil.TempDir("", "v2ray")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
binaryPath = filepath.Join(dir, "v2ray.exe")
|
||||||
|
cmd := exec.Command("go", "build", "-tags=json", "-o="+binaryPath, filepath.Join("github.com", "v2ray", "v2ray-core", "release", "server"))
|
||||||
|
return cmd.Run()
|
||||||
|
}
|
||||||
|
|
||||||
func TestFile(filename string) string {
|
func TestFile(filename string) string {
|
||||||
return filepath.Join(os.Getenv("GOPATH"), "src", "github.com", "v2ray", "v2ray-core", "testing", "scenarios", "data", filename)
|
return filepath.Join(os.Getenv("GOPATH"), "src", "github.com", "v2ray", "v2ray-core", "testing", "scenarios", "data", filename)
|
||||||
}
|
}
|
||||||
|
@ -46,31 +63,30 @@ func InitializeServerClient(testcase string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func InitializeServer(configFile string) error {
|
func InitializeServer(configFile string) error {
|
||||||
config, err := point.LoadConfig(configFile)
|
err := BuildV2Ray()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Failed to read config file (", configFile, "): ", configFile, err)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
vPoint, err := point.NewPoint(config)
|
proc := exec.Command(binaryPath, "-config="+configFile)
|
||||||
|
proc.Stderr = os.Stderr
|
||||||
|
proc.Stdout = os.Stdout
|
||||||
|
|
||||||
|
err = proc.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Failed to create Point server: ", err)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = vPoint.Start()
|
runningServers = append(runningServers, proc)
|
||||||
if err != nil {
|
|
||||||
log.Error("Error starting Point server: ", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
runningServers = append(runningServers, vPoint)
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func CloseAllServers() {
|
func CloseAllServers() {
|
||||||
|
log.Info("Closing all servers.")
|
||||||
for _, server := range runningServers {
|
for _, server := range runningServers {
|
||||||
server.Close()
|
server.Process.Kill()
|
||||||
}
|
}
|
||||||
runningServers = make([]*point.Point, 0, 10)
|
runningServers = make([]*exec.Cmd, 0, 10)
|
||||||
|
log.Info("All server closed.")
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ func (o *Once) Do(f func()) {
|
||||||
o.m.Lock()
|
o.m.Lock()
|
||||||
defer o.m.Unlock()
|
defer o.m.Unlock()
|
||||||
if o.done == 0 {
|
if o.done == 0 {
|
||||||
defer atomic.StoreUint32(&o.done, 1)
|
atomic.StoreUint32(&o.done, 1)
|
||||||
f()
|
f()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,49 +15,50 @@ var (
|
||||||
globalCache = NewConnectionCache()
|
globalCache = NewConnectionCache()
|
||||||
)
|
)
|
||||||
|
|
||||||
func Dial(dest v2net.Destination) (*Connection, error) {
|
func Dial(src v2net.Address, dest v2net.Destination) (*Connection, error) {
|
||||||
destStr := dest.String()
|
if src == nil {
|
||||||
|
src = v2net.AnyIP
|
||||||
|
}
|
||||||
|
id := src.String() + "-" + dest.NetAddr()
|
||||||
var conn net.Conn
|
var conn net.Conn
|
||||||
if transport.IsConnectionReusable() {
|
if dest.IsTCP() && transport.IsConnectionReusable() {
|
||||||
conn = globalCache.Get(destStr)
|
conn = globalCache.Get(id)
|
||||||
}
|
}
|
||||||
if conn == nil {
|
if conn == nil {
|
||||||
var err error
|
var err error
|
||||||
conn, err = DialWithoutCache(dest)
|
conn, err = DialWithoutCache(src, dest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &Connection{
|
return &Connection{
|
||||||
dest: destStr,
|
dest: id,
|
||||||
conn: conn,
|
conn: conn,
|
||||||
listener: globalCache,
|
listener: globalCache,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func DialWithoutCache(dest v2net.Destination) (net.Conn, error) {
|
func DialWithoutCache(src v2net.Address, dest v2net.Destination) (net.Conn, error) {
|
||||||
if dest.Address().IsDomain() {
|
dialer := &net.Dialer{
|
||||||
dialer := &net.Dialer{
|
Timeout: time.Second * 60,
|
||||||
Timeout: time.Second * 60,
|
DualStack: true,
|
||||||
DualStack: true,
|
|
||||||
}
|
|
||||||
network := "tcp"
|
|
||||||
if dest.IsUDP() {
|
|
||||||
network = "udp"
|
|
||||||
}
|
|
||||||
return dialer.Dial(network, dest.NetAddr())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ip := dest.Address().IP()
|
if src != nil && src != v2net.AnyIP {
|
||||||
if dest.IsTCP() {
|
var addr net.Addr
|
||||||
return net.DialTCP("tcp", nil, &net.TCPAddr{
|
if dest.IsTCP() {
|
||||||
IP: ip,
|
addr = &net.TCPAddr{
|
||||||
Port: int(dest.Port()),
|
IP: src.IP(),
|
||||||
})
|
Port: 0,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
addr = &net.UDPAddr{
|
||||||
|
IP: src.IP(),
|
||||||
|
Port: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dialer.LocalAddr = addr
|
||||||
}
|
}
|
||||||
|
|
||||||
return net.DialUDP("udp", nil, &net.UDPAddr{
|
return dialer.Dial(dest.Network().String(), dest.NetAddr())
|
||||||
IP: ip,
|
|
||||||
Port: int(dest.Port()),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package hub_test
|
package hub_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"net"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
v2net "github.com/v2ray/v2ray-core/common/net"
|
v2net "github.com/v2ray/v2ray-core/common/net"
|
||||||
|
@ -20,7 +21,35 @@ func TestDialDomain(t *testing.T) {
|
||||||
assert.Error(err).IsNil()
|
assert.Error(err).IsNil()
|
||||||
defer server.Close()
|
defer server.Close()
|
||||||
|
|
||||||
conn, err := Dial(v2net.TCPDestination(v2net.DomainAddress("local.v2ray.com"), dest.Port()))
|
conn, err := Dial(nil, v2net.TCPDestination(v2net.DomainAddress("local.v2ray.com"), dest.Port()))
|
||||||
|
assert.Error(err).IsNil()
|
||||||
|
assert.String(conn.RemoteAddr().String()).Equals("127.0.0.1:" + dest.Port().String())
|
||||||
|
conn.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDialWithLocalAddr(t *testing.T) {
|
||||||
|
assert := assert.On(t)
|
||||||
|
|
||||||
|
server := &tcp.Server{
|
||||||
|
Port: v2nettesting.PickPort(),
|
||||||
|
}
|
||||||
|
dest, err := server.Start()
|
||||||
|
assert.Error(err).IsNil()
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
var localAddr net.IP
|
||||||
|
addrs, err := net.InterfaceAddrs()
|
||||||
|
assert.Error(err).IsNil()
|
||||||
|
for _, addr := range addrs {
|
||||||
|
str := addr.String()
|
||||||
|
ip := net.ParseIP(str)
|
||||||
|
if ip != nil && ip.To4() != nil {
|
||||||
|
localAddr = ip.To4()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert.Pointer(localAddr).IsNotNil()
|
||||||
|
|
||||||
|
conn, err := Dial(v2net.IPAddress(localAddr), v2net.TCPDestination(v2net.LocalHostIP, dest.Port()))
|
||||||
assert.Error(err).IsNil()
|
assert.Error(err).IsNil()
|
||||||
assert.String(conn.RemoteAddr().String()).Equals("127.0.0.1:" + dest.Port().String())
|
assert.String(conn.RemoteAddr().String()).Equals("127.0.0.1:" + dest.Port().String())
|
||||||
conn.Close()
|
conn.Close()
|
||||||
|
|
|
@ -130,7 +130,7 @@ func (this *UDPServer) locateExistingAndDispatch(name string, payload *alloc.Buf
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *UDPServer) Dispatch(source v2net.Destination, destination v2net.Destination, payload *alloc.Buffer, callback UDPResponseCallback) {
|
func (this *UDPServer) Dispatch(source v2net.Destination, destination v2net.Destination, payload *alloc.Buffer, callback UDPResponseCallback) {
|
||||||
destString := source.NetAddr() + "-" + destination.NetAddr()
|
destString := source.String() + "-" + destination.String()
|
||||||
log.Debug("UDP Server: Dispatch request: ", destString)
|
log.Debug("UDP Server: Dispatch request: ", destString)
|
||||||
if this.locateExistingAndDispatch(destString, payload) {
|
if this.locateExistingAndDispatch(destString, payload) {
|
||||||
return
|
return
|
||||||
|
|
Loading…
Reference in New Issue