using Fleck; using System; using System.Net; namespace SharpChat { public class ConnectionInfo : IDisposable { public const int ID_LENGTH = 20; #if DEBUG public static TimeSpan SessionTimeOut { get; } = TimeSpan.FromMinutes(1); #else public static TimeSpan SessionTimeOut { get; } = TimeSpan.FromMinutes(5); #endif public IWebSocketConnection Socket { get; } public string Id { get; } public bool IsDisposed { get; private set; } public DateTimeOffset LastPing { get; set; } = DateTimeOffset.Now; public UserInfo? User { get; set; } private int CloseCode { get; set; } = 1000; public IPAddress RemoteAddress { get; } public ushort RemotePort { get; } public bool IsAlive => !IsDisposed && !HasTimedOut; public bool IsAuthed => IsAlive && User is not null; public ConnectionInfo(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(ServerPacket packet) { if(!Socket.IsAvailable) return; string data = packet.Pack(); if(!string.IsNullOrWhiteSpace(data)) Socket.Send(data); } public void BumpPing() { LastPing = DateTimeOffset.Now; } public bool HasTimedOut => DateTimeOffset.Now - LastPing > SessionTimeOut; public void PrepareForRestart() { CloseCode = 1012; } ~ConnectionInfo() { DoDispose(); } public void Dispose() { DoDispose(); GC.SuppressFinalize(this); } private void DoDispose() { if(IsDisposed) return; IsDisposed = true; Socket.Close(CloseCode); } public override string ToString() { return Id; } } }