using Fleck; using System; using System.Collections.Generic; using System.Net; namespace SharpChat { public class ChatConnection : 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; private set; } public bool IsDisposed { get; private set; } public DateTimeOffset LastPing { get; set; } = DateTimeOffset.MinValue; 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 ChatConnection(IWebSocketConnection sock) { Socket = sock; Id = RNG.SecureRandomString(ID_LENGTH); } public void Send(IServerPacket packet) { if(!Socket.IsAvailable) return; IEnumerable data = packet.Pack(); if(data != null) foreach(string line in data) if(!string.IsNullOrWhiteSpace(line)) Socket.Send(line); } public void BumpPing() { LastPing = DateTimeOffset.Now; } public bool HasTimedOut => DateTimeOffset.Now - LastPing > SessionTimeOut; public void PrepareForRestart() { CloseCode = 1012; } ~ChatConnection() { DoDispose(); } public void Dispose() { DoDispose(); GC.SuppressFinalize(this); } private void DoDispose() { if(IsDisposed) return; IsDisposed = true; Socket.Close(CloseCode); } public override int GetHashCode() { return Id.GetHashCode(); } } }