2
0
mirror of https://github.com/esiur/esiur-dotnet.git synced 2025-06-26 21:13:13 +00:00
This commit is contained in:
2019-11-10 12:41:31 +03:00
parent 8d06fd05ad
commit 5e87ea5247
41 changed files with 2076 additions and 431 deletions

View File

@ -72,20 +72,20 @@ namespace Esiur.Net.DataLink
{
if (trigger == ResourceTrigger.Initialize)
{
foreach (Instance instance in Instance.Children)
/*
foreach (var resource in Instance.Children<IResource>())
{
if (instance.Resource is PacketFilter)
if (resource is PacketFilter)
{
filters.Add(instance.Resource as PacketFilter);
filters.Add(resource as PacketFilter);
}
else if (instance.Resource is PacketSource)
else if (resource is PacketSource)
{
sources.Add(instance.Resource as PacketSource);
sources.Add(resource as PacketSource);
}
}
*/
foreach (var src in sources)
{
src.OnNewPacket += PacketReceived;

View File

@ -44,6 +44,7 @@ namespace Esiur.Net.HTTP
public class HTTPServer : NetworkServer<HTTPConnection>, IResource
{
Dictionary<string, HTTPSession> sessions= new Dictionary<string, HTTPSession>();
HTTPFilter[] filters = null;
public Instance Instance
{
@ -183,13 +184,8 @@ namespace Esiur.Net.HTTP
{
//Console.WriteLine("OUT: " + this.Connections.Count);
foreach (IResource resource in Instance.Children)
{
if (resource is HTTPFilter)
{
(resource as HTTPFilter).ClientDisconnected(sender);
}
}
foreach (var filter in filters)
filter.ClientDisconnected(sender);
}
@ -268,16 +264,11 @@ namespace Esiur.Net.HTTP
try
{
foreach (IResource resource in Instance.Children)
{
if (resource is HTTPFilter)
{
if ((resource as HTTPFilter).Execute(sender))
return;
}
}
foreach (var resource in filters)
resource.Execute(sender);
sender.Send("Bad Request");
sender.Send("Bad Request");
sender.Close();
}
catch (Exception ex)
@ -289,21 +280,19 @@ namespace Esiur.Net.HTTP
//Console.WriteLine(ex.ToString());
//EventLog.WriteEntry("HttpServer", ex.ToString(), EventLogEntryType.Error);
sender.Send(Return500(ex.Message));
sender.Send(Error500(ex.Message));
}
}
}
private string Return500(string sMessage)
private string Error500(string msg)
{
string sTMP = null;
sTMP = "<HTML><HEAD><TITLE>500 Internal Server Error</TITLE></HEAD><br>\r\n";
sTMP = sTMP + "<BODY BGCOLOR=" + (char)(34) + "#FFFFFF" + (char)(34) + " Text=" + (char)(34) + "#000000" + (char)(34) + " LINK=" + (char)(34) + "#0000FF" + (char)(34) + " VLINK=" + (char)(34) + "#000080" + (char)(34) + " ALINK=" + (char)(34) + "#008000" + (char)(34) + "><br>\r\n";
sTMP = sTMP + "<b>500</b> Sorry - Internal Server Error<br>" + sMessage + "\r\n";
sTMP = sTMP + "</BODY><br>\r\n";
sTMP = sTMP + "</HTML><br>\r\n";
return sTMP;
return "<html><head><title>500 Internal Server Error</title></head><br>\r\n"
+ "<body><br>\r\n"
+ "<b>500</b> Internal Server Error<br>" + msg + "\r\n"
+ "</body><br>\r\n"
+ "</html><br>\r\n";
}
@ -382,6 +371,10 @@ namespace Esiur.Net.HTTP
Trigger(ResourceTrigger.Terminate);
Trigger(ResourceTrigger.Initialize);
}
else if (trigger == ResourceTrigger.SystemInitialized)
{
Instance.Children<HTTPFilter>().Then(x => filters = x);
}
return new AsyncReply<bool>(true);
@ -395,12 +388,9 @@ namespace Esiur.Net.HTTP
//Console.WriteLine("IN: " + this.Connections.Count);
foreach (var resource in Instance.Children)
foreach (var resource in filters)
{
if (resource is HTTPFilter)
{
(resource as HTTPFilter).ClientConnected(sender);
}
resource.ClientConnected(sender);
}
}

View File

@ -46,25 +46,31 @@ namespace Esiur.Net.HTTP
public override bool Execute(HTTPConnection sender)
{
if (DistributedServer == null)
return false;
if (sender.IsWebsocketRequest())
{
if (DistributedServer == null)
return false;
var tcpSocket = sender.Unassign();
var tcpSocket = sender.Unassign();
if (tcpSocket == null)
return false;
if (tcpSocket == null)
return false;
var httpServer = sender.Parent;
var wsSocket = new WSSocket(tcpSocket);
httpServer.RemoveConnection(sender);
var httpServer = sender.Parent;
var wsSocket = new WSSocket(tcpSocket);
httpServer.RemoveConnection(sender);
var iipConnection = new DistributedConnection();
var iipConnection = new DistributedConnection();
DistributedServer.AddConnection(iipConnection);
iipConnection.Assign(wsSocket);
wsSocket.Begin();
DistributedServer.AddConnection(iipConnection);
iipConnection.Assign(wsSocket);
wsSocket.Begin();
return true;
}
return false;
return true;
/*
if (sender.Request.Filename.StartsWith("/iip/"))
{

View File

@ -312,7 +312,7 @@ namespace Esiur.Net.IIP
{
var rt = packet.Parse(msg, offset, ends);
//Console.WriteLine("Rec: " + chunkId + " " + packet.ToString());
/*
if (packet.Command == IIPPacketCommand.Event)
Console.WriteLine("Rec: " + packet.Command.ToString() + " " + packet.Event.ToString());
@ -321,21 +321,27 @@ namespace Esiur.Net.IIP
else
Console.WriteLine("Rec: " + packet.Command.ToString() + " " + packet.Action.ToString() + " " + packet.ResourceId + " " + offset + "/" + ends);
*/
//packs.Add(packet.Command.ToString() + " " + packet.Action.ToString() + " " + packet.Event.ToString());
//if (packs.Count > 1)
// Console.WriteLine("P2");
// Console.WriteLine("P2");
//Console.WriteLine("");
if (rt <= 0)
{
//Console.WriteLine("Hold");
var size = ends - offset;
data.HoldFor(msg, offset, size, size + (uint)(-rt));
return ends;
}
else
{
//Console.WriteLine($"CMD {packet.Command} {offset} {ends}");
offset += (uint)rt;
if (packet.Command == IIPPacket.IIPPacketCommand.Event)
@ -807,7 +813,9 @@ namespace Esiur.Net.IIP
sock.Connect(domain, port).Then((x)=> {
Assign(sock);
//rt.trigger(true);
}).Error((x) => openReply.TriggerError(x));
}).Error((x) =>
openReply.TriggerError(x)
);
return openReply;
}
@ -840,6 +848,65 @@ namespace Esiur.Net.IIP
// nothing to do
return true;
}
AsyncReply<bool> IStore.AddChild(IResource parent, IResource child)
{
// not implemented
throw new NotImplementedException();
}
AsyncReply<bool> IStore.RemoveChild(IResource parent, IResource child)
{
// not implemeneted
throw new NotImplementedException();
}
public AsyncReply<bool> AddParent(IResource child, IResource parent)
{
throw new NotImplementedException();
}
public AsyncReply<bool> RemoveParent(IResource child, IResource parent)
{
throw new NotImplementedException();
}
public AsyncBag<T> Children<T>(IResource resource, string name) where T : IResource
{
throw new Exception("SS");
//if (Codec.IsLocalResource(resource, this))
// return new AsyncBag<T>((resource as DistributedResource).children.Where(x => x.GetType() == typeof(T)).Select(x => (T)x));
return null;
}
public AsyncBag<T> Parents<T>(IResource resource, string name) where T : IResource
{
throw new Exception("SS");
//if (Codec.IsLocalResource(resource, this))
// return (resource as DistributedResource).parents.Where(x => x.GetType() == typeof(T)).Select(x => (T)x);
return null;
}
/*
public AsyncBag<T> Children<T>(IResource resource)
{
if (Codec.IsLocalResource(resource, this))
return (resource as DistributedResource).children.Where(x => x.GetType() == typeof(T)).Select(x => (T)x);
return null;
}
public AsyncBag<T> Parents<T>(IResource resource)
{
if (Codec.IsLocalResource(resource, this))
return (resource as DistributedResource).parents.Where(x => x.GetType() == typeof(T)).Select(x => (T)x);
return null;
}
*/
}
}

View File

@ -387,7 +387,10 @@ namespace Esiur.Net.IIP
{
Fetch(childId).Then(child =>
{
parent.Instance.Children.Add(child);
parent.children.Add(child);
child.parents.Add(parent);
//parent.Instance.Children.Add(child);
});
});
}
@ -398,7 +401,10 @@ namespace Esiur.Net.IIP
{
Fetch(childId).Then(child =>
{
parent.Instance.Children.Remove(child);
parent.children.Remove(child);
child.parents.Remove(parent);
// parent.Instance.Children.Remove(child);
});
});
}
@ -443,16 +449,16 @@ namespace Esiur.Net.IIP
r.Instance.ResourceEventOccurred -= Instance_EventOccurred;
r.Instance.ResourceModified -= Instance_PropertyModified;
r.Instance.ResourceDestroyed -= Instance_ResourceDestroyed;
r.Instance.Children.OnAdd -= Children_OnAdd;
r.Instance.Children.OnRemoved -= Children_OnRemoved;
// r.Instance.Children.OnAdd -= Children_OnAdd;
// r.Instance.Children.OnRemoved -= Children_OnRemoved;
r.Instance.Attributes.OnModified -= Attributes_OnModified;
// subscribe
r.Instance.ResourceEventOccurred += Instance_EventOccurred;
r.Instance.ResourceModified += Instance_PropertyModified;
r.Instance.ResourceDestroyed += Instance_ResourceDestroyed;
r.Instance.Children.OnAdd += Children_OnAdd;
r.Instance.Children.OnRemoved += Children_OnRemoved;
//r.Instance.Children.OnAdd += Children_OnAdd;
//r.Instance.Children.OnRemoved += Children_OnRemoved;
r.Instance.Attributes.OnModified += Attributes_OnModified;
var link = DC.ToBytes(r.Instance.Link);
@ -520,6 +526,28 @@ namespace Esiur.Net.IIP
.Done();
}
public bool RemoveChild(IResource parent, IResource child)
{
SendEvent(IIPPacket.IIPPacketEvent.ChildRemoved)
.AddUInt32((parent as DistributedResource).Id)
.AddUInt32((child as DistributedResource).Id)
.Done();
return true;
}
public bool AddChild(IResource parent, IResource child)
{
SendEvent(IIPPacket.IIPPacketEvent.ChildAdded)
.AddUInt32((parent as DistributedResource).Id)
.AddUInt32((child as DistributedResource).Id)
.Done();
return true;
}
void IIPRequestReattachResource(uint callback, uint resourceId, ulong resourceAge)
{
Warehouse.Get(resourceId).Then((res) =>
@ -531,16 +559,16 @@ namespace Esiur.Net.IIP
r.Instance.ResourceEventOccurred -= Instance_EventOccurred;
r.Instance.ResourceModified -= Instance_PropertyModified;
r.Instance.ResourceDestroyed -= Instance_ResourceDestroyed;
r.Instance.Children.OnAdd -= Children_OnAdd;
r.Instance.Children.OnRemoved -= Children_OnRemoved;
//r.Instance.Children.OnAdd -= Children_OnAdd;
//r.Instance.Children.OnRemoved -= Children_OnRemoved;
r.Instance.Attributes.OnModified -= Attributes_OnModified;
// subscribe
r.Instance.ResourceEventOccurred += Instance_EventOccurred;
r.Instance.ResourceModified += Instance_PropertyModified;
r.Instance.ResourceDestroyed += Instance_ResourceDestroyed;
r.Instance.Children.OnAdd += Children_OnAdd;
r.Instance.Children.OnRemoved += Children_OnRemoved;
//r.Instance.Children.OnAdd += Children_OnAdd;
//r.Instance.Children.OnRemoved += Children_OnRemoved;
r.Instance.Attributes.OnModified += Attributes_OnModified;
// reply ok
@ -646,7 +674,7 @@ namespace Esiur.Net.IIP
Codec.ParseStructure(content, offset, cl, this).Then(values =>
{
#if NETSTANDARD1_5
#if NETSTANDARD
var constructors = Type.GetType(className).GetTypeInfo().GetConstructors();
#else
var constructors = Type.GetType(className).GetConstructors();
@ -791,7 +819,7 @@ namespace Esiur.Net.IIP
return;
}
parent.Instance.Children.Add(child);
parent.Instance.Store.AddChild(parent, child);
SendReply(IIPPacket.IIPPacketAction.AddChild, callback).Done();
//child.Instance.Parents
@ -830,7 +858,7 @@ namespace Esiur.Net.IIP
return;
}
parent.Instance.Children.Remove(child);
parent.Instance.Store.RemoveChild(parent, child);// Children.Remove(child);
SendReply(IIPPacket.IIPPacketAction.RemoveChild, callback).Done();
//child.Instance.Parents
@ -871,9 +899,14 @@ namespace Esiur.Net.IIP
return;
}
SendReply(IIPPacket.IIPPacketAction.ResourceChildren, callback)
.AddUInt8Array(Codec.ComposeResourceArray(resource.Instance.Children.ToArray(), this, true))
.Done();
resource.Instance.Children<IResource>().Then(children =>
{
SendReply(IIPPacket.IIPPacketAction.ResourceChildren, callback)
.AddUInt8Array(Codec.ComposeResourceArray(children, this, true))
.Done();
});
});
}
@ -888,9 +921,14 @@ namespace Esiur.Net.IIP
return;
}
SendReply(IIPPacket.IIPPacketAction.ResourceParents, callback)
.AddUInt8Array(Codec.ComposeResourceArray(resource.Instance.Parents.ToArray(), this, true))
.Done();
resource.Instance.Parents<IResource>().Then(parents =>
{
SendReply(IIPPacket.IIPPacketAction.ResourceParents, callback)
.AddUInt8Array(Codec.ComposeResourceArray(parents, this, true))
.Done();
});
});
}
@ -1010,7 +1048,8 @@ namespace Esiur.Net.IIP
void IIPRequestQueryResources(uint callback, string resourceLink)
{
Warehouse.Query(resourceLink).Then((r) =>
Action<IResource[]> queryCallback = (r) =>
{
//if (r != null)
//{
@ -1022,12 +1061,12 @@ namespace Esiur.Net.IIP
SendReply(IIPPacket.IIPPacketAction.QueryLink, callback)
.AddUInt8Array(Codec.ComposeResourceArray(list, this, true))
.Done();
//}
//else
//{
// reply failed
//}
});
};
if (Server?.EntryPoint != null)
Server.EntryPoint.Query(resourceLink, this).Then(queryCallback);
else
Warehouse.Query(resourceLink).ContinueWith(x => queryCallback(x.Result));
}
void IIPRequestResourceAttribute(uint callback, uint resourceId)
@ -1068,7 +1107,7 @@ namespace Esiur.Net.IIP
}
else
{
#if NETSTANDARD1_5
#if NETSTANDARD
var fi = r.GetType().GetTypeInfo().GetMethod(ft.Name);
#else
var fi = r.GetType().GetMethod(ft.Name);
@ -1134,7 +1173,7 @@ namespace Esiur.Net.IIP
{
(rt as Task).ContinueWith(t =>
{
#if NETSTANDARD1_5
#if NETSTANDARD
var res = t.GetType().GetTypeInfo().GetProperty("Result").GetValue(t);
#else
var res = t.GetType().GetProperty("Result").GetValue(t);
@ -1225,7 +1264,7 @@ namespace Esiur.Net.IIP
}
else
{
#if NETSTANDARD1_5
#if NETSTANDARD
var fi = r.GetType().GetTypeInfo().GetMethod(ft.Name);
#else
var fi = r.GetType().GetMethod(ft.Name);
@ -1285,7 +1324,7 @@ namespace Esiur.Net.IIP
{
(rt as Task).ContinueWith(t =>
{
#if NETSTANDARD1_5
#if NETSTANDARD
var res = t.GetType().GetTypeInfo().GetProperty("Result").GetValue(t);
#else
var res = t.GetType().GetProperty("Result").GetValue(t);
@ -1358,7 +1397,7 @@ namespace Esiur.Net.IIP
}
else
{
#if NETSTANDARD1_5
#if NETSTANDARD
var pi = r.GetType().GetTypeInfo().GetProperty(pt.Name);
#else
var pi = r.GetType().GetProperty(pt.Name);
@ -1435,7 +1474,7 @@ namespace Esiur.Net.IIP
{
if (r.Instance.GetAge(index) > age)
{
#if NETSTANDARD1_5
#if NETSTANDARD
var pi = r.GetType().GetTypeInfo().GetProperty(pt.Name);
#else
var pi = r.GetType().GetProperty(pt.Name);
@ -1498,7 +1537,7 @@ namespace Esiur.Net.IIP
{
/*
#if NETSTANDARD1_5
#if NETSTANDARD
var pi = r.GetType().GetTypeInfo().GetProperty(pt.Name);
#else
var pi = r.GetType().GetProperty(pt.Name);
@ -1748,12 +1787,18 @@ namespace Esiur.Net.IIP
Query(path).Then(ar =>
{
//if (filter != null)
// ar = ar?.Where(filter).ToArray();
// MISSING: should dispatch the unused resources.
if (ar?.Length > 0)
rt.Trigger(ar[0]);
else
rt.Trigger(null);
}).Error(ex => rt.TriggerError(ex));
return rt;
/*

View File

@ -53,7 +53,7 @@ namespace Esiur.Net.IIP
/// Raised when the distributed resource is destroyed.
/// </summary>
public event DestroyedEvent OnDestroy;
public event Instance.ResourceModifiedEvent OnModified;
uint instanceId;
DistributedConnection connection;
@ -68,6 +68,9 @@ namespace Esiur.Net.IIP
//ulong age;
//ulong[] ages;
object[] properties;
internal List<DistributedResource> parents = new List<DistributedResource>();
internal List<DistributedResource> children = new List<DistributedResource>();
DistributedResourceEvent[] events;
//ResourceTemplate template;
@ -171,10 +174,12 @@ namespace Esiur.Net.IIP
this.link = link;
this.connection = connection;
this.instanceId = instanceId;
//this.Instance.Template = template;
//this.Instance.Age = age;
//this.template = template;
//this.age = age;
}
internal void _Ready()
@ -270,16 +275,12 @@ namespace Esiur.Net.IIP
if (args.Length == 1)
{
// Detect anonymous types
var type = args[0].GetType().GetTypeInfo();
var hasCompilerGeneratedAttribute = type.GetCustomAttributes(typeof(CompilerGeneratedAttribute), false).Count() > 0;
var nameContainsAnonymousType = type.FullName.Contains("AnonymousType");
var isAnonymousType = hasCompilerGeneratedAttribute && nameContainsAnonymousType;
if (isAnonymousType)
var type = args[0].GetType();
if (Codec.IsAnonymous(type))
{
var namedArgs = new Structure();
var pi = type.GetProperties();
var pi = type.GetTypeInfo().GetProperties();
foreach (var p in pi)
namedArgs[p.Name] = p.GetValue(args[0]);
result = _InvokeByNamedArguments(ft.Index, namedArgs);
@ -453,9 +454,10 @@ namespace Esiur.Net.IIP
public DistributedResource()
{
//stack = new DistributedResourceStack(this);
//this.Instance.ResourceModified += this.OnModified;
}
/// <summary>
/// Resource interface.
/// </summary>
@ -463,6 +465,10 @@ namespace Esiur.Net.IIP
/// <returns></returns>
public AsyncReply<bool> Trigger(ResourceTrigger trigger)
{
if (trigger == ResourceTrigger.Initialize)
this.Instance.ResourceModified += this.OnModified;
// do nothing.
return new AsyncReply<bool>(true);
}

View File

@ -56,6 +56,12 @@ namespace Esiur.Net.IIP
set;
}
public EntryPoint EntryPoint
{
get;
set;
}
//[Storable]
//[ResourceProperty]
public ushort port
@ -128,8 +134,7 @@ namespace Esiur.Net.IIP
protected override void ClientConnected(DistributedConnection sender)
{
Console.WriteLine("DistributedConnection Client Connected");
//Console.WriteLine("DistributedConnection Client Connected");
}
private void Sender_OnReady(DistributedConnection sender)

View File

@ -0,0 +1,40 @@
/*
Copyright (c) 2019 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic;
using System.Text;
using Esiur.Core;
using Esiur.Data;
using Esiur.Resource;
using Esiur.Resource.Template;
namespace Esiur.Net.IIP
{
public abstract class EntryPoint : Esiur.Resource.Resource
{
public abstract AsyncReply<IResource[]> Query(string path, DistributedConnection sender);
public abstract override bool Create();
}
}

View File

@ -209,8 +209,8 @@ namespace Esiur.Net.Packets
{
if (offset + needed > ends)
{
//dataLengthNeeded = needed - (ends - offset);
dataLengthNeeded = needed - (ends - originalOffset);
dataLengthNeeded = needed - (ends - offset);
//dataLengthNeeded = needed - (ends - originalOffset);
return true;
}

View File

@ -53,6 +53,7 @@ namespace Esiur.Net.Sockets
bool asyncSending;
bool began = false;
SocketState state = SocketState.Initial;
public event ISocketReceiveEvent OnReceive;
@ -313,23 +314,23 @@ namespace Esiur.Net.Sockets
public void Close()
{
if (state != SocketState.Closed && state != SocketState.Terminated)
{
state = SocketState.Closed;
if (sock.Connected)
{
try
if (sock.Connected)
{
sock.Shutdown(SocketShutdown.Both);
}
catch
{
state = SocketState.Terminated;
try
{
sock.Shutdown(SocketShutdown.Both);
}
catch
{
state = SocketState.Terminated;
}
}
sock.Shutdown(SocketShutdown.Both);// Close();
OnClose?.Invoke();
}
}
public void Send(byte[] message)

View File

@ -65,18 +65,24 @@ namespace Esiur.Net.TCP
}
public Instance Instance { get; set; }
TCPFilter[] filters = null;
public AsyncReply<bool> Trigger(ResourceTrigger trigger)
{
if (trigger == ResourceTrigger.Initialize)
{
TCPSocket listener;
if (ip != null)
listener =new TCPSocket(new IPEndPoint(IPAddress.Parse(ip), port));
else
listener = new TCPSocket(new IPEndPoint(IPAddress.Any, port));
Start(listener, timeout, clock);
}
else if (trigger == ResourceTrigger.Terminate)
{
@ -87,6 +93,10 @@ namespace Esiur.Net.TCP
Trigger(ResourceTrigger.Terminate);
Trigger(ResourceTrigger.Initialize);
}
else if (trigger == ResourceTrigger.SystemInitialized)
{
Instance.Children<TCPFilter>().Then(x => filters = x);
}
return new AsyncReply<bool>(true);
}
@ -97,14 +107,10 @@ namespace Esiur.Net.TCP
{
var msg = data.Read();
foreach (var resource in Instance.Children)
{
if (resource is TCPFilter)
{
var f = resource as TCPFilter;
if (f.Execute(msg, data, sender))
foreach (var filter in filters)
{
if (filter.Execute(msg, data, sender))
return;
}
}
}
@ -115,25 +121,17 @@ namespace Esiur.Net.TCP
protected override void ClientConnected(TCPConnection sender)
{
foreach (var resource in Instance.Children)
foreach (var filter in filters)
{
if (resource is TCPFilter)
{
var f = resource as TCPFilter;
f.Connected(sender);
}
filter.Connected(sender);
}
}
protected override void ClientDisconnected(TCPConnection sender)
{
foreach (var resource in Instance.Children)
foreach (var filter in filters)
{
if (resource is TCPFilter)
{
var f = resource as TCPFilter;
f.Disconnected(sender);
}
filter.Disconnected(sender);
}
}