private Task <Tunnel> ConnectIfNecessaryAsync(TunnelDestination endpoint)
        {
            lock (this.tunnelsLock)
            {
                if (!this.tunnels.TryGetValue(endpoint, out Task <Tunnel> tunnel))
                {
                    return(ConnectAndCacheAsync(endpoint));
                }
                else if (tunnel.IsFaulted)
                {
                    TraceSources.IapDesktop.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));
                }
                else
                {
                    TraceSources.IapDesktop.TraceVerbose(
                        "Reusing tunnel to {0}", endpoint);

                    // This tunnel is good or still in the process
                    // of connecting.
                    return(tunnel);
                }
            }
        }
        public async Task <Tunnel> ConnectAsync(TunnelDestination endpoint, TimeSpan timeout)
        {
            using (TraceSources.IapDesktop.TraceMethod().WithParameters(endpoint, timeout))
            {
                var tunnel = await ConnectIfNecessaryAsync(endpoint);

                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);

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

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

                    throw;
                }

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

                return(tunnel);
            }
        }
Esempio n. 3
0
        public Task <ITunnel> CreateTunnelAsync(TunnelDestination tunnelEndpoint)
        {
            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);
                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)));
            }
        }
        private Task <Tunnel> ConnectAndCacheAsync(TunnelDestination endpoint)
        {
            var tunnel = this.tunnelService.CreateTunnelAsync(endpoint);

            TraceSources.IapDesktop.TraceVerbose("Created tunnel to {0}", endpoint);

            this.tunnels[endpoint] = tunnel;
            return(tunnel);
        }
 public bool IsConnected(TunnelDestination endpoint)
 {
     lock (this.tunnelsLock)
     {
         if (this.tunnels.TryGetValue(endpoint, out Task <Tunnel> tunnel))
         {
             return(!tunnel.IsFaulted);
         }
         else
         {
             return(false);
         }
     }
 }
        public async Task DisconnectAsync(TunnelDestination endpoint)
        {
            using (TraceSources.IapDesktop.TraceMethod().WithParameters(endpoint))
            {
                lock (this.tunnelsLock)
                {
                    if (!this.tunnels.TryGetValue(endpoint, out var tunnel))
                    {
                        throw new KeyNotFoundException($"No active tunnel to {endpoint}");
                    }

                    tunnel.Result.Close();
                    this.tunnels.Remove(endpoint);
                }

                await this.eventService.FireAsync(new TunnelClosedEvent(endpoint));
            }
        }
 public TunnelClosedEvent(TunnelDestination destination)
 {
     this.Destination = destination;
 }
 public TunnelOpenedEvent(TunnelDestination destination)
 {
     this.Destination = destination;
 }