sharp-chat/SharpChat.SockChat/SockChatConnectionsContext.cs

177 lines
5.8 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
namespace SharpChat.SockChat {
public class SockChatConnectionsContext {
public static readonly TimeSpan TimeOut = TimeSpan.FromMinutes(5);
private readonly HashSet<SockChatConnectionInfo> Connections = new();
private readonly HashSet<SockChatConnectionInfo> AuthedConnections = new();
private readonly Dictionary<long, HashSet<SockChatConnectionInfo>> UserConnections = new();
public SockChatConnectionInfo[] All => Connections.ToArray();
public SockChatConnectionInfo[] Authed => AuthedConnections.ToArray();
public void WithAll(Action<SockChatConnectionInfo> body) {
foreach(SockChatConnectionInfo conn in Connections)
body(conn);
}
public void WithAuthed(Action<SockChatConnectionInfo> body) {
foreach(SockChatConnectionInfo conn in AuthedConnections)
body(conn);
}
public SockChatConnectionInfo[] GetTimedOut() {
List<SockChatConnectionInfo> conns = new();
foreach(SockChatConnectionInfo conn in Connections)
if(DateTimeOffset.UtcNow - conn.LastPing > TimeOut)
conns.Add(conn);
return conns.ToArray();
}
public int GetCountForUser(long userId) {
return UserConnections.ContainsKey(userId) ? UserConnections.Count : 0;
}
public int GetCountForUser(UserInfo userInfo) {
return GetCountForUser(userInfo.UserId);
}
public bool HasUser(long userId) {
return GetCountForUser(userId) > 0;
}
public bool HasUser(UserInfo userInfo) {
return HasUser(userInfo.UserId);
}
public SockChatConnectionInfo[] GetUser(long userId) {
if(!UserConnections.ContainsKey(userId))
return Array.Empty<SockChatConnectionInfo>();
return UserConnections[userId].ToArray();
}
public SockChatConnectionInfo[] GetUser(UserInfo userInfo) {
return GetUser(userInfo.UserId);
}
public void WithUser(long userId, Action<SockChatConnectionInfo> body) {
if(!UserConnections.ContainsKey(userId))
return;
foreach(SockChatConnectionInfo conn in UserConnections[userId])
body(conn);
}
public void WithUser(UserInfo userInfo, Action<SockChatConnectionInfo> body) {
WithUser(userInfo.UserId, body);
}
public string[] GetAllRemoteAddresses() {
HashSet<string> addrs = new();
foreach(SockChatConnectionInfo conn in Connections)
addrs.Add(conn.RemoteAddress);
return addrs.ToArray();
}
public string[] GetAuthedRemoteAddresses() {
HashSet<string> addrs = new();
foreach(SockChatConnectionInfo conn in AuthedConnections)
addrs.Add(conn.RemoteAddress);
return addrs.ToArray();
}
public string[] GetUserRemoteAddresses(long userId) {
if(!UserConnections.ContainsKey(userId))
return Array.Empty<string>();
HashSet<string> addrs = new();
foreach(SockChatConnectionInfo conn in UserConnections[userId])
addrs.Add(conn.RemoteAddress);
return addrs.ToArray();
}
public string[] GetUserRemoteAddresses(UserInfo userInfo) {
return GetUserRemoteAddresses(userInfo.UserId);
}
public void Add(SockChatConnectionInfo conn) {
if(Connections.Contains(conn))
return;
Connections.Add(conn);
if(conn.UserId > 0) {
AuthedConnections.Add(conn);
if(UserConnections.ContainsKey(conn.UserId))
UserConnections[conn.UserId].Add(conn);
else
UserConnections.Add(conn.UserId, new() { conn });
}
}
public void Remove(SockChatConnectionInfo conn) {
if(Connections.Contains(conn))
Connections.Remove(conn);
if(AuthedConnections.Contains(conn))
AuthedConnections.Remove(conn);
if(conn.UserId > 0 && UserConnections.ContainsKey(conn.UserId)) {
UserConnections[conn.UserId].Remove(conn);
if(UserConnections[conn.UserId].Count < 1)
UserConnections.Remove(conn.UserId);
}
}
public void SetUser(SockChatConnectionInfo conn, long userId) {
if(!Connections.Contains(conn))
return;
// so yeah this is implemented but SetUserId will throw an exception if we're trying to re-auth a connection
// will just leave this here but i'm not sure how to go forward with this
if(conn.UserId > 0) {
if(UserConnections[conn.UserId].Contains(conn))
UserConnections[conn.UserId].Remove(conn);
if(UserConnections[conn.UserId].Count < 1)
UserConnections.Remove(conn.UserId);
}
conn.SetUserId(userId);
if(conn.UserId > 0) {
if(UserConnections.ContainsKey(conn.UserId))
UserConnections[conn.UserId].Add(conn);
else
UserConnections.Add(conn.UserId, new() { conn });
}
if(conn.UserId > 0) {
if(!AuthedConnections.Contains(conn))
AuthedConnections.Add(conn);
} else {
if(AuthedConnections.Contains(conn))
AuthedConnections.Remove(conn);
}
}
public void SetUser(SockChatConnectionInfo conn, UserInfo userInfo) {
SetUser(conn, userInfo.UserId);
}
}
}