/// <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); }
/// <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; }
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)); }
/// <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); }
/// <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; }
/// <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; } }
/// <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); } }
/// <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; }
// 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(); }
/// <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); }
// 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); }
public ConnectionMetadata(ITrackingConnection connection) { Connection = connection; Initial = DateTime.UtcNow; LastMarked = DateTime.UtcNow; }
/// <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); }
/// <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); }
/// <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; }
/// <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; } }