mirror of https://github.com/v2ray/v2ray-core
apply mux in client
parent
2111c7e9ca
commit
5686566139
|
@ -57,6 +57,52 @@ func (s *session) closeDownlink() {
|
||||||
s.checkAndRemove()
|
s.checkAndRemove()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ClientManager struct {
|
||||||
|
access sync.Mutex
|
||||||
|
clients []*Client
|
||||||
|
proxy proxy.Outbound
|
||||||
|
dialer proxy.Dialer
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewClientManager(p proxy.Outbound, d proxy.Dialer) *ClientManager {
|
||||||
|
return &ClientManager{
|
||||||
|
proxy: p,
|
||||||
|
dialer: d,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ClientManager) Dispatch(ctx context.Context, outboundRay ray.OutboundRay) error {
|
||||||
|
m.access.Lock()
|
||||||
|
defer m.access.Unlock()
|
||||||
|
|
||||||
|
for _, client := range m.clients {
|
||||||
|
if client.Dispatch(ctx, outboundRay) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := NewClient(m.proxy, m.dialer, m)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
m.clients = append(m.clients, client)
|
||||||
|
client.Dispatch(ctx, outboundRay)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ClientManager) onClientFinish() {
|
||||||
|
m.access.Lock()
|
||||||
|
defer m.access.Unlock()
|
||||||
|
|
||||||
|
nActive := 0
|
||||||
|
for idx, client := range m.clients {
|
||||||
|
if nActive != idx && !client.Closed() {
|
||||||
|
m.clients[nActive] = client
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m.clients = m.clients[:nActive]
|
||||||
|
}
|
||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
access sync.RWMutex
|
access sync.RWMutex
|
||||||
count uint16
|
count uint16
|
||||||
|
@ -64,11 +110,12 @@ type Client struct {
|
||||||
inboundRay ray.InboundRay
|
inboundRay ray.InboundRay
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
cancel context.CancelFunc
|
cancel context.CancelFunc
|
||||||
|
manager *ClientManager
|
||||||
}
|
}
|
||||||
|
|
||||||
var muxCoolDestination = net.TCPDestination(net.DomainAddress("v1.mux.cool"), net.Port(9527))
|
var muxCoolDestination = net.TCPDestination(net.DomainAddress("v1.mux.cool"), net.Port(9527))
|
||||||
|
|
||||||
func NewClient(p proxy.Outbound, dialer proxy.Dialer) (*Client, error) {
|
func NewClient(p proxy.Outbound, dialer proxy.Dialer, m *ClientManager) (*Client, error) {
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
ctx = proxy.ContextWithTarget(ctx, muxCoolDestination)
|
ctx = proxy.ContextWithTarget(ctx, muxCoolDestination)
|
||||||
pipe := ray.NewRay(ctx)
|
pipe := ray.NewRay(ctx)
|
||||||
|
@ -82,6 +129,7 @@ func NewClient(p proxy.Outbound, dialer proxy.Dialer) (*Client, error) {
|
||||||
inboundRay: pipe,
|
inboundRay: pipe,
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
cancel: cancel,
|
cancel: cancel,
|
||||||
|
manager: m,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,6 +149,7 @@ func (m *Client) remove(id uint16) {
|
||||||
if len(m.sessions) == 0 {
|
if len(m.sessions) == 0 {
|
||||||
m.cancel()
|
m.cancel()
|
||||||
m.inboundRay.InboundInput().Close()
|
m.inboundRay.InboundInput().Close()
|
||||||
|
go m.manager.onClientFinish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,7 +170,10 @@ func (m *Client) fetchInput(ctx context.Context, s *session) {
|
||||||
writer: m.inboundRay.InboundInput(),
|
writer: m.inboundRay.InboundInput(),
|
||||||
}
|
}
|
||||||
_, timer := signal.CancelAfterInactivity(ctx, time.Minute*5)
|
_, timer := signal.CancelAfterInactivity(ctx, time.Minute*5)
|
||||||
buf.PipeUntilEOF(timer, s.input, writer)
|
if err := buf.PipeUntilEOF(timer, s.input, writer); err != nil {
|
||||||
|
log.Info("Proxyman|Mux|Client: Failed to fetch all input: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
writer.Close()
|
writer.Close()
|
||||||
s.closeUplink()
|
s.closeUplink()
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"v2ray.com/core/app"
|
"v2ray.com/core/app"
|
||||||
"v2ray.com/core/app/log"
|
"v2ray.com/core/app/log"
|
||||||
"v2ray.com/core/app/proxyman"
|
"v2ray.com/core/app/proxyman"
|
||||||
|
"v2ray.com/core/app/proxyman/mux"
|
||||||
"v2ray.com/core/common/buf"
|
"v2ray.com/core/common/buf"
|
||||||
"v2ray.com/core/common/errors"
|
"v2ray.com/core/common/errors"
|
||||||
v2net "v2ray.com/core/common/net"
|
v2net "v2ray.com/core/common/net"
|
||||||
|
@ -22,6 +23,7 @@ type Handler struct {
|
||||||
senderSettings *proxyman.SenderConfig
|
senderSettings *proxyman.SenderConfig
|
||||||
proxy proxy.Outbound
|
proxy proxy.Outbound
|
||||||
outboundManager proxyman.OutboundHandlerManager
|
outboundManager proxyman.OutboundHandlerManager
|
||||||
|
mux *mux.ClientManager
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHandler(ctx context.Context, config *proxyman.OutboundHandlerConfig) (*Handler, error) {
|
func NewHandler(ctx context.Context, config *proxyman.OutboundHandlerConfig) (*Handler, error) {
|
||||||
|
@ -54,6 +56,10 @@ func NewHandler(ctx context.Context, config *proxyman.OutboundHandlerConfig) (*H
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if h.senderSettings != nil && h.senderSettings.MultiplexSettings != nil && h.senderSettings.MultiplexSettings.Enabled {
|
||||||
|
h.mux = mux.NewClientManager(h.proxy, h)
|
||||||
|
}
|
||||||
|
|
||||||
proxyHandler, err := config.GetProxyHandler(ctx)
|
proxyHandler, err := config.GetProxyHandler(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -64,20 +70,32 @@ func NewHandler(ctx context.Context, config *proxyman.OutboundHandlerConfig) (*H
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handler) Dispatch(ctx context.Context, outboundRay ray.OutboundRay) {
|
func (h *Handler) Dispatch(ctx context.Context, outboundRay ray.OutboundRay) {
|
||||||
err := h.proxy.Process(ctx, outboundRay, h)
|
if h.mux != nil {
|
||||||
// Ensure outbound ray is properly closed.
|
err := h.mux.Dispatch(ctx, outboundRay)
|
||||||
if err != nil && errors.Cause(err) != io.EOF {
|
if err != nil {
|
||||||
err = errors.Base(err).Message("Proxyman|OutboundHandler: Failed to process outbound traffic.")
|
err = errors.Base(err).Message("Proxyman|OutboundHandler: Failed to process outbound traffic.")
|
||||||
if errors.IsActionRequired(err) {
|
if errors.IsActionRequired(err) {
|
||||||
log.Warning(err)
|
log.Warning(err)
|
||||||
} else {
|
} else {
|
||||||
log.Info(err)
|
log.Info(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
outboundRay.OutboundOutput().CloseError()
|
|
||||||
} else {
|
} else {
|
||||||
outboundRay.OutboundOutput().Close()
|
err := h.proxy.Process(ctx, outboundRay, h)
|
||||||
|
// Ensure outbound ray is properly closed.
|
||||||
|
if err != nil && errors.Cause(err) != io.EOF {
|
||||||
|
err = errors.Base(err).Message("Proxyman|OutboundHandler: Failed to process outbound traffic.")
|
||||||
|
if errors.IsActionRequired(err) {
|
||||||
|
log.Warning(err)
|
||||||
|
} else {
|
||||||
|
log.Info(err)
|
||||||
|
}
|
||||||
|
outboundRay.OutboundOutput().CloseError()
|
||||||
|
} else {
|
||||||
|
outboundRay.OutboundOutput().Close()
|
||||||
|
}
|
||||||
|
outboundRay.OutboundInput().CloseError()
|
||||||
}
|
}
|
||||||
outboundRay.OutboundInput().CloseError()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dial implements proxy.Dialer.Dial().
|
// Dial implements proxy.Dialer.Dial().
|
||||||
|
|
|
@ -80,6 +80,10 @@ func (v *InboundConnectionConfig) Build() (*proxyman.InboundHandlerConfig, error
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type MuxConfig struct {
|
||||||
|
Enabled bool `json:"enabled"`
|
||||||
|
}
|
||||||
|
|
||||||
type OutboundConnectionConfig struct {
|
type OutboundConnectionConfig struct {
|
||||||
Protocol string `json:"protocol"`
|
Protocol string `json:"protocol"`
|
||||||
SendThrough *Address `json:"sendThrough"`
|
SendThrough *Address `json:"sendThrough"`
|
||||||
|
@ -87,6 +91,7 @@ type OutboundConnectionConfig struct {
|
||||||
ProxySettings *ProxyConfig `json:"proxySettings"`
|
ProxySettings *ProxyConfig `json:"proxySettings"`
|
||||||
Settings json.RawMessage `json:"settings"`
|
Settings json.RawMessage `json:"settings"`
|
||||||
Tag string `json:"tag"`
|
Tag string `json:"tag"`
|
||||||
|
MuxSettings *MuxConfig `json:"mux"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *OutboundConnectionConfig) Build() (*proxyman.OutboundHandlerConfig, error) {
|
func (v *OutboundConnectionConfig) Build() (*proxyman.OutboundHandlerConfig, error) {
|
||||||
|
@ -114,6 +119,12 @@ func (v *OutboundConnectionConfig) Build() (*proxyman.OutboundHandlerConfig, err
|
||||||
senderSettings.ProxySettings = ps
|
senderSettings.ProxySettings = ps
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if v.MuxSettings != nil && v.MuxSettings.Enabled {
|
||||||
|
senderSettings.MultiplexSettings = &proxyman.MultiplexingConfig{
|
||||||
|
Enabled: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
rawConfig, err := outboundConfigLoader.LoadWithID(v.Settings, v.Protocol)
|
rawConfig, err := outboundConfigLoader.LoadWithID(v.Settings, v.Protocol)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Base(err).Message("Config: Failed to parse outbound config.")
|
return nil, errors.Base(err).Message("Config: Failed to parse outbound config.")
|
||||||
|
@ -228,6 +239,7 @@ type OutboundDetourConfig struct {
|
||||||
Settings json.RawMessage `json:"settings"`
|
Settings json.RawMessage `json:"settings"`
|
||||||
StreamSetting *StreamConfig `json:"streamSettings"`
|
StreamSetting *StreamConfig `json:"streamSettings"`
|
||||||
ProxySettings *ProxyConfig `json:"proxySettings"`
|
ProxySettings *ProxyConfig `json:"proxySettings"`
|
||||||
|
MuxSettings *MuxConfig `json:"mux"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *OutboundDetourConfig) Build() (*proxyman.OutboundHandlerConfig, error) {
|
func (v *OutboundDetourConfig) Build() (*proxyman.OutboundHandlerConfig, error) {
|
||||||
|
@ -257,6 +269,12 @@ func (v *OutboundDetourConfig) Build() (*proxyman.OutboundHandlerConfig, error)
|
||||||
senderSettings.ProxySettings = ps
|
senderSettings.ProxySettings = ps
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if v.MuxSettings != nil && v.MuxSettings.Enabled {
|
||||||
|
senderSettings.MultiplexSettings = &proxyman.MultiplexingConfig{
|
||||||
|
Enabled: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
rawConfig, err := outboundConfigLoader.LoadWithID(v.Settings, v.Protocol)
|
rawConfig, err := outboundConfigLoader.LoadWithID(v.Settings, v.Protocol)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Base(err).Message("Config: Failed to parse to outbound detour config.")
|
return nil, errors.Base(err).Message("Config: Failed to parse to outbound detour config.")
|
||||||
|
|
Loading…
Reference in New Issue