Esempio n. 1
0
        /// <summary>
        /// Get direct access to the underlying client stream.
        /// </summary>
        /// <param name="ipPort">The client IP:port string.</param>
        /// <returns>Stream.</returns>
        public Stream GetStream(string ipPort)
        {
            if (String.IsNullOrEmpty(ipPort))
            {
                throw new ArgumentNullException(nameof(ipPort));
            }

            ClientMetadata client = null;

            lock (_ClientsLock)
            {
                if (!_Clients.ContainsKey(ipPort))
                {
                    throw new KeyNotFoundException("Client with IP:port of " + ipPort + " not found.");
                }

                client = _Clients[ipPort];
            }

            if (!_Ssl)
            {
                return(client.NetworkStream);
            }
            else
            {
                return(client.SslStream);
            }
        }
Esempio n. 2
0
        private void ClientConnectionMonitor(ClientMetadata client)
        {
            string ipPort = client.IpPort;

            while (true)
            {
                Task.Delay(1000).Wait();

                if (client == null || client.Client == null || !IsClientConnected(client.Client))
                {
                    Logger?.Invoke(_Header + "Client " + ipPort + " no longer connected");
                    DisconnectClient(ipPort);
                    break;
                }
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Disconnects the specified client.
        /// </summary>
        /// <param name="ipPort">IP:port of the client.</param>
        public void DisconnectClient(string ipPort)
        {
            if (String.IsNullOrEmpty(ipPort))
            {
                throw new ArgumentNullException(nameof(ipPort));
            }

            lock (_ClientsLock)
            {
                if (_Clients.ContainsKey(ipPort))
                {
                    ClientMetadata client = _Clients[ipPort];
                    client.Dispose();
                    _Clients.Remove(ipPort);
                }

                Logger?.Invoke(_Header + "Removed: " + ipPort);
            }

            ClientDisconnected?.Invoke(this, new ClientDisconnectedEventArgs(ipPort, DisconnectReason.Kicked));
        }
Esempio n. 4
0
        private async Task <bool> StartTls(ClientMetadata client)
        {
            try
            {
                await client.SslStream.AuthenticateAsServerAsync(
                    _SslCertificate,
                    MutuallyAuthenticate,
                    SslProtocols.Tls12,
                    !AcceptInvalidCertificates);

                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 (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.ToString());
                client.Dispose();
                return(false);
            }

            return(true);
        }
Esempio n. 5
0
        private async Task <ReadResult> ReadInternalAsync(string ipPort, long count)
        {
            if (count < 1)
            {
                return(new ReadResult(ReadResultStatus.Success, 0, null));
            }

            ClientMetadata client = null;

            lock (_ClientsLock)
            {
                if (!_Clients.ContainsKey(ipPort))
                {
                    return(new ReadResult(ReadResultStatus.ClientNotFound, 0, null));
                }

                client = _Clients[ipPort];
            }

            ReadResult result = new ReadResult(ReadResultStatus.Success, 0, null);

            try
            {
                await client.ReadSemaphore.WaitAsync(1);

                MemoryStream ms             = new MemoryStream();
                long         bytesRemaining = count;

                while (bytesRemaining > 0)
                {
                    byte[] buffer = null;
                    if (bytesRemaining >= _StreamBufferSize)
                    {
                        buffer = new byte[_StreamBufferSize];
                    }
                    else
                    {
                        buffer = new byte[bytesRemaining];
                    }

                    int bytesRead = 0;
                    if (!_Ssl)
                    {
                        bytesRead = await client.NetworkStream.ReadAsync(buffer, 0, buffer.Length);
                    }
                    else
                    {
                        bytesRead = await client.SslStream.ReadAsync(buffer, 0, buffer.Length);
                    }

                    if (bytesRead > 0)
                    {
                        if (bytesRead == buffer.Length)
                        {
                            await ms.WriteAsync(buffer, 0, buffer.Length);
                        }
                        else
                        {
                            await ms.WriteAsync(buffer, 0, bytesRead);
                        }

                        result.BytesRead    += bytesRead;
                        Stats.ReceivedBytes += bytesRead;
                        bytesRemaining      -= bytesRead;
                    }
                }

                ms.Seek(0, SeekOrigin.Begin);
                result.DataStream = ms;
                return(result);
            }
            catch (Exception)
            {
                result.Status     = ReadResultStatus.Disconnected;
                result.BytesRead  = 0;
                result.DataStream = null;
                return(result);
            }
            finally
            {
                client.ReadSemaphore.Release();
            }
        }
Esempio n. 6
0
        private async Task <WriteResult> SendInternalAsync(string ipPort, long contentLength, Stream stream)
        {
            ClientMetadata client = null;

            lock (_ClientsLock)
            {
                if (!_Clients.ContainsKey(ipPort))
                {
                    return(new WriteResult(WriteResultStatus.ClientNotFound, 0));
                }

                client = _Clients[ipPort];
            }

            WriteResult result = new WriteResult(WriteResultStatus.Success, 0);

            try
            {
                client.WriteSemaphore.Wait(1);

                if (contentLength > 0 && stream != null && stream.CanRead)
                {
                    long bytesRemaining = contentLength;

                    while (bytesRemaining > 0)
                    {
                        byte[] buffer    = new byte[_StreamBufferSize];
                        int    bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);

                        if (bytesRead > 0)
                        {
                            byte[] data = null;
                            if (bytesRead == buffer.Length)
                            {
                                data = new byte[buffer.Length];
                                Buffer.BlockCopy(buffer, 0, data, 0, buffer.Length);
                            }
                            else
                            {
                                data = new byte[bytesRead];
                                Buffer.BlockCopy(buffer, 0, data, 0, bytesRead);
                            }

                            if (!_Ssl)
                            {
                                await client.NetworkStream.WriteAsync(data, 0, data.Length);

                                await client.NetworkStream.FlushAsync();
                            }
                            else
                            {
                                await client.SslStream.WriteAsync(data, 0, data.Length);

                                await client.SslStream.FlushAsync();
                            }

                            result.BytesWritten += bytesRead;
                            Stats.SentBytes     += bytesRead;
                            bytesRemaining      -= bytesRead;
                        }
                    }
                }

                return(result);
            }
            catch (Exception)
            {
                result.Status = WriteResultStatus.Disconnected;
                return(result);
            }
            finally
            {
                client.WriteSemaphore.Release();
            }
        }
Esempio n. 7
0
        private async void AcceptConnections()
        {
            while (!_Token.IsCancellationRequested)
            {
                ClientMetadata client = null;

                try
                {
                    System.Net.Sockets.TcpClient tcpClient = await _Listener.AcceptTcpClientAsync();

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

                    client = new ClientMetadata(tcpClient);

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

                        bool success = await StartTls(client);

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

                    lock (_Clients)
                    {
                        _Clients.Add(clientIp, client);
                    }

                    Logger?.Invoke("Starting connection monitor for: " + clientIp);
                    Task unawaited = Task.Run(() => ClientConnectionMonitor(client), client.Token);
                    ClientConnected?.Invoke(this, new ClientConnectedEventArgs(clientIp));
                }
                catch (OperationCanceledException)
                {
                    return;
                }
                catch (ObjectDisposedException)
                {
                    if (client != null)
                    {
                        client.Dispose();
                    }
                    continue;
                }
                catch (Exception e)
                {
                    if (client != null)
                    {
                        client.Dispose();
                    }
                    Logger?.Invoke(_Header + "Exception while awaiting connections: " + e.ToString());
                    continue;
                }
            }

            _IsListening = false;
        }