Ejemplo n.º 1
0
        /// <summary>
        /// Event raise every heartbeat
        /// </summary>
        /// <param name="source"></param>
        /// <param name="e"></param>
        private static void Heartbeat(Object source, ElapsedEventArgs e)
        {
            IHubContext hub = GlobalHost.ConnectionManager.GetHubContext <DatabaseHub>();

            if (hub == null)
            {
                return;
            }

            Info("Running heartbeat ...");

            using (Module.Administration.DatabaseContext requester = new Module.Administration.DatabaseContext())
            {
                Debug("Ping all clients connected ...");

                foreach (ConnectionRecord connection in requester._Connection.Where(c => c.Allow && c.Status).ToList())
                {
                    try
                    {
                        Verbose($"Ping the client {connection}");
                        hub.Clients.Client(connection.ConnectionId).ping();
                    }
                    catch (System.Exception exception)
                    {
                        Exception("Unable to ping the client", exception);
                    }
                }

                Debug("Disconnect all clients without any updates since a while ...");

                foreach (ConnectionRecord connection in requester._Connection.Where(c => c.Allow && c.Status).ToList())
                {
                    if (connection.ConnectionLast < DateTime.Now.AddSeconds(-ConfigurationManager.ClientHubTimeout))
                    {
                        try
                        {
                            Info($"Disconnecting the client {connection} ...");
                            hub.Clients.Client(connection.ConnectionId).stop();
                            connection.Allow = false;
                            requester.SaveChanges();
                        }
                        catch (System.Exception exception)
                        {
                            Exception("Unable to disconnect the client", exception);
                        }
                    }
                }
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Launch the heartbeat of the application if it is enabled
        /// </summary>
        public static void StartHeartbeat()
        {
            // Start Heartbeat to disconnect client if no updated done since a while

            if (ConfigurationManager.HeartbeatDelay <= 0 || ConfigurationManager.ClientHubTimeout <= 0)
            {
                return;
            }

            Info($"Launching heartbeat every {ConfigurationManager.HeartbeatDelay} seconds and disconnect clients after {ConfigurationManager.ClientHubTimeout} seconds without response ...");

            // Disconnect all connections if no updates done since a while ...

            IHubContext hub = GlobalHost.ConnectionManager.GetHubContext <DatabaseHub>();

            using (Module.Administration.DatabaseContext requester = new Module.Administration.DatabaseContext())
                foreach (ConnectionRecord connection in requester._Connection.Where(c => c.Allow && c.Status).ToList())
                {
                    if (connection.ConnectionLast < DateTime.Now.AddSeconds(-ConfigurationManager.ClientHubTimeout))
                    {
                        try
                        {
                            Info($"Disconnecting the client {connection} ...");
                            if (hub != null)
                            {
                                hub.Clients.Client(connection.ConnectionId).stop();
                            }
                            connection.Allow = false;
                            requester.SaveChanges();
                        }
                        catch (System.Exception exception)
                        {
                            Exception("Unable to disconnect the client", exception);
                        }
                    }
                }

            // Run the heartbeat

            Debug("Starting heartbeat ...");
            Timer heartbeat = new Timer(ConfigurationManager.HeartbeatDelay * 1000);

            heartbeat.Elapsed += Heartbeat;
            heartbeat.Start();
        }
Ejemplo n.º 3
0
        /// <summary>
        /// The client tests if the server if up ... this call generally occurs on connection on an existing account!
        /// </summary>
        public void Ping()
        {
            try
            {
                DateTime now = DateTime.Now;

                Debug($"Ping from '{Context.ConnectionId}'");

                using (Module.Administration.DatabaseContext database = new Module.Administration.DatabaseContext())
                {
                    // receive the ping from the client

                    PingRecord existingPing = database._Ping.Find(Context.ConnectionId);
                    if (existingPing != null)
                    {
                        existingPing.Date = now;
                    }
                    else
                    {
                        database._Ping.Add(new PingRecord {
                            ConnectionId = Context.ConnectionId
                        });
                    }

                    // update the last connection time of the client

                    ConnectionRecord currentConnection = database._Connection.Find(Context.ConnectionId);
                    if (currentConnection != null)
                    {
                        currentConnection.ConnectionLast = now;
                    }

                    database.SaveChanges();
                }
            }
            catch (System.Exception ex)
            {
                Exception($"An exception occurs on pinging of the connection '{Context.ConnectionId}'", ex);
                Warn("This exception is ignored ... may be the connection was previously deleted or disconnected!");
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Check if the given user is already connected through hub
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public static bool IsAlreadyConnected(int userId)
        {
            // the user exists, check if it's already connected
            // In case of reloading page, the connection can't be disconnected as quick as expected ...

            IHubContext hub = GlobalHost.ConnectionManager.GetHubContext <DatabaseHub>();

            if (hub == null)
            {
                // no hub ... disconnect the user and go to the index page

                Common.Logger.LoggerManager.Instance.Info(MODULE, $"Cleaning up all connections for the user {userId} ...");

                using (Module.Administration.DatabaseContext database = new Module.Administration.DatabaseContext())
                {
                    ConnectionRecord currentConnection = database._Connection.FirstOrDefault(c => c.UserId == userId && c.Allow);
                    while (currentConnection != null)
                    {
                        Common.Logger.LoggerManager.Instance.Debug(MODULE, $"Connection {currentConnection} removed ...");
                        try { database._Connection.Remove(currentConnection); } catch { }
                        currentConnection = database._Connection.FirstOrDefault(c => c.UserId == userId && c.Allow);
                    }
                    database.SaveChanges();
                }

                return(false);
            }

            // DatabaseCommonContext is frequently open/close here to clean up the cache of the database (else the ping record is never updated) ...

            bool     alreadyConnected = true;
            DateTime pingDate         = DateTime.Now;
            int      count            = 0;

            while (count < ConfigurationManager.ConnectionMaxWaiting && alreadyConnected)
            {
                count++;

                ConnectionRecord currentConnection = null;

                using (Module.Administration.DatabaseContext database = new Module.Administration.DatabaseContext())
                    currentConnection = database._Connection.FirstOrDefault(c => c.UserId == userId && c.Allow);

                if (currentConnection != null && count < ConfigurationManager.ConnectionMaxWaiting)
                {
                    // Ping the client and wait 1 secondes to check if the client responses

                    if (count == 1)
                    {
                        Thread.Sleep(1000);
                        Common.Logger.LoggerManager.Instance.Debug(MODULE, $"Ping to '{currentConnection.ConnectionId}'");
                        hub.Clients.Client(currentConnection.ConnectionId).ping();
                    }

                    // Did the client answer to the ping ?

                    PingRecord currentPing = null;
                    using (Module.Administration.DatabaseContext database = new Module.Administration.DatabaseContext())
                        currentPing = database._Ping.Find(currentConnection.ConnectionId);

                    // The client has answered to the ping ... So, it already exists

                    if (currentPing != null && DateTime.Compare(currentPing.Date, pingDate) >= 0)
                    {
                        break;
                    }

                    // The client didn't answer ... wait a few more second

                    if (count > 1)
                    {
                        Thread.Sleep(1000);
                    }
                }
                else if (currentConnection != null)
                {
                    // The max seconds has expired ... it means that no client is already connected ... disconnect it

                    alreadyConnected = false;

                    try
                    {
                        hub.Clients.Client(currentConnection.ConnectionId).stop();
                        Common.Logger.LoggerManager.Instance.Info(MODULE, $"The connection '{currentConnection.ConnectionId}' is disconnected");
                    }
                    catch (System.Exception ex)
                    {
                        Common.Logger.LoggerManager.Instance.Exception(MODULE, $"(Warning) Unable to disconnect '{currentConnection.ConnectionId}' due to an exception", ex);
                    }

                    using (Module.Administration.DatabaseContext database = new Module.Administration.DatabaseContext())
                    {
                        currentConnection       = database._Connection.Find(currentConnection.ConnectionId);
                        currentConnection.Allow = false;
                        database.SaveChanges();
                    }
                }
                else
                {
                    alreadyConnected = false;
                    Common.Logger.LoggerManager.Instance.Info(MODULE, $"No connection already existing or the previous connection is disconnected ...");
                }
            }

            if (alreadyConnected)
            {
                Common.Logger.LoggerManager.Instance.Debug(MODULE, $"The user '{userId}' is already connected on another support");
                return(true);
            }

            return(false);
        }