#nullable enable using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Threading; using Cysharp.Threading.Tasks; namespace ShrinkNetwork { public sealed class ShrinkNetworkSession { private readonly ConcurrentDictionary _items = new(); private readonly ConcurrentDictionary _permissions = new(); internal ShrinkNetworkSession(long sessionId, string remoteAddress, ShrinkNetworkService service) { SessionId = sessionId; RemoteAddress = remoteAddress; Service = service; } public long SessionId { get; } public string RemoteAddress { get; internal set; } public ShrinkNetworkService Service { get; } public ShrinkNetworkPeerKind PeerKind { get; private set; } = ShrinkNetworkPeerKind.Unknown; public string SessionToken { get; private set; } = string.Empty; public DateTimeOffset? SessionTokenExpiresAtUtc { get; private set; } public IDictionary Items => _items; public void SetPeerKind(ShrinkNetworkPeerKind peerKind) { PeerKind = peerKind; } public void SetSessionToken(string sessionToken, DateTimeOffset? expiresAtUtc = null) { SessionToken = string.IsNullOrWhiteSpace(sessionToken) ? string.Empty : sessionToken.Trim(); SessionTokenExpiresAtUtc = string.IsNullOrWhiteSpace(SessionToken) ? null : expiresAtUtc; } public void ClearSessionToken() { SessionToken = string.Empty; SessionTokenExpiresAtUtc = null; } public void GrantPermission(string permission) { if (!string.IsNullOrWhiteSpace(permission)) _permissions[permission.Trim()] = 0; } public void RevokePermission(string permission) { if (!string.IsNullOrWhiteSpace(permission)) _permissions.TryRemove(permission.Trim(), out _); } public bool HasPermission(string permission) { return !string.IsNullOrWhiteSpace(permission) && _permissions.ContainsKey(permission.Trim()); } public IReadOnlyCollection GetPermissions() => _permissions.Keys.ToArray(); public UniTask SendAsync(TMessage message, string? route = null) where TMessage : IShrinkNetworkMessage => Service.SendAsync(this, message, route); public UniTask SendAsync(IShrinkNetworkMessage message, string? route = null) => Service.SendAsync(this, message, route); public UniTask NotifyAsync(TMessage message, string? route = null) where TMessage : IShrinkNetworkMessage => Service.SendAsync(this, message, route); public UniTask NotifyAsync(IShrinkNetworkMessage message, string? route = null) => Service.SendAsync(this, message, route); public UniTask CallAsync(TRequest request, string? route = null) where TRequest : IShrinkNetworkRequest where TResponse : class, IShrinkNetworkResponse => Service.CallAsync(this, request, route); public UniTask CallAsync(TRequest request, ShrinkRpcCallOptions options) where TRequest : IShrinkNetworkRequest where TResponse : class, IShrinkNetworkResponse => Service.CallAsync(this, request, options); public UniTask RpcAsync(TRequest request, string? route = null) where TRequest : IShrinkNetworkRequest where TResponse : class, IShrinkNetworkResponse => Service.CallAsync(this, request, route); public UniTask RpcAsync(TRequest request, ShrinkRpcCallOptions options) where TRequest : IShrinkNetworkRequest where TResponse : class, IShrinkNetworkResponse => Service.CallAsync(this, request, options); public UniTask RpcAsync(TRequest request, int timeoutMs, CancellationToken cancellationToken = default) where TRequest : IShrinkNetworkRequest where TResponse : class, IShrinkNetworkResponse => Service.CallAsync(this, request, new ShrinkRpcCallOptions { TimeoutMs = timeoutMs, CancellationToken = cancellationToken }); } }