예제 #1
0
        /// <summary>
        /// Adds a new connection to the list of tracked connections.
        /// </summary>
        /// <param name="connection">The connection to be added.</param>
        public bool AddConnection(ITrackingConnection connection)
        {
            var newMetadata = new ConnectionMetadata(connection);
            ConnectionMetadata oldMetadata = null;
            bool isNewConnection = true;

            _connections.AddOrUpdate(connection.ConnectionId, newMetadata, (key, old) =>
            {
                oldMetadata = old;
                return newMetadata;
            });

            if (oldMetadata != null)
            {
                // Kick out the older connection. This should only happen when
                // a previous connection attempt fails on the client side (e.g. transport fallback).
                oldMetadata.Connection.End();

                // If we have old metadata this isn't a new connection
                isNewConnection = false;
            }

            // Set the initial connection time
            newMetadata.Initial = DateTime.UtcNow;

            // Set the keep alive time
            newMetadata.UpdateKeepAlive(_configurationManager.KeepAlive);

            return isNewConnection;
        }
        /// <summary>
        /// Adds a new connection to the list of tracked connections.
        /// </summary>
        /// <param name="connection">The connection to be added.</param>
        public ITrackingConnection AddOrUpdateConnection(ITrackingConnection connection)
        {
            if (connection == null)
            {
                throw new ArgumentNullException("connection");
            }

            var newMetadata = new ConnectionMetadata(connection);
            bool isNewConnection = true;
            ITrackingConnection oldConnection = null;

            _connections.AddOrUpdate(connection.ConnectionId, newMetadata, (key, old) =>
            {
                Logger.LogVerbose(String.Format("Connection {0} exists. Closing previous connection.", old.Connection.ConnectionId));
                // Kick out the older connection. This should only happen when
                // a previous connection attempt fails on the client side (e.g. transport fallback).

                old.Connection.ApplyState(TransportConnectionStates.Replaced);

                // Don't bother disposing the registration here since the token source
                // gets disposed after the request has ended
                old.Connection.End();

                // If we have old metadata this isn't a new connection
                isNewConnection = false;
                oldConnection = old.Connection;

                return newMetadata;
            });

            if (isNewConnection)
            {
                Logger.LogInformation(String.Format("Connection {0} is New.", connection.ConnectionId));
                connection.IncrementConnectionsCount();
            }

            lock (_counterLock)
            {
                _counters.ConnectionsCurrent.RawValue = _connections.Count;
            }

            // Set the initial connection time
            newMetadata.Initial = DateTime.UtcNow;

            newMetadata.Connection.ApplyState(TransportConnectionStates.Added);

            return oldConnection;
        }
        /// <summary>
        /// Adds a new connection to the list of tracked connections.
        /// </summary>
        /// <param name="connection">The connection to be added.</param>
        public ITrackingConnection AddOrUpdateConnection(ITrackingConnection connection)
        {
            if (connection == null)
            {
                throw new ArgumentNullException("connection");
            }

            var  newMetadata     = new ConnectionMetadata(connection);
            bool isNewConnection = true;
            ITrackingConnection oldConnection = null;

            _connections.AddOrUpdate(connection.ConnectionId, newMetadata, (key, old) =>
            {
                Trace.TraceEvent(TraceEventType.Verbose, 0, "Connection {0} exists. Closing previous connection.", old.Connection.ConnectionId);
                // Kick out the older connection. This should only happen when
                // a previous connection attempt fails on the client side (e.g. transport fallback).

                old.Connection.ApplyState(TransportConnectionStates.Replaced);

                // Don't bother disposing the registration here since the token source
                // gets disposed after the request has ended
                old.Connection.End();

                // If we have old metadata this isn't a new connection
                isNewConnection = false;
                oldConnection   = old.Connection;

                return(newMetadata);
            });

            if (isNewConnection)
            {
                Trace.TraceInformation("Connection {0} is New.", connection.ConnectionId);
            }

            lock (_counterLock)
            {
                _counters.ConnectionsCurrent.RawValue = _connections.Count;
            }

            // Set the initial connection time
            newMetadata.Initial = DateTime.UtcNow;

            newMetadata.Connection.ApplyState(TransportConnectionStates.Added);

            return(oldConnection);
        }
예제 #4
0
        /// <summary>
        /// Adds a new connection to the list of tracked connections.
        /// </summary>
        /// <param name="connection">The connection to be added.</param>
        public bool AddConnection(ITrackingConnection connection)
        {
            if (connection == null)
            {
                throw new ArgumentNullException("connection");
            }

            var newMetadata = new ConnectionMetadata(connection);
            ConnectionMetadata oldMetadata = null;
            bool isNewConnection = true;

            _connections.AddOrUpdate(connection.ConnectionId, newMetadata, (key, old) =>
            {
                oldMetadata = old;
                return newMetadata;
            });

            if (oldMetadata != null)
            {
                Trace.TraceInformation("Connection exists. Closing previous connection. Old=({0}, {1}) New=({2})", oldMetadata.Connection.IsAlive, oldMetadata.Connection.Url, connection.Url);

                // Kick out the older connection. This should only happen when
                // a previous connection attempt fails on the client side (e.g. transport fallback).
                oldMetadata.Connection.End();

                // If we have old metadata this isn't a new connection
                isNewConnection = false;
            }
            else
            {
                Trace.TraceInformation("Connection is New=({0}).", connection.Url);
            }

            lock (_counterLock)
            {
                _counters.ConnectionsCurrent.RawValue = _connections.Count;
            }

            // Set the initial connection time
            newMetadata.Initial = DateTime.UtcNow;

            // Set the keep alive time
            newMetadata.UpdateKeepAlive(_configurationManager.KeepAlive);

            return isNewConnection;
        }
예제 #5
0
        private Task ProcessReceiveRequest(ITransportConnection connection)
        {
            Func <Task> initialize = null;

            // If this transport isn't replacing an existing transport, oldConnection will be null.
            ITrackingConnection oldConnection = Heartbeat.AddOrUpdateConnection(this);
            bool newConnection = oldConnection == null;

            if (IsConnectRequest)
            {
                Func <Task> connected;
                if (newConnection)
                {
                    connected = Connected ?? _emptyTaskFunc;
                    _counters.ConnectionsConnected.Increment();
                }
                else
                {
                    // Wait until the previous call to Connected completes.
                    // We don't want to call Connected twice
                    connected = () => oldConnection.ConnectTask;
                }

                initialize = () =>
                {
                    return(connected().Then((conn, id) => conn.Initialize(id), connection, ConnectionId));
                };
            }
            else
            {
                initialize = Reconnected;
            }

            var series = new Func <object, Task>[]
            {
                state => ((Func <Task>)state).Invoke(),
                state => ((Func <Task>)state).Invoke()
            };

            var states = new object[] { TransportConnected ?? _emptyTaskFunc,
                                        initialize ?? _emptyTaskFunc };

            Func <Task> fullInit = () => TaskAsyncHelper.Series(series, states).ContinueWith(_connectTcs);

            return(ProcessMessages(connection, fullInit));
        }
예제 #6
0
        /// <summary>
        /// Adds a new connection to the list of tracked connections.
        /// </summary>
        /// <param name="connection">The connection to be added.</param>
        public bool AddConnection(ITrackingConnection connection)
        {
            if (connection == null)
            {
                throw new ArgumentNullException("connection");
            }

            var newMetadata = new ConnectionMetadata(connection);
            ConnectionMetadata oldMetadata = null;
            bool isNewConnection           = true;

            _connections.AddOrUpdate(connection.ConnectionId, newMetadata, (key, old) =>
            {
                oldMetadata = old;
                return(newMetadata);
            });

            if (oldMetadata != null)
            {
                Trace.TraceInformation("Connection exists. Closing previous connection. Old=({0}, {1}) New=({2})", oldMetadata.Connection.IsAlive, oldMetadata.Connection.Url, connection.Url);

                // Kick out the older connection. This should only happen when
                // a previous connection attempt fails on the client side (e.g. transport fallback).
                oldMetadata.Connection.End();

                // If we have old metadata this isn't a new connection
                isNewConnection = false;
            }
            else
            {
                Trace.TraceInformation("Connection is New=({0}).", connection.Url);
            }

            lock (_counterLock)
            {
                _counters.ConnectionsCurrent.RawValue = _connections.Count;
            }

            // Set the initial connection time
            newMetadata.Initial = DateTime.UtcNow;

            // Set the keep alive time
            newMetadata.UpdateKeepAlive(_configurationManager.KeepAlive);

            return(isNewConnection);
        }
예제 #7
0
        /// <summary>
        /// Marks an existing connection as active.
        /// </summary>
        /// <param name="connection">The connection to mark.</param>
        public void MarkConnection(ITrackingConnection connection)
        {
            // See if there's an old metadata value
            ConnectionMetadata oldMetadata;

            _connectionMetadata.TryGetValue(connection, out oldMetadata);

            // Mark this time this connection was used
            var metadata = _connectionMetadata.GetOrAdd(connection, _ => new ConnectionMetadata());

            if (oldMetadata != null)
            {
                // Use the same initial time (if it exists)
                metadata.Initial = oldMetadata.Initial;
            }

            metadata.LastMarked = DateTime.UtcNow;
        }
예제 #8
0
        /// <summary>
        /// Marks an existing connection as active.
        /// </summary>
        /// <param name="connection">The connection to mark.</param>
        public void MarkConnection(ITrackingConnection connection)
        {
            if (connection == null)
            {
                throw new ArgumentNullException("connection");
            }

            // Do nothing if the connection isn't alive
            if (!connection.IsAlive)
            {
                return;
            }

            ConnectionMetadata metadata;

            if (_connections.TryGetValue(connection.ConnectionId, out metadata))
            {
                metadata.LastMarked = DateTime.UtcNow;
            }
        }
예제 #9
0
        /// <summary>
        /// Removes a connection from the list of tracked connections.
        /// </summary>
        /// <param name="connection">The connection to remove.</param>
        public void RemoveConnection(ITrackingConnection connection)
        {
            if (connection == null)
            {
                throw new ArgumentNullException("connection");
            }

            // Remove the connection and associated metadata
            ConnectionMetadata metadata;

            if (_connections.TryRemove(connection.ConnectionId, out metadata))
            {
                lock (_counterLock)
                {
                    _counters.ConnectionsCurrent.RawValue = _connections.Count;
                }

                connection.ApplyState(TransportConnectionStates.Removed);

                Trace.TraceInformation("Removing connection {0}", connection.ConnectionId);
            }
        }
예제 #10
0
        /// <summary>
        /// Adds a new connection to the list of tracked connections.
        /// </summary>
        /// <param name="connection">The connection to be added.</param>
        public bool AddConnection(ITrackingConnection connection)
        {
            _trace.Source.TraceInformation("TransportHeartBeat: Adding connection {0}", connection.ConnectionId);

            var newMetadata = new ConnectionMetadata(connection);
            ConnectionMetadata oldMetadata = null;
            bool isNewConnection = true;

            _connections.AddOrUpdate(connection.ConnectionId, newMetadata, (key, old) =>
            {
                oldMetadata = old;
                return newMetadata;
            });

            if (oldMetadata != null)
            {
                _trace.Source.TraceInformation("TransportHeartBeat: Connection {0} already exists and alive={1}. Closing previous connection id.", oldMetadata.Connection.ConnectionId, oldMetadata.Connection.IsAlive);

                // Kick out the older connection. This should only happen when
                // a previous connection attempt fails on the client side (e.g. transport fallback).
                oldMetadata.Connection.End();

                // If we have old metadata this isn't a new connection
                isNewConnection = false;
            }
            else
            {
                _trace.Source.TraceInformation("TransportHeartBeat: Connection {0} is new.", connection.ConnectionId);
            }

            // Set the initial connection time
            newMetadata.Initial = DateTime.UtcNow;

            // Set the keep alive time
            newMetadata.UpdateKeepAlive(_configurationManager.KeepAlive);

            return isNewConnection;
        }
예제 #11
0
        // This is an uber hack to make sure the db is in sync with SignalR
        private void EnsureClientConnected(ILogger logger, IJabbrRepository repo, ITrackingConnection connection)
        {
            var contextField = connection.GetType().GetField("_context",
                                          BindingFlags.NonPublic | BindingFlags.Instance);
            if (contextField == null)
            {
                return;
            }

            var context = contextField.GetValue(connection) as HostContext;

            if (context == null)
            {
                return;
            }

            string connectionData = context.Request.QueryString["connectionData"];

            if (String.IsNullOrEmpty(connectionData))
            {
                return;
            }

            var hubs = JsonConvert.DeserializeObject<HubConnectionData[]>(connectionData);

            if (hubs.Length != 1)
            {
                return;
            }

            // We only care about the chat hub
            if (!hubs[0].Name.Equals("chat", StringComparison.OrdinalIgnoreCase))
            {
                return;
            }

            logger.Log("Connection {0} exists but isn't tracked.", connection.ConnectionId);

            string userId = context.Request.User.GetUserId();

            ChatUser user = repo.GetUserById(userId);
            if (user == null)
            {
                logger.Log("Unable to find user with id {0}", userId);
                return;
            }

            var client = new ChatClient
            {
                Id = connection.ConnectionId,
                User = user,
                UserAgent = context.Request.Headers["User-Agent"],
                LastActivity = DateTimeOffset.UtcNow,
                LastClientActivity = user.LastActivity
            };

            repo.Add(client);
            repo.CommitChanges();
        }
예제 #12
0
 /// <summary>
 /// Removes a connection from the list of tracked connections.
 /// </summary>
 /// <param name="connection">The connection to remove.</param>
 public void RemoveConnection(ITrackingConnection connection)
 {
     // Remove the connection and associated metadata
     RemoveConnection(connection.ConnectionId);
 }
예제 #13
0
        // This is an uber hack to make sure the db is in sync with SignalR
        private void EnsureClientConnected(ILogger logger, IRepository <ChatUser> repo, IRepository <ChatClient> repoChatClient, ITrackingConnection connection)
        {
            var contextField = connection.GetType().GetField("_context",
                                                             BindingFlags.NonPublic | BindingFlags.Instance);

            if (contextField == null)
            {
                return;
            }

            var context = contextField.GetValue(connection) as HostContext;

            if (context == null)
            {
                return;
            }

            string connectionData = context.Request.QueryString["connectionData"];

            if (String.IsNullOrEmpty(connectionData))
            {
                return;
            }

            var hubs = JsonConvert.DeserializeObject <HubConnectionData[]>(connectionData);

            if (hubs.Length != 1)
            {
                return;
            }

            // We only care about the chat hub
            if (!hubs[0].Name.Equals("chat", StringComparison.OrdinalIgnoreCase))
            {
                return;
            }

            logger.Log("Connection {0} exists but isn't tracked.", connection.ConnectionId);

            string userId = context.Request.User.GetUserId();

            ChatUser user = repo.GetById(userId);

            if (user == null)
            {
                logger.Log("Unable to find user with id {0}", userId);
                return;
            }

            var client = new ChatClient
            {
                Id                 = connection.ConnectionId,
                User               = user,
                UserAgent          = context.Request.Headers["User-Agent"],
                LastActivity       = DateTimeOffset.UtcNow,
                LastClientActivity = user.LastActivity
            };

            repoChatClient.Insert(client);
        }
예제 #14
0
 public ConnectionMetadata(ITrackingConnection connection)
 {
     Connection = connection;
     Initial = DateTime.UtcNow;
     LastMarked = DateTime.UtcNow;
 }
예제 #15
0
        /// <summary>
        /// Marks an existing connection as active.
        /// </summary>
        /// <param name="connection">The connection to mark.</param>
        public void MarkConnection(ITrackingConnection connection)
        {
            if (connection == null)
            {
                throw new ArgumentNullException("connection");
            }

            // Do nothing if the connection isn't alive
            if (!connection.IsAlive)
            {
                return;
            }

            ConnectionMetadata metadata;
            if (_connections.TryGetValue(connection.ConnectionId, out metadata))
            {
                metadata.LastMarked = DateTime.UtcNow;
            }
        }
예제 #16
0
        /// <summary>
        /// Removes a connection from the list of tracked connections.
        /// </summary>
        /// <param name="connection">The connection to remove.</param>
        public void RemoveConnection(ITrackingConnection connection)
        {
            if (connection == null)
            {
                throw new ArgumentNullException("connection");
            }

            // Remove the connection and associated metadata
            ConnectionMetadata metadata;
            if (_connections.TryRemove(connection.ConnectionId, out metadata))
            {
                lock (_counterLock)
                {
                    _counters.ConnectionsCurrent.RawValue = _connections.Count;
                }

                connection.ApplyState(TransportConnectionStates.Removed);

                Trace.TraceInformation("Removing connection {0}", connection.ConnectionId);
            }
        }
예제 #17
0
 /// <summary>
 /// Removes a connection from the list of tracked connections.
 /// </summary>
 /// <param name="connection">The connection to remove.</param>
 public void RemoveConnection(ITrackingConnection connection)
 {
     // Remove the connection and associated metadata
     RemoveConnection(connection.ConnectionId);
 }
예제 #18
0
 /// <summary>
 /// Updates an existing connection and it's metadata.
 /// </summary>
 /// <param name="connection">The connection to be updated.</param>
 public void UpdateConnection(ITrackingConnection connection)
 {
     // Remove and re-add the connection so we have the correct object reference
     _connections.Remove(connection);
     _connections.Add(connection);
 }
예제 #19
0
        /// <summary>
        /// Removes a connection from the list of tracked connections.
        /// </summary>
        /// <param name="connection">The connection to remove.</param>
        public void RemoveConnection(ITrackingConnection connection)
        {
            if (connection == null)
            {
                throw new ArgumentNullException("connection");
            }

            // Remove the connection and associated metadata
            RemoveConnection(connection.ConnectionId);
        }
예제 #20
0
        /// <summary>
        /// Adds a new connection to the list of tracked connections.
        /// </summary>
        /// <param name="connection">The connection to be added.</param>
        public bool AddConnection(ITrackingConnection connection)
        {
            if (connection == null)
            {
                throw new ArgumentNullException("connection");
            }

            var newMetadata = new ConnectionMetadata(connection);
            ConnectionMetadata oldMetadata = null;
            bool isNewConnection = true;

            _connections.AddOrUpdate(connection.ConnectionId, newMetadata, (key, old) =>
            {
                oldMetadata = old;
                return newMetadata;
            });

            if (oldMetadata != null)
            {
                Trace.TraceInformation("Connection {0} exists. Closing previous connection.", oldMetadata.Connection.ConnectionId);

                // Kick out the older connection. This should only happen when
                // a previous connection attempt fails on the client side (e.g. transport fallback).

                // Don't bother disposing the registration here since the token source
                // gets disposed after the request has ended
                EndConnection(oldMetadata, disposeRegistration: false);

                // If we have old metadata this isn't a new connection
                isNewConnection = false;
            }
            else
            {
                Trace.TraceInformation("Connection {0} is New.", connection.ConnectionId);
            }

            lock (_counterLock)
            {
                _counters.ConnectionsCurrent.RawValue = _connections.Count;
            }

            // Set the initial connection time
            newMetadata.Initial = DateTime.UtcNow;

            // Register for disconnect cancellation
            newMetadata.Registration = connection.CancellationToken.SafeRegister(OnConnectionEnded, newMetadata);

            return isNewConnection;
        }
예제 #21
0
 public ConnectionMetadata(ITrackingConnection connection)
 {
     Connection = connection;
     Initial    = DateTime.UtcNow;
     LastMarked = DateTime.UtcNow;
 }
예제 #22
0
 /// <summary>
 /// Marks an existing connection as active.
 /// </summary>
 /// <param name="connection">The connection to mark.</param>
 public void MarkConnection(ITrackingConnection connection)
 {
     ConnectionMetadata metadata;
     if (_connections.TryGetValue(connection.ConnectionId, out metadata))
     {
         metadata.LastMarked = DateTime.UtcNow;
     }
 }