|
|
@@ -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() {
|