Hunter0x7c7
2022-08-11 a82f9cb69f63aaeba40c024960deda7d75b9fece
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package internet
 
import (
    "context"
 
    "github.com/v2fly/v2ray-core/v5/common/net"
    "github.com/v2fly/v2ray-core/v5/common/session"
    "github.com/v2fly/v2ray-core/v5/transport/internet/tagged"
)
 
// Dialer is the interface for dialing outbound connections.
type Dialer interface {
    // Dial dials a system connection to the given destination.
    Dial(ctx context.Context, destination net.Destination) (Connection, error)
 
    // Address returns the address used by this Dialer. Maybe nil if not known.
    Address() net.Address
}
 
// dialFunc is an interface to dial network connection to a specific destination.
type dialFunc func(ctx context.Context, dest net.Destination, streamSettings *MemoryStreamConfig) (Connection, error)
 
var transportDialerCache = make(map[string]dialFunc)
 
// RegisterTransportDialer registers a Dialer with given name.
func RegisterTransportDialer(protocol string, dialer dialFunc) error {
    if _, found := transportDialerCache[protocol]; found {
        return newError(protocol, " dialer already registered").AtError()
    }
    transportDialerCache[protocol] = dialer
    return nil
}
 
// Dial dials a internet connection towards the given destination.
func Dial(ctx context.Context, dest net.Destination, streamSettings *MemoryStreamConfig) (Connection, error) {
    if dest.Network == net.Network_TCP {
        if streamSettings == nil {
            s, err := ToMemoryStreamConfig(nil)
            if err != nil {
                return nil, newError("failed to create default stream settings").Base(err)
            }
            streamSettings = s
        }
 
        protocol := streamSettings.ProtocolName
 
        if originalProtocolName := getOriginalMessageName(streamSettings); originalProtocolName != "" {
            protocol = originalProtocolName
        }
 
        dialer := transportDialerCache[protocol]
        if dialer == nil {
            return nil, newError(protocol, " dialer not registered").AtError()
        }
        return dialer(ctx, dest, streamSettings)
    }
 
    if dest.Network == net.Network_UDP {
        udpDialer := transportDialerCache["udp"]
        if udpDialer == nil {
            return nil, newError("UDP dialer not registered").AtError()
        }
        return udpDialer(ctx, dest, streamSettings)
    }
 
    return nil, newError("unknown network ", dest.Network)
}
 
// DialSystem calls system dialer to create a network connection.
func DialSystem(ctx context.Context, dest net.Destination, sockopt *SocketConfig) (net.Conn, error) {
    var src net.Address
    if outbound := session.OutboundFromContext(ctx); outbound != nil {
        src = outbound.Gateway
    }
 
    if transportLayerOutgoingTag := session.GetTransportLayerProxyTagFromContext(ctx); transportLayerOutgoingTag != "" {
        return DialTaggedOutbound(ctx, dest, transportLayerOutgoingTag)
    }
 
    return effectiveSystemDialer.Dial(ctx, src, dest, sockopt)
}
 
func DialTaggedOutbound(ctx context.Context, dest net.Destination, tag string) (net.Conn, error) {
    if tagged.Dialer == nil {
        return nil, newError("tagged dial not enabled")
    }
    return tagged.Dialer(ctx, dest, tag)
}