Exemplo n.º 1
0
        private async Task <bool> StartTls(ClientMetadata client)
        {
            try
            {
                // the two bools in this should really be contruction paramaters
                // maybe re-use mutualAuthentication and acceptInvalidCerts ?
                await client.SslStream.AuthenticateAsServerAsync(_SslCertificate, true, SslProtocols.Tls12, false);

                if (!client.SslStream.IsEncrypted)
                {
                    Log("*** StartTls stream from " + client.IpPort + " not encrypted");
                    client.Dispose();
                    return(false);
                }

                if (!client.SslStream.IsAuthenticated)
                {
                    Log("*** StartTls stream from " + client.IpPort + " not authenticated");
                    client.Dispose();
                    return(false);
                }

                if (_MutuallyAuthenticate && !client.SslStream.IsMutuallyAuthenticated)
                {
                    Log("*** StartTls stream from " + client.IpPort + " failed mutual authentication");
                    client.Dispose();
                    return(false);
                }
            }
            catch (IOException ex)
            {
                // Some type of problem initiating the SSL connection
                switch (ex.Message)
                {
                case "Authentication failed because the remote party has closed the transport stream.":
                case "Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.":
                    Log("*** StartTls IOException " + client.IpPort + " closed the connection.");
                    break;

                case "The handshake failed due to an unexpected packet format.":
                    Log("*** StartTls IOException " + client.IpPort + " disconnected, invalid handshake.");
                    break;

                default:
                    Log("*** StartTls IOException from " + client.IpPort + Environment.NewLine + ex.ToString());
                    break;
                }

                client.Dispose();
                return(false);
            }
            catch (Exception ex)
            {
                Log("*** StartTls Exception from " + client.IpPort + Environment.NewLine + ex.ToString());
                client.Dispose();
                return(false);
            }

            return(true);
        }
Exemplo n.º 2
0
        private void FinalizeConnection(ClientMetadata client)
        {
            #region Add-to-Client-List

            if (!AddClient(client))
            {
                Log("*** FinalizeConnection unable to add client " + client.IpPort);
                client.Dispose();
                return;
            }

            // Do not decrement in this block, decrement is done by the connection reader
            int activeCount = Interlocked.Increment(ref _ActiveClients);

            #endregion

            #region Start-Data-Receiver

            Log("*** FinalizeConnection starting data receiver for " + client.IpPort + " (now " + activeCount + " clients)");
            if (_ClientConnected != null)
            {
                Task.Run(() => _ClientConnected(client.IpPort));
            }

            Task.Run(async() => await DataReceiver(client));

            #endregion
        }
Exemplo n.º 3
0
        private async Task DataReceiver(ClientMetadata client)
        {
            try
            {
                #region Wait-for-Data

                while (true)
                {
                    try
                    {
                        if (!IsConnected(client))
                        {
                            break;
                        }

                        byte[] data = await MessageReadAsync(client);

                        if (data == null)
                        {
                            // no message available
                            await Task.Delay(30);

                            continue;
                        }

                        if (_MessageReceived != null)
                        {
                            Task <bool> unawaited = Task.Run(() => _MessageReceived(client.IpPort, data));
                        }
                    }
                    catch (Exception)
                    {
                        break;
                    }
                }

                #endregion
            }
            finally
            {
                int activeCount = Interlocked.Decrement(ref _ActiveClients);
                RemoveClient(client);
                if (_ClientDisconnected != null)
                {
                    Task <bool> unawaited = Task.Run(() => _ClientDisconnected(client.IpPort));
                }
                Log("*** DataReceiver client " + client.IpPort + " disconnected (now " + activeCount + " clients active)");

                client.Dispose();
            }
        }
Exemplo n.º 4
0
        private void FinalizeConnection(ClientMetadata client)
        {
            #region Add-to-Client-List

            if (!AddClient(client))
            {
                Log("*** FinalizeConnection unable to add client " + client.IpPort);
                client.Dispose();
                return;
            }

            // Do not decrement in this block, decrement is done by the connection reader
            int activeCount = Interlocked.Increment(ref _ActiveClients);

            #endregion

            #region Request-Authentication

            if (!String.IsNullOrEmpty(PresharedKey))
            {
                Log("*** FinalizeConnection soliciting authentication material from " + client.IpPort);
                _UnauthenticatedClients.TryAdd(client.IpPort, DateTime.Now);

                byte[]        data    = Encoding.UTF8.GetBytes("Authentication required");
                WatsonMessage authMsg = new WatsonMessage();
                authMsg.Status        = MessageStatus.AuthRequired;
                authMsg.Data          = null;
                authMsg.ContentLength = 0;
                MessageWrite(client, authMsg, null);
            }

            #endregion

            #region Start-Data-Receiver

            Log("*** FinalizeConnection starting data receiver for " + client.IpPort + " (now " + activeCount + " clients)");
            if (ClientConnected != null)
            {
                Task.Run(() => ClientConnected(client.IpPort));
            }

            Task.Run(async() => await DataReceiver(client));

            #endregion
        }
Exemplo n.º 5
0
        private async Task DataReceiver(ClientMetadata client, CancellationToken token)
        {
            string header = "[" + client.IpPort + "]";

            while (true)
            {
                try
                {
                    token.ThrowIfCancellationRequested();

                    if (!IsConnected(client))
                    {
                        break;
                    }

                    WatsonMessage msg          = null;
                    bool          buildSuccess = false;

                    if (_Mode == Mode.Ssl)
                    {
                        msg = new WatsonMessage(client.SslStream, Debug);
                    }
                    else if (_Mode == Mode.Tcp)
                    {
                        msg = new WatsonMessage(client.NetworkStream, Debug);
                    }

                    if (_MessageReceived != null)
                    {
                        buildSuccess = await msg.Build();
                    }
                    else if (_StreamReceived != null)
                    {
                        buildSuccess = await msg.BuildStream();
                    }
                    else
                    {
                        break;
                    }

                    if (!buildSuccess)
                    {
                        break;
                    }

                    if (msg == null)
                    {
                        // no message available
                        await Task.Delay(30);

                        continue;
                    }

                    if (!String.IsNullOrEmpty(PresharedKey))
                    {
                        if (_UnauthenticatedClients.ContainsKey(client.IpPort))
                        {
                            Log(header + " message received from unauthenticated endpoint");

                            if (msg.Status == MessageStatus.AuthRequested)
                            {
                                // check preshared key
                                if (msg.PresharedKey != null && msg.PresharedKey.Length > 0)
                                {
                                    string clientPsk = Encoding.UTF8.GetString(msg.PresharedKey).Trim();
                                    if (PresharedKey.Trim().Equals(clientPsk))
                                    {
                                        Log(header + " accepted authentication");
                                        _UnauthenticatedClients.TryRemove(client.IpPort, out DateTime dt);
                                        byte[]        data    = Encoding.UTF8.GetBytes("Authentication successful");
                                        WatsonMessage authMsg = new WatsonMessage(data, Debug);
                                        authMsg.Status = MessageStatus.AuthSuccess;
                                        MessageWrite(client, authMsg, null);
                                        continue;
                                    }
                                    else
                                    {
                                        Log(header + " declined authentication");
                                        byte[]        data    = Encoding.UTF8.GetBytes("Authentication declined");
                                        WatsonMessage authMsg = new WatsonMessage(data, Debug);
                                        authMsg.Status = MessageStatus.AuthFailure;
                                        MessageWrite(client, authMsg, null);
                                        continue;
                                    }
                                }
                                else
                                {
                                    Log(header + " no authentication material");
                                    byte[]        data    = Encoding.UTF8.GetBytes("No authentication material");
                                    WatsonMessage authMsg = new WatsonMessage(data, Debug);
                                    authMsg.Status = MessageStatus.AuthFailure;
                                    MessageWrite(client, authMsg, null);
                                    continue;
                                }
                            }
                            else
                            {
                                // decline the message
                                Log(header + " no authentication material");
                                byte[]        data    = Encoding.UTF8.GetBytes("Authentication required");
                                WatsonMessage authMsg = new WatsonMessage(data, Debug);
                                authMsg.Status = MessageStatus.AuthRequired;
                                MessageWrite(client, authMsg, null);
                                continue;
                            }
                        }
                    }

                    if (msg.Status == MessageStatus.Disconnecting)
                    {
                        Log(header + " sent notification of disconnection");
                        break;
                    }

                    if (msg.Status == MessageStatus.Removed)
                    {
                        Log(header + " sent notification of removal");
                        break;
                    }

                    if (_MessageReceived != null)
                    {
                        // does not need to be awaited, because the stream has been fully read
                        Task unawaited = Task.Run(() => _MessageReceived(client.IpPort, msg.Data));
                    }
                    else if (_StreamReceived != null)
                    {
                        // must be awaited, the stream has not been fully read
                        await _StreamReceived(client.IpPort, msg.ContentLength, msg.DataStream);
                    }
                    else
                    {
                        break;
                    }

                    UpdateClientLastSeen(client.IpPort);
                }
                catch (Exception e)
                {
                    Log(Environment.NewLine +
                        "[" + client.IpPort + "] Data receiver exception:" +
                        Environment.NewLine +
                        e.ToString() +
                        Environment.NewLine);
                    break;
                }
            }

            Log(header + " data receiver terminated");

            if (ClientDisconnected != null)
            {
                Task unawaited = null;

                if (_ClientsKicked.ContainsKey(client.IpPort))
                {
                    unawaited = Task.Run(() => ClientDisconnected(client.IpPort, DisconnectReason.Kicked));
                }
                else if (_ClientsTimedout.ContainsKey(client.IpPort))
                {
                    unawaited = Task.Run(() => ClientDisconnected(client.IpPort, DisconnectReason.Timeout));
                }
                else
                {
                    unawaited = Task.Run(() => ClientDisconnected(client.IpPort, DisconnectReason.Normal));
                }
            }

            DateTime removedTs;

            _Clients.TryRemove(client.IpPort, out ClientMetadata removedClient);
            _ClientsLastSeen.TryRemove(client.IpPort, out removedTs);
            _ClientsKicked.TryRemove(client.IpPort, out removedTs);
            _ClientsTimedout.TryRemove(client.IpPort, out removedTs);
            _UnauthenticatedClients.TryRemove(client.IpPort, out removedTs);

            Log(header + " disposing");
            client.Dispose();
        }
Exemplo n.º 6
0
        private async Task DataReceiver(ClientMetadata client)
        {
            try
            {
                #region Wait-for-Data

                while (true)
                {
                    try
                    {
                        if (!IsConnected(client))
                        {
                            break;
                        }

                        WatsonMessage msg = await MessageReadAsync(client);

                        if (msg == null)
                        {
                            // no message available
                            await Task.Delay(30);

                            continue;
                        }

                        if (!String.IsNullOrEmpty(PresharedKey))
                        {
                            if (_UnauthenticatedClients.ContainsKey(client.IpPort))
                            {
                                Log("*** DataReceiver message received from unauthenticated endpoint: " + client.IpPort);

                                if (msg.Status == MessageStatus.AuthRequested)
                                {
                                    // check preshared key
                                    if (msg.PresharedKey != null && msg.PresharedKey.Length > 0)
                                    {
                                        string clientPsk = Encoding.UTF8.GetString(msg.PresharedKey).Trim();
                                        if (PresharedKey.Trim().Equals(clientPsk))
                                        {
                                            if (Debug)
                                            {
                                                Log("DataReceiver accepted authentication from " + client.IpPort);
                                            }
                                            _UnauthenticatedClients.TryRemove(client.IpPort, out DateTime dt);
                                            byte[]        data    = Encoding.UTF8.GetBytes("Authentication successful");
                                            WatsonMessage authMsg = new WatsonMessage(data, Debug);
                                            authMsg.Status = MessageStatus.AuthSuccess;
                                            MessageWrite(client, authMsg, null);
                                            continue;
                                        }
                                        else
                                        {
                                            if (Debug)
                                            {
                                                Log("DataReceiver declined authentication from " + client.IpPort);
                                            }
                                            byte[]        data    = Encoding.UTF8.GetBytes("Authentication declined");
                                            WatsonMessage authMsg = new WatsonMessage(data, Debug);
                                            authMsg.Status = MessageStatus.AuthFailure;
                                            MessageWrite(client, authMsg, null);
                                            continue;
                                        }
                                    }
                                    else
                                    {
                                        if (Debug)
                                        {
                                            Log("DataReceiver no authentication material from " + client.IpPort);
                                        }
                                        byte[]        data    = Encoding.UTF8.GetBytes("No authentication material");
                                        WatsonMessage authMsg = new WatsonMessage(data, Debug);
                                        authMsg.Status = MessageStatus.AuthFailure;
                                        MessageWrite(client, authMsg, null);
                                        continue;
                                    }
                                }
                                else
                                {
                                    // decline the message
                                    if (Debug)
                                    {
                                        Log("DataReceiver no authentication material from " + client.IpPort);
                                    }
                                    byte[]        data    = Encoding.UTF8.GetBytes("Authentication required");
                                    WatsonMessage authMsg = new WatsonMessage(data, Debug);
                                    authMsg.Status = MessageStatus.AuthRequired;
                                    MessageWrite(client, authMsg, null);
                                    continue;
                                }
                            }
                        }

                        if (ReadDataStream)
                        {
                            if (MessageReceived != null)
                            {
                                Task <bool> unawaited = Task.Run(() => MessageReceived(client.IpPort, msg.Data));
                            }
                        }
                        else
                        {
                            if (StreamReceived != null)
                            {
                                StreamReceived(client.IpPort, msg.ContentLength, msg.DataStream);
                            }
                        }
                    }
                    catch (Exception)
                    {
                        break;
                    }
                }

                #endregion
            }
            finally
            {
                int activeCount = Interlocked.Decrement(ref _ActiveClients);
                RemoveClient(client);

                if (ClientDisconnected != null)
                {
                    Task <bool> unawaited = Task.Run(() => ClientDisconnected(client.IpPort));
                }

                Log("*** DataReceiver client " + client.IpPort + " disconnected (now " + activeCount + " clients active)");
                client.Dispose();
            }
        }