mirror of https://github.com/v2ray/v2ray-core
receiver manager
parent
7a01d644e4
commit
06f9b65ec4
|
@ -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,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
Loading…
Reference in New Issue