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 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();
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in a new issue