2022-08-30 15:00:58 +00:00
|
|
|
|
using Fleck;
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Net;
|
|
|
|
|
|
|
|
|
|
namespace SharpChat {
|
2023-02-16 21:25:41 +00:00
|
|
|
|
public class ChatConnection : IDisposable {
|
|
|
|
|
public const int ID_LENGTH = 20;
|
2022-08-30 15:00:58 +00:00
|
|
|
|
|
|
|
|
|
#if DEBUG
|
|
|
|
|
public static TimeSpan SessionTimeOut { get; } = TimeSpan.FromMinutes(1);
|
|
|
|
|
#else
|
|
|
|
|
public static TimeSpan SessionTimeOut { get; } = TimeSpan.FromMinutes(5);
|
|
|
|
|
#endif
|
|
|
|
|
|
2023-02-16 21:25:41 +00:00
|
|
|
|
public IWebSocketConnection Socket { get; }
|
2022-08-30 15:00:58 +00:00
|
|
|
|
|
2023-02-17 22:17:24 +00:00
|
|
|
|
public string Id { get; }
|
2022-08-30 15:00:58 +00:00
|
|
|
|
public bool IsDisposed { get; private set; }
|
2023-02-16 22:33:48 +00:00
|
|
|
|
public DateTimeOffset LastPing { get; set; } = DateTimeOffset.Now;
|
2022-08-30 15:00:58 +00:00
|
|
|
|
public ChatUser User { get; set; }
|
|
|
|
|
|
2023-02-07 15:01:56 +00:00
|
|
|
|
private int CloseCode { get; set; } = 1000;
|
2022-08-30 18:29:11 +00:00
|
|
|
|
|
2023-02-17 22:17:24 +00:00
|
|
|
|
public IPAddress RemoteAddress { get; }
|
|
|
|
|
public ushort RemotePort { get; }
|
2022-08-30 15:00:58 +00:00
|
|
|
|
|
2023-02-16 22:33:48 +00:00
|
|
|
|
public bool IsAlive => !IsDisposed && !HasTimedOut;
|
|
|
|
|
|
|
|
|
|
public bool IsAuthed => IsAlive && User is not null;
|
|
|
|
|
|
2023-02-16 21:25:41 +00:00
|
|
|
|
public ChatConnection(IWebSocketConnection sock) {
|
|
|
|
|
Socket = sock;
|
2023-02-10 07:06:07 +00:00
|
|
|
|
Id = RNG.SecureRandomString(ID_LENGTH);
|
2023-02-17 22:17:24 +00:00
|
|
|
|
|
|
|
|
|
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;
|
2022-08-30 15:00:58 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Send(IServerPacket packet) {
|
2023-02-16 21:25:41 +00:00
|
|
|
|
if(!Socket.IsAvailable)
|
2022-08-30 15:00:58 +00:00
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
IEnumerable<string> data = packet.Pack();
|
|
|
|
|
|
2022-08-30 18:29:11 +00:00
|
|
|
|
if(data != null)
|
|
|
|
|
foreach(string line in data)
|
|
|
|
|
if(!string.IsNullOrWhiteSpace(line))
|
2023-02-16 21:25:41 +00:00
|
|
|
|
Socket.Send(line);
|
2022-08-30 15:00:58 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-02-07 15:01:56 +00:00
|
|
|
|
public void BumpPing() {
|
|
|
|
|
LastPing = DateTimeOffset.Now;
|
|
|
|
|
}
|
2022-08-30 15:00:58 +00:00
|
|
|
|
|
|
|
|
|
public bool HasTimedOut
|
|
|
|
|
=> DateTimeOffset.Now - LastPing > SessionTimeOut;
|
|
|
|
|
|
2023-02-07 15:01:56 +00:00
|
|
|
|
public void PrepareForRestart() {
|
|
|
|
|
CloseCode = 1012;
|
|
|
|
|
}
|
2022-08-30 18:29:11 +00:00
|
|
|
|
|
2023-02-16 21:25:41 +00:00
|
|
|
|
~ChatConnection() {
|
2023-02-07 15:01:56 +00:00
|
|
|
|
DoDispose();
|
|
|
|
|
}
|
2022-08-30 15:00:58 +00:00
|
|
|
|
|
2023-02-07 15:01:56 +00:00
|
|
|
|
public void Dispose() {
|
|
|
|
|
DoDispose();
|
|
|
|
|
GC.SuppressFinalize(this);
|
|
|
|
|
}
|
2022-08-30 15:00:58 +00:00
|
|
|
|
|
2023-02-07 15:01:56 +00:00
|
|
|
|
private void DoDispose() {
|
2022-08-30 18:29:11 +00:00
|
|
|
|
if(IsDisposed)
|
2022-08-30 15:00:58 +00:00
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
IsDisposed = true;
|
2023-02-16 21:25:41 +00:00
|
|
|
|
Socket.Close(CloseCode);
|
2022-08-30 15:00:58 +00:00
|
|
|
|
}
|
2023-02-16 20:34:59 +00:00
|
|
|
|
|
2023-02-17 22:17:24 +00:00
|
|
|
|
public override string ToString() {
|
|
|
|
|
return Id;
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-16 20:34:59 +00:00
|
|
|
|
public override int GetHashCode() {
|
|
|
|
|
return Id.GetHashCode();
|
|
|
|
|
}
|
2022-08-30 15:00:58 +00:00
|
|
|
|
}
|
|
|
|
|
}
|