Esempio n. 1
0
        private async Task <bool> StartTls(ClientMetadata client)
        {
            try
            {
                await client.SslStream.AuthenticateAsServerAsync(
                    _sslCertificate,
                    _settings.MutuallyAuthenticate,
                    SslProtocols.Tls12,
                    !_settings.AcceptInvalidCertificates).ConfigureAwait(false);

                if (!client.SslStream.IsEncrypted)
                {
                    Logger?.Invoke($"{_header}client {client.IpPort} not encrypted, disconnecting");
                    client.Dispose();
                    return(false);
                }

                if (!client.SslStream.IsAuthenticated)
                {
                    Logger?.Invoke($"{_header}client {client.IpPort} not SSL/TLS authenticated, disconnecting");
                    client.Dispose();
                    return(false);
                }

                if (_settings.MutuallyAuthenticate && !client.SslStream.IsMutuallyAuthenticated)
                {
                    Logger?.Invoke($"{_header}client {client.IpPort} failed mutual authentication, disconnecting");
                    client.Dispose();
                    return(false);
                }
            }
            catch (Exception e)
            {
                Logger?.Invoke($"{_header}client {client.IpPort} SSL/TLS exception: {Environment.NewLine}{e}");
                client.Dispose();
                return(false);
            }

            return(true);
        }
Esempio n. 2
0
        private async Task DataReceiver(ClientMetadata client)
        {
            string ipPort = client.IpPort;

            Logger?.Invoke($"{_header}data receiver started for client {ipPort}");

            CancellationTokenSource linkedCts = CancellationTokenSource.CreateLinkedTokenSource(_token, client.Token);

            while (true)
            {
                try
                {
                    if (!IsClientConnected(client.Client))
                    {
                        Logger?.Invoke($"{_header}client {ipPort} disconnected");
                        break;
                    }

                    if (client.Token.IsCancellationRequested)
                    {
                        Logger?.Invoke($"{_header}cancellation requested (data receiver for client {ipPort})");
                        break;
                    }

                    byte[] data = await DataReadAsync(client, linkedCts.Token).ConfigureAwait(false);

                    if (data == null)
                    {
                        await Task.Delay(10, linkedCts.Token).ConfigureAwait(false);

                        continue;
                    }

                    _ = Task.Run(() => _events.HandleDataReceived(this, new DataReceivedEventArgs(ipPort, data)), linkedCts.Token);
                    _statistics.ReceivedBytes += data.Length;
                    UpdateClientLastSeen(client.IpPort);
                }
                catch (IOException)
                {
                    Logger?.Invoke($"{_header}data receiver canceled, peer disconnected [{ipPort}]");
                    break;
                }
                catch (SocketException)
                {
                    Logger?.Invoke($"{_header}data receiver canceled, peer disconnected [{ipPort}]");
                    break;
                }
                catch (TaskCanceledException)
                {
                    Logger?.Invoke($"{_header}data receiver task canceled [{ipPort}]");
                    break;
                }
                catch (ObjectDisposedException)
                {
                    Logger?.Invoke($"{_header}data receiver canceled due to disposal [{ipPort}]");
                    break;
                }
                catch (Exception e)
                {
                    Logger?.Invoke($"{_header}data receiver exception [{ipPort}]:{ Environment.NewLine}{e}{Environment.NewLine}");
                    break;
                }
            }

            Logger?.Invoke($"{_header}data receiver terminated for client {ipPort}");

            if (_clientsKicked.ContainsKey(ipPort))
            {
                _events.HandleClientDisconnected(this, new ConnectionEventArgs(ipPort, DisconnectReason.Kicked));
            }
            else if (_clientsTimedout.ContainsKey(client.IpPort))
            {
                _events.HandleClientDisconnected(this, new ConnectionEventArgs(ipPort, DisconnectReason.Timeout));
            }
            else
            {
                _events.HandleClientDisconnected(this, new ConnectionEventArgs(ipPort, DisconnectReason.Normal));
            }

            _clients.TryRemove(ipPort, out _);
            _clientsLastSeen.TryRemove(ipPort, out _);
            _clientsKicked.TryRemove(ipPort, out _);
            _clientsTimedout.TryRemove(ipPort, out _);

            if (client != null)
            {
                client.Dispose();
            }
        }
Esempio n. 3
0
        private async Task AcceptConnections()
        {
            while (!_listenerToken.IsCancellationRequested)
            {
                ClientMetadata client = null;

                try
                {
                    TcpClient tcpClient = await _listener.AcceptTcpClientAsync().ConfigureAwait(false);

                    string clientIp = tcpClient.Client.RemoteEndPoint.ToString();

                    client = new ClientMetadata(tcpClient);

                    if (_ssl)
                    {
                        if (_settings.AcceptInvalidCertificates)
                        {
                            client.SslStream = new SslStream(client.NetworkStream, false, new RemoteCertificateValidationCallback(AcceptCertificate));
                        }
                        else
                        {
                            client.SslStream = new SslStream(client.NetworkStream, false);
                        }

                        bool success = await StartTls(client).ConfigureAwait(false);

                        if (!success)
                        {
                            client.Dispose();
                            continue;
                        }
                    }

                    _clients.TryAdd(clientIp, client);
                    _clientsLastSeen.TryAdd(clientIp, DateTime.Now);
                    Logger?.Invoke($"{_header}starting data receiver for: {clientIp}");
                    _events.HandleClientConnected(this, new ConnectionEventArgs(clientIp));

                    if (_keepalive.EnableTcpKeepAlives)
                    {
                        EnableKeepalives(tcpClient);
                    }

                    CancellationTokenSource linkedCts = CancellationTokenSource.CreateLinkedTokenSource(client.Token, _token);
                    Task unawaited = Task.Run(() => DataReceiver(client), linkedCts.Token);
                }
                catch (Exception ex)
                {
                    if (ex is TaskCanceledException ||
                        ex is OperationCanceledException ||
                        ex is ObjectDisposedException ||
                        ex is InvalidOperationException)
                    {
                        _isListening = false;
                        if (client != null)
                        {
                            client.Dispose();
                        }
                        Logger?.Invoke($"{_header}stopped listening");
                        break;
                    }
                    else
                    {
                        if (client != null)
                        {
                            client.Dispose();
                        }
                        Logger?.Invoke($"{_header}exception while awaiting connections: {ex}");
                        continue;
                    }
                }
            }

            _isListening = false;
        }