2
0
mirror of https://github.com/esiur/esiur-dotnet.git synced 2025-06-27 05:23:13 +00:00

.Net 6 Upgrade

This commit is contained in:
2021-12-01 12:17:45 +03:00
parent 1166e93ba9
commit 530df018ec
164 changed files with 21247 additions and 21425 deletions

View File

@ -31,26 +31,24 @@ using Esiur.Data;
using Esiur.Net.Packets;
using Esiur.Resource;
namespace Esiur.Net.DataLink
namespace Esiur.Net.DataLink;
public abstract class PacketFilter : IResource
{
public abstract class PacketFilter : IResource
public Instance Instance
{
get;
set;
}
public Instance Instance
{
get;
set;
}
public event DestroyedEvent OnDestroy;
public event DestroyedEvent OnDestroy;
public abstract AsyncReply<bool> Trigger(ResourceTrigger trigger);
public abstract AsyncReply<bool> Trigger(ResourceTrigger trigger);
public abstract bool Execute(Packet packet);
public abstract bool Execute(Packet packet);
public void Destroy()
{
OnDestroy?.Invoke(this);
}
public void Destroy()
{
OnDestroy?.Invoke(this);
}
}

View File

@ -32,91 +32,89 @@ using System.Runtime.InteropServices;
using Esiur.Net.Packets;
using Esiur.Resource;
namespace Esiur.Net.DataLink
namespace Esiur.Net.DataLink;
public class PacketServer : IResource
{
public class PacketServer:IResource
List<PacketSource> sources = new List<PacketSource>();
List<PacketFilter> filters = new List<PacketFilter>();
[Storable]
public string Mode
{
List<PacketSource> sources = new List<PacketSource>();
List<PacketFilter> filters = new List<PacketFilter>();
get;
set;
}
[Storable]
public string Mode
public Instance Instance
{
get;
set;
}
public List<PacketSource> Sources
{
get
{
get;
set;
return sources;
}
}
public Instance Instance
{
get;
set;
}
public event DestroyedEvent OnDestroy;
public List<PacketSource> Sources
public void Destroy()
{
OnDestroy?.Invoke(this);
}
public AsyncReply<bool> Trigger(ResourceTrigger trigger)
{
if (trigger == ResourceTrigger.Initialize)
{
get
/*
foreach (var resource in Instance.Children<IResource>())
{
return sources;
if (resource is PacketFilter)
{
filters.Add(resource as PacketFilter);
}
else if (resource is PacketSource)
{
sources.Add(resource as PacketSource);
}
}
*/
foreach (var src in sources)
{
src.OnNewPacket += PacketReceived;
src.Open();
}
}
else if (trigger == ResourceTrigger.Terminate)
{
// foreach (var src in sources)
// src.Close();
}
else if (trigger == ResourceTrigger.SystemReload)
{
foreach (var src in sources)
{
src.Close();
src.Open();
}
}
public event DestroyedEvent OnDestroy;
return new AsyncReply<bool>(true);
}
public void Destroy()
void PacketReceived(Packet Packet)
{
foreach (var f in filters)
{
OnDestroy?.Invoke(this);
}
public AsyncReply<bool> Trigger(ResourceTrigger trigger)
{
if (trigger == ResourceTrigger.Initialize)
if (f.Execute(Packet))
{
/*
foreach (var resource in Instance.Children<IResource>())
{
if (resource is PacketFilter)
{
filters.Add(resource as PacketFilter);
}
else if (resource is PacketSource)
{
sources.Add(resource as PacketSource);
}
}
*/
foreach (var src in sources)
{
src.OnNewPacket += PacketReceived;
src.Open();
}
}
else if (trigger == ResourceTrigger.Terminate)
{
// foreach (var src in sources)
// src.Close();
}
else if (trigger == ResourceTrigger.SystemReload)
{
foreach (var src in sources)
{
src.Close();
src.Open();
}
}
return new AsyncReply<bool>( true);
}
void PacketReceived(Packet Packet)
{
foreach (var f in filters)
{
if (f.Execute(Packet))
{
break;
}
break;
}
}
}

View File

@ -30,66 +30,64 @@ using System.Text;
using Esiur.Core;
using Esiur.Resource;
namespace Esiur.Net.DataLink
namespace Esiur.Net.DataLink;
public abstract class PacketSource : IResource
{
public abstract class PacketSource: IResource
public delegate void NewPacket(Packet Packet);
public abstract event NewPacket OnNewPacket;
public event DestroyedEvent OnDestroy;
public Instance Instance
{
public delegate void NewPacket(Packet Packet);
public abstract event NewPacket OnNewPacket;
public event DestroyedEvent OnDestroy;
get;
set;
}
public Instance Instance
public abstract AsyncReply<bool> Trigger(ResourceTrigger trigger);
public abstract bool RawMode
{
set;
get;
}
//public PacketSource(PacketServer Server, bool RawMode)
//{
// this.RawMode = RawMode;
//}
public abstract bool Open();
public abstract bool Close();
public abstract bool Write(Packet packet);
public void Destroy()
{
OnDestroy?.Invoke(this);
}
/*
public virtual string TypeName
{
get
{
get;
set;
}
public abstract AsyncReply<bool> Trigger(ResourceTrigger trigger);
public abstract bool RawMode
{
set;
get;
}
//public PacketSource(PacketServer Server, bool RawMode)
//{
// this.RawMode = RawMode;
//}
public abstract bool Open();
public abstract bool Close();
public abstract bool Write(Packet packet);
public void Destroy()
{
OnDestroy?.Invoke(this);
}
/*
public virtual string TypeName
{
get
{
return "Raw";
}
}
*/
public abstract byte[] Address
{
get;
}
public abstract string DeviceId
{
get;
return "Raw";
}
}
*/
public abstract byte[] Address
{
get;
}
public abstract string DeviceId
{
get;
}
}

View File

@ -38,400 +38,399 @@ using Esiur.Misc;
using System.Security.Cryptography;
using Esiur.Core;
namespace Esiur.Net.HTTP
namespace Esiur.Net.HTTP;
public class HTTPConnection : NetworkConnection
{
public class HTTPConnection : NetworkConnection
public bool WSMode { get; internal set; }
public HTTPServer Server { get; internal set; }
public WebsocketPacket WSRequest { get; set; }
public HTTPRequestPacket Request { get; set; }
public HTTPResponsePacket Response { get; } = new HTTPResponsePacket();
HTTPSession session;
public KeyList<string, object> Variables { get; } = new KeyList<string, object>();
internal long Parse(byte[] data)
{
public bool WSMode { get; internal set; }
public HTTPServer Server { get; internal set; }
public WebsocketPacket WSRequest { get; set; }
public HTTPRequestPacket Request { get; set; }
public HTTPResponsePacket Response { get; } = new HTTPResponsePacket();
HTTPSession session;
public KeyList<string, object> Variables { get; } = new KeyList<string, object>();
internal long Parse(byte[] data)
if (WSMode)
{
if (WSMode)
// now parse WS protocol
WebsocketPacket ws = new WebsocketPacket();
var pSize = ws.Parse(data, 0, (uint)data.Length);
if (pSize > 0)
{
// now parse WS protocol
WebsocketPacket ws = new WebsocketPacket();
var pSize = ws.Parse(data, 0, (uint)data.Length);
if (pSize > 0)
{
WSRequest = ws;
return 0;
}
else
{
return pSize;
}
WSRequest = ws;
return 0;
}
else
{
var rp = new HTTPRequestPacket();
var pSize = rp.Parse(data, 0, (uint)data.Length);
if (pSize > 0)
{
Request = rp;
return 0;
}
else
{
return pSize;
}
return pSize;
}
}
public void Flush()
else
{
// close the connection
if (Request.Headers["connection"].ToLower() != "keep-alive" & IsConnected)
Close();
var rp = new HTTPRequestPacket();
var pSize = rp.Parse(data, 0, (uint)data.Length);
if (pSize > 0)
{
Request = rp;
return 0;
}
else
{
return pSize;
}
}
}
public void Flush()
{
// close the connection
if (Request.Headers["connection"].ToLower() != "keep-alive" & IsConnected)
Close();
}
public bool Upgrade()
{
if (IsWebsocketRequest())
{
string magicString = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
string ret = Request.Headers["Sec-WebSocket-Key"] + magicString;
// Compute the SHA1 hash
SHA1 sha = SHA1.Create();
byte[] sha1Hash = sha.ComputeHash(Encoding.UTF8.GetBytes(ret));
Response.Headers["Upgrade"] = Request.Headers["Upgrade"];
Response.Headers["Connection"] = Request.Headers["Connection"];// "Upgrade";
Response.Headers["Sec-WebSocket-Accept"] = Convert.ToBase64String(sha1Hash);
if (Request.Headers.ContainsKey("Sec-WebSocket-Protocol"))
Response.Headers["Sec-WebSocket-Protocol"] = Request.Headers["Sec-WebSocket-Protocol"];
Response.Number = HTTPResponsePacket.ResponseCode.Switching;
Response.Text = "Switching Protocols";
WSMode = true;
Send();
return true;
}
public bool Upgrade()
return false;
}
public HTTPServer Parent
{
get
{
if (IsWebsocketRequest())
return Server;
}
}
public void Send(WebsocketPacket packet)
{
if (packet.Data != null)
base.Send(packet.Data);
}
public override void Send(string data)
{
Response.Message = Encoding.UTF8.GetBytes(data);
Send();
}
public override void Send(byte[] msg, int offset, int length)
{
Response.Message = DC.Clip(msg, (uint)offset, (uint)length);
Send();
}
public override void Send(byte[] message)
{
Response.Message = message;
Send();
}
public void Send(HTTPResponsePacket.ComposeOptions Options = HTTPResponsePacket.ComposeOptions.AllCalculateLength)
{
if (Response.Handled)
return;
try
{
Response.Compose(Options);
base.Send(Response.Data);
// Refresh the current session
if (session != null)
session.Refresh();
}
catch
{
try
{
string magicString = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
string ret = Request.Headers["Sec-WebSocket-Key"] + magicString;
// Compute the SHA1 hash
SHA1 sha = SHA1.Create();
byte[] sha1Hash = sha.ComputeHash(Encoding.UTF8.GetBytes(ret));
Response.Headers["Upgrade"] = Request.Headers["Upgrade"];
Response.Headers["Connection"] = Request.Headers["Connection"];// "Upgrade";
Response.Headers["Sec-WebSocket-Accept"] = Convert.ToBase64String(sha1Hash);
Close();
}
finally { }
}
finally
{
if (Request.Headers.ContainsKey("Sec-WebSocket-Protocol"))
Response.Headers["Sec-WebSocket-Protocol"] = Request.Headers["Sec-WebSocket-Protocol"];
}
}
Response.Number = HTTPResponsePacket.ResponseCode.Switching;
Response.Text = "Switching Protocols";
WSMode = true;
public void CreateNewSession()
{
if (session == null)
{
// Create a new one
session = Server.CreateSession(Global.GenerateCode(12), 60 * 20);
Send();
HTTPResponsePacket.HTTPCookie cookie = new HTTPResponsePacket.HTTPCookie("SID", session.Id);
cookie.Expires = DateTime.MaxValue;
cookie.Path = "/";
cookie.HttpOnly = true;
Response.Cookies.Add(cookie);
}
}
public bool IsWebsocketRequest()
{
if (Request.Headers.ContainsKey("connection")
&& Request.Headers["connection"].ToLower().Contains("upgrade")
&& Request.Headers.ContainsKey("upgrade")
&& Request.Headers["upgrade"].ToLower() == "websocket"
&& Request.Headers.ContainsKey("Sec-WebSocket-Version")
&& Request.Headers["Sec-WebSocket-Version"] == "13"
&& Request.Headers.ContainsKey("Sec-WebSocket-Key"))
//&& Request.Headers.ContainsKey("Sec-WebSocket-Protocol"))
{
return true;
}
else
{
return false;
}
}
protected override void DataReceived(NetworkBuffer data)
{
byte[] msg = data.Read();
var BL = Parse(msg);
if (BL == 0)
{
if (Request.Method == HTTPRequestPacket.HTTPMethod.UNKNOWN)
{
Close();
return;
}
if (Request.URL == "")
{
Close();
return;
}
}
else if (BL == -1)
{
data.HoldForNextWrite(msg);
return;
}
else if (BL < 0)
{
data.HoldFor(msg, (uint)(msg.Length - BL));
return;
}
else if (BL > 0)
{
if (BL > Server.MaxPost)
{
Send(
"<html><body>POST method content is larger than "
+ Server.MaxPost
+ " bytes.</body></html>");
Close();
}
else
{
data.HoldFor(msg, (uint)(msg.Length + BL));
}
return;
}
else if (BL < 0) // for security
{
Close();
return;
}
if (IsWebsocketRequest() & !WSMode)
{
Upgrade();
//return;
}
//return;
try
{
if (!Server.Execute(this))
{
Response.Number = HTTPResponsePacket.ResponseCode.InternalServerError;
Send("Bad Request");
Close();
}
}
catch (Exception ex)
{
if (ex.Message != "Thread was being aborted.")
{
Global.Log("HTTPServer", LogType.Error, ex.ToString());
//Console.WriteLine(ex.ToString());
//EventLog.WriteEntry("HttpServer", ex.ToString(), EventLogEntryType.Error);
Send(Error500(ex.Message));
}
}
}
private string Error500(string msg)
{
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";
}
public async AsyncReply<bool> SendFile(string filename)
{
if (Response.Handled == true)
return false;
try
{
//HTTP/1.1 200 OK
//Server: Microsoft-IIS/5.0
//Content-Location: http://127.0.0.1/index.html
//Date: Wed, 10 Dec 2003 19:10:25 GMT
//Content-Type: text/html
//Accept-Ranges: bytes
//Last-Modified: Mon, 22 Sep 2003 22:36:56 GMT
//Content-Length: 1957
if (!File.Exists(filename))
{
Response.Number = HTTPResponsePacket.ResponseCode.NotFound;
Send("File Not Found");
return true;
}
return false;
}
public HTTPServer Parent
{
get
{
return Server;
}
}
public void Send(WebsocketPacket packet)
{
if (packet.Data != null)
base.Send(packet.Data);
}
public override void Send(string data)
{
Response.Message = Encoding.UTF8.GetBytes(data);
Send();
}
public override void Send(byte[] msg, int offset, int length)
{
Response.Message = DC.Clip(msg, (uint)offset, (uint)length);
Send();
}
public override void Send(byte[] message)
{
Response.Message = message;
Send();
}
public void Send(HTTPResponsePacket.ComposeOptions Options = HTTPResponsePacket.ComposeOptions.AllCalculateLength)
{
if (Response.Handled)
return;
try
{
Response.Compose(Options);
base.Send(Response.Data);
// Refresh the current session
if (session != null)
session.Refresh();
}
catch
var fileEditTime = File.GetLastWriteTime(filename).ToUniversalTime();
if (Request.Headers.ContainsKey("if-modified-since"))
{
try
{
Close();
var ims = DateTime.Parse(Request.Headers["if-modified-since"]);
if ((fileEditTime - ims).TotalSeconds < 2)
{
Response.Number = HTTPResponsePacket.ResponseCode.NotModified;
Response.Headers.Clear();
//Response.Text = "Not Modified";
Send(HTTPResponsePacket.ComposeOptions.SpecifiedHeadersOnly);
return true;
}
}
finally { }
catch
{
return false;
}
}
Response.Number = HTTPResponsePacket.ResponseCode.OK;
// Fri, 30 Oct 2007 14:19:41 GMT
Response.Headers["Last-Modified"] = fileEditTime.ToString("ddd, dd MMM yyyy HH:mm:ss");
FileInfo fi = new FileInfo(filename);
Response.Headers["Content-Length"] = fi.Length.ToString();
Send(HTTPResponsePacket.ComposeOptions.SpecifiedHeadersOnly);
//var fd = File.ReadAllBytes(filename);
//base.Send(fd);
using (var fs = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read))
{
var buffer = new byte[60000];
while (true)
{
var n = fs.Read(buffer, 0, 60000);
if (n <= 0)
break;
//Thread.Sleep(50);
await base.SendAsync(buffer, 0, n);
}
}
return true;
}
catch
{
try
{
Close();
}
finally
{
}
}
public void CreateNewSession()
{
if (session == null)
{
// Create a new one
session = Server.CreateSession(Global.GenerateCode(12), 60 * 20);
HTTPResponsePacket.HTTPCookie cookie = new HTTPResponsePacket.HTTPCookie("SID", session.Id);
cookie.Expires = DateTime.MaxValue;
cookie.Path = "/";
cookie.HttpOnly = true;
Response.Cookies.Add(cookie);
}
}
public bool IsWebsocketRequest()
{
if (Request.Headers.ContainsKey("connection")
&& Request.Headers["connection"].ToLower().Contains("upgrade")
&& Request.Headers.ContainsKey("upgrade")
&& Request.Headers["upgrade"].ToLower() == "websocket"
&& Request.Headers.ContainsKey("Sec-WebSocket-Version")
&& Request.Headers["Sec-WebSocket-Version"] == "13"
&& Request.Headers.ContainsKey("Sec-WebSocket-Key"))
//&& Request.Headers.ContainsKey("Sec-WebSocket-Protocol"))
{
return true;
}
else
{
return false;
}
}
protected override void DataReceived(NetworkBuffer data)
{
byte[] msg = data.Read();
var BL = Parse(msg);
if (BL == 0)
{
if (Request.Method == HTTPRequestPacket.HTTPMethod.UNKNOWN)
{
Close();
return;
}
if (Request.URL == "")
{
Close();
return;
}
}
else if (BL == -1)
{
data.HoldForNextWrite(msg);
return;
}
else if (BL < 0)
{
data.HoldFor(msg, (uint)(msg.Length - BL));
return;
}
else if (BL > 0)
{
if (BL > Server.MaxPost)
{
Send(
"<html><body>POST method content is larger than "
+ Server.MaxPost
+ " bytes.</body></html>");
Close();
}
else
{
data.HoldFor(msg, (uint)(msg.Length + BL));
}
return;
}
else if (BL < 0) // for security
{
Close();
return;
}
if (IsWebsocketRequest() & !WSMode)
{
Upgrade();
//return;
}
//return;
try
{
if (!Server.Execute(this))
{
Response.Number = HTTPResponsePacket.ResponseCode.InternalServerError;
Send("Bad Request");
Close();
}
}
catch (Exception ex)
{
if (ex.Message != "Thread was being aborted.")
{
Global.Log("HTTPServer", LogType.Error, ex.ToString());
//Console.WriteLine(ex.ToString());
//EventLog.WriteEntry("HttpServer", ex.ToString(), EventLogEntryType.Error);
Send(Error500(ex.Message));
}
}
}
private string Error500(string msg)
{
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";
}
public async AsyncReply<bool> SendFile(string filename)
{
if (Response.Handled == true)
return false;
try
{
//HTTP/1.1 200 OK
//Server: Microsoft-IIS/5.0
//Content-Location: http://127.0.0.1/index.html
//Date: Wed, 10 Dec 2003 19:10:25 GMT
//Content-Type: text/html
//Accept-Ranges: bytes
//Last-Modified: Mon, 22 Sep 2003 22:36:56 GMT
//Content-Length: 1957
if (!File.Exists(filename))
{
Response.Number = HTTPResponsePacket.ResponseCode.NotFound;
Send("File Not Found");
return true;
}
var fileEditTime = File.GetLastWriteTime(filename).ToUniversalTime();
if (Request.Headers.ContainsKey("if-modified-since"))
{
try
{
var ims = DateTime.Parse(Request.Headers["if-modified-since"]);
if ((fileEditTime - ims).TotalSeconds < 2)
{
Response.Number = HTTPResponsePacket.ResponseCode.NotModified;
Response.Headers.Clear();
//Response.Text = "Not Modified";
Send(HTTPResponsePacket.ComposeOptions.SpecifiedHeadersOnly);
return true;
}
}
catch
{
return false;
}
}
Response.Number = HTTPResponsePacket.ResponseCode.OK;
// Fri, 30 Oct 2007 14:19:41 GMT
Response.Headers["Last-Modified"] = fileEditTime.ToString("ddd, dd MMM yyyy HH:mm:ss");
FileInfo fi = new FileInfo(filename);
Response.Headers["Content-Length"] = fi.Length.ToString();
Send(HTTPResponsePacket.ComposeOptions.SpecifiedHeadersOnly);
//var fd = File.ReadAllBytes(filename);
//base.Send(fd);
using (var fs = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read))
{
var buffer = new byte[60000];
while (true)
{
var n = fs.Read(buffer, 0, 60000);
if (n <= 0)
break;
//Thread.Sleep(50);
await base.SendAsync(buffer, 0, n);
}
}
return true;
}
catch
{
try
{
Close();
}
finally {
}
return false;
}
}
protected override void Connected()
{
// do nothing
}
protected override void Disconencted()
{
// do nothing
return false;
}
}
}
protected override void Connected()
{
// do nothing
}
protected override void Disconencted()
{
// do nothing
}
}

View File

@ -35,48 +35,46 @@ using Esiur.Data;
using Esiur.Core;
using Esiur.Resource;
namespace Esiur.Net.HTTP
namespace Esiur.Net.HTTP;
public abstract class HTTPFilter : IResource
{
public abstract class HTTPFilter : IResource
public Instance Instance
{
public Instance Instance
{
get;
set;
}
public event DestroyedEvent OnDestroy;
public abstract AsyncReply<bool> Trigger(ResourceTrigger trigger);
/*
public virtual void SessionModified(HTTPSession session, string key, object oldValue, object newValue)
{
}
public virtual void SessionExpired(HTTPSession session)
{
}
*/
public abstract AsyncReply<bool> Execute(HTTPConnection sender);
public virtual void ClientConnected(HTTPConnection HTTP)
{
//return false;
}
public virtual void ClientDisconnected(HTTPConnection HTTP)
{
//return false;
}
public void Destroy()
{
OnDestroy?.Invoke(this);
}
get;
set;
}
}
public event DestroyedEvent OnDestroy;
public abstract AsyncReply<bool> Trigger(ResourceTrigger trigger);
/*
public virtual void SessionModified(HTTPSession session, string key, object oldValue, object newValue)
{
}
public virtual void SessionExpired(HTTPSession session)
{
}
*/
public abstract AsyncReply<bool> Execute(HTTPConnection sender);
public virtual void ClientConnected(HTTPConnection HTTP)
{
//return false;
}
public virtual void ClientDisconnected(HTTPConnection HTTP)
{
//return false;
}
public void Destroy()
{
OnDestroy?.Invoke(this);
}
}

View File

@ -39,262 +39,260 @@ using Esiur.Net.Packets;
using System.Security.Cryptography.X509Certificates;
using Esiur.Resource;
namespace Esiur.Net.HTTP
namespace Esiur.Net.HTTP;
public class HTTPServer : NetworkServer<HTTPConnection>, IResource
{
public class HTTPServer : NetworkServer<HTTPConnection>, IResource
Dictionary<string, HTTPSession> sessions = new Dictionary<string, HTTPSession>();
HTTPFilter[] filters = new HTTPFilter[0];
public Instance Instance
{
Dictionary<string, HTTPSession> sessions= new Dictionary<string, HTTPSession>();
HTTPFilter[] filters = new HTTPFilter[0];
get;
set;
}
public Instance Instance
[Attribute]
public virtual string IP
{
get;
set;
}
[Attribute]
public virtual ushort Port
{
get;
set;
}
//[Attribute]
//public virtual uint Timeout
//{
// get;
// set;
//}
//[Attribute]
//public virtual uint Clock
//{
// get;
// set;
//}
[Attribute]
public virtual uint MaxPost
{
get;
set;
}
[Attribute]
public virtual bool SSL
{
get;
set;
}
[Attribute]
public virtual string Certificate
{
get;
set;
}
public HTTPSession CreateSession(string id, int timeout)
{
var s = new HTTPSession();
s.Set(id, timeout);
sessions.Add(id, s);
return s;
}
public static string MakeCookie(string Item, string Value, DateTime Expires, string Domain, string Path, bool HttpOnly)
{
//Set-Cookie: ckGeneric=CookieBody; expires=Sun, 30-Dec-2001 21:00:00 GMT; domain=.com.au; path=/
//Set-Cookie: SessionID=another; expires=Fri, 29 Jun 2006 20:47:11 UTC; path=/
string Cookie = Item + "=" + Value;
if (Expires.Ticks != 0)
{
get;
set;
Cookie += "; expires=" + Expires.ToUniversalTime().ToString("ddd, dd MMM yyyy HH:mm:ss") + " GMT";
}
[Attribute]
public virtual string IP
if (Domain != null)
{
get;
set;
Cookie += "; domain=" + Domain;
}
[Attribute]
public virtual ushort Port
if (Path != null)
{
get;
set;
Cookie += "; path=" + Path;
}
//[Attribute]
//public virtual uint Timeout
//{
// get;
// set;
//}
//[Attribute]
//public virtual uint Clock
//{
// get;
// set;
//}
[Attribute]
public virtual uint MaxPost
if (HttpOnly)
{
get;
set;
Cookie += "; HttpOnly";
}
return Cookie;
}
[Attribute]
public virtual bool SSL
protected override void ClientDisconnected(HTTPConnection connection)
{
foreach (var filter in filters)
filter.ClientDisconnected(connection);
}
internal bool Execute(HTTPConnection sender)
{
foreach (var resource in filters)
if (resource.Execute(sender).Wait(30000))
return true;
return false;
}
/*
protected override void SessionEnded(NetworkSession session)
{
// verify wether there are no active connections related to the session
foreach (HTTPConnection c in Connections)//.Values)
{
get;
set;
}
[Attribute]
public virtual string Certificate
{
get;
set;
}
public HTTPSession CreateSession(string id, int timeout)
{
var s = new HTTPSession();
s.Set(id, timeout);
sessions.Add(id, s);
return s;
}
public static string MakeCookie(string Item, string Value, DateTime Expires, string Domain, string Path, bool HttpOnly)
{
//Set-Cookie: ckGeneric=CookieBody; expires=Sun, 30-Dec-2001 21:00:00 GMT; domain=.com.au; path=/
//Set-Cookie: SessionID=another; expires=Fri, 29 Jun 2006 20:47:11 UTC; path=/
string Cookie = Item + "=" + Value;
if (Expires.Ticks != 0)
if (c.Session == session)
{
Cookie += "; expires=" + Expires.ToUniversalTime().ToString("ddd, dd MMM yyyy HH:mm:ss") + " GMT";
}
if (Domain != null)
{
Cookie += "; domain=" + Domain;
}
if (Path != null)
{
Cookie += "; path=" + Path;
}
if (HttpOnly)
{
Cookie += "; HttpOnly";
}
return Cookie;
}
protected override void ClientDisconnected(HTTPConnection connection)
{
foreach (var filter in filters)
filter.ClientDisconnected(connection);
}
internal bool Execute(HTTPConnection sender)
{
foreach (var resource in filters)
if (resource.Execute(sender).Wait(30000))
return true;
return false;
}
/*
protected override void SessionEnded(NetworkSession session)
{
// verify wether there are no active connections related to the session
foreach (HTTPConnection c in Connections)//.Values)
{
if (c.Session == session)
{
session.Refresh();
return;
}
}
foreach (Instance instance in Instance.Children)
{
var f = (HTTPFilter)instance.Resource;
f.SessionExpired((HTTPSession)session);
}
base.SessionEnded((HTTPSession)session);
//Sessions.Remove(Session.ID);
//Session.Dispose();
}
*/
/*
public int TTL
{
get
{
return Timeout;// mTimeout;
}
}
*/
public async AsyncReply<bool> Trigger(ResourceTrigger trigger)
{
if (trigger == ResourceTrigger.Initialize)
{
//var ip = (IPAddress)Instance.Attributes["ip"];
//var port = (int)Instance.Attributes["port"];
//var ssl = (bool)Instance.Attributes["ssl"];
//var cert = (string)Instance.Attributes["certificate"];
//if (ip == null) ip = IPAddress.Any;
Sockets.ISocket listener;
IPAddress ipAdd;
if (IP == null)
ipAdd = IPAddress.Any;
else
ipAdd = IPAddress.Parse(IP);
if (SSL)
listener = new SSLSocket(new IPEndPoint(ipAdd, Port), new X509Certificate2(Certificate));
else
listener = new TCPSocket(new IPEndPoint(ipAdd, Port));
Start(listener);
}
else if (trigger == ResourceTrigger.Terminate)
{
Stop();
}
else if (trigger == ResourceTrigger.SystemReload)
{
await Trigger(ResourceTrigger.Terminate);
await Trigger(ResourceTrigger.Initialize);
}
else if (trigger == ResourceTrigger.SystemInitialized)
{
filters = await Instance.Children<HTTPFilter>();
}
return true;
}
public override void Add(HTTPConnection connection)
{
connection.Server = this;
base.Add(connection);
}
public override void Remove(HTTPConnection connection)
{
connection.Server = null;
base.Remove(connection);
}
protected override void ClientConnected(HTTPConnection connection)
{
if (filters.Length == 0)
{
connection.Close();
session.Refresh();
return;
}
foreach (var resource in filters)
{
resource.ClientConnected(connection);
}
}
/*
public int LocalPort
{
get
{
return cServer.LocalPort;
}
}
*/
/*
public HTTPServer(int Port)
foreach (Instance instance in Instance.Children)
{
cServer = new TServer();
cServer.LocalPort = Port;
cServer.StartServer();
cServer.ClientConnected += new TServer.eClientConnected(ClientConnected);
cServer.ClientDisConnected += new TServer.eClientDisConnected(ClientDisConnected);
cServer.ClientIsSwitching += new TServer.eClientIsSwitching(ClientIsSwitching);
cServer.DataReceived += new TServer.eDataReceived(DataReceived);
var f = (HTTPFilter)instance.Resource;
f.SessionExpired((HTTPSession)session);
}
}*/
//~HTTPServer()
//{
// cServer.StopServer();
//}
base.SessionEnded((HTTPSession)session);
//Sessions.Remove(Session.ID);
//Session.Dispose();
}
}
*/
/*
public int TTL
{
get
{
return Timeout;// mTimeout;
}
}
*/
public async AsyncReply<bool> Trigger(ResourceTrigger trigger)
{
if (trigger == ResourceTrigger.Initialize)
{
//var ip = (IPAddress)Instance.Attributes["ip"];
//var port = (int)Instance.Attributes["port"];
//var ssl = (bool)Instance.Attributes["ssl"];
//var cert = (string)Instance.Attributes["certificate"];
//if (ip == null) ip = IPAddress.Any;
Sockets.ISocket listener;
IPAddress ipAdd;
if (IP == null)
ipAdd = IPAddress.Any;
else
ipAdd = IPAddress.Parse(IP);
if (SSL)
listener = new SSLSocket(new IPEndPoint(ipAdd, Port), new X509Certificate2(Certificate));
else
listener = new TCPSocket(new IPEndPoint(ipAdd, Port));
Start(listener);
}
else if (trigger == ResourceTrigger.Terminate)
{
Stop();
}
else if (trigger == ResourceTrigger.SystemReload)
{
await Trigger(ResourceTrigger.Terminate);
await Trigger(ResourceTrigger.Initialize);
}
else if (trigger == ResourceTrigger.SystemInitialized)
{
filters = await Instance.Children<HTTPFilter>();
}
return true;
}
public override void Add(HTTPConnection connection)
{
connection.Server = this;
base.Add(connection);
}
public override void Remove(HTTPConnection connection)
{
connection.Server = null;
base.Remove(connection);
}
protected override void ClientConnected(HTTPConnection connection)
{
if (filters.Length == 0)
{
connection.Close();
return;
}
foreach (var resource in filters)
{
resource.ClientConnected(connection);
}
}
/*
public int LocalPort
{
get
{
return cServer.LocalPort;
}
}
*/
/*
public HTTPServer(int Port)
{
cServer = new TServer();
cServer.LocalPort = Port;
cServer.StartServer();
cServer.ClientConnected += new TServer.eClientConnected(ClientConnected);
cServer.ClientDisConnected += new TServer.eClientDisConnected(ClientDisConnected);
cServer.ClientIsSwitching += new TServer.eClientIsSwitching(ClientIsSwitching);
cServer.DataReceived += new TServer.eDataReceived(DataReceived);
}*/
//~HTTPServer()
//{
// cServer.StopServer();
//}
}

View File

@ -35,96 +35,94 @@ using Esiur.Data;
using Esiur.Misc;
using Esiur.Core;
namespace Esiur.Net.HTTP
namespace Esiur.Net.HTTP;
public class HTTPSession : IDestructible //<T> where T : TClient
{
public class HTTPSession : IDestructible //<T> where T : TClient
public delegate void SessionModifiedEvent(HTTPSession session, string key, object oldValue, object newValue);
public delegate void SessionEndedEvent(HTTPSession session);
private string id;
private Timer timer;
private int timeout;
DateTime creation;
DateTime lastAction;
private KeyList<string, object> variables;
public event SessionEndedEvent OnEnd;
public event SessionModifiedEvent OnModify;
public event DestroyedEvent OnDestroy;
public KeyList<string, object> Variables
{
public delegate void SessionModifiedEvent(HTTPSession session, string key, object oldValue, object newValue);
public delegate void SessionEndedEvent(HTTPSession session);
get { return variables; }
}
private string id;
private Timer timer;
private int timeout;
DateTime creation;
DateTime lastAction;
public HTTPSession()
{
variables = new KeyList<string, object>();
variables.OnModified += new KeyList<string, object>.Modified(VariablesModified);
creation = DateTime.Now;
}
private KeyList<string, object> variables;
internal void Set(string id, int timeout)
{
//modified = sessionModifiedEvent;
//ended = sessionEndEvent;
this.id = id;
public event SessionEndedEvent OnEnd;
public event SessionModifiedEvent OnModify;
public event DestroyedEvent OnDestroy;
public KeyList<string, object> Variables
if (this.timeout != 0)
{
get { return variables; }
}
public HTTPSession()
{
variables = new KeyList<string, object>();
variables.OnModified += new KeyList<string, object>.Modified(VariablesModified);
this.timeout = timeout;
timer = new Timer(OnSessionEndTimerCallback, null, TimeSpan.FromSeconds(timeout), TimeSpan.FromSeconds(0));
creation = DateTime.Now;
}
internal void Set(string id, int timeout)
{
//modified = sessionModifiedEvent;
//ended = sessionEndEvent;
this.id = id;
if (this.timeout != 0)
{
this.timeout = timeout;
timer = new Timer(OnSessionEndTimerCallback, null, TimeSpan.FromSeconds(timeout), TimeSpan.FromSeconds(0));
creation = DateTime.Now;
}
}
private void OnSessionEndTimerCallback(object o)
{
OnEnd?.Invoke(this);
}
void VariablesModified(string key, object oldValue, object newValue, KeyList<string, object> sender)
{
OnModify?.Invoke(this, key, oldValue, newValue);
}
public void Destroy()
{
OnDestroy?.Invoke(this);
timer.Dispose();
timer = null;
}
internal void Refresh()
{
lastAction = DateTime.Now;
timer.Change(TimeSpan.FromSeconds(timeout), TimeSpan.FromSeconds(0));
}
public int Timeout // Seconds
{
get
{
return timeout;
}
set
{
timeout = value;
Refresh();
}
}
public string Id
{
get { return id; }
}
public DateTime LastAction
{
get { return lastAction; }
}
}
}
private void OnSessionEndTimerCallback(object o)
{
OnEnd?.Invoke(this);
}
void VariablesModified(string key, object oldValue, object newValue, KeyList<string, object> sender)
{
OnModify?.Invoke(this, key, oldValue, newValue);
}
public void Destroy()
{
OnDestroy?.Invoke(this);
timer.Dispose();
timer = null;
}
internal void Refresh()
{
lastAction = DateTime.Now;
timer.Change(TimeSpan.FromSeconds(timeout), TimeSpan.FromSeconds(0));
}
public int Timeout // Seconds
{
get
{
return timeout;
}
set
{
timeout = value;
Refresh();
}
}
public string Id
{
get { return id; }
}
public DateTime LastAction
{
get { return lastAction; }
}
}

View File

@ -6,34 +6,32 @@ using System;
using System.Collections.Generic;
using System.Text;
namespace Esiur.Net.HTTP
namespace Esiur.Net.HTTP;
public class IIPoHTTP : HTTPFilter
{
public class IIPoHTTP : HTTPFilter
[Attribute]
EntryPoint EntryPoint { get; set; }
public override AsyncReply<bool> Execute(HTTPConnection sender)
{
[Attribute]
EntryPoint EntryPoint { get; set; }
if (sender.Request.URL != "iip")
return new AsyncReply<bool>(false);
public override AsyncReply<bool> Execute(HTTPConnection sender)
IIPPacket.IIPPacketAction action = (IIPPacket.IIPPacketAction)Convert.ToByte(sender.Request.Query["a"]);
if (action == IIPPacket.IIPPacketAction.QueryLink)
{
if (sender.Request.URL != "iip")
return new AsyncReply<bool>(false);
IIPPacket.IIPPacketAction action = (IIPPacket.IIPPacketAction)Convert.ToByte(sender.Request.Query["a"]);
if (action == IIPPacket.IIPPacketAction.QueryLink)
EntryPoint.Query(sender.Request.Query["l"], null).Then(x =>
{
EntryPoint.Query(sender.Request.Query["l"], null).Then(x =>
{
});
}
return new AsyncReply<bool>(true);
});
}
public override AsyncReply<bool> Trigger(ResourceTrigger trigger)
{
return new AsyncReply<bool>(true);
}
return new AsyncReply<bool>(true);
}
public override AsyncReply<bool> Trigger(ResourceTrigger trigger)
{
return new AsyncReply<bool>(true);
}
}

View File

@ -32,94 +32,91 @@ using Esiur.Net.IIP;
using Esiur.Net.Sockets;
using Esiur.Core;
namespace Esiur.Net.HTTP
namespace Esiur.Net.HTTP;
public class IIPoWS : HTTPFilter
{
public class IIPoWS: HTTPFilter
[Attribute]
public DistributedServer Server
{
[Attribute]
public DistributedServer Server
get;
set;
}
public override AsyncReply<bool> Execute(HTTPConnection sender)
{
if (sender.IsWebsocketRequest())
{
get;
set;
}
if (Server == null)
return new AsyncReply<bool>(false);
public override AsyncReply<bool> Execute(HTTPConnection sender)
{
var tcpSocket = sender.Unassign();
if (sender.IsWebsocketRequest())
{
if (Server == null)
return new AsyncReply<bool>(false);
if (tcpSocket == null)
return new AsyncReply<bool>(false);
var tcpSocket = sender.Unassign();
var httpServer = sender.Parent;
var wsSocket = new WSocket(tcpSocket);
httpServer.Remove(sender);
if (tcpSocket == null)
return new AsyncReply<bool>(false);
var iipConnection = new DistributedConnection();
var httpServer = sender.Parent;
var wsSocket = new WSocket(tcpSocket);
httpServer.Remove(sender);
Server.Add(iipConnection);
iipConnection.Assign(wsSocket);
wsSocket.Begin();
var iipConnection = new DistributedConnection();
Server.Add(iipConnection);
iipConnection.Assign(wsSocket);
wsSocket.Begin();
return new AsyncReply<bool>(true);
}
return new AsyncReply<bool>( false);
/*
if (sender.Request.Filename.StartsWith("/iip/"))
{
// find the service
var path = sender.Request.Filename.Substring(5);// sender.Request.Query["path"];
Warehouse.Get(path).Then((r) =>
{
if (r is DistributedServer)
{
var httpServer = sender.Parent;
var iipServer = r as DistributedServer;
var tcpSocket = sender.Unassign();
if (tcpSocket == null)
return;
var wsSocket = new WSSocket(tcpSocket);
httpServer.RemoveConnection(sender);
//httpServer.Connections.Remove(sender);
var iipConnection = new DistributedConnection();
// iipConnection.OnReady += IipConnection_OnReady;
// iipConnection.Server = iipServer;
// iipConnection.Assign(wsSocket);
iipServer.AddConnection(iipConnection);
iipConnection.Assign(wsSocket);
wsSocket.Begin();
}
});
return true;
}
return false;
*/
}
private void IipConnection_OnReady(DistributedConnection sender)
{
Warehouse.Put(sender.RemoteUsername, sender, null, sender.Server).Wait();
}
public override AsyncReply<bool> Trigger(ResourceTrigger trigger)
{
return new AsyncReply<bool>(true);
}
return new AsyncReply<bool>(false);
/*
if (sender.Request.Filename.StartsWith("/iip/"))
{
// find the service
var path = sender.Request.Filename.Substring(5);// sender.Request.Query["path"];
Warehouse.Get(path).Then((r) =>
{
if (r is DistributedServer)
{
var httpServer = sender.Parent;
var iipServer = r as DistributedServer;
var tcpSocket = sender.Unassign();
if (tcpSocket == null)
return;
var wsSocket = new WSSocket(tcpSocket);
httpServer.RemoveConnection(sender);
//httpServer.Connections.Remove(sender);
var iipConnection = new DistributedConnection();
// iipConnection.OnReady += IipConnection_OnReady;
// iipConnection.Server = iipServer;
// iipConnection.Assign(wsSocket);
iipServer.AddConnection(iipConnection);
iipConnection.Assign(wsSocket);
wsSocket.Begin();
}
});
return true;
}
return false;
*/
}
private void IipConnection_OnReady(DistributedConnection sender)
{
Warehouse.Put(sender.RemoteUsername, sender, null, sender.Server).Wait();
}
public override AsyncReply<bool> Trigger(ResourceTrigger trigger)
{
return new AsyncReply<bool>(true);
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -2,26 +2,24 @@
using System.Collections.Generic;
using System.Text;
namespace Esiur.Net.IIP
namespace Esiur.Net.IIP;
public class DistributedPropertyContext
{
public class DistributedPropertyContext
public object Value { get; private set; }
public DistributedConnection Connection { get; private set; }
public Func<DistributedConnection, object> Method { get; private set; }
public DistributedPropertyContext(DistributedConnection connection, object value)
{
public object Value { get; private set; }
public DistributedConnection Connection { get; private set; }
public Func<DistributedConnection, object> Method { get; private set; }
public DistributedPropertyContext(DistributedConnection connection, object value)
{
this.Value = value;
this.Connection = connection;
}
public DistributedPropertyContext(Func<DistributedConnection, object> method)
{
this.Method = method;
}
public static implicit operator DistributedPropertyContext(Func<DistributedConnection, object> method)
=> new DistributedPropertyContext(method);
this.Value = value;
this.Connection = connection;
}
public DistributedPropertyContext(Func<DistributedConnection, object> method)
{
this.Method = method;
}
public static implicit operator DistributedPropertyContext(Func<DistributedConnection, object> method)
=> new DistributedPropertyContext(method);
}

View File

@ -42,465 +42,463 @@ using System.Threading.Tasks;
using Esiur.Resource;
using Esiur.Resource.Template;
namespace Esiur.Net.IIP
namespace Esiur.Net.IIP;
//[System.Runtime.InteropServices.ComVisible(true)]
public class DistributedResource : DynamicObject, IResource
{
//[System.Runtime.InteropServices.ComVisible(true)]
public class DistributedResource : DynamicObject, IResource
/// <summary>
/// Raised when the distributed resource is destroyed.
/// </summary>
public event DestroyedEvent OnDestroy;
public event Instance.ResourceModifiedEvent OnModified;
uint instanceId;
DistributedConnection connection;
bool attached = false;
bool destroyed = false;
bool suspended = false;
//Structure properties = new Structure();
string link;
//ulong age;
//ulong[] ages;
protected object[] properties;
internal List<DistributedResource> parents = new List<DistributedResource>();
internal List<DistributedResource> children = new List<DistributedResource>();
DistributedResourceEvent[] events;
/// <summary>
/// Resource template for the remotely located resource.
/// </summary>
//public ResourceTemplate Template
//{
// get { return template; }
//}
/// <summary>
/// Connection responsible for the distributed resource.
/// </summary>
public DistributedConnection Connection
{
get { return connection; }
}
/// <summary>
/// Resource link
/// </summary>
public string Link
{
get { return link; }
}
/// <summary>
/// Instance Id given by the other end.
/// </summary>
public uint Id
{
get { return instanceId; }
}
/// <summary>
/// IDestructible interface.
/// </summary>
public void Destroy()
{
destroyed = true;
attached = false;
connection.SendDetachRequest(instanceId);
OnDestroy?.Invoke(this);
}
/// <summary>
/// Suspend resource
/// </summary>
internal void Suspend()
{
suspended = true;
attached = false;
}
/// <summary>
/// Resource is attached when all its properties are received.
/// </summary>
internal bool Attached => attached;
internal bool Suspended => suspended;
// public DistributedResourceStack Stack
//{
// get { return stack; }
//}
/// <summary>
/// Create a new distributed resource.
/// </summary>
/// <param name="connection">Connection responsible for the distributed resource.</param>
/// <param name="template">Resource template.</param>
/// <param name="instanceId">Instance Id given by the other end.</param>
/// <param name="age">Resource age.</param>
public DistributedResource(DistributedConnection connection, uint instanceId, ulong age, string link)
{
this.link = link;
this.connection = connection;
this.instanceId = instanceId;
//this.Instance.Template = template;
//this.Instance.Age = age;
//this.template = template;
//this.age = age;
}
/// <summary>
/// Export all properties with ResourceProperty attributed as bytes array.
/// </summary>
/// <returns></returns>
internal PropertyValue[] _Serialize()
{
/// <summary>
/// Raised when the distributed resource is destroyed.
/// </summary>
public event DestroyedEvent OnDestroy;
public event Instance.ResourceModifiedEvent OnModified;
uint instanceId;
DistributedConnection connection;
var props = new PropertyValue[properties.Length];
bool attached = false;
bool destroyed = false;
bool suspended = false;
for (byte i = 0; i < properties.Length; i++)
props[i] = new PropertyValue(properties[i], Instance.GetAge(i), Instance.GetModificationDate(i));
//Structure properties = new Structure();
return props;
}
string link;
//ulong age;
//ulong[] ages;
protected object[] properties;
internal List<DistributedResource> parents = new List<DistributedResource>();
internal List<DistributedResource> children = new List<DistributedResource>();
DistributedResourceEvent[] events;
/// <summary>
/// Resource template for the remotely located resource.
/// </summary>
//public ResourceTemplate Template
//{
// get { return template; }
//}
/// <summary>
/// Connection responsible for the distributed resource.
/// </summary>
public DistributedConnection Connection
internal bool _Attach(PropertyValue[] properties)
{
if (attached)
return false;
else
{
get { return connection; }
}
suspended = false;
/// <summary>
/// Resource link
/// </summary>
public string Link
{
get { return link; }
}
/// <summary>
/// Instance Id given by the other end.
/// </summary>
public uint Id
{
get { return instanceId; }
}
/// <summary>
/// IDestructible interface.
/// </summary>
public void Destroy()
{
destroyed = true;
attached = false;
connection.SendDetachRequest(instanceId);
OnDestroy?.Invoke(this);
}
/// <summary>
/// Suspend resource
/// </summary>
internal void Suspend()
{
suspended = true;
attached = false;
}
/// <summary>
/// Resource is attached when all its properties are received.
/// </summary>
internal bool Attached => attached;
internal bool Suspended => suspended;
// public DistributedResourceStack Stack
//{
// get { return stack; }
//}
/// <summary>
/// Create a new distributed resource.
/// </summary>
/// <param name="connection">Connection responsible for the distributed resource.</param>
/// <param name="template">Resource template.</param>
/// <param name="instanceId">Instance Id given by the other end.</param>
/// <param name="age">Resource age.</param>
public DistributedResource(DistributedConnection connection, uint instanceId, ulong age, string link)
{
this.link = link;
this.connection = connection;
this.instanceId = instanceId;
//this.Instance.Template = template;
//this.Instance.Age = age;
//this.template = template;
//this.age = age;
}
/// <summary>
/// Export all properties with ResourceProperty attributed as bytes array.
/// </summary>
/// <returns></returns>
internal PropertyValue[] _Serialize()
{
var props = new PropertyValue[properties.Length];
this.properties = new object[properties.Length];
this.events = new DistributedResourceEvent[Instance.Template.Events.Length];
for (byte i = 0; i < properties.Length; i++)
props[i] = new PropertyValue(properties[i], Instance.GetAge(i), Instance.GetModificationDate(i));
return props;
}
internal bool _Attach(PropertyValue[] properties)
{
if (attached)
return false;
else
{
suspended = false;
this.properties = new object[properties.Length];
this.events = new DistributedResourceEvent[Instance.Template.Events.Length];
for (byte i = 0; i < properties.Length; i++)
{
Instance.SetAge(i, properties[i].Age);
Instance.SetModificationDate(i, properties[i].Date);
this.properties[i] = properties[i].Value;
}
// trigger holded events/property updates.
//foreach (var r in afterAttachmentTriggers)
// r.Key.Trigger(r.Value);
//afterAttachmentTriggers.Clear();
attached = true;
Instance.SetAge(i, properties[i].Age);
Instance.SetModificationDate(i, properties[i].Date);
this.properties[i] = properties[i].Value;
}
return true;
// trigger holded events/property updates.
//foreach (var r in afterAttachmentTriggers)
// r.Key.Trigger(r.Value);
//afterAttachmentTriggers.Clear();
attached = true;
}
return true;
}
protected internal virtual void _EmitEventByIndex(byte index, object args)
protected internal virtual void _EmitEventByIndex(byte index, object args)
{
var et = Instance.Template.GetEventTemplateByIndex(index);
events[index]?.Invoke(this, args);
Instance.EmitResourceEvent(et.Name, args);
}
public AsyncReply<object> _InvokeByNamedArguments(byte index, Structure namedArgs)
{
if (destroyed)
throw new Exception("Trying to access destroyed object");
if (suspended)
throw new Exception("Trying to access suspended object");
if (index >= Instance.Template.Functions.Length)
throw new Exception("Function index is incorrect");
return connection.SendInvokeByNamedArguments(instanceId, index, namedArgs);
}
public AsyncReply<object> _InvokeByArrayArguments(byte index, object[] args)
{
if (destroyed)
throw new Exception("Trying to access destroyed object");
if (suspended)
throw new Exception("Trying to access suspended object");
if (index >= Instance.Template.Functions.Length)
throw new Exception("Function index is incorrect");
return connection.SendInvokeByArrayArguments(instanceId, index, args);
}
public AsyncReply Listen(EventTemplate et)
{
if (et == null)
return new AsyncReply().TriggerError(new AsyncException(ErrorType.Management, (ushort)ExceptionCode.MethodNotFound, ""));
if (!et.Listenable)
return new AsyncReply().TriggerError(new AsyncException(ErrorType.Management, (ushort)ExceptionCode.NotListenable, ""));
return connection.SendListenRequest(instanceId, et.Index);
}
public AsyncReply Listen(string eventName)
{
var et = Instance.Template.GetEventTemplateByName(eventName);
return Listen(et);
}
public AsyncReply Unlisten(EventTemplate et)
{
if (et == null)
return new AsyncReply().TriggerError(new AsyncException(ErrorType.Management, (ushort)ExceptionCode.MethodNotFound, ""));
if (!et.Listenable)
return new AsyncReply().TriggerError(new AsyncException(ErrorType.Management, (ushort)ExceptionCode.NotListenable, ""));
return connection.SendUnlistenRequest(instanceId, et.Index);
}
public AsyncReply Unlisten(string eventName)
{
var et = Instance.Template.GetEventTemplateByName(eventName);
return Unlisten(et);
}
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
{
var ft = Instance.Template.GetFunctionTemplateByName(binder.Name);
var reply = new AsyncReply<object>();
if (attached && ft != null)
{
var et = Instance.Template.GetEventTemplateByIndex(index);
events[index]?.Invoke(this, args);
Instance.EmitResourceEvent(et.Name, args);
}
public AsyncReply<object> _InvokeByNamedArguments(byte index, Structure namedArgs)
{
if (destroyed)
throw new Exception("Trying to access destroyed object");
if (suspended)
throw new Exception("Trying to access suspended object");
if (index >= Instance.Template.Functions.Length)
throw new Exception("Function index is incorrect");
return connection.SendInvokeByNamedArguments(instanceId, index, namedArgs);
}
public AsyncReply<object> _InvokeByArrayArguments(byte index, object[] args)
{
if (destroyed)
throw new Exception("Trying to access destroyed object");
if (suspended)
throw new Exception("Trying to access suspended object");
if (index >= Instance.Template.Functions.Length)
throw new Exception("Function index is incorrect");
return connection.SendInvokeByArrayArguments(instanceId, index, args);
}
public AsyncReply Listen(EventTemplate et)
{
if (et == null)
return new AsyncReply().TriggerError(new AsyncException(ErrorType.Management, (ushort)ExceptionCode.MethodNotFound, ""));
if (!et.Listenable)
return new AsyncReply().TriggerError(new AsyncException(ErrorType.Management, (ushort)ExceptionCode.NotListenable, ""));
return connection.SendListenRequest(instanceId, et.Index);
}
public AsyncReply Listen(string eventName)
{
var et = Instance.Template.GetEventTemplateByName(eventName);
return Listen(et);
}
public AsyncReply Unlisten(EventTemplate et)
{
if (et == null)
return new AsyncReply().TriggerError(new AsyncException(ErrorType.Management, (ushort)ExceptionCode.MethodNotFound, ""));
if (!et.Listenable)
return new AsyncReply().TriggerError(new AsyncException(ErrorType.Management, (ushort)ExceptionCode.NotListenable, ""));
return connection.SendUnlistenRequest(instanceId, et.Index);
}
public AsyncReply Unlisten(string eventName)
{
var et = Instance.Template.GetEventTemplateByName(eventName);
return Unlisten(et);
}
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
{
var ft = Instance.Template.GetFunctionTemplateByName(binder.Name);
var reply = new AsyncReply<object>();
if (attached && ft != null)
if (args.Length == 1)
{
if (args.Length == 1)
// Detect anonymous types
var type = args[0].GetType();
if (Codec.IsAnonymous(type))
{
// Detect anonymous types
var type = args[0].GetType();
if (Codec.IsAnonymous(type))
{
var namedArgs = new Structure();
var pi = type.GetTypeInfo().GetProperties();
foreach (var p in pi)
namedArgs[p.Name] = p.GetValue(args[0]);
result = _InvokeByNamedArguments(ft.Index, namedArgs);
}
else
{
result = _InvokeByArrayArguments(ft.Index, args);
}
var namedArgs = new Structure();
var pi = type.GetTypeInfo().GetProperties();
foreach (var p in pi)
namedArgs[p.Name] = p.GetValue(args[0]);
result = _InvokeByNamedArguments(ft.Index, namedArgs);
}
else
{
result = _InvokeByArrayArguments(ft.Index, args);
}
return true;
}
else
{
result = null;
return false;
result = _InvokeByArrayArguments(ft.Index, args);
}
return true;
}
/// <summary>
/// Get a property value.
/// </summary>
/// <param name="index">Zero-based property index.</param>
/// <returns>Value</returns>
protected internal object _Get(byte index)
else
{
if (index >= properties.Length)
return null;
return properties[index];
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
if (destroyed)
throw new Exception("Trying to access destroyed object");
result = null;
return false;
}
}
if (!attached)
/// <summary>
/// Get a property value.
/// </summary>
/// <param name="index">Zero-based property index.</param>
/// <returns>Value</returns>
protected internal object _Get(byte index)
{
if (index >= properties.Length)
return null;
return properties[index];
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
if (destroyed)
throw new Exception("Trying to access destroyed object");
result = null;
if (!attached)
return false;
var pt = Instance.Template.GetPropertyTemplateByName(binder.Name);
if (pt != null)
{
result = properties[pt.Index];
return true;
}
else
{
var et = Instance.Template.GetEventTemplateByName(binder.Name);
if (et == null)
return false;
var pt = Instance.Template.GetPropertyTemplateByName(binder.Name);
result = events[et.Index];
if (pt != null)
{
result = properties[pt.Index];
return true;
}
else
{
var et = Instance.Template.GetEventTemplateByName(binder.Name);
if (et == null)
return false;
result = events[et.Index];
return true;
}
return true;
}
}
internal void _UpdatePropertyByIndex(byte index, object value)
{
var pt = Instance.Template.GetPropertyTemplateByIndex(index);
properties[index] = value;
Instance.EmitModification(pt, value);
}
internal void _UpdatePropertyByIndex(byte index, object value)
{
var pt = Instance.Template.GetPropertyTemplateByIndex(index);
properties[index] = value;
Instance.EmitModification(pt, value);
}
/// <summary>
/// Set property value.
/// </summary>
/// <param name="index">Zero-based property index.</param>
/// <param name="value">Value</param>
/// <returns>Indicator when the property is set.</returns>
protected internal AsyncReply<object> _Set(byte index, object value)
{
if (index >= properties.Length)
return null;
/// <summary>
/// Set property value.
/// </summary>
/// <param name="index">Zero-based property index.</param>
/// <param name="value">Value</param>
/// <returns>Indicator when the property is set.</returns>
protected internal AsyncReply<object> _Set(byte index, object value)
{
if (index >= properties.Length)
return null;
var reply = new AsyncReply<object>();
var reply = new AsyncReply<object>();
var parameters = Codec.Compose(value, connection);
connection.SendRequest(Packets.IIPPacket.IIPPacketAction.SetProperty)
.AddUInt32(instanceId)
.AddUInt8(index)
.AddUInt8Array(parameters)
.Done()
.Then((res) =>
{
var parameters = Codec.Compose(value, connection);
connection.SendRequest(Packets.IIPPacket.IIPPacketAction.SetProperty)
.AddUInt32(instanceId)
.AddUInt8(index)
.AddUInt8Array(parameters)
.Done()
.Then((res) =>
{
// not really needed, server will always send property modified,
// this only happens if the programmer forgot to emit in property setter
properties[index] = value;
reply.Trigger(null);
});
reply.Trigger(null);
});
return reply;
}
return reply;
}
public override bool TrySetMember(SetMemberBinder binder, object value)
public override bool TrySetMember(SetMemberBinder binder, object value)
{
if (destroyed)
throw new Exception("Trying to access destroyed object");
if (suspended)
throw new Exception("Trying to access suspended object");
if (!attached)
return false;
var pt = Instance.Template.GetPropertyTemplateByName(binder.Name);
if (pt != null)
{
if (destroyed)
throw new Exception("Trying to access destroyed object");
if (suspended)
throw new Exception("Trying to access suspended object");
if (!attached)
_Set(pt.Index, value);
return true;
}
else
{
var et = Instance.Template.GetEventTemplateByName(binder.Name);
if (et == null)
return false;
var pt = Instance.Template.GetPropertyTemplateByName(binder.Name);
if (pt != null)
{
_Set(pt.Index, value);
return true;
}
else
{
var et = Instance.Template.GetEventTemplateByName(binder.Name);
if (et == null)
return false;
events[et.Index] = (DistributedResourceEvent)value;
return true;
}
events[et.Index] = (DistributedResourceEvent)value;
return true;
}
/*
public async void InvokeMethod(byte index, object[] arguments, DistributedConnection sender)
{
// get function parameters
Type t = this.GetType();
}
MethodInfo mi = t.GetMethod(GetFunctionName(index), BindingFlags.DeclaredOnly |
BindingFlags.Public |
BindingFlags.Instance | BindingFlags.InvokeMethod);
if (mi != null)
/*
public async void InvokeMethod(byte index, object[] arguments, DistributedConnection sender)
{
// get function parameters
Type t = this.GetType();
MethodInfo mi = t.GetMethod(GetFunctionName(index), BindingFlags.DeclaredOnly |
BindingFlags.Public |
BindingFlags.Instance | BindingFlags.InvokeMethod);
if (mi != null)
{
try
{
try
{
var res = await invokeMethod(mi, arguments, sender);
object rt = Codec.Compose(res);
sender.SendParams((byte)0x80, instanceId, index, rt);
}
catch(Exception ex)
{
var msg = ex.InnerException != null ? ex.InnerException.Message : ex.Message;
sender.SendParams((byte)0x8E, instanceId, index, Codec.Compose(msg));
}
var res = await invokeMethod(mi, arguments, sender);
object rt = Codec.Compose(res);
sender.SendParams((byte)0x80, instanceId, index, rt);
}
catch(Exception ex)
{
var msg = ex.InnerException != null ? ex.InnerException.Message : ex.Message;
sender.SendParams((byte)0x8E, instanceId, index, Codec.Compose(msg));
}
}
*/
}
*/
/// <summary>
/// Resource interface.
/// </summary>
public Instance Instance
{
get;
set;
}
/// <summary>
/// Resource interface.
/// </summary>
public Instance Instance
{
get;
set;
}
/// <summary>
/// Create a new instance of distributed resource.
/// </summary>
public DistributedResource()
{
//stack = new DistributedResourceStack(this);
//this.Instance.ResourceModified += this.OnModified;
/// <summary>
/// Create a new instance of distributed resource.
/// </summary>
public DistributedResource()
{
//stack = new DistributedResourceStack(this);
//this.Instance.ResourceModified += this.OnModified;
}
}
/// <summary>
/// Resource interface.
/// </summary>
/// <param name="trigger"></param>
/// <returns></returns>
public AsyncReply<bool> Trigger(ResourceTrigger trigger)
{
/// <summary>
/// Resource interface.
/// </summary>
/// <param name="trigger"></param>
/// <returns></returns>
public AsyncReply<bool> Trigger(ResourceTrigger trigger)
{
if (trigger == ResourceTrigger.Initialize)
this.Instance.ResourceModified += this.OnModified;
if (trigger == ResourceTrigger.Initialize)
this.Instance.ResourceModified += this.OnModified;
// do nothing.
return new AsyncReply<bool>(true);
}
// do nothing.
return new AsyncReply<bool>(true);
}
}

View File

@ -28,7 +28,6 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Esiur.Net.IIP
{
public delegate void DistributedResourceEvent(DistributedResource sender, object argument);
}
namespace Esiur.Net.IIP;
public delegate void DistributedResourceEvent(DistributedResource sender, object argument);

View File

@ -28,46 +28,44 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Esiur.Net.IIP
namespace Esiur.Net.IIP;
public class DistributedResourceQueueItem
{
public class DistributedResourceQueueItem
public enum DistributedResourceQueueItemType
{
public enum DistributedResourceQueueItemType
{
Propery,
Event
}
Propery,
Event
}
DistributedResourceQueueItemType type;
byte index;
object value;
DistributedResource resource;
DistributedResourceQueueItemType type;
byte index;
object value;
DistributedResource resource;
public DistributedResourceQueueItem(DistributedResource resource, DistributedResourceQueueItemType type, object value, byte index)
{
this.resource = resource;
this.index = index;
this.type = type;
this.value = value;
}
public DistributedResourceQueueItem(DistributedResource resource, DistributedResourceQueueItemType type, object value, byte index)
{
this.resource = resource;
this.index = index;
this.type = type;
this.value = value;
}
public DistributedResource Resource
{
get { return resource; }
}
public DistributedResourceQueueItemType Type
{
get { return type; }
}
public DistributedResource Resource
{
get { return resource; }
}
public DistributedResourceQueueItemType Type
{
get { return type; }
}
public byte Index
{
get { return index; }
}
public byte Index
{
get { return index; }
}
public object Value
{
get { return value; }
}
public object Value
{
get { return value; }
}
}

View File

@ -35,143 +35,141 @@ using System.Net;
using Esiur.Resource;
using Esiur.Security.Membership;
namespace Esiur.Net.IIP
namespace Esiur.Net.IIP;
public class DistributedServer : NetworkServer<DistributedConnection>, IResource
{
public class DistributedServer : NetworkServer<DistributedConnection>, IResource
[Attribute]
public string IP
{
[Attribute]
public string IP
{
get;
set;
}
[Attribute]
public IMembership Membership
{
get;
set;
}
[Attribute]
public EntryPoint EntryPoint
{
get;
set;
}
[Attribute]
public ushort Port
{
get;
set;
} = 10518;
[Attribute]
public ExceptionLevel ExceptionLevel { get; set; }
= ExceptionLevel.Code
| ExceptionLevel.Source
| ExceptionLevel.Message
| ExceptionLevel.Trace;
public Instance Instance
{
get;
set;
}
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);
}
else if (trigger == ResourceTrigger.Terminate)
{
Stop();
}
else if (trigger == ResourceTrigger.SystemReload)
{
Trigger(ResourceTrigger.Terminate);
Trigger(ResourceTrigger.Initialize);
}
return new AsyncReply<bool>(true);
}
//protected override void DataReceived(DistributedConnection sender, NetworkBuffer data)
//{
// //throw new NotImplementedException();
//}
//protected override void ClientConnected(DistributedConnection sender)
//{
// //Console.WriteLine("DistributedConnection Client Connected");
//}
//private void ConnectionReadyEventReceiver(DistributedConnection sender)
//{
// sender.OnReady -= ConnectionReadyEventReceiver;
// Warehouse.Put(sender, sender.LocalUsername, null, this);
//}
//public override void RemoveConnection(DistributedConnection connection)
//{
// connection.OnReady -= Sender_OnReady;
// //connection.Server = null;
// base.RemoveConnection(connection);
//}
//public override void AddConnection(DistributedConnection connection)
//{
// connection.OnReady += Sender_OnReady;
// connection.Server = this;
// base.AddConnection(connection);
//}
protected override void ClientConnected(DistributedConnection connection)
{
//connection.OnReady += ConnectionReadyEventReceiver;
}
public override void Add(DistributedConnection connection)
{
connection.Server = this;
connection.ExceptionLevel = ExceptionLevel;
base.Add(connection);
}
public override void Remove(DistributedConnection connection)
{
connection.Server = null;
base.Remove(connection);
}
protected override void ClientDisconnected(DistributedConnection connection)
{
//connection.OnReady -= ConnectionReadyEventReceiver;
//Warehouse.Remove(connection);
}
get;
set;
}
[Attribute]
public IMembership Membership
{
get;
set;
}
[Attribute]
public EntryPoint EntryPoint
{
get;
set;
}
[Attribute]
public ushort Port
{
get;
set;
} = 10518;
[Attribute]
public ExceptionLevel ExceptionLevel { get; set; }
= ExceptionLevel.Code
| ExceptionLevel.Source
| ExceptionLevel.Message
| ExceptionLevel.Trace;
public Instance Instance
{
get;
set;
}
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);
}
else if (trigger == ResourceTrigger.Terminate)
{
Stop();
}
else if (trigger == ResourceTrigger.SystemReload)
{
Trigger(ResourceTrigger.Terminate);
Trigger(ResourceTrigger.Initialize);
}
return new AsyncReply<bool>(true);
}
//protected override void DataReceived(DistributedConnection sender, NetworkBuffer data)
//{
// //throw new NotImplementedException();
//}
//protected override void ClientConnected(DistributedConnection sender)
//{
// //Console.WriteLine("DistributedConnection Client Connected");
//}
//private void ConnectionReadyEventReceiver(DistributedConnection sender)
//{
// sender.OnReady -= ConnectionReadyEventReceiver;
// Warehouse.Put(sender, sender.LocalUsername, null, this);
//}
//public override void RemoveConnection(DistributedConnection connection)
//{
// connection.OnReady -= Sender_OnReady;
// //connection.Server = null;
// base.RemoveConnection(connection);
//}
//public override void AddConnection(DistributedConnection connection)
//{
// connection.OnReady += Sender_OnReady;
// connection.Server = this;
// base.AddConnection(connection);
//}
protected override void ClientConnected(DistributedConnection connection)
{
//connection.OnReady += ConnectionReadyEventReceiver;
}
public override void Add(DistributedConnection connection)
{
connection.Server = this;
connection.ExceptionLevel = ExceptionLevel;
base.Add(connection);
}
public override void Remove(DistributedConnection connection)
{
connection.Server = null;
base.Remove(connection);
}
protected override void ClientDisconnected(DistributedConnection connection)
{
//connection.OnReady -= ConnectionReadyEventReceiver;
//Warehouse.Remove(connection);
}
}

View File

@ -28,11 +28,9 @@ using System.Text;
using Esiur.Net.Sockets;
using Esiur.Security.Authority;
namespace Esiur.Net.IIP
namespace Esiur.Net.IIP;
public class DistributedSession : NetworkSession
{
public class DistributedSession : NetworkSession
{
public Source Source { get; set; }
public Authentication Authentication { get; set; }
}
public Source Source { get; set; }
public Authentication Authentication { get; set; }
}

View File

@ -29,12 +29,11 @@ using Esiur.Data;
using Esiur.Resource;
using Esiur.Resource.Template;
namespace Esiur.Net.IIP
{
public abstract class EntryPoint : Esiur.Resource.Resource
{
namespace Esiur.Net.IIP;
public abstract AsyncReply<IResource[]> Query(string path, DistributedConnection sender);
protected abstract override bool Create();
}
public abstract class EntryPoint : Esiur.Resource.Resource
{
public abstract AsyncReply<IResource[]> Query(string path, DistributedConnection sender);
protected abstract override bool Create();
}

View File

@ -2,14 +2,13 @@
using System.Collections.Generic;
using System.Text;
namespace Esiur.Net
{
public interface INetworkReceiver<T>
{
void NetworkClose(T sender);
void NetworkReceive(T sender, NetworkBuffer buffer);
//void NetworkError(T sender);
namespace Esiur.Net;
void NetworkConnect(T sender);
}
public interface INetworkReceiver<T>
{
void NetworkClose(T sender);
void NetworkReceive(T sender, NetworkBuffer buffer);
//void NetworkError(T sender);
void NetworkConnect(T sender);
}

View File

@ -29,180 +29,178 @@ using System.Text;
using Esiur.Data;
using Esiur.Misc;
namespace Esiur.Net
namespace Esiur.Net;
public class NetworkBuffer
{
public class NetworkBuffer
byte[] data;
uint neededDataLength = 0;
//bool trim;
object syncLock = new object();
//public object SyncLock
//{
// get { return syncLock; }
//}
public NetworkBuffer()
{
byte[] data;
data = new byte[0];
}
uint neededDataLength = 0;
//bool trim;
object syncLock = new object();
//public object SyncLock
//{
// get { return syncLock; }
//}
public NetworkBuffer()
public bool Protected
{
get
{
data = new byte[0];
return neededDataLength > data.Length;
}
}
public bool Protected
public uint Available
{
get
{
get
return (uint)data.Length;
}
}
//public void HoldForAtLeast(byte[] src, uint offset, uint size, uint needed)
//{
// HoldFor(src, offset, size, needed);
// //trim = false;
//}
//public void HoldForAtLeast(byte[] src, uint needed)
//{
// HoldForAtLeast(src, 0, (uint)src.Length, needed);
//}
public void HoldForNextWrite(byte[] src)
{
//HoldForAtLeast(src, (uint)src.Length + 1);
HoldFor(src, (uint)src.Length + 1);
}
public void HoldForNextWrite(byte[] src, uint offset, uint size)
{
//HoldForAtLeast(src, offset, size, size + 1);
HoldFor(src, offset, size, size + 1);
}
public void HoldFor(byte[] src, uint offset, uint size, uint needed)
{
lock (syncLock)
{
if (size >= needed)
throw new Exception("Size >= Needed !");
//trim = true;
data = DC.Combine(src, offset, size, data, 0, (uint)data.Length);
neededDataLength = needed;
// Console.WriteLine("Hold StackTrace: '{0}'", Environment.StackTrace);
//Console.WriteLine("Holded {0} {1} {2} {3} - {4}", offset, size, needed, data.Length, GetHashCode());
}
}
public void HoldFor(byte[] src, uint needed)
{
HoldFor(src, 0, (uint)src.Length, needed);
}
public bool Protect(byte[] data, uint offset, uint needed)//, bool exact = false)
{
uint dataLength = (uint)data.Length - offset;
// protection
if (dataLength < needed)
{
//if (exact)
// HoldFor(data, offset, dataLength, needed);
//else
//HoldForAtLeast(data, offset, dataLength, needed);
HoldFor(data, offset, dataLength, needed);
return true;
}
else
return false;
}
public void Write(byte[] src)
{
Write(src, 0, (uint)src.Length);
}
public void Write(byte[] src, uint offset, uint length)
{
//if (data.Length > 0)
// Console.WriteLine();
lock (syncLock)
DC.Append(ref data, src, offset, length);
}
public bool CanRead
{
get
{
if (data.Length == 0)
return false;
if (data.Length < neededDataLength)
return false;
return true;
}
}
public byte[] Read()
{
lock (syncLock)
{
if (data.Length == 0)
return null;
byte[] rt = null;
if (neededDataLength == 0)
{
return neededDataLength > data.Length;
}
}
public uint Available
{
get
{
return (uint)data.Length;
}
}
//public void HoldForAtLeast(byte[] src, uint offset, uint size, uint needed)
//{
// HoldFor(src, offset, size, needed);
// //trim = false;
//}
//public void HoldForAtLeast(byte[] src, uint needed)
//{
// HoldForAtLeast(src, 0, (uint)src.Length, needed);
//}
public void HoldForNextWrite(byte[] src)
{
//HoldForAtLeast(src, (uint)src.Length + 1);
HoldFor(src, (uint)src.Length + 1);
}
public void HoldForNextWrite(byte[] src, uint offset, uint size)
{
//HoldForAtLeast(src, offset, size, size + 1);
HoldFor(src, offset, size, size + 1);
}
public void HoldFor(byte[] src, uint offset, uint size, uint needed)
{
lock (syncLock)
{
if (size >= needed)
throw new Exception("Size >= Needed !");
//trim = true;
data = DC.Combine(src, offset, size, data, 0, (uint)data.Length);
neededDataLength = needed;
// Console.WriteLine("Hold StackTrace: '{0}'", Environment.StackTrace);
//Console.WriteLine("Holded {0} {1} {2} {3} - {4}", offset, size, needed, data.Length, GetHashCode());
}
}
public void HoldFor(byte[] src, uint needed)
{
HoldFor(src, 0, (uint)src.Length, needed);
}
public bool Protect(byte[] data, uint offset, uint needed)//, bool exact = false)
{
uint dataLength = (uint)data.Length - offset;
// protection
if (dataLength < needed)
{
//if (exact)
// HoldFor(data, offset, dataLength, needed);
//else
//HoldForAtLeast(data, offset, dataLength, needed);
HoldFor(data, offset, dataLength, needed);
return true;
rt = data;
data = new byte[0];
}
else
return false;
}
public void Write(byte[] src)
{
Write(src, 0, (uint)src.Length);
}
public void Write(byte[] src, uint offset, uint length)
{
//if (data.Length > 0)
// Console.WriteLine();
lock(syncLock)
DC.Append(ref data, src, offset, length);
}
public bool CanRead
{
get
{
if (data.Length == 0)
return false;
if (data.Length < neededDataLength)
return false;
//Console.WriteLine("P STATE:" + data.Length + " " + neededDataLength);
return true;
}
}
public byte[] Read()
{
lock (syncLock)
{
if (data.Length == 0)
return null;
byte[] rt = null;
if (neededDataLength == 0)
if (data.Length >= neededDataLength)
{
//Console.WriteLine("data.Length >= neededDataLength " + data.Length + " >= " + neededDataLength + " " + trim);
//if (trim)
//{
// rt = DC.Clip(data, 0, neededDataLength);
// data = DC.Clip(data, neededDataLength, (uint)data.Length - neededDataLength);
//}
//else
//{
// return all data
rt = data;
data = new byte[0];
//}
neededDataLength = 0;
return rt;
}
else
{
//Console.WriteLine("P STATE:" + data.Length + " " + neededDataLength);
if (data.Length >= neededDataLength)
{
//Console.WriteLine("data.Length >= neededDataLength " + data.Length + " >= " + neededDataLength + " " + trim);
//if (trim)
//{
// rt = DC.Clip(data, 0, neededDataLength);
// data = DC.Clip(data, neededDataLength, (uint)data.Length - neededDataLength);
//}
//else
//{
// return all data
rt = data;
data = new byte[0];
//}
neededDataLength = 0;
return rt;
}
else
{
return null;
}
return null;
}
}
return rt;
}
return rt;
}
}
}

View File

@ -36,332 +36,330 @@ using Esiur.Data;
using Esiur.Net.Sockets;
using Esiur.Resource;
namespace Esiur.Net
namespace Esiur.Net;
public abstract class NetworkConnection : IDestructible, INetworkReceiver<ISocket>// <TS>: IResource where TS : NetworkSession
{
public abstract class NetworkConnection: IDestructible, INetworkReceiver<ISocket>// <TS>: IResource where TS : NetworkSession
private Sockets.ISocket sock;
// private bool connected;
private DateTime lastAction;
//public delegate void DataReceivedEvent(NetworkConnection sender, NetworkBuffer data);
//public delegate void ConnectionClosedEvent(NetworkConnection sender);
public delegate void NetworkConnectionEvent(NetworkConnection connection);
public event NetworkConnectionEvent OnConnect;
//public event DataReceivedEvent OnDataReceived;
public event NetworkConnectionEvent OnClose;
public event DestroyedEvent OnDestroy;
//object receivingLock = new object();
//object sendLock = new object();
bool processing = false;
// public INetworkReceiver<NetworkConnection> Receiver { get; set; }
public virtual void Destroy()
{
private Sockets.ISocket sock;
// private bool connected;
// remove references
//sock.OnClose -= Socket_OnClose;
//sock.OnConnect -= Socket_OnConnect;
//sock.OnReceive -= Socket_OnReceive;
sock?.Destroy();
//Receiver = null;
Close();
sock = null;
private DateTime lastAction;
OnClose = null;
OnConnect = null;
//OnDataReceived = null;
OnDestroy?.Invoke(this);
OnDestroy = null;
}
//public delegate void DataReceivedEvent(NetworkConnection sender, NetworkBuffer data);
//public delegate void ConnectionClosedEvent(NetworkConnection sender);
public delegate void NetworkConnectionEvent(NetworkConnection connection);
public event NetworkConnectionEvent OnConnect;
//public event DataReceivedEvent OnDataReceived;
public event NetworkConnectionEvent OnClose;
public event DestroyedEvent OnDestroy;
//object receivingLock = new object();
//object sendLock = new object();
bool processing = false;
// public INetworkReceiver<NetworkConnection> Receiver { get; set; }
public virtual void Destroy()
public ISocket Socket
{
get
{
// remove references
return sock;
}
}
public virtual void Assign(ISocket socket)
{
lastAction = DateTime.Now;
sock = socket;
sock.Receiver = this;
//socket.OnReceive += Socket_OnReceive;
//socket.OnClose += Socket_OnClose;
//socket.OnConnect += Socket_OnConnect;
}
//private void Socket_OnConnect()
//{
// OnConnect?.Invoke(this);
//}
//private void Socket_OnClose()
//{
// ConnectionClosed();
// OnClose?.Invoke(this);
//}
//protected virtual void ConnectionClosed()
//{
//}
//private void Socket_OnReceive(NetworkBuffer buffer)
//{
//}
public ISocket Unassign()
{
if (sock != null)
{
// connected = false;
//sock.OnClose -= Socket_OnClose;
//sock.OnConnect -= Socket_OnConnect;
//sock.OnReceive -= Socket_OnReceive;
sock?.Destroy();
//Receiver = null;
Close();
sock.Receiver = null;
var rt = sock;
sock = null;
OnClose = null;
OnConnect = null;
//OnDataReceived = null;
OnDestroy?.Invoke(this);
OnDestroy = null;
return rt;
}
else
return null;
}
public ISocket Socket
{
get
{
return sock;
}
}
//protected virtual void DataReceived(NetworkBuffer data)
//{
// if (OnDataReceived != null)
// {
// try
// {
// OnDataReceived?.Invoke(this, data);
// }
// catch (Exception ex)
// {
// Global.Log("NetworkConenction:DataReceived", LogType.Error, ex.ToString());
// }
// }
//}
public virtual void Assign(ISocket socket)
{
lastAction = DateTime.Now;
sock = socket;
sock.Receiver = this;
public void Close()
{
//if (!connected)
// return;
//socket.OnReceive += Socket_OnReceive;
//socket.OnClose += Socket_OnClose;
//socket.OnConnect += Socket_OnConnect;
}
//private void Socket_OnConnect()
//{
// OnConnect?.Invoke(this);
//}
//private void Socket_OnClose()
//{
// ConnectionClosed();
// OnClose?.Invoke(this);
//}
//protected virtual void ConnectionClosed()
//{
//}
//private void Socket_OnReceive(NetworkBuffer buffer)
//{
//}
public ISocket Unassign()
try
{
if (sock != null)
{
// connected = false;
//sock.OnClose -= Socket_OnClose;
//sock.OnConnect -= Socket_OnConnect;
//sock.OnReceive -= Socket_OnReceive;
sock.Receiver = null;
sock.Close();
}
catch (Exception ex)
{
Global.Log("NetworkConenction:Close", LogType.Error, ex.ToString());
var rt = sock;
sock = null;
}
return rt;
}
//finally
//{
//connected = false;
//}
}
public DateTime LastAction
{
get { return lastAction; }
}
public IPEndPoint RemoteEndPoint
{
get
{
if (sock != null)
return (IPEndPoint)sock.RemoteEndPoint;
else
return null;
}
}
//protected virtual void DataReceived(NetworkBuffer data)
//{
// if (OnDataReceived != null)
// {
// try
// {
// OnDataReceived?.Invoke(this, data);
// }
// catch (Exception ex)
// {
// Global.Log("NetworkConenction:DataReceived", LogType.Error, ex.ToString());
// }
// }
//}
public void Close()
public IPEndPoint LocalEndPoint
{
get
{
//if (!connected)
// return;
if (sock != null)
return (IPEndPoint)sock.LocalEndPoint;
else
return null;
}
}
try
{
public bool IsConnected
{
get
{
return sock.State == SocketState.Established;
}
}
/*
public void CloseAndWait()
{
try
{
if (!connected)
return;
if (sock != null)
sock.Close();
}
catch (Exception ex)
{
Global.Log("NetworkConenction:Close", LogType.Error, ex.ToString());
}
//finally
//{
//connected = false;
//}
}
public DateTime LastAction
{
get { return lastAction; }
}
public IPEndPoint RemoteEndPoint
{
get
{
if (sock != null)
return (IPEndPoint)sock.RemoteEndPoint;
else
return null;
}
}
public IPEndPoint LocalEndPoint
{
get
{
if (sock != null)
return (IPEndPoint)sock.LocalEndPoint;
else
return null;
}
}
public bool IsConnected
{
get
{
return sock.State == SocketState.Established;
}
}
/*
public void CloseAndWait()
{
try
{
if (!connected)
return;
if (sock != null)
sock.Close();
while (connected)
{
Thread.Sleep(100);
}
}
finally
{
}
}
*/
public virtual AsyncReply<bool> SendAsync(byte[] message, int offset, int length)
{
try
{
lastAction = DateTime.Now;
return sock.SendAsync(message, offset, length);
}
catch
{
return new AsyncReply<bool>(false);
}
}
public virtual void Send(byte[] msg)
{
try
{
sock?.Send(msg);
lastAction = DateTime.Now;
}
catch
{
}
}
public virtual void Send(byte[] msg, int offset, int length)
{
try
{
sock.Send(msg, offset, length);
lastAction = DateTime.Now;
}
catch
{
}
}
public virtual void Send(string data)
{
Send(Encoding.UTF8.GetBytes(data));
}
public void NetworkClose(ISocket socket)
{
Disconencted();
OnClose?.Invoke(this);
}
public void NetworkConnect(ISocket socket)
{
Connected();
OnConnect?.Invoke(this);
}
//{
//ConnectionClosed();
//OnClose?.Invoke(this);
//Receiver?.NetworkClose(this);
//}
//public void NetworkConenct(ISocket sender)
//{
// OnConnect?.Invoke(this);
//}
protected abstract void DataReceived(NetworkBuffer buffer);
protected abstract void Connected();
protected abstract void Disconencted();
public void NetworkReceive(ISocket sender, NetworkBuffer buffer)
{
try
{
// Unassigned ?
if (sock == null)
return;
// Closed ?
if (sock.State == SocketState.Closed)// || sock.State == SocketState.Terminated) // || !connected)
return;
lastAction = DateTime.Now;
if (!processing)
while (connected)
{
processing = true;
Thread.Sleep(100);
}
}
finally
{
try
}
}
*/
public virtual AsyncReply<bool> SendAsync(byte[] message, int offset, int length)
{
try
{
lastAction = DateTime.Now;
return sock.SendAsync(message, offset, length);
}
catch
{
return new AsyncReply<bool>(false);
}
}
public virtual void Send(byte[] msg)
{
try
{
sock?.Send(msg);
lastAction = DateTime.Now;
}
catch
{
}
}
public virtual void Send(byte[] msg, int offset, int length)
{
try
{
sock.Send(msg, offset, length);
lastAction = DateTime.Now;
}
catch
{
}
}
public virtual void Send(string data)
{
Send(Encoding.UTF8.GetBytes(data));
}
public void NetworkClose(ISocket socket)
{
Disconencted();
OnClose?.Invoke(this);
}
public void NetworkConnect(ISocket socket)
{
Connected();
OnConnect?.Invoke(this);
}
//{
//ConnectionClosed();
//OnClose?.Invoke(this);
//Receiver?.NetworkClose(this);
//}
//public void NetworkConenct(ISocket sender)
//{
// OnConnect?.Invoke(this);
//}
protected abstract void DataReceived(NetworkBuffer buffer);
protected abstract void Connected();
protected abstract void Disconencted();
public void NetworkReceive(ISocket sender, NetworkBuffer buffer)
{
try
{
// Unassigned ?
if (sock == null)
return;
// Closed ?
if (sock.State == SocketState.Closed)// || sock.State == SocketState.Terminated) // || !connected)
return;
lastAction = DateTime.Now;
if (!processing)
{
processing = true;
try
{
//lock(buffer.SyncLock)
while (buffer.Available > 0 && !buffer.Protected)
{
//lock(buffer.SyncLock)
while (buffer.Available > 0 && !buffer.Protected)
{
//Receiver?.NetworkReceive(this, buffer);
DataReceived(buffer);
}
//Receiver?.NetworkReceive(this, buffer);
DataReceived(buffer);
}
catch
{
}
catch
{
}
processing = false;
}
processing = false;
}
catch (Exception ex)
{
Global.Log("NetworkConnection", LogType.Warning, ex.ToString());
}
}
catch (Exception ex)
{
Global.Log("NetworkConnection", LogType.Warning, ex.ToString());
}
//{
// Receiver?.NetworkError(this);
//throw new NotImplementedException();
//}
//public void NetworkConnect(ISocket sender)
//{
// Receiver?.NetworkConnect(this);
//throw new NotImplementedException();
//}
}
}
//{
// Receiver?.NetworkError(this);
//throw new NotImplementedException();
//}
//public void NetworkConnect(ISocket sender)
//{
// Receiver?.NetworkConnect(this);
//throw new NotImplementedException();
//}
}

View File

@ -33,279 +33,277 @@ using Esiur.Resource;
using System.Threading.Tasks;
using System.Diagnostics;
namespace Esiur.Net
namespace Esiur.Net;
public abstract class NetworkServer<TConnection> : IDestructible where TConnection : NetworkConnection, new()
{
//private bool isRunning;
private Sockets.ISocket listener;
public AutoList<TConnection, NetworkServer<TConnection>> Connections { get; internal set; }
public abstract class NetworkServer<TConnection> : IDestructible where TConnection : NetworkConnection, new()
private Thread thread;
//protected abstract void DataReceived(TConnection sender, NetworkBuffer data);
//protected abstract void ClientConnected(TConnection sender);
//protected abstract void ClientDisconnected(TConnection sender);
private Timer timer;
//public KeyList<string, TSession> Sessions = new KeyList<string, TSession>();
public event DestroyedEvent OnDestroy;
//public AutoList<TConnection, NetworkServer<TConnection>> Connections => connections;
private void MinuteThread(object state)
{
//private bool isRunning;
private Sockets.ISocket listener;
public AutoList<TConnection, NetworkServer<TConnection>> Connections { get; private set; }
private Thread thread;
//protected abstract void DataReceived(TConnection sender, NetworkBuffer data);
//protected abstract void ClientConnected(TConnection sender);
//protected abstract void ClientDisconnected(TConnection sender);
List<TConnection> ToBeClosed = null;
private Timer timer;
//public KeyList<string, TSession> Sessions = new KeyList<string, TSession>();
public event DestroyedEvent OnDestroy;
//public AutoList<TConnection, NetworkServer<TConnection>> Connections => connections;
private void MinuteThread(object state)
lock (Connections.SyncRoot)
{
List<TConnection> ToBeClosed = null;
lock (Connections.SyncRoot)
foreach (TConnection c in Connections)
{
foreach (TConnection c in Connections)
if (DateTime.Now.Subtract(c.LastAction).TotalSeconds >= Timeout)
{
if (DateTime.Now.Subtract(c.LastAction).TotalSeconds >= Timeout)
{
if (ToBeClosed == null)
ToBeClosed = new List<TConnection>();
ToBeClosed.Add(c);
}
if (ToBeClosed == null)
ToBeClosed = new List<TConnection>();
ToBeClosed.Add(c);
}
}
if (ToBeClosed != null)
{
//Console.WriteLine("Term: " + ToBeClosed.Count + " " + this.listener.LocalEndPoint.ToString());
foreach (TConnection c in ToBeClosed)
c.Close();// CloseAndWait();
ToBeClosed.Clear();
ToBeClosed = null;
}
}
public void Start(Sockets.ISocket socket)//, uint timeout, uint clock)
if (ToBeClosed != null)
{
if (listener != null)
return;
//Console.WriteLine("Term: " + ToBeClosed.Count + " " + this.listener.LocalEndPoint.ToString());
foreach (TConnection c in ToBeClosed)
c.Close();// CloseAndWait();
ToBeClosed.Clear();
ToBeClosed = null;
}
}
public void Start(Sockets.ISocket socket)//, uint timeout, uint clock)
{
if (listener != null)
return;
Connections = new AutoList<TConnection, NetworkServer<TConnection>>(this);
Connections = new AutoList<TConnection, NetworkServer<TConnection>>(this);
if (Timeout > 0 & Clock > 0)
if (Timeout > 0 & Clock > 0)
{
timer = new Timer(MinuteThread, null, TimeSpan.FromMinutes(0), TimeSpan.FromSeconds(Clock));
}
listener = socket;
// Start accepting
//var r = listener.Accept();
//r.Then(NewConnection);
//r.timeout?.Dispose();
//var rt = listener.Accept().Then()
thread = new Thread(new ThreadStart(() =>
{
while (true)
{
timer = new Timer(MinuteThread, null, TimeSpan.FromMinutes(0), TimeSpan.FromSeconds(Clock));
}
listener = socket;
// Start accepting
//var r = listener.Accept();
//r.Then(NewConnection);
//r.timeout?.Dispose();
//var rt = listener.Accept().Then()
thread = new Thread(new ThreadStart(() =>
{
while (true)
try
{
try
var s = listener.Accept();
if (s == null)
{
var s = listener.Accept();
Console.Write("sock == null");
return;
}
if (s == null)
{
Console.Write("sock == null");
return;
}
var c = new TConnection();
var c = new TConnection();
//c.OnClose += ClientDisconnectedEventReceiver;
c.Assign(s);
Add(c);
Add(c);
//Connections.Add(c);
try
{
{
//ClientConnected(c);
ClientConnected(c);
//NetworkConnect(c);
}
catch
{
catch
{
// something wrong with the child.
}
s.Begin();
s.Begin();
// Accept more
//listener.Accept().Then(NewConnection);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}));
thread.Start();
}
[Attribute]
public uint Timeout
{
get;
set;
}
[Attribute]
public uint Clock
{
get;
set;
}
public void Stop()
{
var port = 0;
try
{
if (listener != null)
catch (Exception ex)
{
port = listener.LocalEndPoint.Port;
listener.Close();
Console.WriteLine(ex);
}
// wait until the listener stops
//while (isRunning)
//{
// Thread.Sleep(100);
//}
//Console.WriteLine("Listener stopped");
var cons = Connections.ToArray();
//lock (connections.SyncRoot)
//{
foreach (TConnection con in cons)
con.Close();
//}
//Console.WriteLine("Sockets Closed");
//while (connections.Count > 0)
//{
// Console.WriteLine("Waiting... " + connections.Count);
// Thread.Sleep(1000);
//}
}
finally
}));
thread.Start();
}
[Attribute]
public uint Timeout
{
get;
set;
}
[Attribute]
public uint Clock
{
get;
set;
}
public void Stop()
{
var port = 0;
try
{
if (listener != null)
{
Console.WriteLine("Server@{0} is down", port);
port = listener.LocalEndPoint.Port;
listener.Close();
}
// wait until the listener stops
//while (isRunning)
//{
// Thread.Sleep(100);
//}
//Console.WriteLine("Listener stopped");
var cons = Connections.ToArray();
//lock (connections.SyncRoot)
//{
foreach (TConnection con in cons)
con.Close();
//}
//Console.WriteLine("Sockets Closed");
//while (connections.Count > 0)
//{
// Console.WriteLine("Waiting... " + connections.Count);
// Thread.Sleep(1000);
//}
}
public virtual void Remove(TConnection connection)
finally
{
//connection.OnDataReceived -= OnDataReceived;
//connection.OnConnect -= OnClientConnect;
connection.OnClose -= ClientDisconnectedEventReceiver;
Connections.Remove(connection);
}
public virtual void Add(TConnection connection)
{
//connection.OnDataReceived += OnDataReceived;
//connection.OnConnect += OnClientConnect;
connection.OnClose += ClientDisconnectedEventReceiver;// OnClientClose;
Connections.Add(connection);
}
public bool IsRunning
{
get
{
return listener.State == SocketState.Listening;
//isRunning;
}
}
//public void OnDataReceived(ISocket sender, NetworkBuffer data)
//{
// DataReceived((TConnection)sender, data);
//}
//public void OnClientConnect(ISocket sender)
//{
// if (sender == null)
// return;
// if (sender.RemoteEndPoint == null || sender.LocalEndPoint == null)
// { }
// //Console.WriteLine("NULL");
// else
// Global.Log("Connections", LogType.Debug, sender.RemoteEndPoint.Address.ToString()
// + "->" + sender.LocalEndPoint.Port + " at " + DateTime.UtcNow.ToString("d")
// + " " + DateTime.UtcNow.ToString("d"), false);
// // Console.WriteLine("Connected " + sender.RemoteEndPoint.ToString());
// ClientConnected((TConnection)sender);
//}
//public void OnClientClose(ISocket sender)
//{
//}
public void Destroy()
{
Stop();
OnDestroy?.Invoke(this);
}
private void ClientDisconnectedEventReceiver(NetworkConnection connection)
{
try
{
var con = connection as TConnection;
con.Destroy();
// con.OnClose -= ClientDisconnectedEventReceiver;
Remove(con);
//Connections.Remove(con);
ClientDisconnected(con);
//RemoveConnection((TConnection)sender);
//connections.Remove(sender)
//ClientDisconnected((TConnection)sender);
}
catch (Exception ex)
{
Global.Log("NetworkServer:OnClientDisconnect", LogType.Error, ex.ToString());
}
}
protected abstract void ClientDisconnected(TConnection connection);
protected abstract void ClientConnected(TConnection connection);
~NetworkServer()
{
Stop();
listener = null;
Console.WriteLine("Server@{0} is down", port);
}
}
}
public virtual void Remove(TConnection connection)
{
//connection.OnDataReceived -= OnDataReceived;
//connection.OnConnect -= OnClientConnect;
connection.OnClose -= ClientDisconnectedEventReceiver;
Connections.Remove(connection);
}
public virtual void Add(TConnection connection)
{
//connection.OnDataReceived += OnDataReceived;
//connection.OnConnect += OnClientConnect;
connection.OnClose += ClientDisconnectedEventReceiver;// OnClientClose;
Connections.Add(connection);
}
public bool IsRunning
{
get
{
return listener.State == SocketState.Listening;
//isRunning;
}
}
//public void OnDataReceived(ISocket sender, NetworkBuffer data)
//{
// DataReceived((TConnection)sender, data);
//}
//public void OnClientConnect(ISocket sender)
//{
// if (sender == null)
// return;
// if (sender.RemoteEndPoint == null || sender.LocalEndPoint == null)
// { }
// //Console.WriteLine("NULL");
// else
// Global.Log("Connections", LogType.Debug, sender.RemoteEndPoint.Address.ToString()
// + "->" + sender.LocalEndPoint.Port + " at " + DateTime.UtcNow.ToString("d")
// + " " + DateTime.UtcNow.ToString("d"), false);
// // Console.WriteLine("Connected " + sender.RemoteEndPoint.ToString());
// ClientConnected((TConnection)sender);
//}
//public void OnClientClose(ISocket sender)
//{
//}
public void Destroy()
{
Stop();
OnDestroy?.Invoke(this);
}
private void ClientDisconnectedEventReceiver(NetworkConnection connection)
{
try
{
var con = connection as TConnection;
con.Destroy();
// con.OnClose -= ClientDisconnectedEventReceiver;
Remove(con);
//Connections.Remove(con);
ClientDisconnected(con);
//RemoveConnection((TConnection)sender);
//connections.Remove(sender)
//ClientDisconnected((TConnection)sender);
}
catch (Exception ex)
{
Global.Log("NetworkServer:OnClientDisconnect", LogType.Error, ex.ToString());
}
}
protected abstract void ClientDisconnected(TConnection connection);
protected abstract void ClientConnected(TConnection connection);
~NetworkServer()
{
Stop();
listener = null;
}
}

View File

@ -35,96 +35,94 @@ using Esiur.Data;
using Esiur.Misc;
using Esiur.Core;
namespace Esiur.Net
namespace Esiur.Net;
public class NetworkSession : IDestructible //<T> where T : TClient
{
public class NetworkSession:IDestructible //<T> where T : TClient
public delegate void SessionModifiedEvent(NetworkSession session, string key, object oldValue, object newValue);
public delegate void SessionEndedEvent(NetworkSession session);
private string id;
private Timer timer;
private int timeout;
DateTime creation;
DateTime lastAction;
private KeyList<string, object> variables;
public event SessionEndedEvent OnEnd;
public event SessionModifiedEvent OnModify;
public event DestroyedEvent OnDestroy;
public KeyList<string, object> Variables
{
public delegate void SessionModifiedEvent(NetworkSession session, string key, object oldValue, object newValue);
public delegate void SessionEndedEvent(NetworkSession session);
get { return variables; }
}
private string id;
private Timer timer;
private int timeout;
DateTime creation;
DateTime lastAction;
public NetworkSession()
{
variables = new KeyList<string, object>();
variables.OnModified += new KeyList<string, object>.Modified(VariablesModified);
creation = DateTime.Now;
}
private KeyList<string, object> variables;
internal void Set(string id, int timeout)
{
//modified = sessionModifiedEvent;
//ended = sessionEndEvent;
this.id = id;
public event SessionEndedEvent OnEnd;
public event SessionModifiedEvent OnModify;
public event DestroyedEvent OnDestroy;
public KeyList<string, object> Variables
if (this.timeout != 0)
{
get { return variables; }
}
public NetworkSession()
{
variables = new KeyList<string, object>();
variables.OnModified += new KeyList<string, object>.Modified(VariablesModified);
this.timeout = timeout;
timer = new Timer(OnSessionEndTimerCallback, null, TimeSpan.FromSeconds(timeout), TimeSpan.FromSeconds(0));
creation = DateTime.Now;
}
internal void Set(string id, int timeout )
{
//modified = sessionModifiedEvent;
//ended = sessionEndEvent;
this.id = id;
if (this.timeout != 0)
{
this.timeout = timeout;
timer = new Timer(OnSessionEndTimerCallback, null, TimeSpan.FromSeconds(timeout), TimeSpan.FromSeconds(0));
creation = DateTime.Now;
}
}
private void OnSessionEndTimerCallback(object o)
{
OnEnd?.Invoke(this);
}
void VariablesModified(string key, object oldValue, object newValue, KeyList<string, object> sender)
{
OnModify?.Invoke(this, key, oldValue, newValue);
}
public void Destroy()
{
OnDestroy?.Invoke(this);
timer.Dispose();
timer = null;
}
internal void Refresh()
{
lastAction = DateTime.Now;
timer.Change(TimeSpan.FromSeconds(timeout), TimeSpan.FromSeconds(0));
}
public int Timeout // Seconds
{
get
{
return timeout;
}
set
{
timeout = value;
Refresh();
}
}
public string Id
{
get { return id; }
}
public DateTime LastAction
{
get { return lastAction; }
}
}
}
private void OnSessionEndTimerCallback(object o)
{
OnEnd?.Invoke(this);
}
void VariablesModified(string key, object oldValue, object newValue, KeyList<string, object> sender)
{
OnModify?.Invoke(this, key, oldValue, newValue);
}
public void Destroy()
{
OnDestroy?.Invoke(this);
timer.Dispose();
timer = null;
}
internal void Refresh()
{
lastAction = DateTime.Now;
timer.Change(TimeSpan.FromSeconds(timeout), TimeSpan.FromSeconds(0));
}
public int Timeout // Seconds
{
get
{
return timeout;
}
set
{
timeout = value;
Refresh();
}
}
public string Id
{
get { return id; }
}
public DateTime LastAction
{
get { return lastAction; }
}
}

View File

@ -32,287 +32,284 @@ using Esiur.Data;
using System.Net;
using System.Text.Json.Serialization;
namespace Esiur.Net.Packets
namespace Esiur.Net.Packets;
public class HTTPRequestPacket : Packet
{
public class HTTPRequestPacket : Packet
public enum HTTPMethod : byte
{
GET,
POST,
HEAD,
PUT,
DELETE,
OPTIONS,
TRACE,
CONNECT,
UNKNOWN
}
public enum HTTPMethod:byte
public StringKeyList Query;
public HTTPMethod Method;
public StringKeyList Headers;
public bool WSMode;
public string Version;
public StringKeyList Cookies; // String
public string URL; /// With query
public string Filename; /// Without query
//public byte[] PostContents;
public KeyList<string, object> PostForms;
public byte[] Message;
private HTTPMethod getMethod(string method)
{
switch (method.ToLower())
{
GET,
POST,
HEAD,
PUT,
DELETE,
OPTIONS,
TRACE,
CONNECT,
UNKNOWN
case "get":
return HTTPMethod.GET;
case "post":
return HTTPMethod.POST;
case "head":
return HTTPMethod.HEAD;
case "put":
return HTTPMethod.PUT;
case "delete":
return HTTPMethod.DELETE;
case "options":
return HTTPMethod.OPTIONS;
case "trace":
return HTTPMethod.TRACE;
case "connect":
return HTTPMethod.CONNECT;
default:
return HTTPMethod.UNKNOWN;
}
}
public StringKeyList Query;
public HTTPMethod Method;
public StringKeyList Headers;
public override string ToString()
{
return "HTTPRequestPacket"
+ "\n\tVersion: " + Version
+ "\n\tMethod: " + Method
+ "\n\tURL: " + URL
+ "\n\tMessage: " + (Message != null ? Message.Length.ToString() : "NULL");
}
public bool WSMode;
public override long Parse(byte[] data, uint offset, uint ends)
{
string[] sMethod = null;
string[] sLines = null;
public string Version;
public StringKeyList Cookies; // String
public string URL; /// With query
public string Filename; /// Without query
//public byte[] PostContents;
public KeyList<string, object> PostForms;
public byte[] Message;
uint headerSize = 0;
private HTTPMethod getMethod(string method)
for (uint i = offset; i < ends - 3; i++)
{
switch (method.ToLower())
if (data[i] == '\r' && data[i + 1] == '\n'
&& data[i + 2] == '\r' && data[i + 3] == '\n')
{
case "get":
return HTTPMethod.GET;
case "post":
return HTTPMethod.POST;
case "head":
return HTTPMethod.HEAD;
case "put":
return HTTPMethod.PUT;
case "delete":
return HTTPMethod.DELETE;
case "options":
return HTTPMethod.OPTIONS;
case "trace":
return HTTPMethod.TRACE;
case "connect":
return HTTPMethod.CONNECT;
default:
return HTTPMethod.UNKNOWN;
sLines = Encoding.ASCII.GetString(data, (int)offset, (int)(i - offset)).Split(new string[] { "\r\n" },
StringSplitOptions.None);
headerSize = i + 4;
break;
}
}
public override string ToString()
{
return "HTTPRequestPacket"
+ "\n\tVersion: " + Version
+ "\n\tMethod: " + Method
+ "\n\tURL: " + URL
+ "\n\tMessage: " + (Message != null ? Message.Length.ToString() : "NULL");
}
if (headerSize == 0)
return -1;
public override long Parse(byte[] data, uint offset, uint ends)
{
string[] sMethod = null;
string[] sLines = null;
uint headerSize = 0;
Cookies = new StringKeyList();
PostForms = new KeyList<string, object>();
Query = new StringKeyList();
Headers = new StringKeyList();
for (uint i = offset; i < ends - 3; i++)
sMethod = sLines[0].Split(' ');
Method = getMethod(sMethod[0].Trim());
if (sMethod.Length == 3)
{
sMethod[1] = WebUtility.UrlDecode(sMethod[1]);
if (sMethod[1].Length >= 7)
{
if (data[i] == '\r' && data[i + 1] == '\n'
&& data[i + 2] == '\r' && data[i + 3] == '\n')
if (sMethod[1].StartsWith("http://"))
{
sLines = Encoding.ASCII.GetString(data, (int)offset,(int)( i - offset)).Split(new string[] { "\r\n" },
StringSplitOptions.None);
headerSize = i + 4;
break;
sMethod[1] = sMethod[1].Substring(sMethod[1].IndexOf("/", 7));
}
}
if (headerSize == 0)
return -1;
URL = sMethod[1].Trim();
Cookies = new StringKeyList();
PostForms = new KeyList<string, object>();
Query = new StringKeyList();
Headers = new StringKeyList();
sMethod = sLines[0].Split(' ');
Method = getMethod(sMethod[0].Trim());
if (sMethod.Length == 3)
if (URL.IndexOf("?", 0) != -1)
{
sMethod[1] = WebUtility.UrlDecode(sMethod[1]);
if (sMethod[1].Length >= 7)
Filename = URL.Split(new char[] { '?' }, 2)[0];
}
else
{
Filename = URL;
}
if (Filename.IndexOf("%", 0) != -1)
{
Filename = WebUtility.UrlDecode(Filename);
}
Version = sMethod[2].Trim();
}
// Read all headers
for (int i = 1; i < sLines.Length; i++)
{
if (sLines[i] == String.Empty)
{
// Invalid header
return 0;
}
if (sLines[i].IndexOf(':') == -1)
{
// Invalid header
return 0;
}
string[] header = sLines[i].Split(new char[] { ':' }, 2);
header[0] = header[0].ToLower();
Headers[header[0]] = header[1].Trim();
if (header[0] == "cookie")
{
string[] cookies = header[1].Split(';');
foreach (string cookie in cookies)
{
if (sMethod[1].StartsWith("http://"))
if (cookie.IndexOf('=') != -1)
{
sMethod[1] = sMethod[1].Substring(sMethod[1].IndexOf("/", 7));
string[] splitCookie = cookie.Split('=');
splitCookie[0] = splitCookie[0].Trim();
splitCookie[1] = splitCookie[1].Trim();
if (!(Cookies.ContainsKey(splitCookie[0].Trim())))
Cookies.Add(splitCookie[0], splitCookie[1]);
}
else
{
if (!(Cookies.ContainsKey(cookie.Trim())))
{
Cookies.Add(cookie.Trim(), String.Empty);
}
}
}
}
}
URL = sMethod[1].Trim();
if (URL.IndexOf("?", 0) != -1)
// Query String
if (URL.IndexOf("?", 0) != -1)
{
string[] SQ = URL.Split(new char[] { '?' }, 2)[1].Split('&');
foreach (string S in SQ)
{
if (S.IndexOf("=", 0) != -1)
{
Filename = URL.Split(new char[] { '?' }, 2)[0];
string[] qp = S.Split(new char[] { '=' }, 2);
if (!Query.ContainsKey(WebUtility.UrlDecode(qp[0])))
{
Query.Add(WebUtility.UrlDecode(qp[0]), WebUtility.UrlDecode(qp[1]));
}
}
else
{
Filename = URL;
}
if (Filename.IndexOf("%", 0) != -1)
{
Filename = WebUtility.UrlDecode(Filename);
}
Version = sMethod[2].Trim();
}
// Read all headers
for (int i = 1; i < sLines.Length; i++)
{
if (sLines[i] == String.Empty)
{
// Invalid header
return 0;
}
if (sLines[i].IndexOf(':') == -1)
{
// Invalid header
return 0;
}
string[] header = sLines[i].Split(new char[] { ':' }, 2);
header[0] = header[0].ToLower();
Headers[header[0]] = header[1].Trim();
if (header[0] == "cookie")
{
string[] cookies = header[1].Split(';');
foreach (string cookie in cookies)
if (!(Query.ContainsKey(WebUtility.UrlDecode(S))))
{
if (cookie.IndexOf('=') != -1)
Query.Add(WebUtility.UrlDecode(S), null);
}
}
}
}
// Post Content-Length
if (Method == HTTPMethod.POST)
{
try
{
uint postSize = uint.Parse((string)Headers["content-length"]);
// check limit
if (postSize > data.Length - headerSize)
return -(postSize - (data.Length - headerSize));
if (
Headers["content-type"] == null
|| Headers["content-type"] == ""
|| Headers["content-type"].StartsWith("application/x-www-form-urlencoded"))
{
string[] PostVars = null;
PostVars = Encoding.UTF8.GetString(data, (int)headerSize, (int)postSize).Split('&');
for (int J = 0; J < PostVars.Length; J++)
{
if (PostVars[J].IndexOf("=") != -1)
{
string[] splitCookie = cookie.Split('=');
splitCookie[0] = splitCookie[0].Trim();
splitCookie[1] = splitCookie[1].Trim();
if (!(Cookies.ContainsKey(splitCookie[0].Trim())))
Cookies.Add(splitCookie[0], splitCookie[1]);
string key = WebUtility.HtmlDecode(
WebUtility.UrlDecode(PostVars[J].Split(new char[] { '=' }, 2)[0]));
if (PostForms.Contains(key))
PostForms[key] = WebUtility.HtmlDecode(
WebUtility.UrlDecode(PostVars[J].Split(new char[] { '=' }, 2)[1]));
else
PostForms.Add(key, WebUtility.HtmlDecode(
WebUtility.UrlDecode(PostVars[J].Split(new char[] { '=' }, 2)[1])));
}
else
{
if (!(Cookies.ContainsKey(cookie.Trim())))
{
Cookies.Add(cookie.Trim(), String.Empty);
}
}
if (PostForms.Contains("unknown"))
PostForms["unknown"] = PostForms["unknown"]
+ "&" + WebUtility.HtmlDecode(WebUtility.UrlDecode(PostVars[J]));
else
PostForms.Add("unknown", WebUtility.HtmlDecode(WebUtility.UrlDecode(PostVars[J])));
}
}
}
else if (Headers["content-type"].StartsWith("multipart/form-data"))
{
int st = 1;
int ed = 0;
string strBoundry = "--" + Headers["content-type"].Substring(
Headers["content-type"].IndexOf("boundary=", 0) + 9);
// Query String
if (URL.IndexOf("?", 0) != -1)
string[] sc = Encoding.UTF8.GetString(data, (int)headerSize, (int)postSize).Split(
new string[] { strBoundry }, StringSplitOptions.None);
for (int j = 1; j < sc.Length - 1; j++)
{
string[] ps = sc[j].Split(new string[] { "\r\n\r\n" }, 2, StringSplitOptions.None);
ps[1] = ps[1].Substring(0, ps[1].Length - 2); // remove the empty line
st = ps[0].IndexOf("name=", 0) + 6;
ed = ps[0].IndexOf("\"", st);
PostForms.Add(ps[0].Substring(st, ed - st), ps[1]);
}
}
//else if (Headers["content-type"] == "application/json")
//{
// var json = DC.Clip(data, headerSize, postSize);
//}
else
{
//PostForms.Add(Headers["content-type"], Encoding.Default.GetString( ));
Message = DC.Clip(data, headerSize, postSize);
}
return headerSize + postSize;
}
catch
{
string[] SQ = URL.Split(new char[] { '?' }, 2)[1].Split('&');
foreach (string S in SQ)
{
if (S.IndexOf("=", 0) != -1)
{
string[] qp = S.Split(new char[] { '=' }, 2);
if (!Query.ContainsKey(WebUtility.UrlDecode(qp[0])))
{
Query.Add(WebUtility.UrlDecode(qp[0]), WebUtility.UrlDecode(qp[1]));
}
}
else
{
if (!(Query.ContainsKey(WebUtility.UrlDecode(S))))
{
Query.Add(WebUtility.UrlDecode(S), null);
}
}
}
return 0;
}
// Post Content-Length
if (Method == HTTPMethod.POST)
{
try
{
uint postSize = uint.Parse((string)Headers["content-length"]);
// check limit
if (postSize > data.Length - headerSize)
return -(postSize - (data.Length - headerSize));
if (
Headers["content-type"] == null
|| Headers["content-type"] == ""
|| Headers["content-type"].StartsWith("application/x-www-form-urlencoded"))
{
string[] PostVars = null;
PostVars = Encoding.UTF8.GetString(data, (int)headerSize, (int)postSize).Split('&');
for (int J = 0; J < PostVars.Length; J++)
{
if (PostVars[J].IndexOf("=") != -1)
{
string key = WebUtility.HtmlDecode(
WebUtility.UrlDecode(PostVars[J].Split(new char[] { '=' }, 2)[0]));
if (PostForms.Contains(key))
PostForms[key] = WebUtility.HtmlDecode(
WebUtility.UrlDecode(PostVars[J].Split(new char[] { '=' }, 2)[1]));
else
PostForms.Add(key, WebUtility.HtmlDecode(
WebUtility.UrlDecode(PostVars[J].Split(new char[] { '=' }, 2)[1])));
}
else
if (PostForms.Contains("unknown"))
PostForms["unknown"] = PostForms["unknown"]
+ "&" + WebUtility.HtmlDecode(WebUtility.UrlDecode(PostVars[J]));
else
PostForms.Add("unknown", WebUtility.HtmlDecode(WebUtility.UrlDecode(PostVars[J])));
}
}
else if (Headers["content-type"].StartsWith("multipart/form-data"))
{
int st = 1;
int ed = 0;
string strBoundry = "--" + Headers["content-type"].Substring(
Headers["content-type"].IndexOf("boundary=", 0) + 9);
string[] sc = Encoding.UTF8.GetString(data, (int)headerSize, (int)postSize).Split(
new string[] { strBoundry }, StringSplitOptions.None);
for (int j = 1; j < sc.Length - 1; j++)
{
string[] ps = sc[j].Split(new string[] { "\r\n\r\n" }, 2, StringSplitOptions.None);
ps[1] = ps[1].Substring(0, ps[1].Length - 2); // remove the empty line
st = ps[0].IndexOf("name=", 0) + 6;
ed = ps[0].IndexOf("\"", st);
PostForms.Add(ps[0].Substring(st, ed - st), ps[1]);
}
}
//else if (Headers["content-type"] == "application/json")
//{
// var json = DC.Clip(data, headerSize, postSize);
//}
else
{
//PostForms.Add(Headers["content-type"], Encoding.Default.GetString( ));
Message = DC.Clip(data, headerSize, postSize);
}
return headerSize + postSize;
}
catch
{
return 0;
}
}
return headerSize;
}
return headerSize;
}
}

View File

@ -27,278 +27,276 @@ using System.Linq;
using System.Text;
using Esiur.Misc;
using Esiur.Data;
namespace Esiur.Net.Packets
namespace Esiur.Net.Packets;
public class HTTPResponsePacket : Packet
{
public class HTTPResponsePacket : Packet
public enum ComposeOptions : int
{
AllCalculateLength,
AllDontCalculateLength,
SpecifiedHeadersOnly,
DataOnly
}
public enum ComposeOptions : int
public enum ResponseCode : int
{
Switching = 101,
OK = 200,
Created = 201,
Accepted = 202,
NoContent = 204,
MovedPermanently = 301,
Found = 302,
SeeOther = 303,
NotModified = 304,
TemporaryRedirect = 307,
BadRequest = 400,
Unauthorized = 401,
Forbidden = 403,
NotFound = 404,
MethodNotAllowed = 405,
NotAcceptable = 406,
PreconditionFailed = 412,
UnsupportedMediaType = 415,
InternalServerError = 500,
NotImplemented = 501,
}
public struct HTTPCookie
{
public string Name;
public string Value;
public DateTime Expires;
public string Path;
public bool HttpOnly;
public string Domain;
public HTTPCookie(string name, string value)
{
AllCalculateLength,
AllDontCalculateLength,
SpecifiedHeadersOnly,
DataOnly
this.Name = name;
this.Value = value;
this.Path = null;
this.Expires = DateTime.MinValue;
this.HttpOnly = false;
this.Domain = null;
}
public enum ResponseCode : int
public HTTPCookie(string name, string value, DateTime expires)
{
Switching= 101,
OK = 200,
Created = 201,
Accepted = 202,
NoContent = 204,
MovedPermanently = 301,
Found = 302,
SeeOther = 303,
NotModified = 304,
TemporaryRedirect = 307,
BadRequest = 400,
Unauthorized = 401,
Forbidden = 403,
NotFound = 404,
MethodNotAllowed = 405,
NotAcceptable = 406,
PreconditionFailed = 412,
UnsupportedMediaType = 415,
InternalServerError = 500,
NotImplemented = 501,
this.Name = name;
this.Value = value;
this.Expires = expires;
this.HttpOnly = false;
this.Domain = null;
this.Path = null;
}
public struct HTTPCookie
{
public string Name;
public string Value;
public DateTime Expires;
public string Path;
public bool HttpOnly;
public string Domain;
public HTTPCookie(string name, string value)
{
this.Name = name;
this.Value = value;
this.Path = null;
this.Expires = DateTime.MinValue;
this.HttpOnly = false;
this.Domain = null;
}
public HTTPCookie(string name, string value, DateTime expires)
{
this.Name = name;
this.Value = value;
this.Expires = expires;
this.HttpOnly = false;
this.Domain = null;
this.Path = null;
}
public override string ToString()
{
//Set-Cookie: ckGeneric=CookieBody; expires=Sun, 30-Dec-2001 21:00:00 GMT; domain=.com.au; path=/
//Set-Cookie: SessionID=another; expires=Fri, 29 Jun 2006 20:47:11 UTC; path=/
var cookie = Name + "=" + Value;
if (Expires.Ticks != 0)
cookie += "; expires=" + Expires.ToUniversalTime().ToString("ddd, dd MMM yyyy HH:mm:ss") + " GMT";
if (Domain != null)
cookie += "; domain=" + Domain;
if (Path != null)
cookie += "; path=" + Path;
if (HttpOnly)
cookie += "; HttpOnly";
return cookie;
}
}
public StringKeyList Headers = new StringKeyList(true);
public string Version = "HTTP/1.1";
public byte[] Message;
public ResponseCode Number;
public string Text;
public List<HTTPCookie> Cookies = new List<HTTPCookie>();
public bool Handled;
public override string ToString()
{
return "HTTPResponsePacket"
+ "\n\tVersion: " + Version
//+ "\n\tMethod: " + Method
//+ "\n\tURL: " + URL
+ "\n\tMessage: " + (Message != null ? Message.Length.ToString() : "NULL");
//Set-Cookie: ckGeneric=CookieBody; expires=Sun, 30-Dec-2001 21:00:00 GMT; domain=.com.au; path=/
//Set-Cookie: SessionID=another; expires=Fri, 29 Jun 2006 20:47:11 UTC; path=/
var cookie = Name + "=" + Value;
if (Expires.Ticks != 0)
cookie += "; expires=" + Expires.ToUniversalTime().ToString("ddd, dd MMM yyyy HH:mm:ss") + " GMT";
if (Domain != null)
cookie += "; domain=" + Domain;
if (Path != null)
cookie += "; path=" + Path;
if (HttpOnly)
cookie += "; HttpOnly";
return cookie;
}
}
public StringKeyList Headers = new StringKeyList(true);
public string Version = "HTTP/1.1";
public byte[] Message;
public ResponseCode Number;
public string Text;
public List<HTTPCookie> Cookies = new List<HTTPCookie>();
public bool Handled;
public override string ToString()
{
return "HTTPResponsePacket"
+ "\n\tVersion: " + Version
//+ "\n\tMethod: " + Method
//+ "\n\tURL: " + URL
+ "\n\tMessage: " + (Message != null ? Message.Length.ToString() : "NULL");
}
private string MakeHeader(ComposeOptions options)
{
string header = $"{Version} {(int)Number} {Text}\r\nServer: Esiur {Global.Version}\r\nDate: {DateTime.Now.ToUniversalTime().ToString("r")}\r\n";
if (options == ComposeOptions.AllCalculateLength)
Headers["Content-Length"] = Message?.Length.ToString() ?? "0";
foreach (var kv in Headers)
header += kv.Key + ": " + kv.Value + "\r\n";
// Set-Cookie: ckGeneric=CookieBody; expires=Sun, 30-Dec-2007 21:00:00 GMT; path=/
// Set-Cookie: ASPSESSIONIDQABBDSQA=IPDPMMMALDGFLMICEJIOCIPM; path=/
foreach (var Cookie in Cookies)
header += "Set-Cookie: " + Cookie.ToString() + "\r\n";
header += "\r\n";
return header;
}
public bool Compose(ComposeOptions options)
{
List<byte> msg = new List<byte>();
if (options != ComposeOptions.DataOnly)
{
msg.AddRange(Encoding.UTF8.GetBytes(MakeHeader(options)));
}
private string MakeHeader(ComposeOptions options)
if (options != ComposeOptions.SpecifiedHeadersOnly)
{
string header = $"{Version} {(int)Number} {Text}\r\nServer: Esiur {Global.Version}\r\nDate: {DateTime.Now.ToUniversalTime().ToString("r")}\r\n";
if (options == ComposeOptions.AllCalculateLength)
Headers["Content-Length"] = Message?.Length.ToString() ?? "0";
foreach (var kv in Headers)
header += kv.Key + ": " + kv.Value + "\r\n";
// Set-Cookie: ckGeneric=CookieBody; expires=Sun, 30-Dec-2007 21:00:00 GMT; path=/
// Set-Cookie: ASPSESSIONIDQABBDSQA=IPDPMMMALDGFLMICEJIOCIPM; path=/
foreach (var Cookie in Cookies)
header += "Set-Cookie: " + Cookie.ToString() + "\r\n";
header += "\r\n";
return header;
if (Message != null)
msg.AddRange(Message);
}
Data = msg.ToArray();
public bool Compose(ComposeOptions options)
return true;
}
public override bool Compose()
{
return Compose(ComposeOptions.AllDontCalculateLength);
}
public override long Parse(byte[] data, uint offset, uint ends)
{
string[] sMethod = null;
string[] sLines = null;
uint headerSize = 0;
for (uint i = offset; i < ends - 3; i++)
{
List<byte> msg = new List<byte>();
if (options != ComposeOptions.DataOnly)
if (data[i] == '\r' && data[i + 1] == '\n'
&& data[i + 2] == '\r' && data[i + 3] == '\n')
{
msg.AddRange(Encoding.UTF8.GetBytes(MakeHeader(options)));
}
sLines = Encoding.ASCII.GetString(data, (int)offset, (int)(i - offset)).Split(new string[] { "\r\n" },
StringSplitOptions.None);
if (options != ComposeOptions.SpecifiedHeadersOnly)
{
if (Message != null)
msg.AddRange(Message);
headerSize = i + 4;
break;
}
Data = msg.ToArray();
return true;
}
public override bool Compose()
if (headerSize == 0)
return -1;
//Cookies = new DStringDictionary();
//Headers = new DStringDictionary(true);
sMethod = sLines[0].Split(' ');
if (sMethod.Length == 3)
{
return Compose(ComposeOptions.AllDontCalculateLength);
Version = sMethod[0].Trim();
Number = (ResponseCode)(Convert.ToInt32(sMethod[1].Trim()));
Text = sMethod[2];
}
public override long Parse(byte[] data, uint offset, uint ends)
// Read all headers
for (int i = 1; i < sLines.Length; i++)
{
string[] sMethod = null;
string[] sLines = null;
uint headerSize = 0;
for (uint i = offset; i < ends - 3; i++)
if (sLines[i] == String.Empty)
{
if (data[i] == '\r' && data[i + 1] == '\n'
&& data[i + 2] == '\r' && data[i + 3] == '\n')
{
sLines = Encoding.ASCII.GetString(data, (int)offset, (int)(i - offset)).Split(new string[] { "\r\n" },
StringSplitOptions.None);
headerSize = i + 4;
break;
}
// Invalid header
return 0;
}
if (headerSize == 0)
return -1;
//Cookies = new DStringDictionary();
//Headers = new DStringDictionary(true);
sMethod = sLines[0].Split(' ');
if (sMethod.Length == 3)
if (sLines[i].IndexOf(':') == -1)
{
Version = sMethod[0].Trim();
Number = (ResponseCode)(Convert.ToInt32(sMethod[1].Trim()));
Text = sMethod[2];
// Invalid header
return 0;
}
// Read all headers
string[] header = sLines[i].Split(new char[] { ':' }, 2);
for (int i = 1; i < sLines.Length; i++)
header[0] = header[0].ToLower();
Headers[header[0]] = header[1].Trim();
//Set-Cookie: NAME=VALUE; expires=DATE;
if (header[0] == "set-cookie")
{
if (sLines[i] == String.Empty)
string[] cookie = header[1].Split(';');
if (cookie.Length >= 1)
{
// Invalid header
return 0;
}
string[] splitCookie = cookie[0].Split('=');
HTTPCookie c = new HTTPCookie(splitCookie[0], splitCookie[1]);
if (sLines[i].IndexOf(':') == -1)
{
// Invalid header
return 0;
}
string[] header = sLines[i].Split(new char[] { ':' }, 2);
header[0] = header[0].ToLower();
Headers[header[0]] = header[1].Trim();
//Set-Cookie: NAME=VALUE; expires=DATE;
if (header[0] == "set-cookie")
{
string[] cookie = header[1].Split(';');
if (cookie.Length >= 1)
for (int j = 1; j < cookie.Length; j++)
{
string[] splitCookie = cookie[0].Split('=');
HTTPCookie c = new HTTPCookie(splitCookie[0], splitCookie[1]);
for (int j = 1; j < cookie.Length; j++)
splitCookie = cookie[j].Split('=');
switch (splitCookie[0].ToLower())
{
splitCookie = cookie[j].Split('=');
switch (splitCookie[0].ToLower())
{
case "domain":
c.Domain = splitCookie[1];
break;
case "path":
c.Path = splitCookie[1];
break;
case "httponly":
c.HttpOnly = true;
break;
case "expires":
// Wed, 13-Jan-2021 22:23:01 GMT
c.Expires = DateTime.Parse(splitCookie[1]);
break;
}
case "domain":
c.Domain = splitCookie[1];
break;
case "path":
c.Path = splitCookie[1];
break;
case "httponly":
c.HttpOnly = true;
break;
case "expires":
// Wed, 13-Jan-2021 22:23:01 GMT
c.Expires = DateTime.Parse(splitCookie[1]);
break;
}
}
}
}
}
// Content-Length
// Content-Length
try
try
{
uint contentLength = uint.Parse((string)Headers["content-length"]);
// check limit
if (contentLength > data.Length - headerSize)
{
uint contentLength = uint.Parse((string)Headers["content-length"]);
// check limit
if (contentLength > data.Length - headerSize)
{
return contentLength - (data.Length - headerSize);
}
Message = DC.Clip(data, offset, contentLength);
return headerSize + contentLength;
}
catch
{
return 0;
return contentLength - (data.Length - headerSize);
}
Message = DC.Clip(data, offset, contentLength);
return headerSize + contentLength;
}
catch
{
return 0;
}
}
}

View File

@ -31,385 +31,384 @@ using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace Esiur.Net.Packets
namespace Esiur.Net.Packets;
class IIPAuthPacket : Packet
{
class IIPAuthPacket : Packet
public enum IIPAuthPacketCommand : byte
{
public enum IIPAuthPacketCommand : byte
Action = 0,
Declare,
Acknowledge,
Error,
}
public enum IIPAuthPacketAction : byte
{
// Authenticate
AuthenticateHash,
//Challenge,
//CertificateRequest,
//CertificateReply,
//EstablishRequest,
//EstablishReply
NewConnection = 0x20,
ResumeConnection,
ConnectionEstablished = 0x28
}
public IIPAuthPacketCommand Command
{
get;
set;
}
public IIPAuthPacketAction Action
{
get;
set;
}
public byte ErrorCode { get; set; }
public string ErrorMessage { get; set; }
public AuthenticationMethod LocalMethod
{
get;
set;
}
public byte[] SourceInfo
{
get;
set;
}
public byte[] Hash
{
get;
set;
}
public byte[] SessionId
{
get;
set;
}
public AuthenticationMethod RemoteMethod
{
get;
set;
}
public string Domain
{
get;
set;
}
public long CertificateId
{
get; set;
}
public string LocalUsername
{
get;
set;
}
public string RemoteUsername
{
get;
set;
}
public byte[] LocalPassword
{
get;
set;
}
public byte[] RemotePassword
{
get;
set;
}
public byte[] LocalToken
{
get;
set;
}
public byte[] RemoteToken
{
get;
set;
}
public byte[] AsymetricEncryptionKey
{
get;
set;
}
public byte[] LocalNonce
{
get;
set;
}
public byte[] RemoteNonce
{
get;
set;
}
public ulong RemoteTokenIndex { get; set; }
private uint dataLengthNeeded;
bool NotEnough(uint offset, uint ends, uint needed)
{
if (offset + needed > ends)
{
Action = 0,
Declare,
Acknowledge,
Error,
dataLengthNeeded = needed - (ends - offset);
return true;
}
else
return false;
}
public enum IIPAuthPacketAction : byte
public override string ToString()
{
return Command.ToString() + " " + Action.ToString();
}
public override long Parse(byte[] data, uint offset, uint ends)
{
var oOffset = offset;
if (NotEnough(offset, ends, 1))
return -dataLengthNeeded;
Command = (IIPAuthPacketCommand)(data[offset] >> 6);
if (Command == IIPAuthPacketCommand.Action)
{
// Authenticate
AuthenticateHash,
Action = (IIPAuthPacketAction)(data[offset++] & 0x3f);
//Challenge,
//CertificateRequest,
//CertificateReply,
//EstablishRequest,
//EstablishReply
NewConnection = 0x20,
ResumeConnection,
ConnectionEstablished = 0x28
}
public IIPAuthPacketCommand Command
{
get;
set;
}
public IIPAuthPacketAction Action
{
get;
set;
}
public byte ErrorCode { get; set; }
public string ErrorMessage { get; set; }
public AuthenticationMethod LocalMethod
{
get;
set;
}
public byte[] SourceInfo
{
get;
set;
}
public byte[] Hash
{
get;
set;
}
public byte[] SessionId
{
get;
set;
}
public AuthenticationMethod RemoteMethod
{
get;
set;
}
public string Domain
{
get;
set;
}
public long CertificateId
{
get; set;
}
public string LocalUsername
{
get;
set;
}
public string RemoteUsername
{
get;
set;
}
public byte[] LocalPassword
{
get;
set;
}
public byte[] RemotePassword
{
get;
set;
}
public byte[] LocalToken
{
get;
set;
}
public byte[] RemoteToken
{
get;
set;
}
public byte[] AsymetricEncryptionKey
{
get;
set;
}
public byte[] LocalNonce
{
get;
set;
}
public byte[] RemoteNonce
{
get;
set;
}
public ulong RemoteTokenIndex { get; set; }
private uint dataLengthNeeded;
bool NotEnough(uint offset, uint ends, uint needed)
{
if (offset + needed > ends)
if (Action == IIPAuthPacketAction.AuthenticateHash)
{
dataLengthNeeded = needed - (ends - offset);
return true;
if (NotEnough(offset, ends, 32))
return -dataLengthNeeded;
Hash = data.Clip(offset, 32);
//var hash = new byte[32];
//Buffer.BlockCopy(data, (int)offset, hash, 0, 32);
//Hash = hash;
offset += 32;
}
else
return false;
}
else if (Action == IIPAuthPacketAction.NewConnection)
{
if (NotEnough(offset, ends, 2))
return -dataLengthNeeded;
public override string ToString()
{
return Command.ToString() + " " + Action.ToString();
}
var length = data.GetUInt16(offset);
public override long Parse(byte[] data, uint offset, uint ends)
offset += 2;
if (NotEnough(offset, ends, length))
return -dataLengthNeeded;
SourceInfo = data.Clip(offset, length);
//var sourceInfo = new byte[length];
//Buffer.BlockCopy(data, (int)offset, sourceInfo, 0, length);
//SourceInfo = sourceInfo;
offset += 32;
}
else if (Action == IIPAuthPacketAction.ResumeConnection
|| Action == IIPAuthPacketAction.ConnectionEstablished)
{
//var sessionId = new byte[32];
if (NotEnough(offset, ends, 32))
return -dataLengthNeeded;
SessionId = data.Clip(offset, 32);
//Buffer.BlockCopy(data, (int)offset, sessionId, 0, 32);
//SessionId = sessionId;
offset += 32;
}
}
else if (Command == IIPAuthPacketCommand.Declare)
{
var oOffset = offset;
RemoteMethod = (AuthenticationMethod)((data[offset] >> 4) & 0x3);
LocalMethod = (AuthenticationMethod)((data[offset] >> 2) & 0x3);
var encrypt = ((data[offset++] & 0x2) == 0x2);
if (NotEnough(offset, ends, 1))
return -dataLengthNeeded;
Command = (IIPAuthPacketCommand)(data[offset] >> 6);
var domainLength = data[offset++];
if (NotEnough(offset, ends, domainLength))
return -dataLengthNeeded;
if (Command == IIPAuthPacketCommand.Action)
var domain = data.GetString(offset, domainLength);
Domain = domain;
offset += domainLength;
if (RemoteMethod == AuthenticationMethod.Credentials)
{
Action = (IIPAuthPacketAction)(data[offset++] & 0x3f);
if (Action == IIPAuthPacketAction.AuthenticateHash)
if (LocalMethod == AuthenticationMethod.None)
{
if (NotEnough(offset, ends, 32))
if (NotEnough(offset, ends, 33))
return -dataLengthNeeded;
Hash = data.Clip(offset, 32);
//var remoteNonce = new byte[32];
//Buffer.BlockCopy(data, (int)offset, remoteNonce, 0, 32);
//RemoteNonce = remoteNonce;
//var hash = new byte[32];
//Buffer.BlockCopy(data, (int)offset, hash, 0, 32);
//Hash = hash;
RemoteNonce = data.Clip(offset, 32);
offset += 32;
}
else if (Action == IIPAuthPacketAction.NewConnection)
{
if (NotEnough(offset, ends, 2))
return -dataLengthNeeded;
var length = data.GetUInt16(offset);
offset += 2;
var length = data[offset++];
if (NotEnough(offset, ends, length))
return -dataLengthNeeded;
SourceInfo = data.Clip(offset, length);
RemoteUsername = data.GetString(offset, length);
//var sourceInfo = new byte[length];
//Buffer.BlockCopy(data, (int)offset, sourceInfo, 0, length);
//SourceInfo = sourceInfo;
offset += length;
}
}
else if (RemoteMethod == AuthenticationMethod.Token)
{
if (LocalMethod == AuthenticationMethod.None)
{
if (NotEnough(offset, ends, 37))
return -dataLengthNeeded;
RemoteNonce = data.Clip(offset, 32);
offset += 32;
}
else if (Action == IIPAuthPacketAction.ResumeConnection
|| Action == IIPAuthPacketAction.ConnectionEstablished)
{
//var sessionId = new byte[32];
RemoteTokenIndex = data.GetUInt64(offset);
offset += 8;
}
}
if (encrypt)
{
if (NotEnough(offset, ends, 2))
return -dataLengthNeeded;
var keyLength = data.GetUInt16(offset);
offset += 2;
if (NotEnough(offset, ends, keyLength))
return -dataLengthNeeded;
//var key = new byte[keyLength];
//Buffer.BlockCopy(data, (int)offset, key, 0, keyLength);
//AsymetricEncryptionKey = key;
AsymetricEncryptionKey = data.Clip(offset, keyLength);
offset += keyLength;
}
}
else if (Command == IIPAuthPacketCommand.Acknowledge)
{
RemoteMethod = (AuthenticationMethod)((data[offset] >> 4) & 0x3);
LocalMethod = (AuthenticationMethod)((data[offset] >> 2) & 0x3);
var encrypt = ((data[offset++] & 0x2) == 0x2);
if (RemoteMethod == AuthenticationMethod.None)
{
if (LocalMethod == AuthenticationMethod.None)
{
// do nothing
}
}
else if (RemoteMethod == AuthenticationMethod.Credentials
|| RemoteMethod == AuthenticationMethod.Token)
{
if (LocalMethod == AuthenticationMethod.None)
{
if (NotEnough(offset, ends, 32))
return -dataLengthNeeded;
SessionId = data.Clip(offset, 32);
//Buffer.BlockCopy(data, (int)offset, sessionId, 0, 32);
//SessionId = sessionId;
RemoteNonce = data.Clip(offset, 32);
offset += 32;
}
}
else if (Command == IIPAuthPacketCommand.Declare)
if (encrypt)
{
RemoteMethod = (AuthenticationMethod)((data[offset] >> 4) & 0x3);
LocalMethod = (AuthenticationMethod)((data[offset] >> 2) & 0x3);
var encrypt = ((data[offset++] & 0x2) == 0x2);
if (NotEnough(offset, ends, 1))
if (NotEnough(offset, ends, 2))
return -dataLengthNeeded;
var domainLength = data[offset++];
if (NotEnough(offset, ends, domainLength))
return -dataLengthNeeded;
var keyLength = data.GetUInt16(offset);
var domain = data.GetString(offset, domainLength);
Domain = domain;
offset += domainLength;
if (RemoteMethod == AuthenticationMethod.Credentials)
{
if (LocalMethod == AuthenticationMethod.None)
{
if (NotEnough(offset, ends, 33))
return -dataLengthNeeded;
//var remoteNonce = new byte[32];
//Buffer.BlockCopy(data, (int)offset, remoteNonce, 0, 32);
//RemoteNonce = remoteNonce;
RemoteNonce = data.Clip(offset, 32);
offset += 32;
var length = data[offset++];
if (NotEnough(offset, ends, length))
return -dataLengthNeeded;
RemoteUsername = data.GetString(offset, length);
offset += length;
}
}
else if (RemoteMethod == AuthenticationMethod.Token)
{
if (LocalMethod == AuthenticationMethod.None)
{
if (NotEnough(offset, ends, 37))
return -dataLengthNeeded;
RemoteNonce = data.Clip(offset, 32);
offset += 32;
RemoteTokenIndex = data.GetUInt64(offset);
offset += 8;
}
}
if (encrypt)
{
if (NotEnough(offset, ends, 2))
return -dataLengthNeeded;
var keyLength = data.GetUInt16(offset);
offset += 2;
if (NotEnough(offset, ends, keyLength))
return -dataLengthNeeded;
//var key = new byte[keyLength];
//Buffer.BlockCopy(data, (int)offset, key, 0, keyLength);
//AsymetricEncryptionKey = key;
AsymetricEncryptionKey = data.Clip(offset, keyLength);
offset += keyLength;
}
}
else if (Command == IIPAuthPacketCommand.Acknowledge)
{
RemoteMethod = (AuthenticationMethod)((data[offset] >> 4) & 0x3);
LocalMethod = (AuthenticationMethod)((data[offset] >> 2) & 0x3);
var encrypt = ((data[offset++] & 0x2) == 0x2);
if (RemoteMethod == AuthenticationMethod.None)
{
if (LocalMethod == AuthenticationMethod.None)
{
// do nothing
}
}
else if (RemoteMethod == AuthenticationMethod.Credentials
|| RemoteMethod == AuthenticationMethod.Token)
{
if (LocalMethod == AuthenticationMethod.None)
{
if (NotEnough(offset, ends, 32))
return -dataLengthNeeded;
RemoteNonce = data.Clip(offset, 32);
offset += 32;
}
}
if (encrypt)
{
if (NotEnough(offset, ends, 2))
return -dataLengthNeeded;
var keyLength = data.GetUInt16(offset);
offset += 2;
if (NotEnough(offset, ends, keyLength))
return -dataLengthNeeded;
//var key = new byte[keyLength];
//Buffer.BlockCopy(data, (int)offset, key, 0, keyLength);
//AsymetricEncryptionKey = key;
AsymetricEncryptionKey = data.Clip(offset, keyLength);
offset += keyLength;
}
}
else if (Command == IIPAuthPacketCommand.Error)
{
if (NotEnough(offset, ends, 4))
return -dataLengthNeeded;
offset++;
ErrorCode = data[offset++];
var cl = data.GetUInt16(offset);
offset += 2;
if (NotEnough(offset, ends, cl))
if (NotEnough(offset, ends, keyLength))
return -dataLengthNeeded;
ErrorMessage = data.GetString(offset, cl);
offset += cl;
//var key = new byte[keyLength];
//Buffer.BlockCopy(data, (int)offset, key, 0, keyLength);
//AsymetricEncryptionKey = key;
AsymetricEncryptionKey = data.Clip(offset, keyLength);
offset += keyLength;
}
}
else if (Command == IIPAuthPacketCommand.Error)
{
if (NotEnough(offset, ends, 4))
return -dataLengthNeeded;
offset++;
ErrorCode = data[offset++];
return offset - oOffset;
var cl = data.GetUInt16(offset);
offset += 2;
if (NotEnough(offset, ends, cl))
return -dataLengthNeeded;
ErrorMessage = data.GetString(offset, cl);
offset += cl;
}
return offset - oOffset;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -2,21 +2,20 @@
using System.Collections.Generic;
using System.Text;
namespace Esiur.Net.Packets
{
struct IIPPacketAttachInfo
{
public string Link;
public ulong Age;
public byte[] Content;
public Guid ClassId;
namespace Esiur.Net.Packets;
public IIPPacketAttachInfo(Guid classId, ulong age, string link, byte[] content)
{
ClassId = classId;
Age = age;
Content = content;
Link = link;
}
struct IIPPacketAttachInfo
{
public string Link;
public ulong Age;
public byte[] Content;
public Guid ClassId;
public IIPPacketAttachInfo(Guid classId, ulong age, string link, byte[] content)
{
ClassId = classId;
Age = age;
Content = content;
Link = link;
}
}

View File

@ -38,238 +38,219 @@ using Esiur.Net.DataLink;
using System.Net.NetworkInformation;
using Esiur.Data;
namespace Esiur.Net.Packets
namespace Esiur.Net.Packets;
internal static class Functions
{
internal static class Functions
public static void AddData(ref byte[] dest, byte[] src)
{
public static void AddData(ref byte[] dest, byte[] src)
int I = 0;
if (src == null)
{
int I = 0;
if (src == null)
{
return;
}
if (dest != null)
{
I = dest.Length;
Array.Resize(ref dest, dest.Length + src.Length);
//dest = (byte[])Resize(dest, dest.Length + src.Length);
}
else
{
dest = new byte[src.Length];
}
Array.Copy(src, 0, dest, I, src.Length);
return;
}
/*
public static Array Resize(Array array, int newSize)
if (dest != null)
{
Type myType = Type.GetType(array.GetType().FullName.TrimEnd('[', ']'));
Array nA = Array.CreateInstance(myType, newSize);
Array.Copy(array, nA, (newSize > array.Length ? array.Length : newSize));
return nA;
} */
//Computes the checksum used in IP, ARP..., ie the
// "The 16 bit one's complement of the one 's complement sum
//of all 16 bit words" as seen in RFCs
// Returns a 4 characters hex string
// data's lenght must be multiple of 4, else zero padding
public static ushort IP_CRC16(byte[] data)
{
ulong Sum = 0;
bool Padding = false;
/// * Padding if needed
if (data.Length % 2 != 0)
{
Array.Resize(ref data, data.Length + 1);
//data = (byte[])Resize(data, data.Length + 1);
Padding = true;
}
int count = data.Length;
///* add 16-bit words */
while (count > 0) //1)
{
///* this is the inner loop */
Sum += GetInteger(data[count - 2], data[count - 1]);
///* Fold 32-bit sum to 16-bit */
while (Sum >> 16 != 0)
{
Sum = (Sum & 0XFFFF) + (Sum >> 16);
}
count -= 2;
}
/// * reverse padding
if (Padding)
{
Array.Resize(ref data, data.Length - 1);
//data = (byte[])Resize(data, data.Length - 1);
}
///* Return one's compliment of final sum.
//return (ushort)(ushort.MaxValue - (ushort)Sum);
return (ushort)(~Sum);
I = dest.Length;
Array.Resize(ref dest, dest.Length + src.Length);
//dest = (byte[])Resize(dest, dest.Length + src.Length);
}
public static ushort GetInteger(byte B1, byte B2)
else
{
return BitConverter.ToUInt16(new byte[] { B2, B1 }, 0);
//return System.Convert.ToUInt16("&h" + GetHex(B1) + GetHex(B2));
dest = new byte[src.Length];
}
public static uint GetLong(byte B1, byte B2, byte B3, byte B4)
{
return BitConverter.ToUInt32(new byte[] { B4, B3, B2, B1 }, 0);
//return System.Convert.ToUInt32("&h" + GetHex(B1) + GetHex(B2) + GetHex(B3) + GetHex(B4));
}
public static string GetHex(byte B)
{
return (((B < 15) ? 0 + System.Convert.ToString(B, 16).ToUpper() : System.Convert.ToString(B, 16).ToUpper()));
}
public static bool GetBit(uint B, byte Pos)
{
//return BitConverter.ToBoolean(BitConverter.GetBytes(B), Pos + 1);
return (B & (uint)(Math.Pow(2, (Pos - 1)))) == (Math.Pow(2, (Pos - 1)));
}
public static ushort RemoveBit(ushort I, byte Pos)
{
return (ushort)RemoveBit((uint)I, Pos);
}
public static uint RemoveBit(uint I, byte Pos)
{
if (GetBit(I, Pos))
{
return I - (uint)(Math.Pow(2, (Pos - 1)));
}
else
{
return I;
}
}
public static void SplitInteger(ushort I, ref byte BLeft, ref byte BRight)
{
byte[] b = BitConverter.GetBytes(I);
BLeft = b[1];
BRight = b[0];
//BLeft = I >> 8;
//BRight = (I << 8) >> 8;
}
public static void SplitLong(uint I, ref byte BLeft, ref byte BLeftMiddle, ref byte BRightMiddle, ref byte BRight)
{
byte[] b = BitConverter.GetBytes(I);
BLeft = b[3];
BLeftMiddle = b[2];
BRightMiddle = b[1];
BRight = b[0];
//BLeft = I >> 24;
//BLeftMiddle = (I << 8) >> 24;
//BRightMiddle = (I << 16) >> 24;
//BRight = (I << 24) >> 24;
}
Array.Copy(src, 0, dest, I, src.Length);
}
public class PosixTime
/*
public static Array Resize(Array array, int newSize)
{
ulong seconds;
ulong microseconds;
Type myType = Type.GetType(array.GetType().FullName.TrimEnd('[', ']'));
Array nA = Array.CreateInstance(myType, newSize);
Array.Copy(array, nA, (newSize > array.Length ? array.Length : newSize));
return nA;
} */
PosixTime(ulong Seconds, ulong Microseconds)
//Computes the checksum used in IP, ARP..., ie the
// "The 16 bit one's complement of the one 's complement sum
//of all 16 bit words" as seen in RFCs
// Returns a 4 characters hex string
// data's lenght must be multiple of 4, else zero padding
public static ushort IP_CRC16(byte[] data)
{
ulong Sum = 0;
bool Padding = false;
/// * Padding if needed
if (data.Length % 2 != 0)
{
seconds = Seconds;
microseconds = Microseconds;
Array.Resize(ref data, data.Length + 1);
//data = (byte[])Resize(data, data.Length + 1);
Padding = true;
}
public override string ToString()
int count = data.Length;
///* add 16-bit words */
while (count > 0) //1)
{
return seconds + "." + microseconds;
///* this is the inner loop */
Sum += GetInteger(data[count - 2], data[count - 1]);
///* Fold 32-bit sum to 16-bit */
while (Sum >> 16 != 0)
{
Sum = (Sum & 0XFFFF) + (Sum >> 16);
}
count -= 2;
}
/// * reverse padding
if (Padding)
{
Array.Resize(ref data, data.Length - 1);
//data = (byte[])Resize(data, data.Length - 1);
}
///* Return one's compliment of final sum.
//return (ushort)(ushort.MaxValue - (ushort)Sum);
return (ushort)(~Sum);
}
public static ushort GetInteger(byte B1, byte B2)
{
return BitConverter.ToUInt16(new byte[] { B2, B1 }, 0);
//return System.Convert.ToUInt16("&h" + GetHex(B1) + GetHex(B2));
}
public static uint GetLong(byte B1, byte B2, byte B3, byte B4)
{
return BitConverter.ToUInt32(new byte[] { B4, B3, B2, B1 }, 0);
//return System.Convert.ToUInt32("&h" + GetHex(B1) + GetHex(B2) + GetHex(B3) + GetHex(B4));
}
public static string GetHex(byte B)
{
return (((B < 15) ? 0 + System.Convert.ToString(B, 16).ToUpper() : System.Convert.ToString(B, 16).ToUpper()));
}
public static bool GetBit(uint B, byte Pos)
{
//return BitConverter.ToBoolean(BitConverter.GetBytes(B), Pos + 1);
return (B & (uint)(Math.Pow(2, (Pos - 1)))) == (Math.Pow(2, (Pos - 1)));
}
public static ushort RemoveBit(ushort I, byte Pos)
{
return (ushort)RemoveBit((uint)I, Pos);
}
public static uint RemoveBit(uint I, byte Pos)
{
if (GetBit(I, Pos))
{
return I - (uint)(Math.Pow(2, (Pos - 1)));
}
else
{
return I;
}
}
public class Packet
public static void SplitInteger(ushort I, ref byte BLeft, ref byte BRight)
{
//public EtherServer2.EthernetSource Source;
byte[] b = BitConverter.GetBytes(I);
BLeft = b[1];
BRight = b[0];
//BLeft = I >> 8;
//BRight = (I << 8) >> 8;
}
public PacketSource Source;
public static void SplitLong(uint I, ref byte BLeft, ref byte BLeftMiddle, ref byte BRightMiddle, ref byte BRight)
{
byte[] b = BitConverter.GetBytes(I);
BLeft = b[3];
BLeftMiddle = b[2];
BRightMiddle = b[1];
BRight = b[0];
//BLeft = I >> 24;
//BLeftMiddle = (I << 8) >> 24;
//BRightMiddle = (I << 16) >> 24;
//BRight = (I << 24) >> 24;
}
public DateTime Timestamp;
}
public enum PPPType : ushort
{
IP = 0x0021, // Internet Protocol version 4 [RFC1332]
SDTP = 0x0049, // Serial Data Transport Protocol (PPP-SDTP) [RFC1963]
IPv6HeaderCompression = 0x004f, // IPv6 Header Compression
IPv6 = 0x0057, // Internet Protocol version 6 [RFC5072]
W8021dHelloPacket = 0x0201, // 802.1d Hello Packets [RFC3518]
IPv6ControlProtocol = 0x8057, // IPv6 Control Protocol [RFC5072]
}
public class PosixTime
{
ulong seconds;
ulong microseconds;
public enum ProtocolType : ushort
{
IP = 0x800, // IPv4
ARP = 0x806, // Address Resolution Protocol
IPv6 = 0x86DD, // IPv6
FrameRelayARP = 0x0808, // Frame Relay ARP [RFC1701]
VINESLoopback = 0x0BAE, // VINES Loopback [RFC1701]
VINESEcho = 0x0BAF, // VINES ECHO [RFC1701]
TransEtherBridging = 0x6558, // TransEther Bridging [RFC1701]
RawFrameRelay = 0x6559, // Raw Frame Relay [RFC1701]
IEE8021QVLAN = 0x8100, // IEEE 802.1Q VLAN-tagged frames (initially Wellfleet)
SNMP = 0x814C, // SNMP [JKR1]
TCPIP_Compression = 0x876B, // TCP/IP Compression [RFC1144]
IPAutonomousSystems = 0x876C, // IP Autonomous Systems [RFC1701]
SecureData = 0x876D, // Secure Data [RFC1701]
PPP = 0x880B, // PPP [IANA]
MPLS = 0x8847, // MPLS [RFC5332]
MPLS_UpstreamAssignedLabel = 0x8848, // MPLS with upstream-assigned label [RFC5332]
PPPoEDiscoveryStage = 0x8863, // PPPoE Discovery Stage [RFC2516]
PPPoESessionStage = 0x8864, // PPPoE Session Stage [RFC2516]
}
PosixTime(ulong Seconds, ulong Microseconds)
{
seconds = Seconds;
microseconds = Microseconds;
}
public override string ToString()
{
return seconds + "." + microseconds;
}
}
public class Packet
{
//public EtherServer2.EthernetSource Source;
public PacketSource Source;
public DateTime Timestamp;
public enum PPPType : ushort
{
IP = 0x0021, // Internet Protocol version 4 [RFC1332]
SDTP = 0x0049, // Serial Data Transport Protocol (PPP-SDTP) [RFC1963]
IPv6HeaderCompression = 0x004f, // IPv6 Header Compression
IPv6 = 0x0057, // Internet Protocol version 6 [RFC5072]
W8021dHelloPacket = 0x0201, // 802.1d Hello Packets [RFC3518]
IPv6ControlProtocol = 0x8057, // IPv6 Control Protocol [RFC5072]
}
public enum ProtocolType : ushort
{
IP = 0x800, // IPv4
ARP = 0x806, // Address Resolution Protocol
IPv6 = 0x86DD, // IPv6
FrameRelayARP = 0x0808, // Frame Relay ARP [RFC1701]
VINESLoopback = 0x0BAE, // VINES Loopback [RFC1701]
VINESEcho = 0x0BAF, // VINES ECHO [RFC1701]
TransEtherBridging = 0x6558, // TransEther Bridging [RFC1701]
RawFrameRelay = 0x6559, // Raw Frame Relay [RFC1701]
IEE8021QVLAN = 0x8100, // IEEE 802.1Q VLAN-tagged frames (initially Wellfleet)
SNMP = 0x814C, // SNMP [JKR1]
TCPIP_Compression = 0x876B, // TCP/IP Compression [RFC1144]
IPAutonomousSystems = 0x876C, // IP Autonomous Systems [RFC1701]
SecureData = 0x876D, // Secure Data [RFC1701]
PPP = 0x880B, // PPP [IANA]
MPLS = 0x8847, // MPLS [RFC5332]
MPLS_UpstreamAssignedLabel = 0x8848, // MPLS with upstream-assigned label [RFC5332]
PPPoEDiscoveryStage = 0x8863, // PPPoE Discovery Stage [RFC2516]
PPPoESessionStage = 0x8864, // PPPoE Session Stage [RFC2516]
}
/*
public static void GetPacketMACAddresses(Packet packet, out byte[] srcMAC, out byte[] dstMAC)
/*
public static void GetPacketMACAddresses(Packet packet, out byte[] srcMAC, out byte[] dstMAC)
{
// get the node address
Packet root = packet.RootPacket;
if (root is TZSPPacket)
{
// get the node address
Packet root = packet.RootPacket;
if (root is TZSPPacket)
TZSPPacket tp = (TZSPPacket)root;
if (tp.Protocol == TZSPPacket.TZSPEncapsulatedProtocol.Ethernet)
{
TZSPPacket tp = (TZSPPacket)root;
if (tp.Protocol == TZSPPacket.TZSPEncapsulatedProtocol.Ethernet)
{
EthernetPacket ep = (EthernetPacket)tp.SubPacket;
srcMAC = ep.SourceMAC;
dstMAC = ep.DestinationMAC;
}
else if (tp.Protocol == TZSPPacket.TZSPEncapsulatedProtocol.IEEE802_11)
{
W802_11Packet wp = (W802_11Packet)tp.SubPacket;
srcMAC = wp.SA;
dstMAC = wp.DA;
}
else
{
srcMAC = null;
dstMAC = null;
}
}
else if (root is EthernetPacket)
{
EthernetPacket ep = (EthernetPacket)root;
EthernetPacket ep = (EthernetPacket)tp.SubPacket;
srcMAC = ep.SourceMAC;
dstMAC = ep.DestinationMAC;
}
else if (root is W802_11Packet)
else if (tp.Protocol == TZSPPacket.TZSPEncapsulatedProtocol.IEEE802_11)
{
W802_11Packet wp = (W802_11Packet)root;
W802_11Packet wp = (W802_11Packet)tp.SubPacket;
srcMAC = wp.SA;
dstMAC = wp.DA;
}
@ -278,92 +259,109 @@ namespace Esiur.Net.Packets
srcMAC = null;
dstMAC = null;
}
}
else if (root is EthernetPacket)
{
EthernetPacket ep = (EthernetPacket)root;
srcMAC = ep.SourceMAC;
dstMAC = ep.DestinationMAC;
}
else if (root is W802_11Packet)
{
W802_11Packet wp = (W802_11Packet)root;
srcMAC = wp.SA;
dstMAC = wp.DA;
}
else
{
srcMAC = null;
dstMAC = null;
}
public static void GetPacketAddresses(Packet packet, ref string srcMAC, ref string dstMAC, ref string srcIP, ref string dstIP)
}
public static void GetPacketAddresses(Packet packet, ref string srcMAC, ref string dstMAC, ref string srcIP, ref string dstIP)
{
if (packet is TCPv4Packet)
{
if (packet.ParentPacket is IPv4Packet)
{
IPv4Packet ip = (IPv4Packet)packet.ParentPacket;
srcIP = ip.SourceIP.ToString();
dstIP = ip.DestinationIP.ToString();
}
}
// get the node address
Packet root = packet.RootPacket;
if (root is TZSPPacket)
{
if (packet is TCPv4Packet)
TZSPPacket tp = (TZSPPacket)root;
if (tp.Protocol == TZSPPacket.TZSPEncapsulatedProtocol.Ethernet)
{
if (packet.ParentPacket is IPv4Packet)
{
IPv4Packet ip = (IPv4Packet)packet.ParentPacket;
srcIP = ip.SourceIP.ToString();
dstIP = ip.DestinationIP.ToString();
}
}
// get the node address
Packet root = packet.RootPacket;
if (root is TZSPPacket)
{
TZSPPacket tp = (TZSPPacket)root;
if (tp.Protocol == TZSPPacket.TZSPEncapsulatedProtocol.Ethernet)
{
EthernetPacket ep = (EthernetPacket)tp.SubPacket;
srcMAC = DC.GetPhysicalAddress(ep.SourceMAC, 0).ToString();
dstMAC = DC.GetPhysicalAddress(ep.DestinationMAC, 0).ToString();
}
else if (tp.Protocol == TZSPPacket.TZSPEncapsulatedProtocol.IEEE802_11)
{
W802_11Packet wp = (W802_11Packet)tp.SubPacket;
srcMAC = DC.GetPhysicalAddress(wp.SA, 0).ToString();
dstMAC = DC.GetPhysicalAddress(wp.DA, 0).ToString();
}
}
else if (root is EthernetPacket)
{
EthernetPacket ep = (EthernetPacket)root;
EthernetPacket ep = (EthernetPacket)tp.SubPacket;
srcMAC = DC.GetPhysicalAddress(ep.SourceMAC, 0).ToString();
dstMAC = DC.GetPhysicalAddress(ep.DestinationMAC, 0).ToString();
}
else if (root is W802_11Packet)
else if (tp.Protocol == TZSPPacket.TZSPEncapsulatedProtocol.IEEE802_11)
{
W802_11Packet wp = (W802_11Packet)root;
W802_11Packet wp = (W802_11Packet)tp.SubPacket;
srcMAC = DC.GetPhysicalAddress(wp.SA, 0).ToString();
dstMAC = DC.GetPhysicalAddress(wp.DA, 0).ToString();
}
}
*/
//PosixTime Timeval;
public byte[] Header;
public byte[] Preamble;
//public byte[] Payload;
public byte[] Data;
public Packet SubPacket;
public Packet ParentPacket;
public virtual long Parse(byte[] data, uint offset, uint ends) { return 0; }
public virtual bool Compose() { return false; }
public Packet RootPacket
else if (root is EthernetPacket)
{
get
{
Packet root = this;
while (root.ParentPacket != null)
root = root.ParentPacket;
return root;
}
EthernetPacket ep = (EthernetPacket)root;
srcMAC = DC.GetPhysicalAddress(ep.SourceMAC, 0).ToString();
dstMAC = DC.GetPhysicalAddress(ep.DestinationMAC, 0).ToString();
}
public Packet LeafPacket
else if (root is W802_11Packet)
{
get
{
Packet leaf = this;
while (leaf.SubPacket != null)
leaf = leaf.SubPacket;
return leaf;
}
W802_11Packet wp = (W802_11Packet)root;
srcMAC = DC.GetPhysicalAddress(wp.SA, 0).ToString();
dstMAC = DC.GetPhysicalAddress(wp.DA, 0).ToString();
}
}
*/
//PosixTime Timeval;
public byte[] Header;
public byte[] Preamble;
//public byte[] Payload;
public byte[] Data;
public Packet SubPacket;
public Packet ParentPacket;
public virtual long Parse(byte[] data, uint offset, uint ends) { return 0; }
public virtual bool Compose() { return false; }
public Packet RootPacket
{
get
{
Packet root = this;
while (root.ParentPacket != null)
root = root.ParentPacket;
return root;
}
}
public Packet LeafPacket
{
get
{
Packet leaf = this;
while (leaf.SubPacket != null)
leaf = leaf.SubPacket;
return leaf;
}
}
}
/************************************ EOF *************************************/

View File

@ -29,189 +29,187 @@ using System.Text;
using Esiur.Misc;
using Esiur.Data;
namespace Esiur.Net.Packets
namespace Esiur.Net.Packets;
public class WebsocketPacket : Packet
{
public class WebsocketPacket : Packet
public enum WSOpcode : byte
{
public enum WSOpcode : byte
ContinuationFrame = 0x0, // %x0 denotes a continuation frame
TextFrame = 0x1, // %x1 denotes a text frame
BinaryFrame = 0x2, // %x2 denotes a binary frame
// %x3-7 are reserved for further non-control frames
ConnectionClose = 0x8, // %x8 denotes a connection close
Ping = 0x9, // %x9 denotes a ping
Pong = 0xA, // %xA denotes a pong
//* %xB-F are reserved for further control frames
}
public bool FIN;
public bool RSV1;
public bool RSV2;
public bool RSV3;
public WSOpcode Opcode;
public bool Mask;
public long PayloadLength;
// public UInt32 MaskKey;
public byte[] MaskKey;
public byte[] Message;
public override string ToString()
{
return "WebsocketPacket"
+ "\n\tFIN: " + FIN
+ "\n\tOpcode: " + Opcode
+ "\n\tPayload: " + PayloadLength
+ "\n\tMaskKey: " + MaskKey
+ "\n\tMessage: " + (Message != null ? Message.Length.ToString() : "NULL");
}
public override bool Compose()
{
var pkt = new List<byte>();
pkt.Add((byte)((FIN ? 0x80 : 0x0) |
(RSV1 ? 0x40 : 0x0) |
(RSV2 ? 0x20 : 0x0) |
(RSV3 ? 0x10 : 0x0) |
(byte)Opcode));
// calculate length
if (Message.Length > UInt16.MaxValue)
// 4 bytes
{
ContinuationFrame = 0x0, // %x0 denotes a continuation frame
TextFrame = 0x1, // %x1 denotes a text frame
BinaryFrame = 0x2, // %x2 denotes a binary frame
// %x3-7 are reserved for further non-control frames
ConnectionClose = 0x8, // %x8 denotes a connection close
Ping = 0x9, // %x9 denotes a ping
Pong = 0xA, // %xA denotes a pong
//* %xB-F are reserved for further control frames
pkt.Add((byte)((Mask ? 0x80 : 0x0) | 127));
pkt.AddRange(DC.ToBytes((UInt64)Message.LongCount()));
}
else if (Message.Length > 125)
// 2 bytes
{
pkt.Add((byte)((Mask ? 0x80 : 0x0) | 126));
pkt.AddRange(DC.ToBytes((UInt16)Message.Length));
}
else
{
pkt.Add((byte)((Mask ? 0x80 : 0x0) | Message.Length));
}
public bool FIN;
public bool RSV1;
public bool RSV2;
public bool RSV3;
public WSOpcode Opcode;
public bool Mask;
public long PayloadLength;
// public UInt32 MaskKey;
public byte[] MaskKey;
public byte[] Message;
public override string ToString()
if (Mask)
{
return "WebsocketPacket"
+ "\n\tFIN: " + FIN
+ "\n\tOpcode: " + Opcode
+ "\n\tPayload: " + PayloadLength
+ "\n\tMaskKey: " + MaskKey
+ "\n\tMessage: " + (Message != null ? Message.Length.ToString() : "NULL");
pkt.AddRange(MaskKey);
}
public override bool Compose()
{
var pkt = new List<byte>();
pkt.Add((byte)((FIN ? 0x80 : 0x0) |
(RSV1 ? 0x40 : 0x0) |
(RSV2 ? 0x20 : 0x0) |
(RSV3 ? 0x10 : 0x0) |
(byte)Opcode));
pkt.AddRange(Message);
// calculate length
if (Message.Length > UInt16.MaxValue)
// 4 bytes
Data = pkt.ToArray();
return true;
}
public override long Parse(byte[] data, uint offset, uint ends)
{
try
{
long needed = 2;
var length = (ends - offset);
if (length < needed)
{
pkt.Add((byte)((Mask ? 0x80 : 0x0) | 127));
pkt.AddRange(DC.ToBytes((UInt64)Message.LongCount()));
}
else if (Message.Length > 125)
// 2 bytes
{
pkt.Add((byte)((Mask ? 0x80 : 0x0) | 126));
pkt.AddRange(DC.ToBytes((UInt16)Message.Length));
}
else
{
pkt.Add((byte)((Mask ? 0x80 : 0x0) | Message.Length));
//Console.WriteLine("stage 1 " + needed);
return length - needed;
}
uint oOffset = offset;
FIN = ((data[offset] & 0x80) == 0x80);
RSV1 = ((data[offset] & 0x40) == 0x40);
RSV2 = ((data[offset] & 0x20) == 0x20);
RSV3 = ((data[offset] & 0x10) == 0x10);
Opcode = (WSOpcode)(data[offset++] & 0xF);
Mask = ((data[offset] & 0x80) == 0x80);
PayloadLength = (long)(data[offset++] & 0x7F);
if (Mask)
needed += 4;
if (PayloadLength == 126)
{
pkt.AddRange(MaskKey);
}
pkt.AddRange(Message);
Data = pkt.ToArray();
return true;
}
public override long Parse(byte[] data, uint offset, uint ends)
{
try
{
long needed = 2;
var length = (ends - offset);
needed += 2;
if (length < needed)
{
//Console.WriteLine("stage 1 " + needed);
//Console.WriteLine("stage 2 " + needed);
return length - needed;
}
PayloadLength = data.GetUInt16(offset);
offset += 2;
}
else if (PayloadLength == 127)
{
needed += 8;
if (length < needed)
{
//Console.WriteLine("stage 3 " + needed);
return length - needed;
}
uint oOffset = offset;
FIN = ((data[offset] & 0x80) == 0x80);
RSV1 = ((data[offset] & 0x40) == 0x40);
RSV2 = ((data[offset] & 0x20) == 0x20);
RSV3 = ((data[offset] & 0x10) == 0x10);
Opcode = (WSOpcode)(data[offset++] & 0xF);
Mask = ((data[offset] & 0x80) == 0x80);
PayloadLength = (long)(data[offset++] & 0x7F);
PayloadLength = data.GetInt64(offset);
offset += 8;
}
/*
if (Mask)
{
MaskKey = new byte[4];
MaskKey[0] = data[offset++];
MaskKey[1] = data[offset++];
MaskKey[2] = data[offset++];
MaskKey[3] = data[offset++];
//MaskKey = DC.GetUInt32(data, offset);
//offset += 4;
}
*/
needed += PayloadLength;
if (length < needed)
{
//Console.WriteLine("stage 4");
return length - needed;
}
else
{
if (Mask)
needed += 4;
if (PayloadLength == 126)
{
needed += 2;
if (length < needed)
{
//Console.WriteLine("stage 2 " + needed);
return length - needed;
}
PayloadLength = data.GetUInt16( offset);
offset += 2;
}
else if (PayloadLength == 127)
{
needed += 8;
if (length < needed)
{
//Console.WriteLine("stage 3 " + needed);
return length - needed;
}
PayloadLength = data.GetInt64(offset);
offset += 8;
}
/*
if (Mask)
{
MaskKey = new byte[4];
MaskKey = new byte[4];
MaskKey[0] = data[offset++];
MaskKey[1] = data[offset++];
MaskKey[2] = data[offset++];
MaskKey[3] = data[offset++];
//MaskKey = DC.GetUInt32(data, offset);
//offset += 4;
}
*/
Message = DC.Clip(data, offset, (uint)PayloadLength);
needed += PayloadLength;
if (length < needed)
{
//Console.WriteLine("stage 4");
return length - needed;
//var aMask = BitConverter.GetBytes(MaskKey);
for (int i = 0; i < Message.Length; i++)
Message[i] = (byte)(Message[i] ^ MaskKey[i % 4]);
}
else
{
if (Mask)
{
MaskKey = new byte[4];
MaskKey[0] = data[offset++];
MaskKey[1] = data[offset++];
MaskKey[2] = data[offset++];
MaskKey[3] = data[offset++];
Message = DC.Clip(data, offset, (uint)PayloadLength);
//var aMask = BitConverter.GetBytes(MaskKey);
for (int i = 0; i < Message.Length; i++)
Message[i] = (byte)(Message[i] ^ MaskKey[i % 4]);
}
else
Message = DC.Clip(data, offset, (uint)PayloadLength);
Message = DC.Clip(data, offset, (uint)PayloadLength);
return (offset - oOffset) + (int)PayloadLength;
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
Console.WriteLine(offset + "::" + DC.ToHex(data));
throw ex;
return (offset - oOffset) + (int)PayloadLength;
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
Console.WriteLine(offset + "::" + DC.ToHex(data));
throw ex;
}
}
}

View File

@ -4,23 +4,22 @@ using System;
using System.Collections.Generic;
using System.Text;
namespace Esiur.Net
namespace Esiur.Net;
public class SendList : BinaryList
{
public class SendList : BinaryList
NetworkConnection connection;
AsyncReply<object[]> reply;
public SendList(NetworkConnection connection, AsyncReply<object[]> reply)
{
NetworkConnection connection;
AsyncReply<object[]> reply;
this.reply = reply;
this.connection = connection;
}
public SendList(NetworkConnection connection, AsyncReply<object[]> reply)
{
this.reply = reply;
this.connection = connection;
}
public override AsyncReply<object[]> Done()
{
connection.Send(this.ToArray());
return reply;
}
public override AsyncReply<object[]> Done()
{
connection.Send(this.ToArray());
return reply;
}
}

View File

@ -36,39 +36,37 @@ using System.Collections.Concurrent;
using Esiur.Resource;
using Esiur.Core;
namespace Esiur.Net.Sockets
namespace Esiur.Net.Sockets;
//public delegate void ISocketReceiveEvent(NetworkBuffer buffer);
//public delegate void ISocketConnectEvent();
//public delegate void ISocketCloseEvent();
public interface ISocket : IDestructible
{
//public delegate void ISocketReceiveEvent(NetworkBuffer buffer);
//public delegate void ISocketConnectEvent();
//public delegate void ISocketCloseEvent();
SocketState State { get; }
public interface ISocket : IDestructible
{
SocketState State { get; }
//event ISocketReceiveEvent OnReceive;
//event ISocketConnectEvent OnConnect;
//event ISocketCloseEvent OnClose;
//event ISocketReceiveEvent OnReceive;
//event ISocketConnectEvent OnConnect;
//event ISocketCloseEvent OnClose;
INetworkReceiver<ISocket> Receiver { get; set; }
INetworkReceiver<ISocket> Receiver { get; set; }
AsyncReply<bool> SendAsync(byte[] message, int offset, int length);
AsyncReply<bool> SendAsync(byte[] message, int offset, int length);
void Send(byte[] message);
void Send(byte[] message, int offset, int length);
void Close();
AsyncReply<bool> Connect(string hostname, ushort port);
bool Begin();
AsyncReply<bool> BeginAsync();
//ISocket Accept();
AsyncReply<ISocket> AcceptAsync();
ISocket Accept();
void Send(byte[] message);
void Send(byte[] message, int offset, int length);
void Close();
AsyncReply<bool> Connect(string hostname, ushort port);
bool Begin();
AsyncReply<bool> BeginAsync();
//ISocket Accept();
AsyncReply<ISocket> AcceptAsync();
ISocket Accept();
IPEndPoint RemoteEndPoint { get; }
IPEndPoint LocalEndPoint { get; }
IPEndPoint RemoteEndPoint { get; }
IPEndPoint LocalEndPoint { get; }
void Hold();
void Hold();
void Unhold();
}
void Unhold();
}

View File

@ -37,519 +37,518 @@ using Esiur.Resource;
using System.Threading.Tasks;
using Esiur.Data;
namespace Esiur.Net.Sockets
namespace Esiur.Net.Sockets;
public class SSLSocket : ISocket
{
public class SSLSocket : ISocket
public INetworkReceiver<ISocket> Receiver { get; set; }
Socket sock;
byte[] receiveBuffer;
bool held;
//ArraySegment<byte> receiveBufferSegment;
NetworkBuffer receiveNetworkBuffer = new NetworkBuffer();
readonly object sendLock = new object();
Queue<KeyValuePair<AsyncReply<bool>, byte[]>> sendBufferQueue = new Queue<KeyValuePair<AsyncReply<bool>, byte[]>>();// Queue<byte[]>();
bool asyncSending;
bool began = false;
SocketState state = SocketState.Initial;
//public event ISocketReceiveEvent OnReceive;
//public event ISocketConnectEvent OnConnect;
//public event ISocketCloseEvent OnClose;
public event DestroyedEvent OnDestroy;
SslStream ssl;
X509Certificate2 cert;
bool server;
string hostname;
public async AsyncReply<bool> Connect(string hostname, ushort port)
{
var rt = new AsyncReply<bool>();
public INetworkReceiver<ISocket> Receiver { get; set; }
this.hostname = hostname;
this.server = false;
Socket sock;
byte[] receiveBuffer;
bool held;
//ArraySegment<byte> receiveBufferSegment;
NetworkBuffer receiveNetworkBuffer = new NetworkBuffer();
readonly object sendLock = new object();
Queue<KeyValuePair<AsyncReply<bool>, byte[]>> sendBufferQueue = new Queue<KeyValuePair<AsyncReply<bool>, byte[]>>();// Queue<byte[]>();
bool asyncSending;
bool began = false;
SocketState state = SocketState.Initial;
//public event ISocketReceiveEvent OnReceive;
//public event ISocketConnectEvent OnConnect;
//public event ISocketCloseEvent OnClose;
public event DestroyedEvent OnDestroy;
state = SocketState.Connecting;
await sock.ConnectAsync(hostname, port);
SslStream ssl;
X509Certificate2 cert;
bool server;
string hostname;
public async AsyncReply<bool> Connect(string hostname, ushort port)
try
{
var rt = new AsyncReply<bool>();
this.hostname = hostname;
this.server = false;
state = SocketState.Connecting;
await sock.ConnectAsync(hostname, port);
try
{
await BeginAsync();
state = SocketState.Established;
//OnConnect?.Invoke();
Receiver?.NetworkConnect(this);
}
catch (Exception ex)
{
state = SocketState.Closed;// .Terminated;
Close();
Global.Log(ex);
}
return true;
await BeginAsync();
state = SocketState.Established;
//OnConnect?.Invoke();
Receiver?.NetworkConnect(this);
}
catch (Exception ex)
{
state = SocketState.Closed;// .Terminated;
Close();
Global.Log(ex);
}
//private void DataSent(Task task)
//{
// try
// {
return true;
}
// if (sendBufferQueue.Count > 0)
// {
// byte[] data = sendBufferQueue.Dequeue();
// lock (sendLock)
// ssl.WriteAsync(data, 0, data.Length).ContinueWith(DataSent);
// }
// else
// {
// asyncSending = false;
// }
// }
// catch (Exception ex)
// {
// if (state != SocketState.Closed && !sock.Connected)
// {
// state = SocketState.Terminated;
// Close();
// }
//private void DataSent(Task task)
//{
// try
// {
// asyncSending = false;
// if (sendBufferQueue.Count > 0)
// {
// byte[] data = sendBufferQueue.Dequeue();
// lock (sendLock)
// ssl.WriteAsync(data, 0, data.Length).ContinueWith(DataSent);
// }
// else
// {
// asyncSending = false;
// }
// }
// catch (Exception ex)
// {
// if (state != SocketState.Closed && !sock.Connected)
// {
// state = SocketState.Terminated;
// Close();
// }
// Global.Log("SSLSocket", LogType.Error, ex.ToString());
// }
//}
// asyncSending = false;
// Global.Log("SSLSocket", LogType.Error, ex.ToString());
// }
//}
private void SendCallback(IAsyncResult ar)
{
if (ar != null)
{
try
{
ssl.EndWrite(ar);
if (ar.AsyncState != null)
((AsyncReply<bool>)ar.AsyncState).Trigger(true);
}
catch
{
if (state != SocketState.Closed && !sock.Connected)
{
//state = SocketState.Closed;//.Terminated;
Close();
}
}
}
lock (sendLock)
{
if (sendBufferQueue.Count > 0)
{
var kv = sendBufferQueue.Dequeue();
try
{
ssl.BeginWrite(kv.Value, 0, kv.Value.Length, SendCallback, kv.Key);
}
catch //(Exception ex)
{
asyncSending = false;
try
{
if (kv.Key != null)
kv.Key.Trigger(false);
if (state != SocketState.Closed && !sock.Connected)
{
//state = SocketState.Terminated;
Close();
}
}
catch //(Exception ex2)
{
//state = SocketState.Closed;// .Terminated;
Close();
}
//Global.Log("TCPSocket", LogType.Error, ex.ToString());
}
}
else
{
asyncSending = false;
}
}
}
public IPEndPoint LocalEndPoint
{
get { return (IPEndPoint)sock.LocalEndPoint; }
}
public SSLSocket()
{
sock = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
receiveBuffer = new byte[sock.ReceiveBufferSize];
}
public SSLSocket(IPEndPoint localEndPoint, X509Certificate2 certificate)
{
// create the socket
sock = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
state = SocketState.Listening;
// bind
sock.Bind(localEndPoint);
// start listening
sock.Listen(UInt16.MaxValue);
cert = certificate;
}
public IPEndPoint RemoteEndPoint
{
get { return (IPEndPoint)sock.RemoteEndPoint; }
}
public SocketState State
{
get
{
return state;
}
}
public SSLSocket(Socket socket, X509Certificate2 certificate, bool authenticateAsServer)
{
cert = certificate;
sock = socket;
receiveBuffer = new byte[sock.ReceiveBufferSize];
ssl = new SslStream(new NetworkStream(sock));
server = authenticateAsServer;
if (socket.Connected)
state = SocketState.Established;
}
public void Close()
{
if (state != SocketState.Closed)// && state != SocketState.Terminated)
{
state = SocketState.Closed;
if (sock.Connected)
{
try
{
sock.Shutdown(SocketShutdown.Both);
}
catch
{
//state = SocketState.Terminated;
}
}
Receiver?.NetworkClose(this);
//OnClose?.Invoke();
}
}
public void Send(byte[] message)
{
Send(message, 0, message.Length);
}
public void Send(byte[] message, int offset, int size)
{
var msg = message.Clip((uint)offset, (uint)size);
lock (sendLock)
{
if (!sock.Connected)
return;
if (asyncSending || held)
{
sendBufferQueue.Enqueue(new KeyValuePair<AsyncReply<bool>, byte[]>(null, msg));// message.Clip((uint)offset, (uint)size));
}
else
{
asyncSending = true;
try
{
ssl.BeginWrite(msg, 0, msg.Length, SendCallback, null);
}
catch
{
asyncSending = false;
//state = SocketState.Terminated;
Close();
}
}
}
}
//public void Send(byte[] message)
//{
// Send(message, 0, message.Length);
//}
//public void Send(byte[] message, int offset, int size)
//{
// lock (sendLock)
// {
// if (asyncSending)
// {
// sendBufferQueue.Enqueue(message.Clip((uint)offset, (uint)size));
// }
// else
// {
// asyncSending = true;
// ssl.WriteAsync(message, offset, size).ContinueWith(DataSent);
// }
// }
//}
//private void DataReceived(Task<int> task)
//{
// try
// {
// if (state == SocketState.Closed || state == SocketState.Terminated)
// return;
// if (task.Result <= 0)
// {
// Close();
// return;
// }
// receiveNetworkBuffer.Write(receiveBuffer, 0, (uint)task.Result);
// OnReceive?.Invoke(receiveNetworkBuffer);
// if (state == SocketState.Established)
// ssl.ReadAsync(receiveBuffer, 0, receiveBuffer.Length).ContinueWith(DataReceived);
// }
// catch (Exception ex)
// {
// if (state != SocketState.Closed && !sock.Connected)
// {
// state = SocketState.Terminated;
// Close();
// }
// Global.Log("SSLSocket", LogType.Error, ex.ToString());
// }
//}
public bool Begin()
{
if (began)
return false;
began = true;
if (server)
ssl.AuthenticateAsServer(cert);
else
ssl.AuthenticateAsClient(hostname);
if (state == SocketState.Established)
{
ssl.BeginRead(receiveBuffer, 0, receiveBuffer.Length, ReceiveCallback, this);
return true;
}
else
return false;
}
public async AsyncReply<bool> BeginAsync()
{
if (began)
return false;
began = true;
if (server)
await ssl.AuthenticateAsServerAsync(cert);
else
await ssl.AuthenticateAsClientAsync(hostname);
if (state == SocketState.Established)
{
ssl.BeginRead(receiveBuffer, 0, receiveBuffer.Length, ReceiveCallback, this);
return true;
}
else
return false;
}
private void ReceiveCallback(IAsyncResult results)
private void SendCallback(IAsyncResult ar)
{
if (ar != null)
{
try
{
if (state != SocketState.Established)
return;
var bytesReceived = ssl.EndRead(results);
if (bytesReceived <= 0)
{
Close();
return;
}
receiveNetworkBuffer.Write(receiveBuffer, 0, (uint)bytesReceived);
//OnReceive?.Invoke(receiveNetworkBuffer);
Receiver?.NetworkReceive(this, receiveNetworkBuffer);
ssl.BeginRead(receiveBuffer, 0, receiveBuffer.Length, ReceiveCallback, this);
ssl.EndWrite(ar);
if (ar.AsyncState != null)
((AsyncReply<bool>)ar.AsyncState).Trigger(true);
}
catch //(Exception ex)
catch
{
if (state != SocketState.Closed && !sock.Connected)
{
//state = SocketState.Terminated;
//state = SocketState.Closed;//.Terminated;
Close();
}
//Global.Log("SSLSocket", LogType.Error, ex.ToString());
}
}
public bool Trigger(ResourceTrigger trigger)
{
return true;
}
public void Destroy()
{
Close();
Receiver = null;
receiveNetworkBuffer = null;
OnDestroy?.Invoke(this);
OnDestroy = null;
}
public async AsyncReply<ISocket> AcceptAsync()
{
try
{
var s = await sock.AcceptAsync();
return new SSLSocket(s, cert, true);
}
catch
{
state = SocketState.Closed;// Terminated;
return null;
}
}
public void Hold()
{
held = true;
}
public void Unhold()
{
try
{
SendCallback(null);
}
catch (Exception ex)
{
Global.Log(ex);
}
finally
{
held = false;
}
}
public AsyncReply<bool> SendAsync(byte[] message, int offset, int length)
lock (sendLock)
{
var msg = message.Clip((uint)offset, (uint)length);
lock (sendLock)
if (sendBufferQueue.Count > 0)
{
if (!sock.Connected)
return new AsyncReply<bool>(false);
var kv = sendBufferQueue.Dequeue();
var rt = new AsyncReply<bool>();
if (asyncSending || held)
try
{
sendBufferQueue.Enqueue(new KeyValuePair<AsyncReply<bool>, byte[]>(rt, msg));
ssl.BeginWrite(kv.Value, 0, kv.Value.Length, SendCallback, kv.Key);
}
else
catch //(Exception ex)
{
asyncSending = true;
asyncSending = false;
try
{
ssl.BeginWrite(msg, 0, msg.Length, SendCallback, rt);// null);
if (kv.Key != null)
kv.Key.Trigger(false);
if (state != SocketState.Closed && !sock.Connected)
{
//state = SocketState.Terminated;
Close();
}
}
catch (Exception ex)
catch //(Exception ex2)
{
rt.TriggerError(ex);
asyncSending = false;
//state = SocketState.Terminated;
//state = SocketState.Closed;// .Terminated;
Close();
}
//Global.Log("TCPSocket", LogType.Error, ex.ToString());
}
return rt;
}
}
public ISocket Accept()
{
try
else
{
return new SSLSocket(sock.Accept(), cert, true);
}
catch
{
state = SocketState.Closed;// .Terminated;
return null;
asyncSending = false;
}
}
}
}
public IPEndPoint LocalEndPoint
{
get { return (IPEndPoint)sock.LocalEndPoint; }
}
public SSLSocket()
{
sock = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
receiveBuffer = new byte[sock.ReceiveBufferSize];
}
public SSLSocket(IPEndPoint localEndPoint, X509Certificate2 certificate)
{
// create the socket
sock = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
state = SocketState.Listening;
// bind
sock.Bind(localEndPoint);
// start listening
sock.Listen(UInt16.MaxValue);
cert = certificate;
}
public IPEndPoint RemoteEndPoint
{
get { return (IPEndPoint)sock.RemoteEndPoint; }
}
public SocketState State
{
get
{
return state;
}
}
public SSLSocket(Socket socket, X509Certificate2 certificate, bool authenticateAsServer)
{
cert = certificate;
sock = socket;
receiveBuffer = new byte[sock.ReceiveBufferSize];
ssl = new SslStream(new NetworkStream(sock));
server = authenticateAsServer;
if (socket.Connected)
state = SocketState.Established;
}
public void Close()
{
if (state != SocketState.Closed)// && state != SocketState.Terminated)
{
state = SocketState.Closed;
if (sock.Connected)
{
try
{
sock.Shutdown(SocketShutdown.Both);
}
catch
{
//state = SocketState.Terminated;
}
}
Receiver?.NetworkClose(this);
//OnClose?.Invoke();
}
}
public void Send(byte[] message)
{
Send(message, 0, message.Length);
}
public void Send(byte[] message, int offset, int size)
{
var msg = message.Clip((uint)offset, (uint)size);
lock (sendLock)
{
if (!sock.Connected)
return;
if (asyncSending || held)
{
sendBufferQueue.Enqueue(new KeyValuePair<AsyncReply<bool>, byte[]>(null, msg));// message.Clip((uint)offset, (uint)size));
}
else
{
asyncSending = true;
try
{
ssl.BeginWrite(msg, 0, msg.Length, SendCallback, null);
}
catch
{
asyncSending = false;
//state = SocketState.Terminated;
Close();
}
}
}
}
//public void Send(byte[] message)
//{
// Send(message, 0, message.Length);
//}
//public void Send(byte[] message, int offset, int size)
//{
// lock (sendLock)
// {
// if (asyncSending)
// {
// sendBufferQueue.Enqueue(message.Clip((uint)offset, (uint)size));
// }
// else
// {
// asyncSending = true;
// ssl.WriteAsync(message, offset, size).ContinueWith(DataSent);
// }
// }
//}
//private void DataReceived(Task<int> task)
//{
// try
// {
// if (state == SocketState.Closed || state == SocketState.Terminated)
// return;
// if (task.Result <= 0)
// {
// Close();
// return;
// }
// receiveNetworkBuffer.Write(receiveBuffer, 0, (uint)task.Result);
// OnReceive?.Invoke(receiveNetworkBuffer);
// if (state == SocketState.Established)
// ssl.ReadAsync(receiveBuffer, 0, receiveBuffer.Length).ContinueWith(DataReceived);
// }
// catch (Exception ex)
// {
// if (state != SocketState.Closed && !sock.Connected)
// {
// state = SocketState.Terminated;
// Close();
// }
// Global.Log("SSLSocket", LogType.Error, ex.ToString());
// }
//}
public bool Begin()
{
if (began)
return false;
began = true;
if (server)
ssl.AuthenticateAsServer(cert);
else
ssl.AuthenticateAsClient(hostname);
if (state == SocketState.Established)
{
ssl.BeginRead(receiveBuffer, 0, receiveBuffer.Length, ReceiveCallback, this);
return true;
}
else
return false;
}
public async AsyncReply<bool> BeginAsync()
{
if (began)
return false;
began = true;
if (server)
await ssl.AuthenticateAsServerAsync(cert);
else
await ssl.AuthenticateAsClientAsync(hostname);
if (state == SocketState.Established)
{
ssl.BeginRead(receiveBuffer, 0, receiveBuffer.Length, ReceiveCallback, this);
return true;
}
else
return false;
}
private void ReceiveCallback(IAsyncResult results)
{
try
{
if (state != SocketState.Established)
return;
var bytesReceived = ssl.EndRead(results);
if (bytesReceived <= 0)
{
Close();
return;
}
receiveNetworkBuffer.Write(receiveBuffer, 0, (uint)bytesReceived);
//OnReceive?.Invoke(receiveNetworkBuffer);
Receiver?.NetworkReceive(this, receiveNetworkBuffer);
ssl.BeginRead(receiveBuffer, 0, receiveBuffer.Length, ReceiveCallback, this);
}
catch //(Exception ex)
{
if (state != SocketState.Closed && !sock.Connected)
{
//state = SocketState.Terminated;
Close();
}
//Global.Log("SSLSocket", LogType.Error, ex.ToString());
}
}
public bool Trigger(ResourceTrigger trigger)
{
return true;
}
public void Destroy()
{
Close();
Receiver = null;
receiveNetworkBuffer = null;
OnDestroy?.Invoke(this);
OnDestroy = null;
}
public async AsyncReply<ISocket> AcceptAsync()
{
try
{
var s = await sock.AcceptAsync();
return new SSLSocket(s, cert, true);
}
catch
{
state = SocketState.Closed;// Terminated;
return null;
}
}
public void Hold()
{
held = true;
}
public void Unhold()
{
try
{
SendCallback(null);
}
catch (Exception ex)
{
Global.Log(ex);
}
finally
{
held = false;
}
}
public AsyncReply<bool> SendAsync(byte[] message, int offset, int length)
{
var msg = message.Clip((uint)offset, (uint)length);
lock (sendLock)
{
if (!sock.Connected)
return new AsyncReply<bool>(false);
var rt = new AsyncReply<bool>();
if (asyncSending || held)
{
sendBufferQueue.Enqueue(new KeyValuePair<AsyncReply<bool>, byte[]>(rt, msg));
}
else
{
asyncSending = true;
try
{
ssl.BeginWrite(msg, 0, msg.Length, SendCallback, rt);// null);
}
catch (Exception ex)
{
rt.TriggerError(ex);
asyncSending = false;
//state = SocketState.Terminated;
Close();
}
}
return rt;
}
}
public ISocket Accept()
{
try
{
return new SSLSocket(sock.Accept(), cert, true);
}
catch
{
state = SocketState.Closed;// .Terminated;
return null;
}
}
}

View File

@ -28,15 +28,13 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Esiur.Net.Sockets
namespace Esiur.Net.Sockets;
public enum SocketState
{
public enum SocketState
{
Initial,
Listening,
Connecting,
Established,
Closed,
//Terminated
}
Initial,
Listening,
Connecting,
Established,
Closed,
//Terminated
}

File diff suppressed because it is too large Load Diff

View File

@ -36,326 +36,324 @@ using Esiur.Resource;
using Esiur.Data;
using System.Globalization;
namespace Esiur.Net.Sockets
namespace Esiur.Net.Sockets;
public class WSocket : ISocket, INetworkReceiver<ISocket>
{
public class WSocket : ISocket, INetworkReceiver<ISocket>
WebsocketPacket pkt_receive = new WebsocketPacket();
WebsocketPacket pkt_send = new WebsocketPacket();
ISocket sock;
NetworkBuffer receiveNetworkBuffer = new NetworkBuffer();
NetworkBuffer sendNetworkBuffer = new NetworkBuffer();
object sendLock = new object();
bool held;
//public event ISocketReceiveEvent OnReceive;
//public event ISocketConnectEvent OnConnect;
//public event ISocketCloseEvent OnClose;
public event DestroyedEvent OnDestroy;
long totalSent, totalReceived;
bool processing = false;
public IPEndPoint LocalEndPoint
{
WebsocketPacket pkt_receive = new WebsocketPacket();
WebsocketPacket pkt_send = new WebsocketPacket();
get { return (IPEndPoint)sock.LocalEndPoint; }
}
ISocket sock;
NetworkBuffer receiveNetworkBuffer = new NetworkBuffer();
NetworkBuffer sendNetworkBuffer = new NetworkBuffer();
public IPEndPoint RemoteEndPoint
{
get { return sock.RemoteEndPoint; }
}
object sendLock = new object();
bool held;
//public event ISocketReceiveEvent OnReceive;
//public event ISocketConnectEvent OnConnect;
//public event ISocketCloseEvent OnClose;
public event DestroyedEvent OnDestroy;
long totalSent, totalReceived;
bool processing = false;
public IPEndPoint LocalEndPoint
public SocketState State
{
get
{
get { return (IPEndPoint)sock.LocalEndPoint; }
}
public IPEndPoint RemoteEndPoint
{
get { return sock.RemoteEndPoint; }
}
public SocketState State
{
get
{
return sock.State;
}
}
public INetworkReceiver<ISocket> Receiver { get; set; }
public WSocket(ISocket socket)
{
pkt_send.FIN = true;
pkt_send.Mask = false;
pkt_send.Opcode = WebsocketPacket.WSOpcode.BinaryFrame;
sock = socket;
sock.Receiver = this;
//sock.OnClose += Sock_OnClose;
//sock.OnConnect += Sock_OnConnect;
//sock.OnReceive += Sock_OnReceive;
}
//private void Sock_OnReceive(NetworkBuffer buffer)
//{
//}
//private void Sock_OnConnect()
//{
// OnConnect?.Invoke();
//}
//private void Sock_OnClose()
//{
// OnClose?.Invoke();
//}
public void Send(WebsocketPacket packet)
{
lock (sendLock)
if (packet.Compose())
sock.Send(packet.Data);
}
public void Send(byte[] message)
{
lock (sendLock)
{
if (held)
{
sendNetworkBuffer.Write(message);
}
else
{
totalSent += message.Length;
//Console.WriteLine("TX " + message.Length +"/"+totalSent);// + " " + DC.ToHex(message, 0, (uint)size));
pkt_send.Message = message;
if (pkt_send.Compose())
sock?.Send(pkt_send.Data);
}
}
}
public void Send(byte[] message, int offset, int size)
{
lock (sendLock)
{
if (held)
{
sendNetworkBuffer.Write(message, (uint)offset, (uint)size);
}
else
{
totalSent += size;
//Console.WriteLine("TX " + size + "/"+totalSent);// + " " + DC.ToHex(message, 0, (uint)size));
pkt_send.Message = new byte[size];
Buffer.BlockCopy(message, offset, pkt_send.Message, 0, size);
if (pkt_send.Compose())
sock.Send(pkt_send.Data);
}
}
}
public void Close()
{
sock?.Close();
}
public AsyncReply<bool> Connect(string hostname, ushort port)
{
throw new NotImplementedException();
}
public bool Begin()
{
return sock.Begin();
}
public bool Trigger(ResourceTrigger trigger)
{
return true;
}
public void Destroy()
{
Close();
//OnClose = null;
//OnConnect = null;
//OnReceive = null;
receiveNetworkBuffer = null;
//sock.OnReceive -= Sock_OnReceive;
//sock.OnClose -= Sock_OnClose;
//sock.OnConnect -= Sock_OnConnect;
sock.Receiver = null;
sock = null;
OnDestroy?.Invoke(this);
OnDestroy = null;
}
public AsyncReply<ISocket> AcceptAsync()
{
throw new NotImplementedException();
}
public void Hold()
{
//Console.WriteLine("WS Hold ");
held = true;
}
public void Unhold()
{
lock (sendLock)
{
held = false;
var message = sendNetworkBuffer.Read();
//Console.WriteLine("WS Unhold {0}", message == null ? 0 : message.Length);
if (message == null)
return;
totalSent += message.Length;
pkt_send.Message = message;
if (pkt_send.Compose())
sock.Send(pkt_send.Data);
}
}
public AsyncReply<bool> SendAsync(byte[] message, int offset, int length)
{
throw new NotImplementedException();
}
public ISocket Accept()
{
throw new NotImplementedException();
}
public AsyncReply<bool> BeginAsync()
{
return sock.BeginAsync();
}
public void NetworkClose(ISocket sender)
{
Receiver?.NetworkClose(sender);
}
public void NetworkReceive(ISocket sender, NetworkBuffer buffer)
{
if (sock.State == SocketState.Closed)// || sock.State == SocketState.Terminated)
return;
if (buffer.Protected)
return;
if (processing)
return;
var msg = buffer.Read();
if (msg == null)
return;
var wsPacketLength = pkt_receive.Parse(msg, 0, (uint)msg.Length);
//Console.WriteLine("WSP: " + wsPacketLength);
if (wsPacketLength < 0)
{
buffer.Protect(msg, 0, (uint)msg.Length + (uint)-wsPacketLength);
return;
}
uint offset = 0;
while (wsPacketLength > 0)
{
if (pkt_receive.Opcode == WebsocketPacket.WSOpcode.ConnectionClose)
{
Close();
return;
}
else if (pkt_receive.Opcode == WebsocketPacket.WSOpcode.Ping)
{
var pkt_pong = new WebsocketPacket();
pkt_pong.FIN = true;
pkt_pong.Mask = false;
pkt_pong.Opcode = WebsocketPacket.WSOpcode.Pong;
pkt_pong.Message = pkt_receive.Message;
offset += (uint)wsPacketLength;
Send(pkt_pong);
}
else if (pkt_receive.Opcode == WebsocketPacket.WSOpcode.Pong)
{
offset += (uint)wsPacketLength;
}
else if (pkt_receive.Opcode == WebsocketPacket.WSOpcode.BinaryFrame
|| pkt_receive.Opcode == WebsocketPacket.WSOpcode.TextFrame
|| pkt_receive.Opcode == WebsocketPacket.WSOpcode.ContinuationFrame)
{
totalReceived += pkt_receive.Message.Length;
//Console.WriteLine("RX " + pkt_receive.Message.Length + "/" + totalReceived);// + " " + DC.ToHex(message, 0, (uint)size));
receiveNetworkBuffer.Write(pkt_receive.Message);
offset += (uint)wsPacketLength;
//Console.WriteLine("WS IN: " + pkt_receive.Opcode.ToString() + " " + pkt_receive.Message.Length + " | " + offset + " " + string.Join(" ", pkt_receive.Message));// DC.ToHex(pkt_receive.Message));
}
else
Console.WriteLine("Unknown WS opcode:" + pkt_receive.Opcode);
if (offset == msg.Length)
{
//OnReceive?.Invoke(receiveNetworkBuffer);
Receiver?.NetworkReceive(this, receiveNetworkBuffer);
return;
}
wsPacketLength = pkt_receive.Parse(msg, offset, (uint)msg.Length);
}
if (wsPacketLength < 0)//(offset < msg.Length) && (offset > 0))
{
//receiveNetworkBuffer.HoldFor(msg, offset, (uint)(msg.Length - offset), (uint)msg.Length + (uint)-wsPacketLength);
// save the incomplete packet to the heldBuffer queue
buffer.HoldFor(msg, offset, (uint)(msg.Length - offset), (uint)(msg.Length - offset) + (uint)-wsPacketLength);
}
//Console.WriteLine("WS IN: " + receiveNetworkBuffer.Available);
//OnReceive?.Invoke(receiveNetworkBuffer);
Receiver?.NetworkReceive(this, receiveNetworkBuffer);
processing = false;
if (buffer.Available > 0 && !buffer.Protected)
Receiver?.NetworkReceive(this, buffer);
//Sock_OnReceive(buffer);
}
public void NetworkConnect(ISocket sender)
{
Receiver?.NetworkConnect(this);
return sock.State;
}
}
}
public INetworkReceiver<ISocket> Receiver { get; set; }
public WSocket(ISocket socket)
{
pkt_send.FIN = true;
pkt_send.Mask = false;
pkt_send.Opcode = WebsocketPacket.WSOpcode.BinaryFrame;
sock = socket;
sock.Receiver = this;
//sock.OnClose += Sock_OnClose;
//sock.OnConnect += Sock_OnConnect;
//sock.OnReceive += Sock_OnReceive;
}
//private void Sock_OnReceive(NetworkBuffer buffer)
//{
//}
//private void Sock_OnConnect()
//{
// OnConnect?.Invoke();
//}
//private void Sock_OnClose()
//{
// OnClose?.Invoke();
//}
public void Send(WebsocketPacket packet)
{
lock (sendLock)
if (packet.Compose())
sock.Send(packet.Data);
}
public void Send(byte[] message)
{
lock (sendLock)
{
if (held)
{
sendNetworkBuffer.Write(message);
}
else
{
totalSent += message.Length;
//Console.WriteLine("TX " + message.Length +"/"+totalSent);// + " " + DC.ToHex(message, 0, (uint)size));
pkt_send.Message = message;
if (pkt_send.Compose())
sock?.Send(pkt_send.Data);
}
}
}
public void Send(byte[] message, int offset, int size)
{
lock (sendLock)
{
if (held)
{
sendNetworkBuffer.Write(message, (uint)offset, (uint)size);
}
else
{
totalSent += size;
//Console.WriteLine("TX " + size + "/"+totalSent);// + " " + DC.ToHex(message, 0, (uint)size));
pkt_send.Message = new byte[size];
Buffer.BlockCopy(message, offset, pkt_send.Message, 0, size);
if (pkt_send.Compose())
sock.Send(pkt_send.Data);
}
}
}
public void Close()
{
sock?.Close();
}
public AsyncReply<bool> Connect(string hostname, ushort port)
{
throw new NotImplementedException();
}
public bool Begin()
{
return sock.Begin();
}
public bool Trigger(ResourceTrigger trigger)
{
return true;
}
public void Destroy()
{
Close();
//OnClose = null;
//OnConnect = null;
//OnReceive = null;
receiveNetworkBuffer = null;
//sock.OnReceive -= Sock_OnReceive;
//sock.OnClose -= Sock_OnClose;
//sock.OnConnect -= Sock_OnConnect;
sock.Receiver = null;
sock = null;
OnDestroy?.Invoke(this);
OnDestroy = null;
}
public AsyncReply<ISocket> AcceptAsync()
{
throw new NotImplementedException();
}
public void Hold()
{
//Console.WriteLine("WS Hold ");
held = true;
}
public void Unhold()
{
lock (sendLock)
{
held = false;
var message = sendNetworkBuffer.Read();
//Console.WriteLine("WS Unhold {0}", message == null ? 0 : message.Length);
if (message == null)
return;
totalSent += message.Length;
pkt_send.Message = message;
if (pkt_send.Compose())
sock.Send(pkt_send.Data);
}
}
public AsyncReply<bool> SendAsync(byte[] message, int offset, int length)
{
throw new NotImplementedException();
}
public ISocket Accept()
{
throw new NotImplementedException();
}
public AsyncReply<bool> BeginAsync()
{
return sock.BeginAsync();
}
public void NetworkClose(ISocket sender)
{
Receiver?.NetworkClose(sender);
}
public void NetworkReceive(ISocket sender, NetworkBuffer buffer)
{
if (sock.State == SocketState.Closed)// || sock.State == SocketState.Terminated)
return;
if (buffer.Protected)
return;
if (processing)
return;
var msg = buffer.Read();
if (msg == null)
return;
var wsPacketLength = pkt_receive.Parse(msg, 0, (uint)msg.Length);
//Console.WriteLine("WSP: " + wsPacketLength);
if (wsPacketLength < 0)
{
buffer.Protect(msg, 0, (uint)msg.Length + (uint)-wsPacketLength);
return;
}
uint offset = 0;
while (wsPacketLength > 0)
{
if (pkt_receive.Opcode == WebsocketPacket.WSOpcode.ConnectionClose)
{
Close();
return;
}
else if (pkt_receive.Opcode == WebsocketPacket.WSOpcode.Ping)
{
var pkt_pong = new WebsocketPacket();
pkt_pong.FIN = true;
pkt_pong.Mask = false;
pkt_pong.Opcode = WebsocketPacket.WSOpcode.Pong;
pkt_pong.Message = pkt_receive.Message;
offset += (uint)wsPacketLength;
Send(pkt_pong);
}
else if (pkt_receive.Opcode == WebsocketPacket.WSOpcode.Pong)
{
offset += (uint)wsPacketLength;
}
else if (pkt_receive.Opcode == WebsocketPacket.WSOpcode.BinaryFrame
|| pkt_receive.Opcode == WebsocketPacket.WSOpcode.TextFrame
|| pkt_receive.Opcode == WebsocketPacket.WSOpcode.ContinuationFrame)
{
totalReceived += pkt_receive.Message.Length;
//Console.WriteLine("RX " + pkt_receive.Message.Length + "/" + totalReceived);// + " " + DC.ToHex(message, 0, (uint)size));
receiveNetworkBuffer.Write(pkt_receive.Message);
offset += (uint)wsPacketLength;
//Console.WriteLine("WS IN: " + pkt_receive.Opcode.ToString() + " " + pkt_receive.Message.Length + " | " + offset + " " + string.Join(" ", pkt_receive.Message));// DC.ToHex(pkt_receive.Message));
}
else
Console.WriteLine("Unknown WS opcode:" + pkt_receive.Opcode);
if (offset == msg.Length)
{
//OnReceive?.Invoke(receiveNetworkBuffer);
Receiver?.NetworkReceive(this, receiveNetworkBuffer);
return;
}
wsPacketLength = pkt_receive.Parse(msg, offset, (uint)msg.Length);
}
if (wsPacketLength < 0)//(offset < msg.Length) && (offset > 0))
{
//receiveNetworkBuffer.HoldFor(msg, offset, (uint)(msg.Length - offset), (uint)msg.Length + (uint)-wsPacketLength);
// save the incomplete packet to the heldBuffer queue
buffer.HoldFor(msg, offset, (uint)(msg.Length - offset), (uint)(msg.Length - offset) + (uint)-wsPacketLength);
}
//Console.WriteLine("WS IN: " + receiveNetworkBuffer.Available);
//OnReceive?.Invoke(receiveNetworkBuffer);
Receiver?.NetworkReceive(this, receiveNetworkBuffer);
processing = false;
if (buffer.Available > 0 && !buffer.Protected)
Receiver?.NetworkReceive(this, buffer);
//Sock_OnReceive(buffer);
}
public void NetworkConnect(ISocket sender)
{
Receiver?.NetworkConnect(this);
}
}

View File

@ -32,35 +32,34 @@ using System.Collections;
using Esiur.Misc;
using Esiur.Data;
namespace Esiur.Net.TCP
namespace Esiur.Net.TCP;
public class TCPConnection : NetworkConnection
{
public class TCPConnection:NetworkConnection {
private KeyList<string, object> variables = new KeyList<string, object>();
private KeyList<string, object> variables = new KeyList<string, object>();
public TCPServer Server { get; internal set; }
public TCPServer Server { get; internal set; }
public KeyList<string, object> Variables
public KeyList<string, object> Variables
{
get
{
get
{
return variables;
}
}
protected override void Connected()
{
// do nothing
}
protected override void DataReceived(NetworkBuffer buffer)
{
Server?.Execute(this, buffer);
}
protected override void Disconencted()
{
// do nothing
return variables;
}
}
protected override void Connected()
{
// do nothing
}
protected override void DataReceived(NetworkBuffer buffer)
{
Server?.Execute(this, buffer);
}
protected override void Disconencted()
{
// do nothing
}
}

View File

@ -32,35 +32,34 @@ using Esiur.Net.Sockets;
using Esiur.Core;
using Esiur.Resource;
namespace Esiur.Net.TCP
namespace Esiur.Net.TCP;
public abstract class TCPFilter : IResource
{
public abstract class TCPFilter: IResource
public Instance Instance
{
public Instance Instance
{
get;
set;
}
get;
set;
}
public event DestroyedEvent OnDestroy;
public event DestroyedEvent OnDestroy;
public abstract AsyncReply<bool> Trigger(ResourceTrigger trigger);
public abstract AsyncReply<bool> Trigger(ResourceTrigger trigger);
public virtual bool Connected(TCPConnection sender)
{
return false;
}
public virtual bool Connected(TCPConnection sender)
{
return false;
}
public virtual bool Disconnected(TCPConnection sender)
{
return false;
}
public virtual bool Disconnected(TCPConnection sender)
{
return false;
}
public abstract bool Execute(byte[] msg, NetworkBuffer data, TCPConnection sender);
public abstract bool Execute(byte[] msg, NetworkBuffer data, TCPConnection sender);
public void Destroy()
{
OnDestroy?.Invoke(this);
}
public void Destroy()
{
OnDestroy?.Invoke(this);
}
}

View File

@ -34,123 +34,121 @@ using Esiur.Core;
using System.Net;
using Esiur.Resource;
namespace Esiur.Net.TCP
namespace Esiur.Net.TCP;
public class TCPServer : NetworkServer<TCPConnection>, IResource
{
public class TCPServer : NetworkServer<TCPConnection>, IResource
[Attribute]
public string IP
{
get;
set;
}
[Attribute]
public ushort Port
{
get;
set;
}
//[Storable]
//public uint Timeout
//{
// get;
// set;
//}
//[Attribute]
//public uint Clock
//{
// get;
// set;
//}
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);
}
else if (trigger == ResourceTrigger.Terminate)
{
Stop();
}
else if (trigger == ResourceTrigger.SystemReload)
{
Trigger(ResourceTrigger.Terminate);
Trigger(ResourceTrigger.Initialize);
}
else if (trigger == ResourceTrigger.SystemInitialized)
{
Instance.Children<TCPFilter>().Then(x => filters = x);
}
return new AsyncReply<bool>(true);
}
internal bool Execute(TCPConnection sender, NetworkBuffer data)
{
var msg = data.Read();
foreach (var filter in filters)
{
if (filter.Execute(msg, data, sender))
return true;
}
return false;
}
private void SessionModified(TCPConnection session, string key, object newValue)
{
[Attribute]
public string IP
}
protected override void ClientDisconnected(TCPConnection connection)
{
foreach (var filter in filters)
{
get;
set;
filter.Disconnected(connection);
}
[Attribute]
public ushort Port
}
public override void Add(TCPConnection connection)
{
connection.Server = this;
base.Add(connection);
}
public override void Remove(TCPConnection connection)
{
connection.Server = null;
base.Remove(connection);
}
protected override void ClientConnected(TCPConnection connection)
{
foreach (var filter in filters)
{
get;
set;
filter.Connected(connection);
}
//[Storable]
//public uint Timeout
//{
// get;
// set;
//}
//[Attribute]
//public uint Clock
//{
// get;
// set;
//}
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);
}
else if (trigger == ResourceTrigger.Terminate)
{
Stop();
}
else if (trigger == ResourceTrigger.SystemReload)
{
Trigger(ResourceTrigger.Terminate);
Trigger(ResourceTrigger.Initialize);
}
else if (trigger == ResourceTrigger.SystemInitialized)
{
Instance.Children<TCPFilter>().Then(x => filters = x);
}
return new AsyncReply<bool>(true);
}
internal bool Execute(TCPConnection sender, NetworkBuffer data)
{
var msg = data.Read();
foreach (var filter in filters)
{
if (filter.Execute(msg, data, sender))
return true;
}
return false;
}
private void SessionModified(TCPConnection session, string key, object newValue)
{
}
protected override void ClientDisconnected(TCPConnection connection)
{
foreach (var filter in filters)
{
filter.Disconnected(connection);
}
}
public override void Add(TCPConnection connection)
{
connection.Server = this;
base.Add(connection);
}
public override void Remove(TCPConnection connection)
{
connection.Server = null;
base.Remove(connection);
}
protected override void ClientConnected(TCPConnection connection)
{
foreach (var filter in filters)
{
filter.Connected(connection);
}
}
}
}

View File

@ -28,10 +28,8 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Esiur.Net.TCP
namespace Esiur.Net.TCP;
public class TCPSession : NetworkSession
{
public class TCPSession : NetworkSession
{
}
}

View File

@ -32,26 +32,24 @@ using Esiur.Data;
using Esiur.Core;
using Esiur.Resource;
namespace Esiur.Net.UDP
namespace Esiur.Net.UDP;
public abstract class UDPFilter : IResource
{
public abstract class UDPFilter : IResource
public Instance Instance
{
public Instance Instance
{
get;
set;
}
public event DestroyedEvent OnDestroy;
public abstract AsyncReply<bool> Trigger(ResourceTrigger trigger);
public abstract bool Execute(byte[] data, IPEndPoint sender);
public void Destroy()
{
OnDestroy?.Invoke(this);
}
get;
set;
}
}
public event DestroyedEvent OnDestroy;
public abstract AsyncReply<bool> Trigger(ResourceTrigger trigger);
public abstract bool Execute(byte[] data, IPEndPoint sender);
public void Destroy()
{
OnDestroy?.Invoke(this);
}
}

View File

@ -33,172 +33,170 @@ using Esiur.Misc;
using Esiur.Resource;
using Esiur.Core;
namespace Esiur.Net.UDP
namespace Esiur.Net.UDP;
/* public class IIPConnection
{
public EndPoint SenderPoint;
public
}*/
public class UDPServer : IResource
{
Thread receiver;
UdpClient udp;
UDPFilter[] filters = new UDPFilter[0];
/* public class IIPConnection
public event DestroyedEvent OnDestroy;
public Instance Instance
{
public EndPoint SenderPoint;
public
}*/
public class UDPServer : IResource
get;
set;
}
[Attribute]
string IP
{
Thread receiver;
UdpClient udp;
UDPFilter[] filters = new UDPFilter[0];
get;
set;
}
public event DestroyedEvent OnDestroy;
[Attribute]
ushort Port
{
get;
set;
}
public Instance Instance
private void Receiving()
{
IPEndPoint ep = new IPEndPoint(IPAddress.Any, 0);
while (true)
{
get;
set;
}
byte[] b = udp.Receive(ref ep);
[Attribute]
string IP
{
get;
set;
}
[Attribute]
ushort Port
{
get;
set;
}
private void Receiving()
{
IPEndPoint ep = new IPEndPoint(IPAddress.Any, 0);
while (true)
foreach (var child in filters)
{
byte[] b = udp.Receive(ref ep);
var f = child as UDPFilter;
foreach (var child in filters)
try
{
var f = child as UDPFilter;
try
if (f.Execute(b, ep))
{
if (f.Execute(b, ep))
{
break;
}
}
catch (Exception ex)
{
Global.Log("UDPServer", LogType.Error, ex.ToString());
//Console.WriteLine(ex.ToString());
break;
}
}
catch (Exception ex)
{
Global.Log("UDPServer", LogType.Error, ex.ToString());
//Console.WriteLine(ex.ToString());
}
}
}
}
public bool Send(byte[] Data, int Count, IPEndPoint EP)
public bool Send(byte[] Data, int Count, IPEndPoint EP)
{
try
{
try
{
udp.Send(Data, Count, EP);
return true;
}
catch
{
return false;
}
}
public bool Send(byte[] Data, IPEndPoint EP)
{
try
{
udp.Send(Data, Data.Length, EP);
return true;
}
catch
{
return false;
}
}
public bool Send(byte[] Data, int Count, string Host, int Port)
{
try
{
udp.Send(Data, Count, Host, Port);
return true;
}
catch
{
return false;
}
}
public bool Send(byte[] Data, string Host, int Port)
{
try
{
udp.Send(Data, Data.Length, Host, Port);
return true;
}
catch
{
return false;
}
}
public bool Send(string Data, IPEndPoint EP)
{
try
{
udp.Send(Encoding.Default.GetBytes(Data), Data.Length, EP);
return true;
}
catch
{
return false;
}
}
public bool Send(string Data, string Host, int Port)
{
try
{
udp.Send(Encoding.Default.GetBytes(Data), Data.Length, Host, Port);
return true;
}
catch
{
return false;
}
}
public void Destroy()
{
udp.Close();
OnDestroy?.Invoke(this);
}
async AsyncReply<bool> IResource.Trigger(ResourceTrigger trigger)
{
if (trigger == ResourceTrigger.Initialize)
{
var address = IP == null ? IPAddress.Any : IPAddress.Parse(IP);
udp = new UdpClient(new IPEndPoint(address, Port));
receiver = new Thread(Receiving);
receiver.Start();
}
else if (trigger == ResourceTrigger.Terminate)
{
if (receiver != null)
receiver.Abort();
}
else if (trigger == ResourceTrigger.SystemInitialized)
{
filters = await Instance.Children<UDPFilter>();
}
udp.Send(Data, Count, EP);
return true;
}
catch
{
return false;
}
}
}
public bool Send(byte[] Data, IPEndPoint EP)
{
try
{
udp.Send(Data, Data.Length, EP);
return true;
}
catch
{
return false;
}
}
public bool Send(byte[] Data, int Count, string Host, int Port)
{
try
{
udp.Send(Data, Count, Host, Port);
return true;
}
catch
{
return false;
}
}
public bool Send(byte[] Data, string Host, int Port)
{
try
{
udp.Send(Data, Data.Length, Host, Port);
return true;
}
catch
{
return false;
}
}
public bool Send(string Data, IPEndPoint EP)
{
try
{
udp.Send(Encoding.Default.GetBytes(Data), Data.Length, EP);
return true;
}
catch
{
return false;
}
}
public bool Send(string Data, string Host, int Port)
{
try
{
udp.Send(Encoding.Default.GetBytes(Data), Data.Length, Host, Port);
return true;
}
catch
{
return false;
}
}
public void Destroy()
{
udp.Close();
OnDestroy?.Invoke(this);
}
async AsyncReply<bool> IResource.Trigger(ResourceTrigger trigger)
{
if (trigger == ResourceTrigger.Initialize)
{
var address = IP == null ? IPAddress.Any : IPAddress.Parse(IP);
udp = new UdpClient(new IPEndPoint(address, Port));
receiver = new Thread(Receiving);
receiver.Start();
}
else if (trigger == ResourceTrigger.Terminate)
{
if (receiver != null)
receiver.Abort();
}
else if (trigger == ResourceTrigger.SystemInitialized)
{
filters = await Instance.Children<UDPFilter>();
}
return true;
}
}