mirror of
https://github.com/v2fly/v2ray-core.git
synced 2026-01-03 15:55:20 -05:00
split listening settings from inbound proxies and apply context
This commit is contained in:
@@ -2,39 +2,58 @@ package outbound
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"v2ray.com/core/app"
|
||||
"v2ray.com/core/app/proxyman"
|
||||
"v2ray.com/core/common/errors"
|
||||
"v2ray.com/core/common/net"
|
||||
"v2ray.com/core/common/buf"
|
||||
"v2ray.com/core/common/log"
|
||||
v2net "v2ray.com/core/common/net"
|
||||
"v2ray.com/core/proxy"
|
||||
"v2ray.com/core/transport/internet"
|
||||
"v2ray.com/core/transport/ray"
|
||||
)
|
||||
|
||||
type Handler struct {
|
||||
config *proxyman.OutboundHandlerConfig
|
||||
streamSettings *proxyman.StreamSenderConfig
|
||||
datagramSettings *proxyman.DatagramSenderConfig
|
||||
proxy proxy.OutboundHandler
|
||||
config *proxyman.OutboundHandlerConfig
|
||||
senderSettings *proxyman.SenderConfig
|
||||
proxy proxy.OutboundHandler
|
||||
outboundManager proxyman.OutboundHandlerManager
|
||||
}
|
||||
|
||||
func NewHandler(ctx context.Context, config *proxyman.OutboundHandlerConfig) (*Handler, error) {
|
||||
h := &Handler{
|
||||
config: config,
|
||||
}
|
||||
for _, rawSettings := range config.SenderSettings {
|
||||
settings, err := rawSettings.GetInstance()
|
||||
space := app.SpaceFromContext(ctx)
|
||||
if space == nil {
|
||||
return nil, errors.New("Proxyman|OutboundHandler: No space in context.")
|
||||
}
|
||||
space.OnInitialize(func() error {
|
||||
ohm := proxyman.OutboundHandlerManagerFromSpace(space)
|
||||
if ohm == nil {
|
||||
return errors.New("Proxyman|OutboundHandler: No OutboundManager in space.")
|
||||
}
|
||||
h.outboundManager = ohm
|
||||
return nil
|
||||
})
|
||||
|
||||
if config.SenderSettings != nil {
|
||||
senderSettings, err := config.SenderSettings.GetInstance()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch ts := settings.(type) {
|
||||
case *proxyman.StreamSenderConfig:
|
||||
h.streamSettings = ts
|
||||
case *proxyman.DatagramSenderConfig:
|
||||
h.datagramSettings = ts
|
||||
switch s := senderSettings.(type) {
|
||||
case *proxyman.SenderConfig:
|
||||
h.senderSettings = s
|
||||
default:
|
||||
return nil, errors.New("Proxyman|DefaultOutboundHandler: Unknown sender settings: ", rawSettings.Type)
|
||||
return nil, errors.New("Proxyman|DefaultOutboundHandler: settings is not SenderConfig.")
|
||||
}
|
||||
}
|
||||
|
||||
proxyHandler, err := config.GetProxyHandler(proxy.ContextWithDialer(ctx, h))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -44,38 +63,114 @@ func NewHandler(ctx context.Context, config *proxyman.OutboundHandlerConfig) (*H
|
||||
return h, nil
|
||||
}
|
||||
|
||||
func (h *Handler) Dial(ctx context.Context, destination net.Destination) (internet.Connection, error) {
|
||||
switch destination.Network {
|
||||
case net.Network_TCP:
|
||||
return h.dialStream(ctx, destination)
|
||||
case net.Network_UDP:
|
||||
return h.dialDatagram(ctx, destination)
|
||||
default:
|
||||
panic("Proxyman|DefaultOutboundHandler: unexpected network.")
|
||||
func (h *Handler) Dispatch(ctx context.Context, outboundRay ray.OutboundRay) {
|
||||
ctx = proxy.ContextWithDialer(ctx, h)
|
||||
h.proxy.Process(ctx, outboundRay)
|
||||
}
|
||||
|
||||
func (h *Handler) Dial(ctx context.Context, dest v2net.Destination) (internet.Connection, error) {
|
||||
if h.senderSettings != nil {
|
||||
if h.senderSettings.ProxySettings.HasTag() {
|
||||
tag := h.senderSettings.ProxySettings.Tag
|
||||
handler := h.outboundManager.GetHandler(tag)
|
||||
if handler != nil {
|
||||
log.Info("Proxyman|OutboundHandler: Proxying to ", dest)
|
||||
ctx = proxy.ContextWithDestination(ctx, dest)
|
||||
stream := ray.NewRay(ctx)
|
||||
go handler.Dispatch(ctx, stream)
|
||||
return NewConnection(stream), nil
|
||||
}
|
||||
|
||||
log.Warning("Proxyman|OutboundHandler: Failed to get outbound handler with tag: ", tag)
|
||||
}
|
||||
|
||||
if h.senderSettings.Via != nil {
|
||||
ctx = internet.ContextWithDialerSource(ctx, h.senderSettings.Via.AsAddress())
|
||||
}
|
||||
if h.senderSettings != nil {
|
||||
ctx = internet.ContextWithStreamSettings(ctx, h.senderSettings.StreamSettings)
|
||||
}
|
||||
}
|
||||
|
||||
return internet.Dial(ctx, dest)
|
||||
}
|
||||
|
||||
type Connection struct {
|
||||
stream ray.Ray
|
||||
closed bool
|
||||
localAddr net.Addr
|
||||
remoteAddr net.Addr
|
||||
|
||||
reader *buf.BufferToBytesReader
|
||||
writer *buf.BytesToBufferWriter
|
||||
}
|
||||
|
||||
func NewConnection(stream ray.Ray) *Connection {
|
||||
return &Connection{
|
||||
stream: stream,
|
||||
localAddr: &net.TCPAddr{
|
||||
IP: []byte{0, 0, 0, 0},
|
||||
Port: 0,
|
||||
},
|
||||
remoteAddr: &net.TCPAddr{
|
||||
IP: []byte{0, 0, 0, 0},
|
||||
Port: 0,
|
||||
},
|
||||
reader: buf.NewBytesReader(stream.InboundOutput()),
|
||||
writer: buf.NewBytesWriter(stream.InboundInput()),
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handler) dialStream(ctx context.Context, destination net.Destination) (internet.Connection, error) {
|
||||
var src net.Address
|
||||
if h.streamSettings != nil {
|
||||
src = h.streamSettings.Via.AsAddress()
|
||||
// Read implements net.Conn.Read().
|
||||
func (v *Connection) Read(b []byte) (int, error) {
|
||||
if v.closed {
|
||||
return 0, io.EOF
|
||||
}
|
||||
var options internet.DialerOptions
|
||||
if h.streamSettings != nil {
|
||||
options.Proxy = h.streamSettings.ProxySettings
|
||||
options.Stream = h.streamSettings.StreamSettings
|
||||
}
|
||||
return internet.Dial(src, destination, options)
|
||||
return v.reader.Read(b)
|
||||
}
|
||||
|
||||
func (h *Handler) dialDatagram(ctx context.Context, destination net.Destination) (internet.Connection, error) {
|
||||
var src net.Address
|
||||
if h.datagramSettings != nil {
|
||||
src = h.datagramSettings.Via.AsAddress()
|
||||
// Write implements net.Conn.Write().
|
||||
func (v *Connection) Write(b []byte) (int, error) {
|
||||
if v.closed {
|
||||
return 0, io.ErrClosedPipe
|
||||
}
|
||||
var options internet.DialerOptions
|
||||
if h.datagramSettings != nil {
|
||||
options.Proxy = h.datagramSettings.ProxySettings
|
||||
}
|
||||
return internet.Dial(src, destination, options)
|
||||
return v.writer.Write(b)
|
||||
}
|
||||
|
||||
// Close implements net.Conn.Close().
|
||||
func (v *Connection) Close() error {
|
||||
v.closed = true
|
||||
v.stream.InboundInput().Close()
|
||||
v.stream.InboundOutput().CloseError()
|
||||
return nil
|
||||
}
|
||||
|
||||
// LocalAddr implements net.Conn.LocalAddr().
|
||||
func (v *Connection) LocalAddr() net.Addr {
|
||||
return v.localAddr
|
||||
}
|
||||
|
||||
// RemoteAddr implements net.Conn.RemoteAddr().
|
||||
func (v *Connection) RemoteAddr() net.Addr {
|
||||
return v.remoteAddr
|
||||
}
|
||||
|
||||
func (v *Connection) SetDeadline(t time.Time) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *Connection) SetReadDeadline(t time.Time) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *Connection) SetWriteDeadline(t time.Time) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *Connection) Reusable() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (v *Connection) SetReusable(bool) {
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user