mirror of
https://github.com/XTLS/Xray-core.git
synced 2025-04-30 09:18:34 +00:00
Add session context outbounds as slice (#3356)
* Add session context outbounds as slice slice is needed for dialer proxy where two outbounds work on top of each other There are two sets of target addr for example It also enable Xtls to correctly do splice copy by checking both outbounds are ready to do direct copy * Fill outbound tag info * Splice now checks capalibility from all outbounds * Fix unit tests
This commit is contained in:
parent
0735053348
commit
017f53b5fc
42 changed files with 303 additions and 236 deletions
|
@ -148,9 +148,10 @@ func (f *DialingWorkerFactory) Create() (*ClientWorker, error) {
|
|||
}
|
||||
|
||||
go func(p proxy.Outbound, d internet.Dialer, c common.Closable) {
|
||||
ctx := session.ContextWithOutbound(context.Background(), &session.Outbound{
|
||||
outbounds := []*session.Outbound{{
|
||||
Target: net.TCPDestination(muxCoolAddress, muxCoolPort),
|
||||
})
|
||||
}}
|
||||
ctx := session.ContextWithOutbounds(context.Background(), outbounds)
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
|
||||
if err := p.Process(ctx, &transport.Link{Reader: uplinkReader, Writer: downlinkWriter}, d); err != nil {
|
||||
|
@ -242,17 +243,18 @@ func writeFirstPayload(reader buf.Reader, writer *Writer) error {
|
|||
}
|
||||
|
||||
func fetchInput(ctx context.Context, s *Session, output buf.Writer) {
|
||||
dest := session.OutboundFromContext(ctx).Target
|
||||
outbounds := session.OutboundsFromContext(ctx)
|
||||
ob := outbounds[len(outbounds) - 1]
|
||||
transferType := protocol.TransferTypeStream
|
||||
if dest.Network == net.Network_UDP {
|
||||
if ob.Target.Network == net.Network_UDP {
|
||||
transferType = protocol.TransferTypePacket
|
||||
}
|
||||
s.transferType = transferType
|
||||
writer := NewWriter(s.ID, dest, output, transferType, xudp.GetGlobalID(ctx))
|
||||
writer := NewWriter(s.ID, ob.Target, output, transferType, xudp.GetGlobalID(ctx))
|
||||
defer s.Close(false)
|
||||
defer writer.Close()
|
||||
|
||||
newError("dispatching request to ", dest).WriteToLog(session.ExportIDToError(ctx))
|
||||
newError("dispatching request to ", ob.Target).WriteToLog(session.ExportIDToError(ctx))
|
||||
if err := writeFirstPayload(s.input, writer); err != nil {
|
||||
newError("failed to write first payload").Base(err).WriteToLog(session.ExportIDToError(ctx))
|
||||
writer.hasError = true
|
||||
|
|
|
@ -86,9 +86,9 @@ func TestClientWorkerClose(t *testing.T) {
|
|||
}
|
||||
|
||||
tr1, tw1 := pipe.New(pipe.WithoutSizeLimit())
|
||||
ctx1 := session.ContextWithOutbound(context.Background(), &session.Outbound{
|
||||
ctx1 := session.ContextWithOutbounds(context.Background(), []*session.Outbound{{
|
||||
Target: net.TCPDestination(net.DomainAddress("www.example.com"), 80),
|
||||
})
|
||||
}})
|
||||
common.Must(manager.Dispatch(ctx1, &transport.Link{
|
||||
Reader: tr1,
|
||||
Writer: tw1,
|
||||
|
@ -103,9 +103,9 @@ func TestClientWorkerClose(t *testing.T) {
|
|||
}
|
||||
|
||||
tr2, tw2 := pipe.New(pipe.WithoutSizeLimit())
|
||||
ctx2 := session.ContextWithOutbound(context.Background(), &session.Outbound{
|
||||
ctx2 := session.ContextWithOutbounds(context.Background(), []*session.Outbound{{
|
||||
Target: net.TCPDestination(net.DomainAddress("www.example.com"), 80),
|
||||
})
|
||||
}})
|
||||
common.Must(manager.Dispatch(ctx2, &transport.Link{
|
||||
Reader: tr2,
|
||||
Writer: tw2,
|
||||
|
|
|
@ -51,13 +51,13 @@ func InboundFromContext(ctx context.Context) *Inbound {
|
|||
return nil
|
||||
}
|
||||
|
||||
func ContextWithOutbound(ctx context.Context, outbound *Outbound) context.Context {
|
||||
return context.WithValue(ctx, outboundSessionKey, outbound)
|
||||
func ContextWithOutbounds(ctx context.Context, outbounds []*Outbound) context.Context {
|
||||
return context.WithValue(ctx, outboundSessionKey, outbounds)
|
||||
}
|
||||
|
||||
func OutboundFromContext(ctx context.Context) *Outbound {
|
||||
if outbound, ok := ctx.Value(outboundSessionKey).(*Outbound); ok {
|
||||
return outbound
|
||||
func OutboundsFromContext(ctx context.Context) []*Outbound {
|
||||
if outbounds, ok := ctx.Value(outboundSessionKey).([]*Outbound); ok {
|
||||
return outbounds
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -50,18 +50,11 @@ type Inbound struct {
|
|||
Conn net.Conn
|
||||
// Timer of the inbound buf copier. May be nil.
|
||||
Timer *signal.ActivityTimer
|
||||
// CanSpliceCopy is a property for this connection, set by both inbound and outbound
|
||||
// CanSpliceCopy is a property for this connection
|
||||
// 1 = can, 2 = after processing protocol info should be able to, 3 = cannot
|
||||
CanSpliceCopy int
|
||||
}
|
||||
|
||||
func(i *Inbound) SetCanSpliceCopy(canSpliceCopy int) int {
|
||||
if canSpliceCopy > i.CanSpliceCopy {
|
||||
i.CanSpliceCopy = canSpliceCopy
|
||||
}
|
||||
return i.CanSpliceCopy
|
||||
}
|
||||
|
||||
// Outbound is the metadata of an outbound connection.
|
||||
type Outbound struct {
|
||||
// Target address of the outbound connection.
|
||||
|
@ -70,10 +63,15 @@ type Outbound struct {
|
|||
RouteTarget net.Destination
|
||||
// Gateway address
|
||||
Gateway net.Address
|
||||
// Tag of the outbound proxy that handles the connection.
|
||||
Tag string
|
||||
// Name of the outbound proxy that handles the connection.
|
||||
Name string
|
||||
// Conn is actually internet.Connection. May be nil. It is currently nil for outbound with proxySettings
|
||||
Conn net.Conn
|
||||
// CanSpliceCopy is a property for this connection
|
||||
// 1 = can, 2 = after processing protocol info should be able to, 3 = cannot
|
||||
CanSpliceCopy int
|
||||
}
|
||||
|
||||
// SniffingRequest controls the behavior of content sniffing.
|
||||
|
|
|
@ -43,9 +43,14 @@ func NewOutboundDialer(outbound proxy.Outbound, dialer internet.Dialer) *XrayOut
|
|||
}
|
||||
|
||||
func (d *XrayOutboundDialer) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
||||
ctx = session.ContextWithOutbound(ctx, &session.Outbound{
|
||||
Target: ToDestination(destination, ToNetwork(network)),
|
||||
})
|
||||
outbounds := session.OutboundsFromContext(ctx)
|
||||
if len(outbounds) == 0 {
|
||||
outbounds = []*session.Outbound{{}}
|
||||
ctx = session.ContextWithOutbounds(ctx, outbounds)
|
||||
}
|
||||
ob := outbounds[len(outbounds) - 1]
|
||||
ob.Target = ToDestination(destination, ToNetwork(network))
|
||||
|
||||
opts := []pipe.Option{pipe.WithSizeLimit(64 * 1024)}
|
||||
uplinkReader, uplinkWriter := pipe.New(opts...)
|
||||
downlinkReader, downlinkWriter := pipe.New(opts...)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue