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