receiver manager

pull/56/head
v2ray 2015-12-05 01:16:21 +01:00
parent 7a01d644e4
commit 06f9b65ec4
4 changed files with 74 additions and 52 deletions

View File

@ -11,22 +11,25 @@ import (
vmessconfig "github.com/v2ray/v2ray-core/proxy/vmess/config" 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 { type ConfigTarget struct {
Address v2net.Address Address v2net.Address
Users []*ConfigUser Users []*ConfigUser
} }
func (t *ConfigTarget) UnmarshalJSON(data []byte) error { 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 var rawConfig RawConfigTarget
if err := json.Unmarshal(data, &rawConfig); err != nil { if err := json.Unmarshal(data, &rawConfig); err != nil {
return err return err
} }
if len(rawConfig.Users) == 0 {
log.Error("0 user configured for VMess outbound.")
return proxyconfig.BadConfiguration
}
t.Users = rawConfig.Users t.Users = rawConfig.Users
ip := net.ParseIP(rawConfig.Address) ip := net.ParseIP(rawConfig.Address)
if ip == nil { if ip == nil {
@ -41,15 +44,27 @@ type Outbound struct {
TargetList []*ConfigTarget `json:"vnext"` TargetList []*ConfigTarget `json:"vnext"`
} }
func (o *Outbound) Targets() []*vmessconfig.OutboundTarget { func (this *Outbound) UnmarshallJSON(data []byte) error {
targets := make([]*vmessconfig.OutboundTarget, 0, 2*len(o.TargetList)) 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 { for _, rawTarget := range o.TargetList {
users := make([]vmessconfig.User, 0, len(rawTarget.Users)) users := make([]vmessconfig.User, 0, len(rawTarget.Users))
for _, rawUser := range rawTarget.Users { for _, rawUser := range rawTarget.Users {
users = append(users, rawUser) users = append(users, rawUser)
} }
targets = append(targets, &vmessconfig.OutboundTarget{ targets = append(targets, &vmessconfig.Receiver{
Destination: v2net.NewTCPDestination(rawTarget.Address), Address: rawTarget.Address,
Accounts: users, Accounts: users,
}) })
} }

View File

@ -4,11 +4,11 @@ import (
v2net "github.com/v2ray/v2ray-core/common/net" v2net "github.com/v2ray/v2ray-core/common/net"
) )
type OutboundTarget struct { type Receiver struct {
Destination v2net.Destination Address v2net.Address
Accounts []User Accounts []User
} }
type Outbound interface { type Outbound interface {
Targets() []*OutboundTarget Receivers() []*Receiver
} }

View File

@ -3,7 +3,6 @@ package outbound
import ( import (
"crypto/md5" "crypto/md5"
"crypto/rand" "crypto/rand"
mrand "math/rand"
"net" "net"
"sync" "sync"
@ -19,41 +18,11 @@ import (
) )
type VMessOutboundHandler struct { type VMessOutboundHandler struct {
vNextList []*config.OutboundTarget receiverManager *ReceiverManager
}
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
} }
func (this *VMessOutboundHandler) Dispatch(firstPacket v2net.Packet, ray ray.OutboundRay) error { func (this *VMessOutboundHandler) Dispatch(firstPacket v2net.Packet, ray ray.OutboundRay) error {
vNextList := this.vNextList vNextAddress, vNextUser := this.receiverManager.PickReceiver()
vNextAddress, vNextUser := pickVNext(vNextList)
command := protocol.CmdTCP command := protocol.CmdTCP
if firstPacket.Destination().IsUDP() { if firstPacket.Destination().IsUDP() {
@ -76,8 +45,8 @@ func (this *VMessOutboundHandler) Dispatch(firstPacket v2net.Packet, ray ray.Out
return startCommunicate(request, vNextAddress, ray, firstPacket) return startCommunicate(request, vNextAddress, ray, firstPacket)
} }
func startCommunicate(request *protocol.VMessRequest, dest v2net.Destination, ray ray.OutboundRay, firstPacket v2net.Packet) error { func startCommunicate(request *protocol.VMessRequest, dest v2net.Address, ray ray.OutboundRay, firstPacket v2net.Packet) error {
conn, err := net.Dial(dest.Network(), dest.Address().String()) conn, err := net.Dial("tcp", dest.String())
if err != nil { if err != nil {
log.Error("Failed to open %s: %v", dest.String(), err) log.Error("Failed to open %s: %v", dest.String(), err)
if ray != nil { if ray != nil {
@ -96,7 +65,7 @@ func startCommunicate(request *protocol.VMessRequest, dest v2net.Destination, ra
responseFinish.Lock() responseFinish.Lock()
go handleRequest(conn, request, firstPacket, input, &requestFinish) 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() requestFinish.Lock()
if tcpConn, ok := conn.(*net.TCPConn); ok { if tcpConn, ok := conn.(*net.TCPConn); ok {
@ -207,7 +176,9 @@ type VMessOutboundHandlerFactory struct {
func (this *VMessOutboundHandlerFactory) Create(rawConfig interface{}) (connhandler.OutboundConnectionHandler, error) { func (this *VMessOutboundHandlerFactory) Create(rawConfig interface{}) (connhandler.OutboundConnectionHandler, error) {
vOutConfig := rawConfig.(config.Outbound) vOutConfig := rawConfig.(config.Outbound)
return NewVMessOutboundHandler(vOutConfig.Targets()), nil return &VMessOutboundHandler{
receiverManager: NewReceiverManager(vOutConfig.Receivers()),
}, nil
} }
func init() { func init() {

View File

@ -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
}