From 70df99fe9b6aa422b22f0c6894b8e6f17576266b Mon Sep 17 00:00:00 2001 From: flashwave Date: Fri, 17 Feb 2023 23:17:24 +0100 Subject: [PATCH] Significantly less stupid connection resolving. --- SharpChat/ChatConnection.cs | 35 +++++++++++++------------- SharpChat/ChatContext.cs | 4 --- SharpChat/ChatUser.cs | 6 ++++- SharpChat/RateLimiter.cs | 10 +------- SharpChat/SockChatServer.cs | 50 +++++++++++-------------------------- 5 files changed, 39 insertions(+), 66 deletions(-) diff --git a/SharpChat/ChatConnection.cs b/SharpChat/ChatConnection.cs index 8d34de2..38f7e7d 100644 --- a/SharpChat/ChatConnection.cs +++ b/SharpChat/ChatConnection.cs @@ -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(); } diff --git a/SharpChat/ChatContext.cs b/SharpChat/ChatContext.cs index 469d480..b6b2739 100644 --- a/SharpChat/ChatContext.cs +++ b/SharpChat/ChatContext.cs @@ -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)); diff --git a/SharpChat/ChatUser.cs b/SharpChat/ChatUser.cs index 2fcca03..24c9a57 100644 --- a/SharpChat/ChatUser.cs +++ b/SharpChat/ChatUser.cs @@ -4,6 +4,10 @@ using System.Text; namespace SharpChat { public class ChatUser : IEquatable { + 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; } diff --git a/SharpChat/RateLimiter.cs b/SharpChat/RateLimiter.cs index 7b95967..394194d 100644 --- a/SharpChat/RateLimiter.cs +++ b/SharpChat/RateLimiter.cs @@ -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) diff --git a/SharpChat/SockChatServer.cs b/SharpChat/SockChatServer.cs index f74c62f..d4f8b77 100644 --- a/SharpChat/SockChatServer.cs +++ b/SharpChat/SockChatServer.cs @@ -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();