aspnetcore/src/WebApplication95/ConnectionManager.cs

110 lines
3.1 KiB
C#

using System;
using System.Collections.Concurrent;
using System.Threading;
using Channels;
namespace WebApplication95
{
public class ConnectionManager
{
private ConcurrentDictionary<string, ConnectionState> _connections = new ConcurrentDictionary<string, ConnectionState>();
private Timer _timer;
public ConnectionManager()
{
_timer = new Timer(Scan, this, 0, 1000);
}
public bool TryGetConnection(string id, out ConnectionState state)
{
return _connections.TryGetValue(id, out state);
}
public ConnectionState ReserveConnection()
{
string id = MakeNewConnectionId();
// REVIEW: Should we create state for this?
var state = _connections.GetOrAdd(id, connectionId => new ConnectionState());
// Mark it as a reservation
state.Connection = new Connection
{
ConnectionId = id
};
return state;
}
public ConnectionState AddNewConnection(IChannel channel)
{
string id = MakeNewConnectionId();
var state = _connections.GetOrAdd(id, connectionId => new ConnectionState());
// If there's no connection object then it's a new connection
if (state.Connection == null)
{
state.Connection = new Connection
{
Channel = channel,
ConnectionId = id
};
}
// Update the last seen and mark the connection as active
state.LastSeen = DateTimeOffset.UtcNow;
state.Active = true;
return state;
}
public void MarkConnectionInactive(string id)
{
ConnectionState state;
if (_connections.TryGetValue(id, out state))
{
// Mark the connection as active so the background thread can look at it
state.Active = false;
}
}
public void RemoveConnection(string id)
{
ConnectionState state;
_connections.TryRemove(id, out state);
// Remove the connection completely
}
private static string MakeNewConnectionId()
{
// TODO: We need to sign and encyrpt this
return Guid.NewGuid().ToString();
}
private static void Scan(object state)
{
((ConnectionManager)state).Scan();
}
private void Scan()
{
// Scan the registered connections looking for ones that have timed out
foreach (var c in _connections)
{
if (!c.Value.Active && (DateTimeOffset.UtcNow - c.Value.LastSeen).TotalSeconds > 30)
{
ConnectionState s;
if (_connections.TryRemove(c.Key, out s))
{
s.Connection.Channel.Dispose();
}
else
{
}
}
}
}
}
}