浏览代码

move session based info into session package

Darien Raymond 7 年之前
父节点
当前提交
94b880d060

+ 5 - 3
app/dispatcher/default.go

@@ -16,7 +16,6 @@ import (
 	"v2ray.com/core/common/protocol"
 	"v2ray.com/core/common/session"
 	"v2ray.com/core/common/stats"
-	"v2ray.com/core/proxy"
 	"v2ray.com/core/transport/pipe"
 )
 
@@ -165,7 +164,10 @@ func (d *DefaultDispatcher) Dispatch(ctx context.Context, destination net.Destin
 	if !destination.IsValid() {
 		panic("Dispatcher: Invalid destination.")
 	}
-	ctx = proxy.ContextWithTarget(ctx, destination)
+	ob := &session.Outbound{
+		Target: destination,
+	}
+	ctx = session.ContextWithOutbound(ctx, ob)
 
 	inbound, outbound := d.getLink(ctx)
 	sniffingConfig := proxyman.SniffingConfigFromContext(ctx)
@@ -185,7 +187,7 @@ func (d *DefaultDispatcher) Dispatch(ctx context.Context, destination net.Destin
 				domain := result.Domain()
 				newError("sniffed domain: ", domain).WriteToLog(session.ExportIDToError(ctx))
 				destination.Address = net.ParseAddress(domain)
-				ctx = proxy.ContextWithTarget(ctx, destination)
+				ob.Target = destination
 			}
 			d.routedDispatch(ctx, outbound, destination)
 		}()

+ 17 - 13
app/proxyman/inbound/worker.go

@@ -55,14 +55,16 @@ func (w *tcpWorker) callback(conn internet.Connection) {
 			newError("failed to get original destination").Base(err).WriteToLog(session.ExportIDToError(ctx))
 		}
 		if dest.IsValid() {
-			ctx = proxy.ContextWithOriginalTarget(ctx, dest)
+			ctx = session.ContextWithOutbound(ctx, &session.Outbound{
+				Target: dest,
+			})
 		}
 	}
-	if len(w.tag) > 0 {
-		ctx = proxy.ContextWithInboundTag(ctx, w.tag)
-	}
-	ctx = proxy.ContextWithInboundEntryPoint(ctx, net.TCPDestination(w.address, w.port))
-	ctx = proxy.ContextWithSource(ctx, net.DestinationFromAddr(conn.RemoteAddr()))
+	ctx = session.ContextWithInbound(ctx, &session.Inbound{
+		Source:  net.DestinationFromAddr(conn.RemoteAddr()),
+		Gateway: net.TCPDestination(w.address, w.port),
+		Tag:     w.tag,
+	})
 	if w.sniffingConfig != nil {
 		ctx = proxyman.ContextWithSniffingConfig(ctx, w.sniffingConfig)
 	}
@@ -268,15 +270,17 @@ func (w *udpWorker) callback(b *buf.Buffer, source net.Destination, originalDest
 			ctx = session.ContextWithID(ctx, sid)
 
 			if originalDest.IsValid() {
-				ctx = proxy.ContextWithOriginalTarget(ctx, originalDest)
-			}
-			if len(w.tag) > 0 {
-				ctx = proxy.ContextWithInboundTag(ctx, w.tag)
+				ctx = session.ContextWithOutbound(ctx, &session.Outbound{
+					Target: originalDest,
+				})
 			}
-			ctx = proxy.ContextWithSource(ctx, source)
-			ctx = proxy.ContextWithInboundEntryPoint(ctx, net.UDPDestination(w.address, w.port))
+			ctx = session.ContextWithInbound(ctx, &session.Inbound{
+				Source:  source,
+				Gateway: net.UDPDestination(w.address, w.port),
+				Tag:     w.tag,
+			})
 			if err := w.proxy.Process(ctx, net.Network_UDP, conn, w.dispatcher); err != nil {
-				newError("connection ends").Base(err).WriteToLog()
+				newError("connection ends").Base(err).WriteToLog(session.ExportIDToError(ctx))
 			}
 			conn.Close() // nolint: errcheck
 			w.removeConn(id)

+ 6 - 4
app/proxyman/mux/mux.go

@@ -88,7 +88,9 @@ var muxCoolPort = net.Port(9527)
 
 // NewClient creates a new mux.Client.
 func NewClient(pctx context.Context, p proxy.Outbound, dialer proxy.Dialer, m *ClientManager) (*Client, error) {
-	ctx := proxy.ContextWithTarget(context.Background(), net.TCPDestination(muxCoolAddress, muxCoolPort))
+	ctx := session.ContextWithOutbound(context.Background(), &session.Outbound{
+		Target: net.TCPDestination(muxCoolAddress, muxCoolPort),
+	})
 	ctx, cancel := context.WithCancel(ctx)
 
 	opts := pipe.OptionsFromContext(pctx)
@@ -160,7 +162,7 @@ func writeFirstPayload(reader buf.Reader, writer *Writer) error {
 }
 
 func fetchInput(ctx context.Context, s *Session, output buf.Writer) {
-	dest, _ := proxy.TargetFromContext(ctx)
+	dest := session.OutboundFromContext(ctx).Target
 	transferType := protocol.TransferTypeStream
 	if dest.Network == net.Network_UDP {
 		transferType = protocol.TransferTypePacket
@@ -367,8 +369,8 @@ func (w *ServerWorker) handleStatusNew(ctx context.Context, meta *FrameMetadata,
 			Status: log.AccessAccepted,
 			Reason: "",
 		}
-		if src, f := proxy.SourceFromContext(ctx); f {
-			msg.From = src
+		if inbound := session.InboundFromContext(ctx); inbound != nil && inbound.Source.IsValid() {
+			msg.From = inbound.Source
 		}
 		log.Record(msg)
 	}

+ 9 - 2
app/proxyman/outbound/handler.go

@@ -107,7 +107,9 @@ func (h *Handler) Dial(ctx context.Context, dest net.Destination) (internet.Conn
 			handler := h.outboundManager.GetHandler(tag)
 			if handler != nil {
 				newError("proxying to ", tag, " for dest ", dest).AtDebug().WriteToLog(session.ExportIDToError(ctx))
-				ctx = proxy.ContextWithTarget(ctx, dest)
+				ctx = session.ContextWithOutbound(ctx, &session.Outbound{
+					Target: dest,
+				})
 
 				opts := pipe.OptionsFromContext(ctx)
 				uplinkReader, uplinkWriter := pipe.New(opts...)
@@ -121,7 +123,12 @@ func (h *Handler) Dial(ctx context.Context, dest net.Destination) (internet.Conn
 		}
 
 		if h.senderSettings.Via != nil {
-			ctx = internet.ContextWithDialerSource(ctx, h.senderSettings.Via.AsAddress())
+			outbound := session.OutboundFromContext(ctx)
+			if outbound == nil {
+				outbound = new(session.Outbound)
+				ctx = session.ContextWithOutbound(ctx, outbound)
+			}
+			outbound.Gateway = h.senderSettings.Via.AsAddress()
 		}
 
 		ctx = internet.ContextWithStreamSettings(ctx, h.streamSettings)

+ 36 - 20
app/router/condition.go

@@ -4,6 +4,8 @@ import (
 	"context"
 	"strings"
 
+	"v2ray.com/core/common/session"
+
 	"v2ray.com/core/app/dispatcher"
 	"v2ray.com/core/common/net"
 	"v2ray.com/core/common/protocol"
@@ -110,11 +112,11 @@ func (m *DomainMatcher) ApplyDomain(domain string) bool {
 }
 
 func (m *DomainMatcher) Apply(ctx context.Context) bool {
-	dest, ok := proxy.TargetFromContext(ctx)
-	if !ok {
+	outbound := session.OutboundFromContext(ctx)
+	if outbound == nil || !outbound.Target.IsValid() {
 		return false
 	}
-
+	dest := outbound.Target
 	if !dest.Address.Family().IsDomain() {
 		return false
 	}
@@ -137,6 +139,22 @@ func NewCIDRMatcher(ip []byte, mask uint32, onSource bool) (*CIDRMatcher, error)
 	}, nil
 }
 
+func sourceFromContext(ctx context.Context) net.Destination {
+	inbound := session.InboundFromContext(ctx)
+	if inbound == nil {
+		return net.Destination{}
+	}
+	return inbound.Source
+}
+
+func targetFromContent(ctx context.Context) net.Destination {
+	outbound := session.OutboundFromContext(ctx)
+	if outbound == nil {
+		return net.Destination{}
+	}
+	return outbound.Target
+}
+
 func (v *CIDRMatcher) Apply(ctx context.Context) bool {
 	ips := make([]net.IP, 0, 4)
 	if resolver, ok := proxy.ResolvedIPsFromContext(ctx); ok {
@@ -150,14 +168,13 @@ func (v *CIDRMatcher) Apply(ctx context.Context) bool {
 	}
 
 	var dest net.Destination
-	var ok bool
 	if v.onSource {
-		dest, ok = proxy.SourceFromContext(ctx)
+		dest = sourceFromContext(ctx)
 	} else {
-		dest, ok = proxy.TargetFromContext(ctx)
+		dest = targetFromContent(ctx)
 	}
 
-	if ok && dest.Address.Family().IsIPv6() {
+	if dest.IsValid() && dest.Address.Family().IsIPv6() {
 		ips = append(ips, dest.Address.IP())
 	}
 
@@ -194,14 +211,13 @@ func (v *IPv4Matcher) Apply(ctx context.Context) bool {
 	}
 
 	var dest net.Destination
-	var ok bool
 	if v.onSource {
-		dest, ok = proxy.SourceFromContext(ctx)
+		dest = sourceFromContext(ctx)
 	} else {
-		dest, ok = proxy.TargetFromContext(ctx)
+		dest = targetFromContent(ctx)
 	}
 
-	if ok && dest.Address.Family().IsIPv4() {
+	if dest.IsValid() && dest.Address.Family().IsIPv4() {
 		ips = append(ips, dest.Address.IP())
 	}
 
@@ -224,11 +240,11 @@ func NewPortMatcher(portRange net.PortRange) *PortMatcher {
 }
 
 func (v *PortMatcher) Apply(ctx context.Context) bool {
-	dest, ok := proxy.TargetFromContext(ctx)
-	if !ok {
+	outbound := session.OutboundFromContext(ctx)
+	if outbound == nil || !outbound.Target.IsValid() {
 		return false
 	}
-	return v.port.Contains(dest.Port)
+	return v.port.Contains(outbound.Target.Port)
 }
 
 type NetworkMatcher struct {
@@ -242,11 +258,11 @@ func NewNetworkMatcher(network *net.NetworkList) *NetworkMatcher {
 }
 
 func (v *NetworkMatcher) Apply(ctx context.Context) bool {
-	dest, ok := proxy.TargetFromContext(ctx)
-	if !ok {
+	outbound := session.OutboundFromContext(ctx)
+	if outbound == nil || !outbound.Target.IsValid() {
 		return false
 	}
-	return v.network.HasNetwork(dest.Network)
+	return v.network.HasNetwork(outbound.Target.Network)
 }
 
 type UserMatcher struct {
@@ -295,11 +311,11 @@ func NewInboundTagMatcher(tags []string) *InboundTagMatcher {
 }
 
 func (v *InboundTagMatcher) Apply(ctx context.Context) bool {
-	tag, ok := proxy.InboundTagFromContext(ctx)
-	if !ok {
+	inbound := session.InboundFromContext(ctx)
+	if inbound == nil || len(inbound.Tag) == 0 {
 		return false
 	}
-
+	tag := inbound.Tag
 	for _, t := range v.tags {
 		if t == tag {
 			return true

+ 15 - 10
app/router/condition_test.go

@@ -8,6 +8,8 @@ import (
 	"testing"
 	"time"
 
+	"v2ray.com/core/common/session"
+
 	proto "github.com/golang/protobuf/proto"
 	"v2ray.com/core/app/dispatcher"
 	. "v2ray.com/core/app/router"
@@ -17,11 +19,14 @@ import (
 	"v2ray.com/core/common/platform"
 	"v2ray.com/core/common/protocol"
 	"v2ray.com/core/common/protocol/http"
-	"v2ray.com/core/proxy"
 	. "v2ray.com/ext/assert"
 	"v2ray.com/ext/sysio"
 )
 
+func withOutbound(outbound *session.Outbound) context.Context {
+	return session.ContextWithOutbound(context.Background(), outbound)
+}
+
 func TestRoutingRule(t *testing.T) {
 	assert := With(t)
 
@@ -53,27 +58,27 @@ func TestRoutingRule(t *testing.T) {
 			},
 			test: []ruleTest{
 				{
-					input:  proxy.ContextWithTarget(context.Background(), net.TCPDestination(net.DomainAddress("v2ray.com"), 80)),
+					input:  withOutbound(&session.Outbound{Target: net.TCPDestination(net.DomainAddress("v2ray.com"), 80)}),
 					output: true,
 				},
 				{
-					input:  proxy.ContextWithTarget(context.Background(), net.TCPDestination(net.DomainAddress("www.v2ray.com.www"), 80)),
+					input:  withOutbound(&session.Outbound{Target: net.TCPDestination(net.DomainAddress("www.v2ray.com.www"), 80)}),
 					output: true,
 				},
 				{
-					input:  proxy.ContextWithTarget(context.Background(), net.TCPDestination(net.DomainAddress("v2ray.co"), 80)),
+					input:  withOutbound(&session.Outbound{Target: net.TCPDestination(net.DomainAddress("v2ray.co"), 80)}),
 					output: false,
 				},
 				{
-					input:  proxy.ContextWithTarget(context.Background(), net.TCPDestination(net.DomainAddress("www.google.com"), 80)),
+					input:  withOutbound(&session.Outbound{Target: net.TCPDestination(net.DomainAddress("www.google.com"), 80)}),
 					output: true,
 				},
 				{
-					input:  proxy.ContextWithTarget(context.Background(), net.TCPDestination(net.DomainAddress("facebook.com"), 80)),
+					input:  withOutbound(&session.Outbound{Target: net.TCPDestination(net.DomainAddress("facebook.com"), 80)}),
 					output: true,
 				},
 				{
-					input:  proxy.ContextWithTarget(context.Background(), net.TCPDestination(net.DomainAddress("www.facebook.com"), 80)),
+					input:  withOutbound(&session.Outbound{Target: net.TCPDestination(net.DomainAddress("www.facebook.com"), 80)}),
 					output: false,
 				},
 				{
@@ -101,15 +106,15 @@ func TestRoutingRule(t *testing.T) {
 			},
 			test: []ruleTest{
 				{
-					input:  proxy.ContextWithTarget(context.Background(), net.TCPDestination(net.ParseAddress("8.8.8.8"), 80)),
+					input:  withOutbound(&session.Outbound{Target: net.TCPDestination(net.ParseAddress("8.8.8.8"), 80)}),
 					output: true,
 				},
 				{
-					input:  proxy.ContextWithTarget(context.Background(), net.TCPDestination(net.ParseAddress("8.8.4.4"), 80)),
+					input:  withOutbound(&session.Outbound{Target: net.TCPDestination(net.ParseAddress("8.8.4.4"), 80)}),
 					output: false,
 				},
 				{
-					input:  proxy.ContextWithTarget(context.Background(), net.TCPDestination(net.ParseAddress("2001:0db8:85a3:0000:0000:8a2e:0370:7334"), 80)),
+					input:  withOutbound(&session.Outbound{Target: net.TCPDestination(net.ParseAddress("2001:0db8:85a3:0000:0000:8a2e:0370:7334"), 80)}),
 					output: true,
 				},
 				{

+ 8 - 4
app/router/router.go

@@ -5,6 +5,8 @@ package router
 import (
 	"context"
 
+	"v2ray.com/core/common/session"
+
 	"v2ray.com/core"
 	"v2ray.com/core/common"
 	"v2ray.com/core/common/net"
@@ -75,9 +77,11 @@ func (r *Router) PickRoute(ctx context.Context) (string, error) {
 	resolver := &ipResolver{
 		dns: r.dns,
 	}
+
+	outbound := session.OutboundFromContext(ctx)
 	if r.domainStrategy == Config_IpOnDemand {
-		if dest, ok := proxy.TargetFromContext(ctx); ok && dest.Address.Family().IsDomain() {
-			resolver.domain = dest.Address.Domain()
+		if outbound != nil && outbound.Target.IsValid() && outbound.Target.Address.Family().IsDomain() {
+			resolver.domain = outbound.Target.Address.Domain()
 			ctx = proxy.ContextWithResolveIPs(ctx, resolver)
 		}
 	}
@@ -88,11 +92,11 @@ func (r *Router) PickRoute(ctx context.Context) (string, error) {
 		}
 	}
 
-	dest, ok := proxy.TargetFromContext(ctx)
-	if !ok {
+	if outbound == nil || !outbound.Target.IsValid() {
 		return "", core.ErrNoClue
 	}
 
+	dest := outbound.Target
 	if r.domainStrategy == Config_IpIfNonMatch && dest.Address.Family().IsDomain() {
 		resolver.domain = dest.Address.Domain()
 		ips := resolver.Resolve()

+ 2 - 3
app/router/router_test.go

@@ -1,7 +1,6 @@
 package router_test
 
 import (
-	"context"
 	"testing"
 
 	"v2ray.com/core"
@@ -12,7 +11,7 @@ import (
 	"v2ray.com/core/common"
 	"v2ray.com/core/common/net"
 	"v2ray.com/core/common/serial"
-	"v2ray.com/core/proxy"
+	"v2ray.com/core/common/session"
 	. "v2ray.com/ext/assert"
 )
 
@@ -41,7 +40,7 @@ func TestSimpleRouter(t *testing.T) {
 
 	r := v.Router()
 
-	ctx := proxy.ContextWithTarget(context.Background(), net.TCPDestination(net.DomainAddress("v2ray.com"), 80))
+	ctx := withOutbound(&session.Outbound{Target: net.TCPDestination(net.DomainAddress("v2ray.com"), 80)})
 	tag, err := r.PickRoute(ctx)
 	assert(err, IsNil)
 	assert(tag, Equals, "test")

+ 46 - 0
common/session/context.go

@@ -0,0 +1,46 @@
+package session
+
+import "context"
+
+type sessionKey int
+
+const (
+	idSessionKey sessionKey = iota
+	inboundSessionKey
+	outboundSessionKey
+)
+
+// ContextWithID returns a new context with the given ID.
+func ContextWithID(ctx context.Context, id ID) context.Context {
+	return context.WithValue(ctx, idSessionKey, id)
+}
+
+// IDFromContext returns ID in this context, or 0 if not contained.
+func IDFromContext(ctx context.Context) ID {
+	if id, ok := ctx.Value(idSessionKey).(ID); ok {
+		return id
+	}
+	return 0
+}
+
+func ContextWithInbound(ctx context.Context, inbound *Inbound) context.Context {
+	return context.WithValue(ctx, inboundSessionKey, inbound)
+}
+
+func InboundFromContext(ctx context.Context) *Inbound {
+	if inbound, ok := ctx.Value(inboundSessionKey).(*Inbound); ok {
+		return inbound
+	}
+	return nil
+}
+
+func ContextWithOutbound(ctx context.Context, outbound *Outbound) context.Context {
+	return context.WithValue(ctx, outboundSessionKey, outbound)
+}
+
+func OutboundFromContext(ctx context.Context) *Outbound {
+	if outbound, ok := ctx.Value(outboundSessionKey).(*Outbound); ok {
+		return outbound
+	}
+	return nil
+}

+ 0 - 6
common/session/request.go

@@ -1,6 +0,0 @@
-package session
-
-type Request struct {
-	//Destination   net.Destination
-	DecodedLayers []interface{}
-}

+ 13 - 19
common/session/session.go

@@ -6,6 +6,7 @@ import (
 	"math/rand"
 
 	"v2ray.com/core/common/errors"
+	"v2ray.com/core/common/net"
 )
 
 // ID of a session.
@@ -22,28 +23,21 @@ func NewID() ID {
 	}
 }
 
-type sessionKey int
-
-const (
-	idSessionKey sessionKey = iota
-)
-
-// ContextWithID returns a new context with the given ID.
-func ContextWithID(ctx context.Context, id ID) context.Context {
-	return context.WithValue(ctx, idSessionKey, id)
-}
-
-// IDFromContext returns ID in this context, or 0 if not contained.
-func IDFromContext(ctx context.Context) ID {
-	if id, ok := ctx.Value(idSessionKey).(ID); ok {
-		return id
-	}
-	return 0
-}
-
 func ExportIDToError(ctx context.Context) errors.ExportOption {
 	id := IDFromContext(ctx)
 	return func(h *errors.ExportOptionHolder) {
 		h.SessionID = uint32(id)
 	}
 }
+
+type Inbound struct {
+	Source  net.Destination
+	Gateway net.Destination
+	Tag     string
+}
+
+type Outbound struct {
+	Target      net.Destination
+	Gateway     net.Address
+	ResolvedIPs []net.IP
+}

+ 2 - 54
proxy/context.go

@@ -6,64 +6,12 @@ import (
 	"v2ray.com/core/common/net"
 )
 
-type key int
+type key uint32
 
 const (
-	sourceKey key = iota
-	targetKey
-	originalTargetKey
-	inboundEntryPointKey
-	inboundTagKey
-	resolvedIPsKey
+	resolvedIPsKey key = iota
 )
 
-// ContextWithSource creates a new context with given source.
-func ContextWithSource(ctx context.Context, src net.Destination) context.Context {
-	return context.WithValue(ctx, sourceKey, src)
-}
-
-// SourceFromContext retrieves source from the given context.
-func SourceFromContext(ctx context.Context) (net.Destination, bool) {
-	v, ok := ctx.Value(sourceKey).(net.Destination)
-	return v, ok
-}
-
-func ContextWithOriginalTarget(ctx context.Context, dest net.Destination) context.Context {
-	return context.WithValue(ctx, originalTargetKey, dest)
-}
-
-func OriginalTargetFromContext(ctx context.Context) (net.Destination, bool) {
-	v, ok := ctx.Value(originalTargetKey).(net.Destination)
-	return v, ok
-}
-
-func ContextWithTarget(ctx context.Context, dest net.Destination) context.Context {
-	return context.WithValue(ctx, targetKey, dest)
-}
-
-func TargetFromContext(ctx context.Context) (net.Destination, bool) {
-	v, ok := ctx.Value(targetKey).(net.Destination)
-	return v, ok
-}
-
-func ContextWithInboundEntryPoint(ctx context.Context, dest net.Destination) context.Context {
-	return context.WithValue(ctx, inboundEntryPointKey, dest)
-}
-
-func InboundEntryPointFromContext(ctx context.Context) (net.Destination, bool) {
-	v, ok := ctx.Value(inboundEntryPointKey).(net.Destination)
-	return v, ok
-}
-
-func ContextWithInboundTag(ctx context.Context, tag string) context.Context {
-	return context.WithValue(ctx, inboundTagKey, tag)
-}
-
-func InboundTagFromContext(ctx context.Context) (string, bool) {
-	v, ok := ctx.Value(inboundTagKey).(string)
-	return v, ok
-}
-
 type IPResolver interface {
 	Resolve() []net.Address
 }

+ 3 - 4
proxy/dokodemo/dokodemo.go

@@ -13,7 +13,6 @@ import (
 	"v2ray.com/core/common/session"
 	"v2ray.com/core/common/signal"
 	"v2ray.com/core/common/task"
-	"v2ray.com/core/proxy"
 	"v2ray.com/core/transport/internet"
 	"v2ray.com/core/transport/pipe"
 )
@@ -65,8 +64,8 @@ func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn in
 		Port:    d.port,
 	}
 	if d.config.FollowRedirect {
-		if origDest, ok := proxy.OriginalTargetFromContext(ctx); ok {
-			dest = origDest
+		if outbound := session.OutboundFromContext(ctx); outbound != nil && outbound.Target.IsValid() {
+			dest = outbound.Target
 		} else if handshake, ok := conn.(hasHandshakeAddress); ok {
 			addr := handshake.HandshakeAddress()
 			if addr != nil {
@@ -117,7 +116,7 @@ func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn in
 						Tproxy: internet.SocketConfig_TProxy,
 					},
 				})
-				tConn, err := internet.DialSystem(tCtx, nil, net.DestinationFromAddr(conn.RemoteAddr()))
+				tConn, err := internet.DialSystem(tCtx, net.DestinationFromAddr(conn.RemoteAddr()))
 				if err != nil {
 					return err
 				}

+ 5 - 1
proxy/freedom/freedom.go

@@ -76,7 +76,11 @@ func isValidAddress(addr *net.IPOrDomain) bool {
 
 // Process implements proxy.Outbound.
 func (h *Handler) Process(ctx context.Context, link *core.Link, dialer proxy.Dialer) error {
-	destination, _ := proxy.TargetFromContext(ctx)
+	outbound := session.OutboundFromContext(ctx)
+	if outbound == nil || !outbound.Target.IsValid() {
+		return newError("target not specified.")
+	}
+	destination := outbound.Target
 	if h.config.DestinationOverride != nil {
 		server := h.config.DestinationOverride.Server
 		if isValidAddress(server.Address) {

+ 4 - 3
proxy/mtproto/client.go

@@ -8,6 +8,7 @@ import (
 	"v2ray.com/core/common/buf"
 	"v2ray.com/core/common/crypto"
 	"v2ray.com/core/common/net"
+	"v2ray.com/core/common/session"
 	"v2ray.com/core/common/task"
 	"v2ray.com/core/proxy"
 )
@@ -20,11 +21,11 @@ func NewClient(ctx context.Context, config *ClientConfig) (*Client, error) {
 }
 
 func (c *Client) Process(ctx context.Context, link *core.Link, dialer proxy.Dialer) error {
-	dest, ok := proxy.TargetFromContext(ctx)
-	if !ok {
+	outbound := session.OutboundFromContext(ctx)
+	if outbound == nil || !outbound.Target.IsValid() {
 		return newError("unknown destination.")
 	}
-
+	dest := outbound.Target
 	if dest.Network != net.Network_TCP {
 		return newError("not TCP traffic", dest)
 	}

+ 3 - 2
proxy/shadowsocks/client.go

@@ -45,10 +45,11 @@ func NewClient(ctx context.Context, config *ClientConfig) (*Client, error) {
 
 // Process implements OutboundHandler.Process().
 func (c *Client) Process(ctx context.Context, link *core.Link, dialer proxy.Dialer) error {
-	destination, ok := proxy.TargetFromContext(ctx)
-	if !ok {
+	outbound := session.OutboundFromContext(ctx)
+	if outbound == nil || !outbound.Target.IsValid() {
 		return newError("target not specified")
 	}
+	destination := outbound.Target
 	network := destination.Network
 
 	var server *protocol.ServerSpec

+ 5 - 6
proxy/shadowsocks/server.go

@@ -13,7 +13,6 @@ import (
 	"v2ray.com/core/common/session"
 	"v2ray.com/core/common/signal"
 	"v2ray.com/core/common/task"
-	"v2ray.com/core/proxy"
 	"v2ray.com/core/transport/internet"
 	"v2ray.com/core/transport/internet/udp"
 	"v2ray.com/core/transport/pipe"
@@ -99,10 +98,10 @@ func (s *Server) handlerUDPPayload(ctx context.Context, conn internet.Connection
 		for _, payload := range mpayload {
 			request, data, err := DecodeUDPPacket(s.user, payload)
 			if err != nil {
-				if source, ok := proxy.SourceFromContext(ctx); ok {
-					newError("dropping invalid UDP packet from: ", source).Base(err).WriteToLog(session.ExportIDToError(ctx))
+				if inbound := session.InboundFromContext(ctx); inbound != nil && inbound.Source.IsValid() {
+					newError("dropping invalid UDP packet from: ", inbound.Source).Base(err).WriteToLog(session.ExportIDToError(ctx))
 					log.Record(&log.AccessMessage{
-						From:   source,
+						From:   inbound.Source,
 						To:     "",
 						Status: log.AccessRejected,
 						Reason: err,
@@ -125,9 +124,9 @@ func (s *Server) handlerUDPPayload(ctx context.Context, conn internet.Connection
 			}
 
 			dest := request.Destination()
-			if source, ok := proxy.SourceFromContext(ctx); ok {
+			if inbound := session.InboundFromContext(ctx); inbound != nil && inbound.Source.IsValid() {
 				log.Record(&log.AccessMessage{
-					From:   source,
+					From:   inbound.Source,
 					To:     dest,
 					Status: log.AccessAccepted,
 					Reason: "",

+ 3 - 2
proxy/socks/client.go

@@ -47,10 +47,11 @@ func NewClient(ctx context.Context, config *ClientConfig) (*Client, error) {
 
 // Process implements proxy.Outbound.Process.
 func (c *Client) Process(ctx context.Context, link *core.Link, dialer proxy.Dialer) error {
-	destination, ok := proxy.TargetFromContext(ctx)
-	if !ok {
+	outbound := session.OutboundFromContext(ctx)
+	if outbound == nil || !outbound.Target.IsValid() {
 		return newError("target not specified.")
 	}
+	destination := outbound.Target
 
 	var server *protocol.ServerSpec
 	var conn internet.Connection

+ 13 - 13
proxy/socks/server.go

@@ -14,7 +14,6 @@ import (
 	"v2ray.com/core/common/session"
 	"v2ray.com/core/common/signal"
 	"v2ray.com/core/common/task"
-	"v2ray.com/core/proxy"
 	"v2ray.com/core/transport/internet"
 	"v2ray.com/core/transport/internet/udp"
 	"v2ray.com/core/transport/pipe"
@@ -73,21 +72,22 @@ func (s *Server) processTCP(ctx context.Context, conn internet.Connection, dispa
 		newError("failed to set deadline").Base(err).WriteToLog(session.ExportIDToError(ctx))
 	}
 
-	inboundDest, ok := proxy.InboundEntryPointFromContext(ctx)
-	if !ok {
-		return newError("inbound entry point not specified")
+	inbound := session.InboundFromContext(ctx)
+	if inbound == nil || !inbound.Gateway.IsValid() {
+		return newError("inbound gateway not specified")
 	}
+
 	svrSession := &ServerSession{
 		config: s.config,
-		port:   inboundDest.Port,
+		port:   inbound.Gateway.Port,
 	}
 
 	reader := &buf.BufferedReader{Reader: buf.NewReader(conn)}
 	request, err := svrSession.Handshake(reader, conn)
 	if err != nil {
-		if source, ok := proxy.SourceFromContext(ctx); ok {
+		if inbound != nil && inbound.Source.IsValid() {
 			log.Record(&log.AccessMessage{
-				From:   source,
+				From:   inbound.Source,
 				To:     "",
 				Status: log.AccessRejected,
 				Reason: err,
@@ -103,9 +103,9 @@ func (s *Server) processTCP(ctx context.Context, conn internet.Connection, dispa
 	if request.Command == protocol.RequestCommandTCP {
 		dest := request.Destination()
 		newError("TCP Connect request to ", dest).WriteToLog(session.ExportIDToError(ctx))
-		if source, ok := proxy.SourceFromContext(ctx); ok {
+		if inbound != nil && inbound.Source.IsValid() {
 			log.Record(&log.AccessMessage{
-				From:   source,
+				From:   inbound.Source,
 				To:     dest,
 				Status: log.AccessAccepted,
 				Reason: "",
@@ -188,8 +188,8 @@ func (s *Server) handleUDPPayload(ctx context.Context, conn internet.Connection,
 		conn.Write(udpMessage.Bytes()) // nolint: errcheck
 	})
 
-	if source, ok := proxy.SourceFromContext(ctx); ok {
-		newError("client UDP connection from ", source).WriteToLog(session.ExportIDToError(ctx))
+	if inbound := session.InboundFromContext(ctx); inbound != nil && inbound.Source.IsValid() {
+		newError("client UDP connection from ", inbound.Source).WriteToLog(session.ExportIDToError(ctx))
 	}
 
 	reader := buf.NewReader(conn)
@@ -214,9 +214,9 @@ func (s *Server) handleUDPPayload(ctx context.Context, conn internet.Connection,
 			}
 
 			newError("send packet to ", request.Destination(), " with ", payload.Len(), " bytes").AtDebug().WriteToLog(session.ExportIDToError(ctx))
-			if source, ok := proxy.SourceFromContext(ctx); ok {
+			if inbound := session.InboundFromContext(ctx); inbound != nil && inbound.Source.IsValid() {
 				log.Record(&log.AccessMessage{
-					From:   source,
+					From:   inbound.Source,
 					To:     request.Destination(),
 					Status: log.AccessAccepted,
 					Reason: "",

+ 4 - 2
proxy/vmess/outbound/outbound.go

@@ -68,10 +68,12 @@ func (v *Handler) Process(ctx context.Context, link *core.Link, dialer proxy.Dia
 	}
 	defer conn.Close() //nolint: errcheck
 
-	target, ok := proxy.TargetFromContext(ctx)
-	if !ok {
+	outbound := session.OutboundFromContext(ctx)
+	if outbound == nil || !outbound.Target.IsValid() {
 		return newError("target not specified").AtError()
 	}
+
+	target := outbound.Target
 	newError("tunneling request to ", target, " via ", rec.Destination()).WriteToLog(session.ExportIDToError(ctx))
 
 	command := protocol.RequestCommandTCP

+ 0 - 11
transport/internet/context.go

@@ -26,17 +26,6 @@ func StreamSettingsFromContext(ctx context.Context) *MemoryStreamConfig {
 	return ss.(*MemoryStreamConfig)
 }
 
-func ContextWithDialerSource(ctx context.Context, addr net.Address) context.Context {
-	return context.WithValue(ctx, dialerSrcKey, addr)
-}
-
-func DialerSourceFromContext(ctx context.Context) net.Address {
-	if addr, ok := ctx.Value(dialerSrcKey).(net.Address); ok {
-		return addr
-	}
-	return net.AnyIP
-}
-
 func ContextWithBindAddress(ctx context.Context, dest net.Destination) context.Context {
 	return context.WithValue(ctx, bindAddrKey, dest)
 }

+ 7 - 1
transport/internet/dialer.go

@@ -3,6 +3,8 @@ package internet
 import (
 	"context"
 
+	"v2ray.com/core/common/session"
+
 	"v2ray.com/core/common/net"
 )
 
@@ -53,6 +55,10 @@ func Dial(ctx context.Context, dest net.Destination) (Connection, error) {
 }
 
 // DialSystem calls system dialer to create a network connection.
-func DialSystem(ctx context.Context, src net.Address, dest net.Destination) (net.Conn, error) {
+func DialSystem(ctx context.Context, dest net.Destination) (net.Conn, error) {
+	var src net.Address
+	if outbound := session.OutboundFromContext(ctx); outbound != nil {
+		src = outbound.Gateway
+	}
 	return effectiveSystemDialer.Dial(ctx, src, dest)
 }

+ 1 - 1
transport/internet/dialer_test.go

@@ -18,7 +18,7 @@ func TestDialWithLocalAddr(t *testing.T) {
 	assert(err, IsNil)
 	defer server.Close()
 
-	conn, err := DialSystem(context.Background(), net.LocalHostIP, net.TCPDestination(net.LocalHostIP, dest.Port))
+	conn, err := DialSystem(context.Background(), net.TCPDestination(net.LocalHostIP, dest.Port))
 	assert(err, IsNil)
 	assert(conn.RemoteAddr().String(), Equals, "127.0.0.1:"+dest.Port.String())
 	conn.Close()

+ 1 - 1
transport/internet/http/dialer.go

@@ -53,7 +53,7 @@ func getHTTPClient(ctx context.Context, dest net.Destination) (*http.Client, err
 			}
 			address := net.ParseAddress(rawHost)
 
-			pconn, err := internet.DialSystem(context.Background(), nil, net.TCPDestination(address, port))
+			pconn, err := internet.DialSystem(context.Background(), net.TCPDestination(address, port))
 			if err != nil {
 				return nil, err
 			}

+ 1 - 2
transport/internet/kcp/dialer.go

@@ -49,8 +49,7 @@ func DialKCP(ctx context.Context, dest net.Destination) (internet.Connection, er
 	dest.Network = net.Network_UDP
 	newError("dialing mKCP to ", dest).WriteToLog()
 
-	src := internet.DialerSourceFromContext(ctx)
-	rawConn, err := internet.DialSystem(ctx, src, dest)
+	rawConn, err := internet.DialSystem(ctx, dest)
 	if err != nil {
 		return nil, newError("failed to dial to dest: ", err).AtWarning().Base(err)
 	}

+ 1 - 3
transport/internet/tcp/dialer.go

@@ -21,9 +21,7 @@ func getTCPSettingsFromContext(ctx context.Context) *Config {
 // Dial dials a new TCP connection to the given destination.
 func Dial(ctx context.Context, dest net.Destination) (internet.Connection, error) {
 	newError("dialing TCP to ", dest).WriteToLog(session.ExportIDToError(ctx))
-	src := internet.DialerSourceFromContext(ctx)
-
-	conn, err := internet.DialSystem(ctx, src, dest)
+	conn, err := internet.DialSystem(ctx, dest)
 	if err != nil {
 		return nil, err
 	}

+ 1 - 2
transport/internet/udp/dialer.go

@@ -11,8 +11,7 @@ import (
 func init() {
 	common.Must(internet.RegisterTransportDialer(protocolName,
 		func(ctx context.Context, dest net.Destination) (internet.Connection, error) {
-			src := internet.DialerSourceFromContext(ctx)
-			conn, err := internet.DialSystem(ctx, src, dest)
+			conn, err := internet.DialSystem(ctx, dest)
 			if err != nil {
 				return nil, err
 			}

+ 1 - 2
transport/internet/websocket/dialer.go

@@ -29,12 +29,11 @@ func init() {
 }
 
 func dialWebsocket(ctx context.Context, dest net.Destination) (net.Conn, error) {
-	src := internet.DialerSourceFromContext(ctx)
 	wsSettings := internet.StreamSettingsFromContext(ctx).ProtocolSettings.(*Config)
 
 	dialer := &websocket.Dialer{
 		NetDial: func(network, addr string) (net.Conn, error) {
-			return internet.DialSystem(ctx, src, dest)
+			return internet.DialSystem(ctx, dest)
 		},
 		ReadBufferSize:   4 * 1024,
 		WriteBufferSize:  4 * 1024,