using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Net; namespace ZeroLevel.Network { internal sealed class ExClientServerCachee : IDisposable { internal event Action OnBrokenConnection; private void RiseBrokenConnectionEvent(IPEndPoint endpoint) { var e = OnBrokenConnection; if (e != null) { e.Invoke(endpoint); } } private static readonly ConcurrentDictionary _clientInstances = new ConcurrentDictionary(); private readonly ConcurrentDictionary _serverInstances = new ConcurrentDictionary(); private HashSet _clients = new HashSet(); internal IEnumerable ServerList => _serverInstances.Values; public ExClient GetClient(IPEndPoint endpoint, bool use_cachee, IRouter router = null) { if (use_cachee) { string key = $"{endpoint.Address}:{endpoint.Port}"; ExClient instance = null; if (_clientInstances.ContainsKey(key)) { instance = _clientInstances[key]; if (instance.Status == SocketClientStatus.Working) { return instance; } _clientInstances.TryRemove(key, out instance); instance.Dispose(); instance = null; } instance = new ExClient(new SocketClient(endpoint, router ?? new Router())); instance.ForceConnect(); if (instance.Status != SocketClientStatus.Initialized && instance.Status != SocketClientStatus.Working) { OnBrokenConnection(endpoint); } else { _clientInstances[key] = instance; return instance; } } else { var instance = new ExClient(new SocketClient(endpoint, router ?? new Router())); if (instance.Status != SocketClientStatus.Initialized && instance.Status != SocketClientStatus.Working) { OnBrokenConnection(endpoint); } else { return instance; } } return null; } public SocketServer GetServer(IPEndPoint endpoint, IRouter router) { string key = $"{endpoint.Address}:{endpoint.Port}"; if (_serverInstances.ContainsKey(key)) { return _serverInstances[key]; } var instance = new SocketServer(endpoint, router); _serverInstances[key] = instance; return instance; } public void Dispose() { ExClient removed; foreach (var client in _clients) { try { if (_clientInstances.TryRemove(client, out removed)) { removed.Dispose(); } } catch (Exception ex) { Log.Error(ex, $"[ExClientServerCachee.Dispose()] Dispose SocketClient to endpoint {client}"); } } _clients.Clear(); foreach (var server in _serverInstances) { try { server.Value.Dispose(); } catch (Exception ex) { Log.Error(ex, $"[ExClientServerCachee.Dispose()] Dispose SocketServer with endpoint {server.Key}"); } } _serverInstances.Clear(); } } }