Example #1
0
        /// <summary>
        /// Perpetually listen and relay traffic until cancelled.
        /// </summary>
        public Task ListenAsync(CancellationToken token)
        {
            // Start listening before returning from the menthod.
            this.listener.Start(BacklogLength);

            // All communication is then handled asynchronously.
            return(Task.Run(() =>
            {
                using (token.Register(this.listener.Stop))
                {
                    while (this.ClientAcceptLimit == 0 || this.ClientAcceptLimit > this.ClientsAccepted)
                    {
                        try
                        {
                            var socket = this.listener.AcceptSocket();
                            if (this.policy.IsClientAllowed((IPEndPoint)socket.RemoteEndPoint))
                            {
                                TraceSources.Compute.TraceInformation(
                                    "Connection from {0} allowed by policy", socket.RemoteEndPoint);
                            }
                            else
                            {
                                TraceSources.Compute.TraceWarning(
                                    "Connection from {0} rejected by policy", socket.RemoteEndPoint);
                                socket.Close();
                                continue;
                            }

                            var clientStream = new SocketStream(socket, this.Statistics);
                            var serverStream = new SshRelayStream(this.server);

                            OnClientConnected(clientStream.ToString());
                            this.ClientsAccepted++;

                            Task.WhenAll(
                                clientStream.RelayToAsync(serverStream, token),
                                serverStream.RelayToAsync(clientStream, token))
                            .ContinueWith(t =>
                            {
                                TraceSources.Compute.TraceVerbose("SshRelayListener: Closed connection");

                                if (t.IsFaulted)
                                {
                                    OnConnectionFailed(t.Exception);
                                }

                                OnClientDisconnected(clientStream.ToString());
                            });
                        }
                        catch (SocketException e) when(e.SocketErrorCode == SocketError.Interrupted)
                        {
                            // Operation cancelled, terminate gracefully.
                            break;
                        }
                    }
                }
            }));
        }