|
|
|
@ -1,19 +1,25 @@
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Concurrent;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Linq.Expressions;
|
|
|
|
|
using System.Net;
|
|
|
|
|
using System.Reflection;
|
|
|
|
|
using System.Threading;
|
|
|
|
|
using ZeroLevel.Network;
|
|
|
|
|
using ZeroLevel.Services.Serialization;
|
|
|
|
|
|
|
|
|
|
namespace ZeroLevel.Services.Applications
|
|
|
|
|
{
|
|
|
|
|
public abstract class BaseZeroService
|
|
|
|
|
: IZeroService
|
|
|
|
|
{
|
|
|
|
|
public string Name { get; protected set; }
|
|
|
|
|
public string Key { get; private set; }
|
|
|
|
|
public string Version { get; private set; }
|
|
|
|
|
public string Group { get; private set; }
|
|
|
|
|
public string Type { get; private set; }
|
|
|
|
|
private readonly ZeroServiceInfo _serviceInfo = new ZeroServiceInfo();
|
|
|
|
|
|
|
|
|
|
public string Name { get { return _serviceInfo.Name; } private set { _serviceInfo.Name = value; } }
|
|
|
|
|
public string Key { get { return _serviceInfo.ServiceKey; } private set { _serviceInfo.ServiceKey = value; } }
|
|
|
|
|
public string Version { get { return _serviceInfo.Version; } private set { _serviceInfo.Version = value; } }
|
|
|
|
|
public string Group { get { return _serviceInfo.ServiceGroup; } private set { _serviceInfo.ServiceGroup = value; } }
|
|
|
|
|
public string Type { get { return _serviceInfo.ServiceType; } private set { _serviceInfo.ServiceType = value; } }
|
|
|
|
|
|
|
|
|
|
public ZeroServiceStatus Status => _state;
|
|
|
|
|
private ZeroServiceStatus _state;
|
|
|
|
@ -113,42 +119,97 @@ namespace ZeroLevel.Services.Applications
|
|
|
|
|
#endregion Config
|
|
|
|
|
|
|
|
|
|
#region Network
|
|
|
|
|
private IRouter _router;
|
|
|
|
|
private static IRouter _null_router = new NullRouter();
|
|
|
|
|
private IDiscoveryClient _discoveryClient;
|
|
|
|
|
private static readonly IRouter _null_router = new NullRouter();
|
|
|
|
|
private IDiscoveryClient _discoveryClient = null; // Feature расширить до нескольких discovery
|
|
|
|
|
private long _update_discovery_table_task = -1;
|
|
|
|
|
private long _register_in_discovery_table_task = -1;
|
|
|
|
|
private readonly AliasSet<IPEndPoint> _aliases = new AliasSet<IPEndPoint>();
|
|
|
|
|
private static TimeSpan _update_discovery_table_period = TimeSpan.FromSeconds(15);
|
|
|
|
|
private static TimeSpan _register_in_discovery_table_period = TimeSpan.FromSeconds(15);
|
|
|
|
|
private static readonly ConcurrentDictionary<string, ExClient> _clientInstances = new ConcurrentDictionary<string, ExClient>();
|
|
|
|
|
private readonly ConcurrentDictionary<string, SocketServer> _serverInstances = new ConcurrentDictionary<string, SocketServer>();
|
|
|
|
|
|
|
|
|
|
private void RestartDiscoveryTasks()
|
|
|
|
|
{
|
|
|
|
|
if (_update_discovery_table_task != -1)
|
|
|
|
|
{
|
|
|
|
|
Sheduller.Remove(_update_discovery_table_task);
|
|
|
|
|
}
|
|
|
|
|
if (_register_in_discovery_table_task != -1)
|
|
|
|
|
{
|
|
|
|
|
Sheduller.Remove(_register_in_discovery_table_task);
|
|
|
|
|
}
|
|
|
|
|
_update_discovery_table_task = Sheduller.RemindEvery(_update_discovery_table_period, RegisterServicesInDiscovery);
|
|
|
|
|
_register_in_discovery_table_task = Sheduller.RemindEvery(_register_in_discovery_table_period, () => { });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void RegisterServicesInDiscovery()
|
|
|
|
|
{
|
|
|
|
|
var services = _serverInstances.
|
|
|
|
|
Values.
|
|
|
|
|
Select(s =>
|
|
|
|
|
{
|
|
|
|
|
var info = MessageSerializer.Copy(this._serviceInfo);
|
|
|
|
|
info.Port = s.LocalEndpoint.Port;
|
|
|
|
|
return info;
|
|
|
|
|
}).
|
|
|
|
|
ToList();
|
|
|
|
|
foreach (var service in services)
|
|
|
|
|
{
|
|
|
|
|
_discoveryClient.Register(service);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void UseDiscovery()
|
|
|
|
|
{
|
|
|
|
|
if (_state == ZeroServiceStatus.Running ||
|
|
|
|
|
_state == ZeroServiceStatus.Initialized)
|
|
|
|
|
if (_state == ZeroServiceStatus.Running
|
|
|
|
|
|| _state == ZeroServiceStatus.Initialized)
|
|
|
|
|
{
|
|
|
|
|
if (_discoveryClient != null)
|
|
|
|
|
{
|
|
|
|
|
_discoveryClient.Dispose();
|
|
|
|
|
_discoveryClient = null;
|
|
|
|
|
}
|
|
|
|
|
var discovery = Configuration.Default.First("discovery");
|
|
|
|
|
_discoveryClient = new DiscoveryClient(GetClient(NetUtils.CreateIPEndPoint(discovery), _null_router, false));
|
|
|
|
|
RestartDiscoveryTasks();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void UseDiscovery(string endpoint)
|
|
|
|
|
{
|
|
|
|
|
if (_state == ZeroServiceStatus.Running ||
|
|
|
|
|
_state == ZeroServiceStatus.Initialized)
|
|
|
|
|
if (_state == ZeroServiceStatus.Running
|
|
|
|
|
|| _state == ZeroServiceStatus.Initialized)
|
|
|
|
|
{
|
|
|
|
|
if (_discoveryClient != null)
|
|
|
|
|
{
|
|
|
|
|
_discoveryClient.Dispose();
|
|
|
|
|
_discoveryClient = null;
|
|
|
|
|
}
|
|
|
|
|
_discoveryClient = new DiscoveryClient(GetClient(NetUtils.CreateIPEndPoint(endpoint), _null_router, false));
|
|
|
|
|
RestartDiscoveryTasks();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void UseDiscovery(IPEndPoint endpoint)
|
|
|
|
|
{
|
|
|
|
|
if (_state == ZeroServiceStatus.Running ||
|
|
|
|
|
_state == ZeroServiceStatus.Initialized)
|
|
|
|
|
if (_state == ZeroServiceStatus.Running
|
|
|
|
|
|| _state == ZeroServiceStatus.Initialized)
|
|
|
|
|
{
|
|
|
|
|
if (_discoveryClient != null)
|
|
|
|
|
{
|
|
|
|
|
_discoveryClient.Dispose();
|
|
|
|
|
_discoveryClient = null;
|
|
|
|
|
}
|
|
|
|
|
_discoveryClient = new DiscoveryClient(GetClient(endpoint, _null_router, false));
|
|
|
|
|
RestartDiscoveryTasks();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public IRouter UseHost()
|
|
|
|
|
{
|
|
|
|
|
if (_state == ZeroServiceStatus.Running ||
|
|
|
|
|
_state == ZeroServiceStatus.Initialized)
|
|
|
|
|
if (_state == ZeroServiceStatus.Running
|
|
|
|
|
|| _state == ZeroServiceStatus.Initialized)
|
|
|
|
|
{
|
|
|
|
|
return GetServer(new IPEndPoint(IPAddress.Any, NetUtils.GetFreeTcpPort()), new Router()).Router;
|
|
|
|
|
}
|
|
|
|
@ -157,8 +218,8 @@ namespace ZeroLevel.Services.Applications
|
|
|
|
|
|
|
|
|
|
public IRouter UseHost(int port)
|
|
|
|
|
{
|
|
|
|
|
if (_state == ZeroServiceStatus.Running ||
|
|
|
|
|
_state == ZeroServiceStatus.Initialized)
|
|
|
|
|
if (_state == ZeroServiceStatus.Running
|
|
|
|
|
|| _state == ZeroServiceStatus.Initialized)
|
|
|
|
|
{
|
|
|
|
|
return GetServer(new IPEndPoint(IPAddress.Any, port), new Router()).Router;
|
|
|
|
|
}
|
|
|
|
@ -167,8 +228,8 @@ namespace ZeroLevel.Services.Applications
|
|
|
|
|
|
|
|
|
|
public IRouter UseHost(IPEndPoint endpoint)
|
|
|
|
|
{
|
|
|
|
|
if (_state == ZeroServiceStatus.Running ||
|
|
|
|
|
_state == ZeroServiceStatus.Initialized)
|
|
|
|
|
if (_state == ZeroServiceStatus.Running
|
|
|
|
|
|| _state == ZeroServiceStatus.Initialized)
|
|
|
|
|
{
|
|
|
|
|
return GetServer(endpoint, new Router()).Router;
|
|
|
|
|
}
|
|
|
|
@ -177,38 +238,210 @@ namespace ZeroLevel.Services.Applications
|
|
|
|
|
|
|
|
|
|
public ExClient ConnectToService(string endpoint)
|
|
|
|
|
{
|
|
|
|
|
if (_state == ZeroServiceStatus.Running)
|
|
|
|
|
if (_state == ZeroServiceStatus.Running
|
|
|
|
|
|| _state == ZeroServiceStatus.Initialized)
|
|
|
|
|
{
|
|
|
|
|
return new ExClient(GetClient(NetUtils.CreateIPEndPoint(endpoint), new Router(), true));
|
|
|
|
|
return GetClient(NetUtils.CreateIPEndPoint(endpoint), new Router(), true);
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public ExClient ConnectToService(string alias, string endpoint)
|
|
|
|
|
public ExClient ConnectToService(IPEndPoint endpoint)
|
|
|
|
|
{
|
|
|
|
|
if (_state == ZeroServiceStatus.Running)
|
|
|
|
|
if (_state == ZeroServiceStatus.Running
|
|
|
|
|
|| _state == ZeroServiceStatus.Initialized)
|
|
|
|
|
{
|
|
|
|
|
return new ExClient(GetClient(NetUtils.CreateIPEndPoint(endpoint), new Router(), true));
|
|
|
|
|
return GetClient(endpoint, new Router(), true);
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public ExClient ConnectToService(IPEndPoint endpoint)
|
|
|
|
|
#region Autoregistration inboxes
|
|
|
|
|
private static Delegate CreateDelegate(Type delegateType, MethodInfo methodInfo, object target)
|
|
|
|
|
{
|
|
|
|
|
if (_state == ZeroServiceStatus.Running)
|
|
|
|
|
Func<Type[], Type> getType;
|
|
|
|
|
var isAction = methodInfo.ReturnType.Equals((typeof(void)));
|
|
|
|
|
if (isAction)
|
|
|
|
|
{
|
|
|
|
|
return new ExClient(GetClient(endpoint, new Router(), true));
|
|
|
|
|
getType = Expression.GetActionType;
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
getType = Expression.GetFuncType;
|
|
|
|
|
}
|
|
|
|
|
if (methodInfo.IsStatic)
|
|
|
|
|
{
|
|
|
|
|
return Delegate.CreateDelegate(delegateType, methodInfo);
|
|
|
|
|
}
|
|
|
|
|
return Delegate.CreateDelegate(delegateType, target, methodInfo.Name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public ExClient ConnectToService(string alias, IPEndPoint endpoint)
|
|
|
|
|
public void AutoregisterInboxes(IServer server)
|
|
|
|
|
{
|
|
|
|
|
if (_state == ZeroServiceStatus.Running)
|
|
|
|
|
var type = server.GetType();
|
|
|
|
|
// Search router registerinbox methods with inbox name
|
|
|
|
|
var register_methods = type.GetMethods(BindingFlags.Instance
|
|
|
|
|
| BindingFlags.Public
|
|
|
|
|
| BindingFlags.NonPublic
|
|
|
|
|
| BindingFlags.FlattenHierarchy)?
|
|
|
|
|
.Where(mi => mi.Name.Equals("RegisterInbox", StringComparison.Ordinal) &&
|
|
|
|
|
mi.GetParameters().First().ParameterType == typeof(string));
|
|
|
|
|
|
|
|
|
|
var register_message_handler = register_methods.First(mi => mi.IsGenericMethod == false);
|
|
|
|
|
var register_message_handler_with_msg = register_methods.First(mi =>
|
|
|
|
|
{
|
|
|
|
|
if (mi.IsGenericMethod)
|
|
|
|
|
{
|
|
|
|
|
var paremeters = mi.GetParameters().ToArray();
|
|
|
|
|
if (paremeters.Length == 2 && paremeters[1].ParameterType.IsAssignableToGenericType(typeof(MessageHandler<>)))
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
});
|
|
|
|
|
var register_request_handler_without_msg = register_methods.First(mi =>
|
|
|
|
|
{
|
|
|
|
|
return new ExClient(GetClient(endpoint, new Router(), true));
|
|
|
|
|
if (mi.IsGenericMethod)
|
|
|
|
|
{
|
|
|
|
|
var paremeters = mi.GetParameters().ToArray();
|
|
|
|
|
if (paremeters.Length == 2 && paremeters[1].ParameterType.IsAssignableToGenericType(typeof(RequestHandler<>)))
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
});
|
|
|
|
|
var register_request_handler = register_methods.First(mi =>
|
|
|
|
|
{
|
|
|
|
|
if (mi.IsGenericMethod)
|
|
|
|
|
{
|
|
|
|
|
var paremeters = mi.GetParameters().ToArray();
|
|
|
|
|
if (paremeters.Length == 2 && paremeters[1].ParameterType.IsAssignableToGenericType(typeof(RequestHandler<,>)))
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
MethodInfo[] methods = this.
|
|
|
|
|
GetType().
|
|
|
|
|
GetMethods(BindingFlags.NonPublic
|
|
|
|
|
| BindingFlags.Public
|
|
|
|
|
| BindingFlags.Instance
|
|
|
|
|
| BindingFlags.FlattenHierarchy
|
|
|
|
|
| BindingFlags.Instance);
|
|
|
|
|
|
|
|
|
|
foreach (MethodInfo mi in methods)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
foreach (Attribute attr in Attribute.GetCustomAttributes(mi, typeof(ExchangeAttribute)))
|
|
|
|
|
{
|
|
|
|
|
var args = mi.GetParameters().ToArray();
|
|
|
|
|
if (attr.GetType() == typeof(ExchangeMainHandlerAttribute))
|
|
|
|
|
{
|
|
|
|
|
if (args.Length == 1)
|
|
|
|
|
{
|
|
|
|
|
var handler = CreateDelegate(typeof(MessageHandler), mi, this);
|
|
|
|
|
register_message_handler.Invoke(server, new object[] { BaseSocket.DEFAULT_MESSAGE_INBOX, handler });
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
var handler = CreateDelegate(typeof(MessageHandler<>).MakeGenericType(args[1].ParameterType), mi, this);
|
|
|
|
|
MethodInfo genericMethod = register_message_handler_with_msg.MakeGenericMethod(args[1].ParameterType);
|
|
|
|
|
genericMethod.Invoke(server, new object[] { BaseSocket.DEFAULT_MESSAGE_INBOX, handler });
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (attr.GetType() == typeof(ExchangeHandlerAttribute))
|
|
|
|
|
{
|
|
|
|
|
if (args.Length == 1)
|
|
|
|
|
{
|
|
|
|
|
var handler = CreateDelegate(typeof(MessageHandler), mi, this);
|
|
|
|
|
register_message_handler.Invoke(server, new object[] { (attr as ExchangeHandlerAttribute).Inbox, handler });
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
var handler = CreateDelegate(typeof(MessageHandler<>).MakeGenericType(args[1].ParameterType), mi, this);
|
|
|
|
|
MethodInfo genericMethod = register_message_handler_with_msg.MakeGenericMethod(args[1].ParameterType);
|
|
|
|
|
genericMethod.Invoke(server, new object[] { (attr as ExchangeHandlerAttribute).Inbox, handler });
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
else if (attr.GetType() == typeof(ExchangeMainReplierAttribute))
|
|
|
|
|
{
|
|
|
|
|
var returnType = mi.ReturnType;
|
|
|
|
|
var genArgType = args[1].ParameterType;
|
|
|
|
|
MethodInfo genericMethod = register_request_handler.MakeGenericMethod(genArgType, returnType);
|
|
|
|
|
var requestHandler = CreateDelegate(typeof(RequestHandler<,>).MakeGenericType(args[1].ParameterType, returnType), mi, this);
|
|
|
|
|
genericMethod.Invoke(server, new object[] { BaseSocket.DEFAULT_REQUEST_INBOX, requestHandler });
|
|
|
|
|
}
|
|
|
|
|
else if (attr.GetType() == typeof(ExchangeReplierAttribute))
|
|
|
|
|
{
|
|
|
|
|
var returnType = mi.ReturnType;
|
|
|
|
|
var genArgType = args[1].ParameterType;
|
|
|
|
|
MethodInfo genericMethod = register_request_handler.MakeGenericMethod(genArgType, returnType);
|
|
|
|
|
var requestHandler = CreateDelegate(typeof(RequestHandler<,>).MakeGenericType(args[1].ParameterType, returnType), mi, this);
|
|
|
|
|
genericMethod.Invoke(server, new object[] { (attr as ExchangeReplierAttribute).Inbox, requestHandler });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
else if (attr.GetType() == typeof(ExchangeMainReplierWithoutArgAttribute))
|
|
|
|
|
{
|
|
|
|
|
var returnType = mi.ReturnType;
|
|
|
|
|
MethodInfo genericMethod = register_request_handler_without_msg.MakeGenericMethod(returnType);
|
|
|
|
|
var requestHandler = CreateDelegate(typeof(RequestHandler<>).MakeGenericType(returnType), mi, this);
|
|
|
|
|
genericMethod.Invoke(server, new object[] { BaseSocket.DEFAULT_REQUEST_WITHOUT_ARGS_INBOX, requestHandler });
|
|
|
|
|
}
|
|
|
|
|
else if (attr.GetType() == typeof(ExchangeReplierWithoutArgAttribute))
|
|
|
|
|
{
|
|
|
|
|
var returnType = mi.ReturnType;
|
|
|
|
|
MethodInfo genericMethod = register_request_handler_without_msg.MakeGenericMethod(returnType);
|
|
|
|
|
var requestHandler = CreateDelegate(typeof(RequestHandler<>).MakeGenericType(returnType), mi, this);
|
|
|
|
|
genericMethod.Invoke(server, new object[] { (attr as ExchangeReplierWithoutArgAttribute).Inbox, requestHandler });
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
Log.Debug($"[ZExchange] Can't register method {mi.Name} as inbox handler. {ex}");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void StoreConnection(string endpoint)
|
|
|
|
|
{
|
|
|
|
|
if (_state == ZeroServiceStatus.Running ||
|
|
|
|
|
_state == ZeroServiceStatus.Initialized)
|
|
|
|
|
{
|
|
|
|
|
_aliases.Set(endpoint, NetUtils.CreateIPEndPoint(endpoint));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
public void StoreConnection(string alias, string endpoint)
|
|
|
|
|
{
|
|
|
|
|
if (_state == ZeroServiceStatus.Running ||
|
|
|
|
|
_state == ZeroServiceStatus.Initialized)
|
|
|
|
|
{
|
|
|
|
|
_aliases.Set(alias, NetUtils.CreateIPEndPoint(endpoint));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
public void StoreConnection(IPEndPoint endpoint)
|
|
|
|
|
{
|
|
|
|
|
if (_state == ZeroServiceStatus.Running ||
|
|
|
|
|
_state == ZeroServiceStatus.Initialized)
|
|
|
|
|
{
|
|
|
|
|
_aliases.Set($"{endpoint.Address}:{endpoint.Port}", endpoint);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
public void StoreConnection(string alias, IPEndPoint endpoint)
|
|
|
|
|
{
|
|
|
|
|
if (_state == ZeroServiceStatus.Running ||
|
|
|
|
|
_state == ZeroServiceStatus.Initialized)
|
|
|
|
|
{
|
|
|
|
|
_aliases.Set(alias, endpoint);
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
@ -284,16 +517,14 @@ namespace ZeroLevel.Services.Applications
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region Utils
|
|
|
|
|
private static readonly ConcurrentDictionary<string, ISocketClient> _clientInstances = new ConcurrentDictionary<string, ISocketClient>();
|
|
|
|
|
private readonly ConcurrentDictionary<string, SocketServer> _serverInstances = new ConcurrentDictionary<string, SocketServer>();
|
|
|
|
|
#region Utils
|
|
|
|
|
|
|
|
|
|
private ISocketClient GetClient(IPEndPoint endpoint, IRouter router, bool use_cachee)
|
|
|
|
|
private ExClient GetClient(IPEndPoint endpoint, IRouter router, bool use_cachee)
|
|
|
|
|
{
|
|
|
|
|
if (use_cachee)
|
|
|
|
|
{
|
|
|
|
|
string key = $"{endpoint.Address}:{endpoint.Port}";
|
|
|
|
|
ISocketClient instance = null;
|
|
|
|
|
ExClient instance = null;
|
|
|
|
|
if (_clientInstances.ContainsKey(key))
|
|
|
|
|
{
|
|
|
|
|
instance = _clientInstances[key];
|
|
|
|
@ -305,11 +536,11 @@ namespace ZeroLevel.Services.Applications
|
|
|
|
|
instance.Dispose();
|
|
|
|
|
instance = null;
|
|
|
|
|
}
|
|
|
|
|
instance = new SocketClient(endpoint, router);
|
|
|
|
|
instance = new ExClient(new SocketClient(endpoint, router));
|
|
|
|
|
_clientInstances[key] = instance;
|
|
|
|
|
return instance;
|
|
|
|
|
}
|
|
|
|
|
return new SocketClient(endpoint, router);
|
|
|
|
|
return new ExClient(new SocketClient(endpoint, router));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private SocketServer GetServer(IPEndPoint endpoint, IRouter router)
|
|
|
|
@ -328,29 +559,42 @@ namespace ZeroLevel.Services.Applications
|
|
|
|
|
|
|
|
|
|
public void Dispose()
|
|
|
|
|
{
|
|
|
|
|
_state = ZeroServiceStatus.Disposed;
|
|
|
|
|
|
|
|
|
|
foreach (var client in _clientInstances)
|
|
|
|
|
if (_state != ZeroServiceStatus.Disposed)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
_state = ZeroServiceStatus.Disposed;
|
|
|
|
|
|
|
|
|
|
if (_update_discovery_table_task != -1)
|
|
|
|
|
{
|
|
|
|
|
client.Value.Dispose();
|
|
|
|
|
Sheduller.Remove(_update_discovery_table_task);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
|
|
|
|
if (_register_in_discovery_table_task != -1)
|
|
|
|
|
{
|
|
|
|
|
Log.Error(ex, $"[BaseZeroService`{Name ?? string.Empty}.Dispose()] Dispose SocketClient to endpoint {client.Key}");
|
|
|
|
|
Sheduller.Remove(_register_in_discovery_table_task);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach (var server in _serverInstances)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
foreach (var client in _clientInstances)
|
|
|
|
|
{
|
|
|
|
|
server.Value.Dispose();
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
client.Value.Dispose();
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
Log.Error(ex, $"[BaseZeroService`{Name ?? string.Empty}.Dispose()] Dispose SocketClient to endpoint {client.Key}");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
|
|
|
|
foreach (var server in _serverInstances)
|
|
|
|
|
{
|
|
|
|
|
Log.Error(ex, $"[BaseZeroService`{Name ?? string.Empty}.Dispose()] Dispose SocketServer with endpoint {server.Key}");
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
server.Value.Dispose();
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
Log.Error(ex, $"[BaseZeroService`{Name ?? string.Empty}.Dispose()] Dispose SocketServer with endpoint {server.Key}");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|