public async Task <ITunnel> 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); } }
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 <ITunnel> ConnectIfNecessaryAsync(TunnelDestination endpoint) { lock (this.tunnelsLock) { if (!this.tunnels.TryGetValue(endpoint, out Task <ITunnel> 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); } } }
private Task <ITunnel> ConnectAndCacheAsync(TunnelDestination endpoint) { var tunnel = this.tunnelService.CreateTunnelAsync(endpoint); TraceSources.IapDesktop.TraceVerbose("Created tunnel to {0}", endpoint); this.tunnels[endpoint] = tunnel; return(tunnel); }
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); }
public bool IsConnected(TunnelDestination endpoint) { lock (this.tunnelsLock) { if (this.tunnels.TryGetValue(endpoint, out Task <ITunnel> 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 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 TunnelClosedEvent(TunnelDestination destination) { this.Destination = destination; }
public TunnelOpenedEvent(TunnelDestination destination) { this.Destination = destination; }