Significantly less stupid connection resolving.

This commit is contained in:
flash 2023-02-17 23:17:24 +01:00
parent 546e8a2c83
commit 70df99fe9b
5 changed files with 39 additions and 66 deletions

View file

@ -15,29 +15,15 @@ namespace SharpChat {
public IWebSocketConnection Socket { get; }
public string Id { get; private set; }
public string Id { get; }
public bool IsDisposed { get; private set; }
public DateTimeOffset LastPing { get; set; } = DateTimeOffset.Now;
public ChatUser User { get; set; }
private int CloseCode { get; set; } = 1000;
private IPAddress _RemoteAddress = null;
public IPAddress RemoteAddress {
get {
if(_RemoteAddress == null) {
if((Socket.ConnectionInfo.ClientIpAddress == "127.0.0.1" || Socket.ConnectionInfo.ClientIpAddress == "::1")
&& Socket.ConnectionInfo.Headers.ContainsKey("X-Real-IP"))
_RemoteAddress = IPAddress.Parse(Socket.ConnectionInfo.Headers["X-Real-IP"]);
else
_RemoteAddress = IPAddress.Parse(Socket.ConnectionInfo.ClientIpAddress);
}
return _RemoteAddress;
}
}
public IPAddress RemoteAddress { get; }
public ushort RemotePort { get; }
public bool IsAlive => !IsDisposed && !HasTimedOut;
@ -46,6 +32,17 @@ namespace SharpChat {
public ChatConnection(IWebSocketConnection sock) {
Socket = sock;
Id = RNG.SecureRandomString(ID_LENGTH);
if(!IPAddress.TryParse(sock.ConnectionInfo.ClientIpAddress, out IPAddress addr))
throw new Exception("Unable to parse remote address?????");
if(IPAddress.IsLoopback(addr)
&& sock.ConnectionInfo.Headers.ContainsKey("X-Real-IP")
&& IPAddress.TryParse(sock.ConnectionInfo.Headers["X-Real-IP"], out IPAddress realAddr))
addr = realAddr;
RemoteAddress = addr;
RemotePort = (ushort)sock.ConnectionInfo.ClientPort;
}
public void Send(IServerPacket packet) {
@ -88,6 +85,10 @@ namespace SharpChat {
Socket.Close(CloseCode);
}
public override string ToString() {
return Id;
}
public override int GetHashCode() {
return Id.GetHashCode();
}

View file

@ -49,10 +49,6 @@ namespace SharpChat {
}
}
public ChatConnection GetConnection(IWebSocketConnection sock) {
return Connections.FirstOrDefault(s => s.Socket == sock);
}
public bool IsInChannel(ChatUser user, ChatChannel channel) {
lock(ChannelUsersAccess)
return ChannelUsers.Contains(new ChannelUserAssoc(user.UserId, channel.Name));

View file

@ -4,6 +4,10 @@ using System.Text;
namespace SharpChat {
public class ChatUser : IEquatable<ChatUser> {
public const int DEFAULT_SIZE = 30;
public const int DEFAULT_MINIMUM_DELAY = 10000;
public const int DEFAULT_RISKY_OFFSET = 5;
private const int RANK_NO_FLOOD = 9;
public long UserId { get; set; }
@ -18,7 +22,7 @@ namespace SharpChat {
public bool HasFloodProtection
=> Rank < RANK_NO_FLOOD;
public readonly RateLimiter RateLimiter = new();
public readonly RateLimiter RateLimiter = new(DEFAULT_SIZE, DEFAULT_MINIMUM_DELAY, DEFAULT_RISKY_OFFSET);
// This needs to be a session thing
public ChatChannel CurrentChannel { get; set; }

View file

@ -2,20 +2,12 @@
namespace SharpChat {
public class RateLimiter {
public const int DEFAULT_SIZE = 30;
public const int DEFAULT_MINIMUM_DELAY = 10000;
public const int DEFAULT_RISKY_OFFSET = 5;
private readonly int Size;
private readonly int MinimumDelay;
private readonly int RiskyOffset;
private readonly long[] TimePoints;
public RateLimiter(
int size = DEFAULT_SIZE,
int minDelay = DEFAULT_MINIMUM_DELAY,
int riskyOffset = DEFAULT_RISKY_OFFSET
) {
public RateLimiter(int size, int minDelay, int riskyOffset) {
if(size < 2)
throw new ArgumentException("Size is too small.", nameof(size));
if(minDelay < 1000)

View file

@ -120,34 +120,29 @@ namespace SharpChat {
return;
}
sock.OnOpen = () => OnOpen(sock);
sock.OnClose = () => OnClose(sock);
sock.OnError = err => OnError(sock, err);
sock.OnMessage = msg => OnMessage(sock, msg);
ChatConnection conn;
lock(Context.ConnectionsAccess)
Context.Connections.Add(conn = new(sock));
sock.OnOpen = () => OnOpen(conn);
sock.OnClose = () => OnClose(conn);
sock.OnError = err => OnError(conn, err);
sock.OnMessage = msg => OnMessage(conn, msg);
});
Logger.Write("Listening...");
}
private void OnOpen(IWebSocketConnection sock) {
Logger.Write($"Connection opened from {sock.ConnectionInfo.ClientIpAddress}:{sock.ConnectionInfo.ClientPort}");
lock(Context.ConnectionsAccess) {
if(!Context.Connections.Any(x => x.Socket == sock))
Context.Connections.Add(new ChatConnection(sock));
}
private void OnOpen(ChatConnection conn) {
Logger.Write($"Connection opened from {conn.RemoteAddress}:{conn.RemotePort}");
Context.Update();
}
private void OnClose(IWebSocketConnection sock) {
Logger.Write($"Connection closed from {sock.ConnectionInfo.ClientIpAddress}:{sock.ConnectionInfo.ClientPort}");
private void OnClose(ChatConnection conn) {
Logger.Write($"Connection closed from {conn.RemoteAddress}:{conn.RemotePort}");
lock(Context.ConnectionsAccess) {
ChatConnection conn = Context.GetConnection(sock);
if(conn == null)
return;
Context.Connections.Remove(conn);
if(conn.User != null && !Context.Connections.Any(c => c.User == conn.User))
@ -157,29 +152,14 @@ namespace SharpChat {
Context.Update();
}
private void OnError(IWebSocketConnection sock, Exception ex) {
string connId;
lock(Context.ConnectionsAccess) {
ChatConnection conn = Context.GetConnection(sock);
connId = conn?.Id ?? new string('0', ChatConnection.ID_LENGTH);
}
Logger.Write($"[{connId} {sock.ConnectionInfo.ClientIpAddress}] {ex}");
private void OnError(ChatConnection conn, Exception ex) {
Logger.Write($"[{conn.Id} {conn.RemoteAddress}] {ex}");
Context.Update();
}
private void OnMessage(IWebSocketConnection sock, string msg) {
private void OnMessage(ChatConnection conn, string msg) {
Context.Update();
ChatConnection conn;
lock(Context.ConnectionsAccess)
conn = Context.GetConnection(sock);
if(conn == null) {
sock.Close();
return;
}
// this doesn't affect non-authed connections?????
if(conn.User is not null && conn.User.HasFloodProtection) {
conn.User.RateLimiter.Update();