From 06f9b65ec44c11066cf25c69e7ff5931f5aae9b0 Mon Sep 17 00:00:00 2001 From: v2ray Date: Sat, 5 Dec 2015 01:16:21 +0100 Subject: [PATCH] receiver manager --- proxy/vmess/config/json/outbound.go | 37 +++++++++++++------ proxy/vmess/config/outbound.go | 8 ++--- proxy/vmess/outbound/outbound.go | 45 +++++------------------- proxy/vmess/outbound/receiver_manager.go | 36 +++++++++++++++++++ 4 files changed, 74 insertions(+), 52 deletions(-) create mode 100644 proxy/vmess/outbound/receiver_manager.go diff --git a/proxy/vmess/config/json/outbound.go b/proxy/vmess/config/json/outbound.go index d13eb6fd7..f5aa0f4b5 100644 --- a/proxy/vmess/config/json/outbound.go +++ b/proxy/vmess/config/json/outbound.go @@ -11,22 +11,25 @@ import ( vmessconfig "github.com/v2ray/v2ray-core/proxy/vmess/config" ) -type RawConfigTarget struct { - Address string `json:"address"` - Port v2net.Port `json:"port"` - Users []*ConfigUser `json:"users"` -} - type ConfigTarget struct { Address v2net.Address Users []*ConfigUser } func (t *ConfigTarget) UnmarshalJSON(data []byte) error { + type RawConfigTarget struct { + Address string `json:"address"` + Port v2net.Port `json:"port"` + Users []*ConfigUser `json:"users"` + } var rawConfig RawConfigTarget if err := json.Unmarshal(data, &rawConfig); err != nil { return err } + if len(rawConfig.Users) == 0 { + log.Error("0 user configured for VMess outbound.") + return proxyconfig.BadConfiguration + } t.Users = rawConfig.Users ip := net.ParseIP(rawConfig.Address) if ip == nil { @@ -41,16 +44,28 @@ type Outbound struct { TargetList []*ConfigTarget `json:"vnext"` } -func (o *Outbound) Targets() []*vmessconfig.OutboundTarget { - targets := make([]*vmessconfig.OutboundTarget, 0, 2*len(o.TargetList)) +func (this *Outbound) UnmarshallJSON(data []byte) error { + err := json.Unmarshal(data, this) + if err != nil { + return err + } + if len(this.TargetList) == 0 { + log.Error("0 VMess receiver configured.") + return proxyconfig.BadConfiguration + } + return nil +} + +func (o *Outbound) Receivers() []*vmessconfig.Receiver { + targets := make([]*vmessconfig.Receiver, 0, 2*len(o.TargetList)) for _, rawTarget := range o.TargetList { users := make([]vmessconfig.User, 0, len(rawTarget.Users)) for _, rawUser := range rawTarget.Users { users = append(users, rawUser) } - targets = append(targets, &vmessconfig.OutboundTarget{ - Destination: v2net.NewTCPDestination(rawTarget.Address), - Accounts: users, + targets = append(targets, &vmessconfig.Receiver{ + Address: rawTarget.Address, + Accounts: users, }) } return targets diff --git a/proxy/vmess/config/outbound.go b/proxy/vmess/config/outbound.go index b050ebd37..6085a3ae6 100644 --- a/proxy/vmess/config/outbound.go +++ b/proxy/vmess/config/outbound.go @@ -4,11 +4,11 @@ import ( v2net "github.com/v2ray/v2ray-core/common/net" ) -type OutboundTarget struct { - Destination v2net.Destination - Accounts []User +type Receiver struct { + Address v2net.Address + Accounts []User } type Outbound interface { - Targets() []*OutboundTarget + Receivers() []*Receiver } diff --git a/proxy/vmess/outbound/outbound.go b/proxy/vmess/outbound/outbound.go index 01b82e03e..9f97d2e8a 100644 --- a/proxy/vmess/outbound/outbound.go +++ b/proxy/vmess/outbound/outbound.go @@ -3,7 +3,6 @@ package outbound import ( "crypto/md5" "crypto/rand" - mrand "math/rand" "net" "sync" @@ -19,41 +18,11 @@ import ( ) type VMessOutboundHandler struct { - vNextList []*config.OutboundTarget -} - -func NewVMessOutboundHandler(vNextList []*config.OutboundTarget) *VMessOutboundHandler { - return &VMessOutboundHandler{ - vNextList: vNextList, - } -} - -func pickVNext(serverList []*config.OutboundTarget) (v2net.Destination, config.User) { - vNextLen := len(serverList) - if vNextLen == 0 { - panic("VMessOut: Zero vNext is configured.") - } - vNextIndex := 0 - if vNextLen > 1 { - vNextIndex = mrand.Intn(vNextLen) - } - - vNext := serverList[vNextIndex] - vNextUserLen := len(vNext.Accounts) - if vNextUserLen == 0 { - panic("VMessOut: Zero User account.") - } - vNextUserIndex := 0 - if vNextUserLen > 1 { - vNextUserIndex = mrand.Intn(vNextUserLen) - } - vNextUser := vNext.Accounts[vNextUserIndex] - return vNext.Destination, vNextUser + receiverManager *ReceiverManager } func (this *VMessOutboundHandler) Dispatch(firstPacket v2net.Packet, ray ray.OutboundRay) error { - vNextList := this.vNextList - vNextAddress, vNextUser := pickVNext(vNextList) + vNextAddress, vNextUser := this.receiverManager.PickReceiver() command := protocol.CmdTCP if firstPacket.Destination().IsUDP() { @@ -76,8 +45,8 @@ func (this *VMessOutboundHandler) Dispatch(firstPacket v2net.Packet, ray ray.Out return startCommunicate(request, vNextAddress, ray, firstPacket) } -func startCommunicate(request *protocol.VMessRequest, dest v2net.Destination, ray ray.OutboundRay, firstPacket v2net.Packet) error { - conn, err := net.Dial(dest.Network(), dest.Address().String()) +func startCommunicate(request *protocol.VMessRequest, dest v2net.Address, ray ray.OutboundRay, firstPacket v2net.Packet) error { + conn, err := net.Dial("tcp", dest.String()) if err != nil { log.Error("Failed to open %s: %v", dest.String(), err) if ray != nil { @@ -96,7 +65,7 @@ func startCommunicate(request *protocol.VMessRequest, dest v2net.Destination, ra responseFinish.Lock() go handleRequest(conn, request, firstPacket, input, &requestFinish) - go handleResponse(conn, request, output, &responseFinish, dest.IsUDP()) + go handleResponse(conn, request, output, &responseFinish, (request.Command == protocol.CmdUDP)) requestFinish.Lock() if tcpConn, ok := conn.(*net.TCPConn); ok { @@ -207,7 +176,9 @@ type VMessOutboundHandlerFactory struct { func (this *VMessOutboundHandlerFactory) Create(rawConfig interface{}) (connhandler.OutboundConnectionHandler, error) { vOutConfig := rawConfig.(config.Outbound) - return NewVMessOutboundHandler(vOutConfig.Targets()), nil + return &VMessOutboundHandler{ + receiverManager: NewReceiverManager(vOutConfig.Receivers()), + }, nil } func init() { diff --git a/proxy/vmess/outbound/receiver_manager.go b/proxy/vmess/outbound/receiver_manager.go new file mode 100644 index 000000000..c3eff03f1 --- /dev/null +++ b/proxy/vmess/outbound/receiver_manager.go @@ -0,0 +1,36 @@ +package outbound + +import ( + "math/rand" + + v2net "github.com/v2ray/v2ray-core/common/net" + "github.com/v2ray/v2ray-core/proxy/vmess/config" +) + +type ReceiverManager struct { + receivers []*config.Receiver +} + +func NewReceiverManager(receivers []*config.Receiver) *ReceiverManager { + return &ReceiverManager{ + receivers: receivers, + } +} + +func (this *ReceiverManager) PickReceiver() (v2net.Address, config.User) { + receiverLen := len(this.receivers) + receiverIdx := 0 + if receiverLen > 1 { + receiverIdx = rand.Intn(receiverLen) + } + + receiver := this.receivers[receiverIdx] + + userLen := len(receiver.Accounts) + userIdx := 0 + if userLen > 1 { + userIdx = rand.Intn(userLen) + } + user := receiver.Accounts[userIdx] + return receiver.Address, user +}