private Task <ITunnel> ConnectIfNecessaryAsync(
            TunnelDestination endpoint,
            ISshRelayPolicy relayPolicy)
        {
            lock (this.tunnelsLock)
            {
                if (!this.tunnels.TryGetValue(endpoint, out Task <ITunnel> tunnel))
                {
                    return(ConnectAndCacheAsync(endpoint, relayPolicy));
                }
                else if (tunnel.IsFaulted)
                {
                    ApplicationTraceSources.Default.TraceVerbose(
                        "Tunnel to {0} is faulted.. reconnecting", endpoint);

                    // There is no point in handing out a faulty attempt
                    // to create a tunnel. So start anew.
                    return(ConnectAndCacheAsync(endpoint, relayPolicy));
                }
                else
                {
                    ApplicationTraceSources.Default.TraceVerbose(
                        "Reusing tunnel to {0}", endpoint);

                    // This tunnel is good or still in the process
                    // of connecting.
                    return(tunnel);
                }
            }
        }
Beispiel #2
0
        public Task <ITunnel> CreateTunnelAsync(
            TunnelDestination tunnelEndpoint,
            ISshRelayPolicy relayPolicy)
        {
            using (TraceSources.IapDesktop.TraceMethod().WithParameters(tunnelEndpoint))
            {
                var iapEndpoint = new IapTunnelingEndpoint(
                    this.authorizationService.Authorization.Credential,
                    tunnelEndpoint.Instance,
                    tunnelEndpoint.RemotePort,
                    IapTunnelingEndpoint.DefaultNetworkInterface,
                    Globals.UserAgent);


                // Start listener to enable clients to connect. Do not await
                // the listener as we want to continue listeining in the
                // background.
                var listener = SshRelayListener.CreateLocalListener(
                    iapEndpoint,
                    relayPolicy);
                var cts = new CancellationTokenSource();

                _ = listener.ListenAsync(cts.Token);

                // Return the tunnel which allows the listener to be stopped
                // via the CancellationTokenSource.
                return(Task.FromResult <ITunnel>(new Tunnel(iapEndpoint, listener, cts)));
            }
        }
        //---------------------------------------------------------------------
        // Ctor
        //---------------------------------------------------------------------

        private SshRelayListener(
            ISshRelayEndpoint server,
            ISshRelayPolicy policy,
            int localPort)
        {
            this.server    = server;
            this.policy    = policy;
            this.LocalPort = localPort;

            this.listener = new TcpListener(new IPEndPoint(IPAddress.Loopback, localPort));
        }
        private Task <ITunnel> ConnectAndCacheAsync(
            TunnelDestination endpoint,
            ISshRelayPolicy relayPolicy)
        {
            var tunnel = this.tunnelService.CreateTunnelAsync(endpoint, relayPolicy);

            ApplicationTraceSources.Default.TraceVerbose("Created tunnel to {0}", endpoint);

            this.tunnels[endpoint] = tunnel;
            return(tunnel);
        }
        /// <summary>
        ///  Create a listener using a defined local port.
        /// </summary>
        public static SshRelayListener CreateLocalListener(
            ISshRelayEndpoint server,
            ISshRelayPolicy policy,
            int port)
        {
            if (port < 0 || port > ushort.MaxValue)
            {
                throw new ArgumentException("port");
            }

            return(new SshRelayListener(server, policy, port));
        }
Beispiel #6
0
        public Task <ITunnel> CreateTunnelAsync(
            TunnelDestination tunnelEndpoint,
            ISshRelayPolicy relayPolicy)
        {
            using (ApplicationTraceSources.Default.TraceMethod().WithParameters(tunnelEndpoint))
            {
                var clientCertificate =
                    (this.authorizationService.DeviceEnrollment != null &&
                     this.authorizationService.DeviceEnrollment.State == DeviceEnrollmentState.Enrolled)
                    ? this.authorizationService.DeviceEnrollment.Certificate
                    : null;

                if (clientCertificate != null)
                {
                    ApplicationTraceSources.Default.TraceInformation(
                        "Using client certificate (valid till {0})", clientCertificate.NotAfter);
                }

                var iapEndpoint = new IapTunnelingEndpoint(
                    this.authorizationService.Authorization.Credential,
                    tunnelEndpoint.Instance,
                    tunnelEndpoint.RemotePort,
                    IapTunnelingEndpoint.DefaultNetworkInterface,
                    Globals.UserAgent,
                    clientCertificate);

                // Start listener to enable clients to connect. Do not await
                // the listener as we want to continue listeining in the
                // background.
                var listener = SshRelayListener.CreateLocalListener(
                    iapEndpoint,
                    relayPolicy);
                var cts = new CancellationTokenSource();

                _ = listener.ListenAsync(cts.Token);

                // Return the tunnel which allows the listener to be stopped
                // via the CancellationTokenSource.
                return(Task.FromResult <ITunnel>(new Tunnel(iapEndpoint, listener, cts)));
            }
        }
        public async Task <ITunnel> ConnectAsync(
            TunnelDestination endpoint,
            ISshRelayPolicy relayPolicy,
            TimeSpan timeout)
        {
            using (ApplicationTraceSources.Default.TraceMethod().WithParameters(endpoint, timeout))
            {
                var tunnel = await ConnectIfNecessaryAsync(endpoint, relayPolicy)
                             .ConfigureAwait(false);

                try
                {
                    // Whether it is a new or existing tunnel, probe it first before
                    // handing it out. It might be broken after all (because of reauth
                    // or for other reasons).
                    await tunnel.Probe(timeout).ConfigureAwait(false);

                    ApplicationTraceSources.Default.TraceVerbose(
                        "Probing tunnel to {0} succeeded", endpoint);
                }
                catch (Exception e)
                {
                    ApplicationTraceSources.Default.TraceVerbose(
                        "Probing tunnel to {0} failed: {1}", endpoint, e.Message);

                    // Un-cache this broken tunnel.
                    await DisconnectAsync(endpoint).ConfigureAwait(false);

                    throw;
                }

                await this.eventService
                .FireAsync(new TunnelOpenedEvent(endpoint))
                .ConfigureAwait(false);

                return(tunnel);
            }
        }
        //---------------------------------------------------------------------
        // Publics
        //---------------------------------------------------------------------

        /// <summary>
        ///  Create a listener using a dynamically selected, unused local port.
        /// </summary>
        public static SshRelayListener CreateLocalListener(
            ISshRelayEndpoint server,
            ISshRelayPolicy policy)
        {
            return(CreateLocalListener(server, policy, PortFinder.FindFreeLocalPort()));
        }