Significantly less stupid connection resolving.
This commit is contained in:
parent
546e8a2c83
commit
70df99fe9b
5 changed files with 39 additions and 66 deletions
|
@ -15,29 +15,15 @@ namespace SharpChat {
|
||||||
|
|
||||||
public IWebSocketConnection Socket { get; }
|
public IWebSocketConnection Socket { get; }
|
||||||
|
|
||||||
public string Id { get; private set; }
|
public string Id { get; }
|
||||||
public bool IsDisposed { get; private set; }
|
public bool IsDisposed { get; private set; }
|
||||||
public DateTimeOffset LastPing { get; set; } = DateTimeOffset.Now;
|
public DateTimeOffset LastPing { get; set; } = DateTimeOffset.Now;
|
||||||
public ChatUser User { get; set; }
|
public ChatUser User { get; set; }
|
||||||
|
|
||||||
private int CloseCode { get; set; } = 1000;
|
private int CloseCode { get; set; } = 1000;
|
||||||
|
|
||||||
private IPAddress _RemoteAddress = null;
|
public IPAddress RemoteAddress { get; }
|
||||||
|
public ushort RemotePort { get; }
|
||||||
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 bool IsAlive => !IsDisposed && !HasTimedOut;
|
public bool IsAlive => !IsDisposed && !HasTimedOut;
|
||||||
|
|
||||||
|
@ -46,6 +32,17 @@ namespace SharpChat {
|
||||||
public ChatConnection(IWebSocketConnection sock) {
|
public ChatConnection(IWebSocketConnection sock) {
|
||||||
Socket = sock;
|
Socket = sock;
|
||||||
Id = RNG.SecureRandomString(ID_LENGTH);
|
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) {
|
public void Send(IServerPacket packet) {
|
||||||
|
@ -88,6 +85,10 @@ namespace SharpChat {
|
||||||
Socket.Close(CloseCode);
|
Socket.Close(CloseCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override string ToString() {
|
||||||
|
return Id;
|
||||||
|
}
|
||||||
|
|
||||||
public override int GetHashCode() {
|
public override int GetHashCode() {
|
||||||
return Id.GetHashCode();
|
return Id.GetHashCode();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
public bool IsInChannel(ChatUser user, ChatChannel channel) {
|
||||||
lock(ChannelUsersAccess)
|
lock(ChannelUsersAccess)
|
||||||
return ChannelUsers.Contains(new ChannelUserAssoc(user.UserId, channel.Name));
|
return ChannelUsers.Contains(new ChannelUserAssoc(user.UserId, channel.Name));
|
||||||
|
|
|
@ -4,6 +4,10 @@ using System.Text;
|
||||||
|
|
||||||
namespace SharpChat {
|
namespace SharpChat {
|
||||||
public class ChatUser : IEquatable<ChatUser> {
|
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;
|
private const int RANK_NO_FLOOD = 9;
|
||||||
|
|
||||||
public long UserId { get; set; }
|
public long UserId { get; set; }
|
||||||
|
@ -18,7 +22,7 @@ namespace SharpChat {
|
||||||
public bool HasFloodProtection
|
public bool HasFloodProtection
|
||||||
=> Rank < RANK_NO_FLOOD;
|
=> 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
|
// This needs to be a session thing
|
||||||
public ChatChannel CurrentChannel { get; set; }
|
public ChatChannel CurrentChannel { get; set; }
|
||||||
|
|
|
@ -2,20 +2,12 @@
|
||||||
|
|
||||||
namespace SharpChat {
|
namespace SharpChat {
|
||||||
public class RateLimiter {
|
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 Size;
|
||||||
private readonly int MinimumDelay;
|
private readonly int MinimumDelay;
|
||||||
private readonly int RiskyOffset;
|
private readonly int RiskyOffset;
|
||||||
private readonly long[] TimePoints;
|
private readonly long[] TimePoints;
|
||||||
|
|
||||||
public RateLimiter(
|
public RateLimiter(int size, int minDelay, int riskyOffset) {
|
||||||
int size = DEFAULT_SIZE,
|
|
||||||
int minDelay = DEFAULT_MINIMUM_DELAY,
|
|
||||||
int riskyOffset = DEFAULT_RISKY_OFFSET
|
|
||||||
) {
|
|
||||||
if(size < 2)
|
if(size < 2)
|
||||||
throw new ArgumentException("Size is too small.", nameof(size));
|
throw new ArgumentException("Size is too small.", nameof(size));
|
||||||
if(minDelay < 1000)
|
if(minDelay < 1000)
|
||||||
|
|
|
@ -120,34 +120,29 @@ namespace SharpChat {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sock.OnOpen = () => OnOpen(sock);
|
ChatConnection conn;
|
||||||
sock.OnClose = () => OnClose(sock);
|
lock(Context.ConnectionsAccess)
|
||||||
sock.OnError = err => OnError(sock, err);
|
Context.Connections.Add(conn = new(sock));
|
||||||
sock.OnMessage = msg => OnMessage(sock, msg);
|
|
||||||
|
sock.OnOpen = () => OnOpen(conn);
|
||||||
|
sock.OnClose = () => OnClose(conn);
|
||||||
|
sock.OnError = err => OnError(conn, err);
|
||||||
|
sock.OnMessage = msg => OnMessage(conn, msg);
|
||||||
});
|
});
|
||||||
|
|
||||||
Logger.Write("Listening...");
|
Logger.Write("Listening...");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnOpen(IWebSocketConnection sock) {
|
private void OnOpen(ChatConnection conn) {
|
||||||
Logger.Write($"Connection opened from {sock.ConnectionInfo.ClientIpAddress}:{sock.ConnectionInfo.ClientPort}");
|
Logger.Write($"Connection opened from {conn.RemoteAddress}:{conn.RemotePort}");
|
||||||
|
|
||||||
lock(Context.ConnectionsAccess) {
|
|
||||||
if(!Context.Connections.Any(x => x.Socket == sock))
|
|
||||||
Context.Connections.Add(new ChatConnection(sock));
|
|
||||||
}
|
|
||||||
|
|
||||||
Context.Update();
|
Context.Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnClose(IWebSocketConnection sock) {
|
private void OnClose(ChatConnection conn) {
|
||||||
Logger.Write($"Connection closed from {sock.ConnectionInfo.ClientIpAddress}:{sock.ConnectionInfo.ClientPort}");
|
Logger.Write($"Connection closed from {conn.RemoteAddress}:{conn.RemotePort}");
|
||||||
|
|
||||||
lock(Context.ConnectionsAccess) {
|
lock(Context.ConnectionsAccess) {
|
||||||
ChatConnection conn = Context.GetConnection(sock);
|
|
||||||
if(conn == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Context.Connections.Remove(conn);
|
Context.Connections.Remove(conn);
|
||||||
|
|
||||||
if(conn.User != null && !Context.Connections.Any(c => c.User == conn.User))
|
if(conn.User != null && !Context.Connections.Any(c => c.User == conn.User))
|
||||||
|
@ -157,29 +152,14 @@ namespace SharpChat {
|
||||||
Context.Update();
|
Context.Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnError(IWebSocketConnection sock, Exception ex) {
|
private void OnError(ChatConnection conn, Exception ex) {
|
||||||
string connId;
|
Logger.Write($"[{conn.Id} {conn.RemoteAddress}] {ex}");
|
||||||
lock(Context.ConnectionsAccess) {
|
|
||||||
ChatConnection conn = Context.GetConnection(sock);
|
|
||||||
connId = conn?.Id ?? new string('0', ChatConnection.ID_LENGTH);
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger.Write($"[{connId} {sock.ConnectionInfo.ClientIpAddress}] {ex}");
|
|
||||||
Context.Update();
|
Context.Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnMessage(IWebSocketConnection sock, string msg) {
|
private void OnMessage(ChatConnection conn, string msg) {
|
||||||
Context.Update();
|
Context.Update();
|
||||||
|
|
||||||
ChatConnection conn;
|
|
||||||
lock(Context.ConnectionsAccess)
|
|
||||||
conn = Context.GetConnection(sock);
|
|
||||||
|
|
||||||
if(conn == null) {
|
|
||||||
sock.Close();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// this doesn't affect non-authed connections?????
|
// this doesn't affect non-authed connections?????
|
||||||
if(conn.User is not null && conn.User.HasFloodProtection) {
|
if(conn.User is not null && conn.User.HasFloodProtection) {
|
||||||
conn.User.RateLimiter.Update();
|
conn.User.RateLimiter.Update();
|
||||||
|
|
Loading…
Reference in a new issue