diff --git a/Esiur/Core/AsyncReplyGeneric.cs b/Esiur/Core/AsyncReplyGeneric.cs index 7bd9070..fc6a311 100644 --- a/Esiur/Core/AsyncReplyGeneric.cs +++ b/Esiur/Core/AsyncReplyGeneric.cs @@ -57,7 +57,7 @@ namespace Esiur.Core //public Timer timeout;// = new Timer() protected bool resultReady = false; AsyncException exception; - StackTrace trace; + // StackTrace trace; AutoResetEvent mutex = new AutoResetEvent(false); public static int MaxId; @@ -103,7 +103,7 @@ namespace Esiur.Core //{ lock (asyncLock) { - trace = new StackTrace(); + // trace = new StackTrace(); if (resultReady) { diff --git a/Esiur/Data/Codec.cs b/Esiur/Data/Codec.cs index 2e63327..49d825c 100644 --- a/Esiur/Data/Codec.cs +++ b/Esiur/Data/Codec.cs @@ -546,7 +546,7 @@ namespace Esiur.Data /// Resource public static AsyncReply ParseResource(byte[] data, uint offset) { - return Warehouse.Get(data.GetUInt32(offset)); + return Warehouse.GetById(data.GetUInt32(offset)); } /// @@ -703,7 +703,7 @@ namespace Esiur.Data previous = new AsyncReply(null); else if (result == ResourceComparisonResult.Local) { - previous = Warehouse.Get(data.GetUInt32(offset)); + previous = Warehouse.GetById(data.GetUInt32(offset)); offset += 4; } else if (result == ResourceComparisonResult.Distributed) @@ -731,7 +731,7 @@ namespace Esiur.Data } else if (result == ResourceComparisonResult.Local) { - current = Warehouse.Get(data.GetUInt32(offset)); + current = Warehouse.GetById(data.GetUInt32(offset)); offset += 4; } else if (result == ResourceComparisonResult.Distributed) diff --git a/Esiur/Data/StringKeyList.cs b/Esiur/Data/StringKeyList.cs index fd48a99..9e76af8 100644 --- a/Esiur/Data/StringKeyList.cs +++ b/Esiur/Data/StringKeyList.cs @@ -89,7 +89,7 @@ namespace Esiur.Data { var key = Key.ToLower(); - var toRemove = m_Variables.Where(x => x.Key.ToLower() == key); + var toRemove = m_Variables.Where(x => x.Key.ToLower() == key).ToArray(); foreach (var item in toRemove) m_Variables.Remove(item); diff --git a/Esiur/Esiur.csproj b/Esiur/Esiur.csproj index 92e44f1..afe1279 100644 --- a/Esiur/Esiur.csproj +++ b/Esiur/Esiur.csproj @@ -7,7 +7,7 @@ https://github.com/esiur/esiur-dotnet/blob/master/LICENSE http://www.esiur.com true - 1.4.0 + 1.4.1 https://github.com/esiur/esiur-dotnet Ahmed Kh. Zamil 1.3.1.0 diff --git a/Esiur/Net/HTTP/HTTPConnection.cs b/Esiur/Net/HTTP/HTTPConnection.cs index 77375f8..9770923 100644 --- a/Esiur/Net/HTTP/HTTPConnection.cs +++ b/Esiur/Net/HTTP/HTTPConnection.cs @@ -39,59 +39,25 @@ using System.Security.Cryptography; namespace Esiur.Net.HTTP { - //[Serializable] public class HTTPConnection : NetworkConnection { - /* - public enum SendOptions : int - { - AllCalculateLength, - AllDontCalculateLength, - SpecifiedHeadersOnly, - DataOnly - } - */ - - public HTTPConnection() - { - Response = new HTTPResponsePacket(); - variables = new KeyList(); - } public void SetParent(HTTPServer Parent) { Server = Parent; } - //public bool HeadersSent; - - - private KeyList variables; - private bool Busy = false; - private DateTime RequestTime = DateTime.MinValue; - - public bool WSMode; + public bool WSMode { get; internal set; } private HTTPServer Server; - public WebsocketPacket WSRequest; - public HTTPRequestPacket Request; - public HTTPResponsePacket Response; + public WebsocketPacket WSRequest { get; set; } + public HTTPRequestPacket Request { get; set; } + public HTTPResponsePacket Response { get; } = new HTTPResponsePacket(); HTTPSession session; - public KeyList Variables - { - get - { - return variables; - } - } + public KeyList Variables { get; } = new KeyList(); - public bool IsBusy() - { - return Busy; - } - internal long Parse(byte[] data) { @@ -115,7 +81,7 @@ namespace Esiur.Net.HTTP } else { - HTTPRequestPacket rp = new HTTPRequestPacket(); + var rp = new HTTPRequestPacket(); var pSize = rp.Parse(data, 0, (uint)data.Length); if (pSize > 0) { @@ -130,31 +96,6 @@ namespace Esiur.Net.HTTP } - /* - public override void Send(string Response) - { - Send(Response, SendOptions.AllCalculateLength); - } - - public void Send(string Message, SendOptions Options) - { - - if (Response.Handled) - return; - - if (Response != null) - Send(Encoding.Default.GetBytes(Response), Options); - else - Send((byte[])null, Options); - } - - public void Send(MemoryStream ms) - { - Send(ms.ToArray(), SendOptions.AllCalculateLength); - } - - */ - public void Flush() { // close the connection @@ -171,21 +112,18 @@ namespace Esiur.Net.HTTP // Compute the SHA1 hash SHA1 sha = SHA1.Create(); byte[] sha1Hash = sha.ComputeHash(Encoding.UTF8.GetBytes(ret)); - Response.Headers["Upgrade"] = Request.Headers["Upgrade"]; + 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.Headers["Sec-WebSocket-Protocol"] = Request.Headers["Sec-WebSocket-Protocol"]; - //Response.Headers["Origin"] = Request.Headers["Origin"]; Response.Number = HTTPResponsePacket.ResponseCode.HTTP_SWITCHING; Response.Text = "Switching Protocols"; WSMode = true; - //Send((byte[])null, SendOptions.AllDontCalculateLength); Send(); return true; @@ -208,6 +146,12 @@ namespace Esiur.Net.HTTP 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; @@ -219,7 +163,6 @@ namespace Esiur.Net.HTTP if (Response.Handled) return; - Busy = true; try { @@ -235,17 +178,17 @@ namespace Esiur.Net.HTTP { try { - Close();// Server.CloseClient(Connection); + Close(); } finally { } } finally { - Busy = false; + } } - + public void CreateNewSession() { if (session == null) @@ -272,7 +215,7 @@ namespace Esiur.Net.HTTP && Request.Headers.ContainsKey("Sec-WebSocket-Version") && Request.Headers["Sec-WebSocket-Version"] == "13" && Request.Headers.ContainsKey("Sec-WebSocket-Key")) - //&& Request.Headers.ContainsKey("Sec-WebSocket-Protocol")) + //&& Request.Headers.ContainsKey("Sec-WebSocket-Protocol")) { return true; } @@ -282,11 +225,14 @@ namespace Esiur.Net.HTTP } } + bool bb; + public void SendFile(string filename) { if (Response.Handled == true) return; + try { @@ -302,22 +248,22 @@ namespace Esiur.Net.HTTP if (!File.Exists(filename)) { Response.Number = HTTPResponsePacket.ResponseCode.HTTP_NOTFOUND; - Send("File Not Found");//, SendOptions.AllCalculateLength); + Send("File Not Found"); return; } - Busy = true; - System.DateTime FWD = File.GetLastWriteTime(filename); - if (Request.Headers.ContainsKey("if-modified-since"))// != DateTime.Parse("12:00:00 AM")) + var fileEditTime = File.GetLastWriteTime(filename).ToUniversalTime(); + if (Request.Headers.ContainsKey("if-modified-since")) { try { - DateTime IMS = DateTime.Parse(Request.Headers["if-modified-since"]); - if (FWD <= IMS) + var ims = DateTime.Parse(Request.Headers["if-modified-since"]); + if (Math.Abs((fileEditTime - ims).TotalSeconds) < 0) { Response.Number = HTTPResponsePacket.ResponseCode.HTTP_NOTMODIFIED; Response.Text = "Not Modified"; + Send((byte[])null); } } catch @@ -327,38 +273,42 @@ namespace Esiur.Net.HTTP } - if (Response.Number == HTTPResponsePacket.ResponseCode.HTTP_NOTMODIFIED) + + Response.Number = HTTPResponsePacket.ResponseCode.HTTP_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)) { - Send((byte[])null); - } - else - { - // Fri, 30 Oct 2007 14:19:41 GMT - Response.Headers["Last-Modified"] = FWD.ToUniversalTime().ToString("ddd, dd MMM yyyy HH:mm:ss"); - FileInfo fi = new FileInfo(filename); - Response.Headers["Content-Length"] = fi.Length.ToString(); - Send(HTTPResponsePacket.ComposeOptions.SpecifiedHeadersOnly); - using (var fs = new FileStream(filename, FileMode.Open)) + + var buffer = new byte[5000]; + + + while (true) { - var buffer = new byte[5000]; - var offset = 0; - while (offset < fs.Length) - { - var n = fs.Read(buffer, offset, buffer.Length); - offset += n; - base.Send(buffer); - } + var n = fs.Read(buffer, 0, 5000); + + if (n <= 0) + break; + + + base.Send(buffer, 0, n); + } } + - Busy = false; - - return; } catch { - Busy = false; - try { Close(); diff --git a/Esiur/Net/HTTP/HTTPServer.cs b/Esiur/Net/HTTP/HTTPServer.cs index 5b6299a..8907193 100644 --- a/Esiur/Net/HTTP/HTTPServer.cs +++ b/Esiur/Net/HTTP/HTTPServer.cs @@ -192,17 +192,9 @@ namespace Esiur.Net.HTTP protected override void DataReceived(HTTPConnection sender, NetworkBuffer data) { - //Console.WriteLine(Data); - // Initialize a new session - //HTTPConnection HTTP = (HTTPConnection)sender.ExtraObject; - - //string Data = System.Text.Encoding.Default.GetString(ReceivedData); - + byte[] msg = data.Read(); - - - - + var BL = sender.Parse(msg); if (BL == 0) @@ -265,7 +257,8 @@ namespace Esiur.Net.HTTP try { foreach (var resource in filters) - resource.Execute(sender); + if (resource.Execute(sender)) + return; sender.Send("Bad Request"); diff --git a/Esiur/Net/IIP/DistributedConnection.cs b/Esiur/Net/IIP/DistributedConnection.cs index 33b6627..cec7838 100644 --- a/Esiur/Net/IIP/DistributedConnection.cs +++ b/Esiur/Net/IIP/DistributedConnection.cs @@ -62,6 +62,9 @@ namespace Esiur.Net.IIP Session session; + + List attachedResources = new List(); + AsyncReply openReply; byte[] localPassword; @@ -304,7 +307,7 @@ namespace Esiur.Net.IIP private uint processPacket(byte[] msg, uint offset, uint ends, NetworkBuffer data, int chunkId) { - var packet = new IIPPacket(); + //var packet = new IIPPacket(); @@ -771,14 +774,17 @@ namespace Esiur.Net.IIP var chunkId = (new Random()).Next(1000, 1000000); - + var list = new List();// double, IIPPacketCommand>(); + + this.Socket.Hold(); while (offset < ends) { - offset = processPacket(msg, offset, ends, data, chunkId); - } + offset = processPacket(msg, offset, ends, data, chunkId); + } - } + this.Socket.Unhold(); + } /// /// Resource interface diff --git a/Esiur/Net/IIP/DistributedConnectionProtocol.cs b/Esiur/Net/IIP/DistributedConnectionProtocol.cs index 758ca0e..9d3adc0 100644 --- a/Esiur/Net/IIP/DistributedConnectionProtocol.cs +++ b/Esiur/Net/IIP/DistributedConnectionProtocol.cs @@ -433,7 +433,7 @@ namespace Esiur.Net.IIP void IIPRequestAttachResource(uint callback, uint resourceId) { - Warehouse.Get(resourceId).Then((res) => + Warehouse.GetById(resourceId).Then((res) => { if (res != null) { @@ -461,6 +461,9 @@ namespace Esiur.Net.IIP //r.Instance.Children.OnRemoved += Children_OnRemoved; r.Instance.Attributes.OnModified += Attributes_OnModified; + // add it to attached resources so GC won't remove it from memory + attachedResources.Add(r); + var link = DC.ToBytes(r.Instance.Link); if (r is DistributedResource) @@ -550,7 +553,7 @@ namespace Esiur.Net.IIP void IIPRequestReattachResource(uint callback, uint resourceId, ulong resourceAge) { - Warehouse.Get(resourceId).Then((res) => + Warehouse.GetById(resourceId).Then((res) => { if (res != null) { @@ -587,7 +590,7 @@ namespace Esiur.Net.IIP void IIPRequestDetachResource(uint callback, uint resourceId) { - Warehouse.Get(resourceId).Then((res) => + Warehouse.GetById(resourceId).Then((res) => { if (res != null) { @@ -595,6 +598,10 @@ namespace Esiur.Net.IIP r.Instance.ResourceEventOccurred -= Instance_EventOccurred; r.Instance.ResourceModified -= Instance_PropertyModified; r.Instance.ResourceDestroyed -= Instance_ResourceDestroyed; + + // remove from attached resources + attachedResources.Remove(res); + // reply ok SendReply(IIPPacket.IIPPacketAction.DetachResource, callback).Done(); } @@ -609,7 +616,7 @@ namespace Esiur.Net.IIP void IIPRequestCreateResource(uint callback, uint storeId, uint parentId, byte[] content) { - Warehouse.Get(storeId).Then(store => + Warehouse.GetById(storeId).Then(store => { if (store == null) { @@ -630,7 +637,7 @@ namespace Esiur.Net.IIP return; } - Warehouse.Get(parentId).Then(parent => + Warehouse.GetById(parentId).Then(parent => { // check security @@ -733,7 +740,7 @@ namespace Esiur.Net.IIP void IIPRequestDeleteResource(uint callback, uint resourceId) { - Warehouse.Get(resourceId).Then(r => + Warehouse.GetById(resourceId).Then(r => { if (r == null) { @@ -757,7 +764,7 @@ namespace Esiur.Net.IIP void IIPRequestGetAttributes(uint callback, uint resourceId, byte[] attributes, bool all = false) { - Warehouse.Get(resourceId).Then(r => + Warehouse.GetById(resourceId).Then(r => { if (r == null) { @@ -791,7 +798,7 @@ namespace Esiur.Net.IIP void IIPRequestAddChild(uint callback, uint parentId, uint childId) { - Warehouse.Get(parentId).Then(parent => + Warehouse.GetById(parentId).Then(parent => { if (parent == null) { @@ -799,7 +806,7 @@ namespace Esiur.Net.IIP return; } - Warehouse.Get(childId).Then(child => + Warehouse.GetById(childId).Then(child => { if (child == null) { @@ -830,7 +837,7 @@ namespace Esiur.Net.IIP void IIPRequestRemoveChild(uint callback, uint parentId, uint childId) { - Warehouse.Get(parentId).Then(parent => + Warehouse.GetById(parentId).Then(parent => { if (parent == null) { @@ -838,7 +845,7 @@ namespace Esiur.Net.IIP return; } - Warehouse.Get(childId).Then(child => + Warehouse.GetById(childId).Then(child => { if (child == null) { @@ -869,7 +876,7 @@ namespace Esiur.Net.IIP void IIPRequestRenameResource(uint callback, uint resourceId, byte[] name) { - Warehouse.Get(resourceId).Then(resource => + Warehouse.GetById(resourceId).Then(resource => { if (resource == null) { @@ -891,7 +898,7 @@ namespace Esiur.Net.IIP void IIPRequestResourceChildren(uint callback, uint resourceId) { - Warehouse.Get(resourceId).Then(resource => + Warehouse.GetById(resourceId).Then(resource => { if (resource == null) { @@ -913,7 +920,7 @@ namespace Esiur.Net.IIP void IIPRequestResourceParents(uint callback, uint resourceId) { - Warehouse.Get(resourceId).Then(resource => + Warehouse.GetById(resourceId).Then(resource => { if (resource == null) { @@ -934,7 +941,7 @@ namespace Esiur.Net.IIP void IIPRequestClearAttributes(uint callback, uint resourceId, byte[] attributes, bool all = false) { - Warehouse.Get(resourceId).Then(r => + Warehouse.GetById(resourceId).Then(r => { if (r == null) { @@ -963,7 +970,7 @@ namespace Esiur.Net.IIP void IIPRequestUpdateAttributes(uint callback, uint resourceId, byte[] attributes, bool clearAttributes = false) { - Warehouse.Get(resourceId).Then(r => + Warehouse.GetById(resourceId).Then(r => { if (r == null) { @@ -1028,7 +1035,7 @@ namespace Esiur.Net.IIP void IIPRequestTemplateFromResourceId(uint callback, uint resourceId) { - Warehouse.Get(resourceId).Then((r) => + Warehouse.GetById(resourceId).Then((r) => { if (r != null) SendReply(IIPPacket.IIPPacketAction.TemplateFromResourceId, callback) @@ -1078,7 +1085,7 @@ namespace Esiur.Net.IIP { //Console.WriteLine("IIPRequestInvokeFunction " + callback + " " + resourceId + " " + index); - Warehouse.Get(resourceId).Then((r) => + Warehouse.GetById(resourceId).Then((r) => { if (r != null) { @@ -1235,7 +1242,7 @@ namespace Esiur.Net.IIP void IIPRequestInvokeFunctionNamedArguments(uint callback, uint resourceId, byte index, byte[] content) { - Warehouse.Get(resourceId).Then((r) => + Warehouse.GetById(resourceId).Then((r) => { if (r != null) { @@ -1382,7 +1389,7 @@ namespace Esiur.Net.IIP void IIPRequestGetProperty(uint callback, uint resourceId, byte index) { - Warehouse.Get(resourceId).Then((r) => + Warehouse.GetById(resourceId).Then((r) => { if (r != null) { @@ -1429,7 +1436,7 @@ namespace Esiur.Net.IIP void IIPRequestInquireResourceHistory(uint callback, uint resourceId, DateTime fromDate, DateTime toDate) { - Warehouse.Get(resourceId).Then((r) => + Warehouse.GetById(resourceId).Then((r) => { if (r != null) { @@ -1465,7 +1472,7 @@ namespace Esiur.Net.IIP void IIPRequestGetPropertyIfModifiedSince(uint callback, uint resourceId, byte index, ulong age) { - Warehouse.Get(resourceId).Then((r) => + Warehouse.GetById(resourceId).Then((r) => { if (r != null) { @@ -1511,7 +1518,7 @@ namespace Esiur.Net.IIP void IIPRequestSetProperty(uint callback, uint resourceId, byte index, byte[] content) { - Warehouse.Get(resourceId).Then((r) => + Warehouse.GetById(resourceId).Then((r) => { if (r != null) { diff --git a/Esiur/Net/NetworkConnection.cs b/Esiur/Net/NetworkConnection.cs index bf81c23..4cbd70f 100644 --- a/Esiur/Net/NetworkConnection.cs +++ b/Esiur/Net/NetworkConnection.cs @@ -259,25 +259,33 @@ namespace Esiur.Net public virtual void Send(byte[] msg) { - //Console.WriteLine("TXX " + msg.Length); - try { - //if (!connected) - //{ - //Console.WriteLine("not connected"); - // return; - //} - if (sock != null) { lastAction = DateTime.Now; sock.Send(msg); } } - catch (Exception ex) + catch { - Console.WriteLine(ex.ToString()); + + } + } + + public virtual void Send(byte[] msg, int offset, int length) + { + try + { + if (sock != null) + { + lastAction = DateTime.Now; + sock.Send(msg, offset, length); + } + } + catch + { + } } diff --git a/Esiur/Net/Packets/HTTPResponsePacket.cs b/Esiur/Net/Packets/HTTPResponsePacket.cs index 3aeaec3..2a97ab9 100644 --- a/Esiur/Net/Packets/HTTPResponsePacket.cs +++ b/Esiur/Net/Packets/HTTPResponsePacket.cs @@ -175,7 +175,7 @@ namespace Esiur.Net.Packets { if (Message != null) msg.AddRange(Message); - } + } Data = msg.ToArray(); diff --git a/Esiur/Net/Packets/IIPPacket.cs b/Esiur/Net/Packets/IIPPacket.cs index ade655a..ef73135 100644 --- a/Esiur/Net/Packets/IIPPacket.cs +++ b/Esiur/Net/Packets/IIPPacket.cs @@ -150,6 +150,12 @@ namespace Esiur.Net.Packets set; } + public bool Bulk + { + get; + set; + } + public IIPPacketEvent Event { get; @@ -174,6 +180,13 @@ namespace Esiur.Net.Packets } + public uint[] ResourcesIds { get; set; } + public uint NewResourcesIds { get; set; } + public uint ChildrenIds { get; set; } + public uint StoresIds { get; set; } + + public IIPPacketAttachInfo[] AttachReply { get; set; } + public uint ResourceId { get; set; } public uint NewResourceId { get; set; } //public uint ParentId { get; set; } @@ -249,11 +262,11 @@ namespace Esiur.Net.Packets CallbackId = data.GetUInt32(offset); offset += 4; } - else + else // response or reply { PreviousAction = Action; - Action = (IIPPacketAction)(data[offset++] & 0x3f); - + Action = (IIPPacketAction)(data[offset] & 0x1f); + Bulk = (data[offset++] & 0x20) == 0x20; if (NotEnough(offset, ends, 4)) return -dataLengthNeeded; @@ -371,8 +384,21 @@ namespace Esiur.Net.Packets if (NotEnough(offset, ends, 4)) return -dataLengthNeeded; - ResourceId = data.GetUInt32(offset); - offset += 4; + if (Bulk) + { + var cl = data.GetUInt32(offset); + offset += 4; + + if (NotEnough(offset, ends, cl)) + return -dataLengthNeeded; + + ResourcesIds = data.GetUInt32Array(offset, cl); + } + else + { + ResourceId = data.GetUInt32(offset); + offset += 4; + } } else if (Action == IIPPacketAction.ReattachResource) { @@ -628,35 +654,74 @@ namespace Esiur.Net.Packets || Action == IIPPacketAction.ReattachResource) { - if (NotEnough(offset, ends, 26)) - return -dataLengthNeeded; + if (Bulk) + { + if (NotEnough(offset, ends, 26)) + return -dataLengthNeeded; - ClassId = data.GetGuid(offset); - offset += 16; + ClassId = data.GetGuid(offset); + offset += 16; - ResourceAge = data.GetUInt64(offset); - offset += 8; + ResourceAge = data.GetUInt64(offset); + offset += 8; - uint cl = data.GetUInt16(offset); - offset += 2; + uint cl = data.GetUInt16(offset); + offset += 2; - if (NotEnough(offset, ends, cl)) - return -dataLengthNeeded; + if (NotEnough(offset, ends, cl)) + return -dataLengthNeeded; - ResourceLink = data.GetString(offset, cl); - offset += cl; + ResourceLink = data.GetString(offset, cl); + offset += cl; - if (NotEnough(offset, ends, 4)) - return -dataLengthNeeded; + if (NotEnough(offset, ends, 4)) + return -dataLengthNeeded; - cl = data.GetUInt32(offset); - offset += 4; + cl = data.GetUInt32(offset); + offset += 4; - if (NotEnough(offset, ends, cl)) - return -dataLengthNeeded; + if (NotEnough(offset, ends, cl)) + return -dataLengthNeeded; - Content = data.Clip(offset, cl); - offset += cl; + Content = data.Clip(offset, cl); + offset += cl; + } + else + { + // length + if (NotEnough(offset, ends, 4)) + return -dataLengthNeeded; + + var cl = data.GetUInt32(offset); + offset += 4; + + if (NotEnough(offset, ends, cl)) + return -dataLengthNeeded; + + // Content = data.Clip(offset, cl); + //offset += cl; + cl += offset; + + var list = new List(); + + while(offset < cl) + { + Guid classId = data.GetGuid(offset); + offset += 16; + ulong age = data.GetUInt64(offset); + offset += 8; + var len = data.GetUInt16(offset); + offset += 2; + var link = data.GetString(offset, len); + offset += len; + var cc = data.GetUInt32(offset); + list.Add(new IIPPacketAttachInfo(classId, age, link, data.Clip(offset, cc))); + offset += cc; + } + + AttachReply = list.ToArray(); + + } } else if (Action == IIPPacketAction.DetachResource) { diff --git a/Esiur/Net/Packets/IIPPacketAttachInfo.cs b/Esiur/Net/Packets/IIPPacketAttachInfo.cs new file mode 100644 index 0000000..53723e7 --- /dev/null +++ b/Esiur/Net/Packets/IIPPacketAttachInfo.cs @@ -0,0 +1,22 @@ +using System; +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; + + public IIPPacketAttachInfo(Guid classId, ulong age, string link, byte[] content) + { + ClassId = classId; + Age = age; + Content = content; + Link = link; + } + } +} diff --git a/Esiur/Net/Sockets/ISocket.cs b/Esiur/Net/Sockets/ISocket.cs index 25c20cf..6686da7 100644 --- a/Esiur/Net/Sockets/ISocket.cs +++ b/Esiur/Net/Sockets/ISocket.cs @@ -59,5 +59,9 @@ namespace Esiur.Net.Sockets AsyncReply Accept(); IPEndPoint RemoteEndPoint { get; } IPEndPoint LocalEndPoint { get; } + + void Hold(); + + void Unhold(); } } diff --git a/Esiur/Net/Sockets/SSLSocket.cs b/Esiur/Net/Sockets/SSLSocket.cs index c98836b..37decef 100644 --- a/Esiur/Net/Sockets/SSLSocket.cs +++ b/Esiur/Net/Sockets/SSLSocket.cs @@ -339,5 +339,15 @@ namespace Esiur.Net.Sockets return reply; } + + public void Hold() + { + throw new NotImplementedException(); + } + + public void Unhold() + { + throw new NotImplementedException(); + } } } \ No newline at end of file diff --git a/Esiur/Net/Sockets/TCPSocket.cs b/Esiur/Net/Sockets/TCPSocket.cs index 75b58f1..a697e10 100644 --- a/Esiur/Net/Sockets/TCPSocket.cs +++ b/Esiur/Net/Sockets/TCPSocket.cs @@ -42,6 +42,8 @@ namespace Esiur.Net.Sockets Socket sock; byte[] receiveBuffer; + bool held; + ArraySegment receiveBufferSegment; NetworkBuffer receiveNetworkBuffer = new NetworkBuffer(); @@ -241,9 +243,12 @@ namespace Esiur.Net.Sockets if (sendBufferQueue.Count > 0) { - byte[] data = sendBufferQueue.Dequeue(); lock (sendLock) + { + byte[] data = sendBufferQueue.Dequeue(); + //Console.WriteLine(Encoding.UTF8.GetString(data)); sock.SendAsync(new ArraySegment(data), SocketFlags.None).ContinueWith(DataSent); + } } else { @@ -340,22 +345,57 @@ namespace Esiur.Net.Sockets public void Send(byte[] message, int offset, int size) { + //sock.Blocking = + //sock.Send(message, offset, size, SocketFlags.None); + //return; if (sock.Connected) lock (sendLock) { - if (asyncSending) + + if (asyncSending || held) { sendBufferQueue.Enqueue(message.Clip((uint)offset, (uint)size)); } else { asyncSending = true; - sock.SendAsync(new ArraySegment(message, offset, size), SocketFlags.None).ContinueWith(DataSent); + sock.BeginSend(message, offset, size, SocketFlags.None, PacketSent, null); + //sock.SendAsync(new ArraySegment(msg), SocketFlags.None).ContinueWith(DataSent); } } } + private void PacketSent(IAsyncResult ar) + { + try + { + if (sendBufferQueue.Count > 0) + { + lock (sendLock) + { + byte[] data = sendBufferQueue.Dequeue(); + sock.BeginSend(data, 0, data.Length, SocketFlags.None, PacketSent, null); + } + } + else + { + asyncSending = false; + } + } + catch (Exception ex) + { + if (state != SocketState.Closed && !sock.Connected) + { + state = SocketState.Terminated; + Close(); + } + + asyncSending = false; + + Global.Log("TCPSocket", LogType.Error, ex.ToString()); + } + } public bool Trigger(ResourceTrigger trigger) { @@ -394,5 +434,16 @@ namespace Esiur.Net.Sockets return reply; } + + public void Hold() + { + held = true; + } + + public void Unhold() + { + DataSent(null); + held = false; + } } } \ No newline at end of file diff --git a/Esiur/Net/Sockets/WSSocket.cs b/Esiur/Net/Sockets/WSSocket.cs index b462a7c..c4ae409 100644 --- a/Esiur/Net/Sockets/WSSocket.cs +++ b/Esiur/Net/Sockets/WSSocket.cs @@ -44,7 +44,10 @@ namespace Esiur.Net.Sockets ISocket sock; NetworkBuffer receiveNetworkBuffer = new NetworkBuffer(); + NetworkBuffer sendNetworkBuffer = new NetworkBuffer(); + object sendLock = new object(); + bool held; public event ISocketReceiveEvent OnReceive; public event ISocketConnectEvent OnConnect; @@ -206,12 +209,19 @@ namespace Esiur.Net.Sockets { lock(sendLock) { - totalSent += message.Length; - //Console.WriteLine("TX " + message.Length +"/"+totalSent);// + " " + DC.ToHex(message, 0, (uint)size)); + 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); + pkt_send.Message = message; + if (pkt_send.Compose()) + sock.Send(pkt_send.Data); + } } } @@ -220,13 +230,20 @@ namespace Esiur.Net.Sockets { lock (sendLock) { - totalSent += size; - //Console.WriteLine("TX " + size + "/"+totalSent);// + " " + DC.ToHex(message, 0, (uint)size)); + 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); + pkt_send.Message = new byte[size]; + Buffer.BlockCopy(message, offset, pkt_send.Message, 0, size); + if (pkt_send.Compose()) + sock.Send(pkt_send.Data); + } } } @@ -262,5 +279,35 @@ namespace Esiur.Net.Sockets { 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); + + + + } + } } } \ No newline at end of file diff --git a/Esiur/Proxy/ResourceProxy.cs b/Esiur/Proxy/ResourceProxy.cs index 050aff0..095e443 100644 --- a/Esiur/Proxy/ResourceProxy.cs +++ b/Esiur/Proxy/ResourceProxy.cs @@ -12,6 +12,7 @@ namespace Esiur.Proxy { static Dictionary cache = new Dictionary(); + #if NETSTANDARD static MethodInfo modifyMethod = typeof(Instance).GetTypeInfo().GetMethod("Modified"); static MethodInfo instanceGet = typeof(IResource).GetTypeInfo().GetProperty("Instance").GetGetMethod(); @@ -74,7 +75,7 @@ namespace Esiur.Proxy TypeAttributes.Public | TypeAttributes.Class, type); foreach (PropertyInfo propertyInfo in props) - CreateProperty(propertyInfo, typeBuilder); + CreateProperty(propertyInfo, typeBuilder, type); @@ -98,7 +99,8 @@ namespace Esiur.Proxy - private static void CreateProperty(PropertyInfo pi, TypeBuilder typeBuilder) + //private static void C + private static void CreateProperty(PropertyInfo pi, TypeBuilder typeBuilder, Type resourceType) { var propertyBuilder = typeBuilder.DefineProperty(pi.Name, PropertyAttributes.None, pi.PropertyType, null); @@ -108,24 +110,51 @@ namespace Esiur.Proxy builder.DefineParameter(1, ParameterAttributes.None, "value"); ILGenerator g = builder.GetILGenerator(); + var getInstance = resourceType.GetTypeInfo().GetProperty("Instance").GetGetMethod(); + + g.Emit(OpCodes.Nop); + g.Emit(OpCodes.Ldarg_0); + g.Emit(OpCodes.Call, getInstance); + g.Emit(OpCodes.Ldstr, pi.Name); + g.Emit(OpCodes.Callvirt, modifyMethod); + + g.Emit(OpCodes.Nop); + g.Emit(OpCodes.Ldarg_0); + g.Emit(OpCodes.Ldarg_1); + g.Emit(OpCodes.Call, pi.GetSetMethod()); + g.Emit(OpCodes.Nop); + g.Emit(OpCodes.Ret); + propertyBuilder.SetSetMethod(builder); + + + // builder = typeBuilder.DefineMethod("get_" + pi.Name, MethodAttributes.Public | MethodAttributes.Virtual, pi.PropertyType, null); + // g = builder.GetILGenerator(); + // g.Emit(OpCodes.Ldarg_0); + // g.Emit(OpCodes.Call, pi.GetGetMethod()); + // g.Emit(OpCodes.Ret); + + // propertyBuilder.SetGetMethod(builder); + + + /* Label callModified = g.DefineLabel(); Label exitMethod = g.DefineLabel(); - /* - IL_0000: ldarg.0 - IL_0001: call instance class [Esiur]Esiur.Resource.Instance [Esiur]Esiur.Resource.Resource::get_Instance() - // (no C# code) - IL_0006: dup - IL_0007: brtrue.s IL_000c - IL_0009: pop - // } - IL_000a: br.s IL_0017 - // (no C# code) - IL_000c: ldstr "Level3" - IL_0011: call instance void [Esiur]Esiur.Resource.Instance::Modified(string) - IL_0016: nop - IL_0017: ret - */ + + // IL_0000: ldarg.0 + //IL_0001: call instance class [Esiur]Esiur.Resource.Instance [Esiur]Esiur.Resource.Resource::get_Instance() + //// (no C# code) + //IL_0006: dup + //IL_0007: brtrue.s IL_000c + //IL_0009: pop + //// } + //IL_000a: br.s IL_0017 + //// (no C# code) + //IL_000c: ldstr "Level3" + //IL_0011: call instance void [Esiur]Esiur.Resource.Instance::Modified(string) + //IL_0016: nop + //IL_0017: ret + // Add IL code for set method g.Emit(OpCodes.Nop); @@ -133,13 +162,13 @@ namespace Esiur.Proxy g.Emit(OpCodes.Ldarg_1); g.Emit(OpCodes.Call, pi.GetSetMethod()); - /* - IL_0000: ldarg.0 - IL_0001: call instance class [Esiur]Esiur.Resource.Instance [Esiur]Esiur.Resource.Resource::get_Instance() - IL_0006: ldstr "Level3" - IL_000b: callvirt instance void [Esiur]Esiur.Resource.Instance::Modified(string) - IL_0010: ret - */ + + // IL_0000: ldarg.0 + // IL_0001: call instance class [Esiur]Esiur.Resource.Instance [Esiur]Esiur.Resource.Resource::get_Instance() + // IL_0006: ldstr "Level3" + //IL_000b: callvirt instance void [Esiur]Esiur.Resource.Instance::Modified(string) + //IL_0010: ret + // Call property changed for object g.Emit(OpCodes.Nop); @@ -158,6 +187,11 @@ namespace Esiur.Proxy g.MarkLabel(exitMethod); g.Emit(OpCodes.Ret); propertyBuilder.SetSetMethod(builder); + + + // create get method + + */ } } diff --git a/Esiur/Resource/Instance.cs b/Esiur/Resource/Instance.cs index f4cd329..28391e9 100644 --- a/Esiur/Resource/Instance.cs +++ b/Esiur/Resource/Instance.cs @@ -388,12 +388,15 @@ namespace Esiur.Resource #endif */ - IResource res; - if (resource.TryGetTarget(out res)) - { - var rt = pt.Info.GetValue(res, null); - props.Add(new PropertyValue(rt, ages[pt.Index], modificationDates[pt.Index])); - } + //if (pt.Serilize) + //{ + IResource res; + if (resource.TryGetTarget(out res)) + { + var rt = pt.Serilize ? pt.Info.GetValue(res, null) : null; + props.Add(new PropertyValue(rt, ages[pt.Index], modificationDates[pt.Index])); + } + //} } return props.ToArray(); diff --git a/Esiur/Resource/ResourceProperty.cs b/Esiur/Resource/ResourceProperty.cs index 82fb3f4..3234025 100644 --- a/Esiur/Resource/ResourceProperty.cs +++ b/Esiur/Resource/ResourceProperty.cs @@ -35,6 +35,7 @@ namespace Esiur.Resource [AttributeUsage(AttributeTargets.Property)] public class ResourceProperty : System.Attribute { + bool serialize; string readExpansion; string writeExpansion; // bool recordable; @@ -47,6 +48,8 @@ namespace Esiur.Resource public StorageMode Storage => storage; + public bool Serialize => serialize; + public string ReadExpansion { get @@ -63,11 +66,12 @@ namespace Esiur.Resource } } - public ResourceProperty(StorageMode storage = StorageMode.NonVolatile, string readExpansion = null, string writeExpansion = null) + public ResourceProperty(StorageMode storage = StorageMode.NonVolatile, bool serialize = true, string readExpansion = null, string writeExpansion = null) { this.readExpansion = readExpansion; this.writeExpansion = writeExpansion; this.storage = storage; + this.serialize = serialize; } } } diff --git a/Esiur/Resource/Template/PropertyTemplate.cs b/Esiur/Resource/Template/PropertyTemplate.cs index 99876c4..5fb29d8 100644 --- a/Esiur/Resource/Template/PropertyTemplate.cs +++ b/Esiur/Resource/Template/PropertyTemplate.cs @@ -24,6 +24,10 @@ namespace Esiur.Resource.Template set; } + public bool Serilize + { + get;set; + } //bool ReadOnly; //IIPTypes::DataType ReturnType; public PropertyPermission Permission { diff --git a/Esiur/Resource/Template/ResourceTemplate.cs b/Esiur/Resource/Template/ResourceTemplate.cs index 6b7e1f1..e105fab 100644 --- a/Esiur/Resource/Template/ResourceTemplate.cs +++ b/Esiur/Resource/Template/ResourceTemplate.cs @@ -161,6 +161,7 @@ namespace Esiur.Resource.Template { var pt = new PropertyTemplate(this, i++, pi.Name, ps[0].ReadExpansion, ps[0].WriteExpansion, ps[0].Storage); pt.Info = pi; + pt.Serilize = ps[0].Serialize; properties.Add(pt); } } diff --git a/Esiur/Resource/Warehouse.cs b/Esiur/Resource/Warehouse.cs index 4275553..25f1eea 100644 --- a/Esiur/Resource/Warehouse.cs +++ b/Esiur/Resource/Warehouse.cs @@ -84,7 +84,7 @@ namespace Esiur.Resource /// /// Instance Id /// - public static AsyncReply Get(uint id) + public static AsyncReply GetById(uint id) { if (resources.ContainsKey(id)) { @@ -317,9 +317,6 @@ namespace Esiur.Resource /// Resource instance. public static AsyncReply Get(string path, object attributes = null, IResource parent = null, IPermissionsManager manager = null) { - - - var rt = new AsyncReply(); // Should we create a new store ? @@ -528,7 +525,7 @@ namespace Esiur.Resource var toBeRemoved = resources.Values.Where(x => { IResource r; return x.TryGetTarget(out r) && r.Instance.Store == resource; - }); + }).ToArray(); foreach (var o in toBeRemoved) {