using System.Collections.Concurrent; using NATS.Server.Subscriptions; namespace NATS.Server.Auth; public sealed class Account : IDisposable { public const string GlobalAccountName = "$G"; public string Name { get; } public SubList SubList { get; } = new(); public Permissions? DefaultPermissions { get; set; } public int MaxConnections { get; set; } // 0 = unlimited public int MaxSubscriptions { get; set; } // 0 = unlimited private readonly ConcurrentDictionary _clients = new(); private int _subscriptionCount; public Account(string name) { Name = name; } public int ClientCount => _clients.Count; public int SubscriptionCount => Volatile.Read(ref _subscriptionCount); /// Returns false if max connections exceeded. public bool AddClient(ulong clientId) { if (MaxConnections > 0 && _clients.Count >= MaxConnections) return false; _clients[clientId] = 0; return true; } public void RemoveClient(ulong clientId) => _clients.TryRemove(clientId, out _); public bool IncrementSubscriptions() { if (MaxSubscriptions > 0 && Volatile.Read(ref _subscriptionCount) >= MaxSubscriptions) return false; Interlocked.Increment(ref _subscriptionCount); return true; } public void DecrementSubscriptions() { Interlocked.Decrement(ref _subscriptionCount); } public void Dispose() => SubList.Dispose(); }