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