2
0
mirror of https://github.com/esiur/esiur-dotnet.git synced 2025-05-06 19:42:58 +00:00

GC bug fix

This commit is contained in:
Ahmed Zamil 2019-11-20 13:19:31 +03:00
parent 76bcd821b5
commit 7de6354857
22 changed files with 442 additions and 236 deletions

View File

@ -57,7 +57,7 @@ namespace Esiur.Core
//public Timer timeout;// = new Timer() //public Timer timeout;// = new Timer()
protected bool resultReady = false; protected bool resultReady = false;
AsyncException exception; AsyncException exception;
StackTrace trace; // StackTrace trace;
AutoResetEvent mutex = new AutoResetEvent(false); AutoResetEvent mutex = new AutoResetEvent(false);
public static int MaxId; public static int MaxId;
@ -103,7 +103,7 @@ namespace Esiur.Core
//{ //{
lock (asyncLock) lock (asyncLock)
{ {
trace = new StackTrace(); // trace = new StackTrace();
if (resultReady) if (resultReady)
{ {

View File

@ -546,7 +546,7 @@ namespace Esiur.Data
/// <returns>Resource</returns> /// <returns>Resource</returns>
public static AsyncReply<IResource> ParseResource(byte[] data, uint offset) public static AsyncReply<IResource> ParseResource(byte[] data, uint offset)
{ {
return Warehouse.Get(data.GetUInt32(offset)); return Warehouse.GetById(data.GetUInt32(offset));
} }
/// <summary> /// <summary>
@ -703,7 +703,7 @@ namespace Esiur.Data
previous = new AsyncReply<IResource>(null); previous = new AsyncReply<IResource>(null);
else if (result == ResourceComparisonResult.Local) else if (result == ResourceComparisonResult.Local)
{ {
previous = Warehouse.Get(data.GetUInt32(offset)); previous = Warehouse.GetById(data.GetUInt32(offset));
offset += 4; offset += 4;
} }
else if (result == ResourceComparisonResult.Distributed) else if (result == ResourceComparisonResult.Distributed)
@ -731,7 +731,7 @@ namespace Esiur.Data
} }
else if (result == ResourceComparisonResult.Local) else if (result == ResourceComparisonResult.Local)
{ {
current = Warehouse.Get(data.GetUInt32(offset)); current = Warehouse.GetById(data.GetUInt32(offset));
offset += 4; offset += 4;
} }
else if (result == ResourceComparisonResult.Distributed) else if (result == ResourceComparisonResult.Distributed)

View File

@ -89,7 +89,7 @@ namespace Esiur.Data
{ {
var key = Key.ToLower(); 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) foreach (var item in toRemove)
m_Variables.Remove(item); m_Variables.Remove(item);

View File

@ -7,7 +7,7 @@
<PackageLicenseUrl>https://github.com/esiur/esiur-dotnet/blob/master/LICENSE</PackageLicenseUrl> <PackageLicenseUrl>https://github.com/esiur/esiur-dotnet/blob/master/LICENSE</PackageLicenseUrl>
<PackageProjectUrl>http://www.esiur.com</PackageProjectUrl> <PackageProjectUrl>http://www.esiur.com</PackageProjectUrl>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild> <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Version>1.4.0</Version> <Version>1.4.1</Version>
<RepositoryUrl>https://github.com/esiur/esiur-dotnet</RepositoryUrl> <RepositoryUrl>https://github.com/esiur/esiur-dotnet</RepositoryUrl>
<Authors>Ahmed Kh. Zamil</Authors> <Authors>Ahmed Kh. Zamil</Authors>
<AssemblyVersion>1.3.1.0</AssemblyVersion> <AssemblyVersion>1.3.1.0</AssemblyVersion>

View File

@ -39,59 +39,25 @@ using System.Security.Cryptography;
namespace Esiur.Net.HTTP namespace Esiur.Net.HTTP
{ {
//[Serializable]
public class HTTPConnection : NetworkConnection public class HTTPConnection : NetworkConnection
{ {
/*
public enum SendOptions : int
{
AllCalculateLength,
AllDontCalculateLength,
SpecifiedHeadersOnly,
DataOnly
}
*/
public HTTPConnection()
{
Response = new HTTPResponsePacket();
variables = new KeyList<string, object>();
}
public void SetParent(HTTPServer Parent) public void SetParent(HTTPServer Parent)
{ {
Server = Parent; Server = Parent;
} }
//public bool HeadersSent; public bool WSMode { get; internal set; }
private KeyList<string, object> variables;
private bool Busy = false;
private DateTime RequestTime = DateTime.MinValue;
public bool WSMode;
private HTTPServer Server; private HTTPServer Server;
public WebsocketPacket WSRequest; public WebsocketPacket WSRequest { get; set; }
public HTTPRequestPacket Request; public HTTPRequestPacket Request { get; set; }
public HTTPResponsePacket Response; public HTTPResponsePacket Response { get; } = new HTTPResponsePacket();
HTTPSession session; HTTPSession session;
public KeyList<string, object> Variables public KeyList<string, object> Variables { get; } = new KeyList<string, object>();
{
get
{
return variables;
}
}
public bool IsBusy()
{
return Busy;
}
internal long Parse(byte[] data) internal long Parse(byte[] data)
{ {
@ -115,7 +81,7 @@ namespace Esiur.Net.HTTP
} }
else else
{ {
HTTPRequestPacket rp = new HTTPRequestPacket(); var rp = new HTTPRequestPacket();
var pSize = rp.Parse(data, 0, (uint)data.Length); var pSize = rp.Parse(data, 0, (uint)data.Length);
if (pSize > 0) 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() public void Flush()
{ {
// close the connection // close the connection
@ -171,21 +112,18 @@ namespace Esiur.Net.HTTP
// Compute the SHA1 hash // Compute the SHA1 hash
SHA1 sha = SHA1.Create(); SHA1 sha = SHA1.Create();
byte[] sha1Hash = sha.ComputeHash(Encoding.UTF8.GetBytes(ret)); 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["Connection"] = Request.Headers["Connection"];// "Upgrade";
Response.Headers["Sec-WebSocket-Accept"] = Convert.ToBase64String(sha1Hash); Response.Headers["Sec-WebSocket-Accept"] = Convert.ToBase64String(sha1Hash);
if (Request.Headers.ContainsKey("Sec-WebSocket-Protocol")) 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["Sec-WebSocket-Protocol"] = Request.Headers["Sec-WebSocket-Protocol"];
//Response.Headers["Origin"] = Request.Headers["Origin"];
Response.Number = HTTPResponsePacket.ResponseCode.HTTP_SWITCHING; Response.Number = HTTPResponsePacket.ResponseCode.HTTP_SWITCHING;
Response.Text = "Switching Protocols"; Response.Text = "Switching Protocols";
WSMode = true; WSMode = true;
//Send((byte[])null, SendOptions.AllDontCalculateLength);
Send(); Send();
return true; return true;
@ -208,6 +146,12 @@ namespace Esiur.Net.HTTP
Send(); 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) public override void Send(byte[] message)
{ {
Response.Message = message; Response.Message = message;
@ -219,7 +163,6 @@ namespace Esiur.Net.HTTP
if (Response.Handled) if (Response.Handled)
return; return;
Busy = true;
try try
{ {
@ -235,13 +178,13 @@ namespace Esiur.Net.HTTP
{ {
try try
{ {
Close();// Server.CloseClient(Connection); Close();
} }
finally { } finally { }
} }
finally finally
{ {
Busy = false;
} }
} }
@ -272,7 +215,7 @@ namespace Esiur.Net.HTTP
&& Request.Headers.ContainsKey("Sec-WebSocket-Version") && Request.Headers.ContainsKey("Sec-WebSocket-Version")
&& Request.Headers["Sec-WebSocket-Version"] == "13" && Request.Headers["Sec-WebSocket-Version"] == "13"
&& Request.Headers.ContainsKey("Sec-WebSocket-Key")) && Request.Headers.ContainsKey("Sec-WebSocket-Key"))
//&& Request.Headers.ContainsKey("Sec-WebSocket-Protocol")) //&& Request.Headers.ContainsKey("Sec-WebSocket-Protocol"))
{ {
return true; return true;
} }
@ -282,11 +225,14 @@ namespace Esiur.Net.HTTP
} }
} }
bool bb;
public void SendFile(string filename) public void SendFile(string filename)
{ {
if (Response.Handled == true) if (Response.Handled == true)
return; return;
try try
{ {
@ -302,22 +248,22 @@ namespace Esiur.Net.HTTP
if (!File.Exists(filename)) if (!File.Exists(filename))
{ {
Response.Number = HTTPResponsePacket.ResponseCode.HTTP_NOTFOUND; Response.Number = HTTPResponsePacket.ResponseCode.HTTP_NOTFOUND;
Send("File Not Found");//, SendOptions.AllCalculateLength); Send("File Not Found");
return; return;
} }
Busy = true;
System.DateTime FWD = File.GetLastWriteTime(filename); var fileEditTime = File.GetLastWriteTime(filename).ToUniversalTime();
if (Request.Headers.ContainsKey("if-modified-since"))// != DateTime.Parse("12:00:00 AM")) if (Request.Headers.ContainsKey("if-modified-since"))
{ {
try try
{ {
DateTime IMS = DateTime.Parse(Request.Headers["if-modified-since"]); var ims = DateTime.Parse(Request.Headers["if-modified-since"]);
if (FWD <= IMS) if (Math.Abs((fileEditTime - ims).TotalSeconds) < 0)
{ {
Response.Number = HTTPResponsePacket.ResponseCode.HTTP_NOTMODIFIED; Response.Number = HTTPResponsePacket.ResponseCode.HTTP_NOTMODIFIED;
Response.Text = "Not Modified"; Response.Text = "Not Modified";
Send((byte[])null);
} }
} }
catch 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);
} var buffer = new byte[5000];
else
{
// Fri, 30 Oct 2007 14:19:41 GMT while (true)
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]; var n = fs.Read(buffer, 0, 5000);
var offset = 0;
while (offset < fs.Length) if (n <= 0)
{ break;
var n = fs.Read(buffer, offset, buffer.Length);
offset += n;
base.Send(buffer); base.Send(buffer, 0, n);
}
} }
} }
Busy = false;
return;
} }
catch catch
{ {
Busy = false;
try try
{ {
Close(); Close();

View File

@ -192,17 +192,9 @@ namespace Esiur.Net.HTTP
protected override void DataReceived(HTTPConnection sender, NetworkBuffer data) 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(); byte[] msg = data.Read();
var BL = sender.Parse(msg); var BL = sender.Parse(msg);
if (BL == 0) if (BL == 0)
@ -265,7 +257,8 @@ namespace Esiur.Net.HTTP
try try
{ {
foreach (var resource in filters) foreach (var resource in filters)
resource.Execute(sender); if (resource.Execute(sender))
return;
sender.Send("Bad Request"); sender.Send("Bad Request");

View File

@ -62,6 +62,9 @@ namespace Esiur.Net.IIP
Session session; Session session;
List<IResource> attachedResources = new List<IResource>();
AsyncReply<bool> openReply; AsyncReply<bool> openReply;
byte[] localPassword; byte[] localPassword;
@ -304,7 +307,7 @@ namespace Esiur.Net.IIP
private uint processPacket(byte[] msg, uint offset, uint ends, NetworkBuffer data, int chunkId) 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 chunkId = (new Random()).Next(1000, 1000000);
var list = new List<Structure>();// double, IIPPacketCommand>();
this.Socket.Hold();
while (offset < ends) while (offset < ends)
{ {
offset = processPacket(msg, offset, ends, data, chunkId); offset = processPacket(msg, offset, ends, data, chunkId);
} }
} this.Socket.Unhold();
}
/// <summary> /// <summary>
/// Resource interface /// Resource interface

View File

@ -433,7 +433,7 @@ namespace Esiur.Net.IIP
void IIPRequestAttachResource(uint callback, uint resourceId) void IIPRequestAttachResource(uint callback, uint resourceId)
{ {
Warehouse.Get(resourceId).Then((res) => Warehouse.GetById(resourceId).Then((res) =>
{ {
if (res != null) if (res != null)
{ {
@ -461,6 +461,9 @@ namespace Esiur.Net.IIP
//r.Instance.Children.OnRemoved += Children_OnRemoved; //r.Instance.Children.OnRemoved += Children_OnRemoved;
r.Instance.Attributes.OnModified += Attributes_OnModified; 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); var link = DC.ToBytes(r.Instance.Link);
if (r is DistributedResource) if (r is DistributedResource)
@ -550,7 +553,7 @@ namespace Esiur.Net.IIP
void IIPRequestReattachResource(uint callback, uint resourceId, ulong resourceAge) void IIPRequestReattachResource(uint callback, uint resourceId, ulong resourceAge)
{ {
Warehouse.Get(resourceId).Then((res) => Warehouse.GetById(resourceId).Then((res) =>
{ {
if (res != null) if (res != null)
{ {
@ -587,7 +590,7 @@ namespace Esiur.Net.IIP
void IIPRequestDetachResource(uint callback, uint resourceId) void IIPRequestDetachResource(uint callback, uint resourceId)
{ {
Warehouse.Get(resourceId).Then((res) => Warehouse.GetById(resourceId).Then((res) =>
{ {
if (res != null) if (res != null)
{ {
@ -595,6 +598,10 @@ namespace Esiur.Net.IIP
r.Instance.ResourceEventOccurred -= Instance_EventOccurred; r.Instance.ResourceEventOccurred -= Instance_EventOccurred;
r.Instance.ResourceModified -= Instance_PropertyModified; r.Instance.ResourceModified -= Instance_PropertyModified;
r.Instance.ResourceDestroyed -= Instance_ResourceDestroyed; r.Instance.ResourceDestroyed -= Instance_ResourceDestroyed;
// remove from attached resources
attachedResources.Remove(res);
// reply ok // reply ok
SendReply(IIPPacket.IIPPacketAction.DetachResource, callback).Done(); SendReply(IIPPacket.IIPPacketAction.DetachResource, callback).Done();
} }
@ -609,7 +616,7 @@ namespace Esiur.Net.IIP
void IIPRequestCreateResource(uint callback, uint storeId, uint parentId, byte[] content) void IIPRequestCreateResource(uint callback, uint storeId, uint parentId, byte[] content)
{ {
Warehouse.Get(storeId).Then(store => Warehouse.GetById(storeId).Then(store =>
{ {
if (store == null) if (store == null)
{ {
@ -630,7 +637,7 @@ namespace Esiur.Net.IIP
return; return;
} }
Warehouse.Get(parentId).Then(parent => Warehouse.GetById(parentId).Then(parent =>
{ {
// check security // check security
@ -733,7 +740,7 @@ namespace Esiur.Net.IIP
void IIPRequestDeleteResource(uint callback, uint resourceId) void IIPRequestDeleteResource(uint callback, uint resourceId)
{ {
Warehouse.Get(resourceId).Then(r => Warehouse.GetById(resourceId).Then(r =>
{ {
if (r == null) if (r == null)
{ {
@ -757,7 +764,7 @@ namespace Esiur.Net.IIP
void IIPRequestGetAttributes(uint callback, uint resourceId, byte[] attributes, bool all = false) void IIPRequestGetAttributes(uint callback, uint resourceId, byte[] attributes, bool all = false)
{ {
Warehouse.Get(resourceId).Then(r => Warehouse.GetById(resourceId).Then(r =>
{ {
if (r == null) if (r == null)
{ {
@ -791,7 +798,7 @@ namespace Esiur.Net.IIP
void IIPRequestAddChild(uint callback, uint parentId, uint childId) void IIPRequestAddChild(uint callback, uint parentId, uint childId)
{ {
Warehouse.Get(parentId).Then(parent => Warehouse.GetById(parentId).Then(parent =>
{ {
if (parent == null) if (parent == null)
{ {
@ -799,7 +806,7 @@ namespace Esiur.Net.IIP
return; return;
} }
Warehouse.Get(childId).Then(child => Warehouse.GetById(childId).Then(child =>
{ {
if (child == null) if (child == null)
{ {
@ -830,7 +837,7 @@ namespace Esiur.Net.IIP
void IIPRequestRemoveChild(uint callback, uint parentId, uint childId) void IIPRequestRemoveChild(uint callback, uint parentId, uint childId)
{ {
Warehouse.Get(parentId).Then(parent => Warehouse.GetById(parentId).Then(parent =>
{ {
if (parent == null) if (parent == null)
{ {
@ -838,7 +845,7 @@ namespace Esiur.Net.IIP
return; return;
} }
Warehouse.Get(childId).Then(child => Warehouse.GetById(childId).Then(child =>
{ {
if (child == null) if (child == null)
{ {
@ -869,7 +876,7 @@ namespace Esiur.Net.IIP
void IIPRequestRenameResource(uint callback, uint resourceId, byte[] name) void IIPRequestRenameResource(uint callback, uint resourceId, byte[] name)
{ {
Warehouse.Get(resourceId).Then(resource => Warehouse.GetById(resourceId).Then(resource =>
{ {
if (resource == null) if (resource == null)
{ {
@ -891,7 +898,7 @@ namespace Esiur.Net.IIP
void IIPRequestResourceChildren(uint callback, uint resourceId) void IIPRequestResourceChildren(uint callback, uint resourceId)
{ {
Warehouse.Get(resourceId).Then(resource => Warehouse.GetById(resourceId).Then(resource =>
{ {
if (resource == null) if (resource == null)
{ {
@ -913,7 +920,7 @@ namespace Esiur.Net.IIP
void IIPRequestResourceParents(uint callback, uint resourceId) void IIPRequestResourceParents(uint callback, uint resourceId)
{ {
Warehouse.Get(resourceId).Then(resource => Warehouse.GetById(resourceId).Then(resource =>
{ {
if (resource == null) if (resource == null)
{ {
@ -934,7 +941,7 @@ namespace Esiur.Net.IIP
void IIPRequestClearAttributes(uint callback, uint resourceId, byte[] attributes, bool all = false) void IIPRequestClearAttributes(uint callback, uint resourceId, byte[] attributes, bool all = false)
{ {
Warehouse.Get(resourceId).Then(r => Warehouse.GetById(resourceId).Then(r =>
{ {
if (r == null) if (r == null)
{ {
@ -963,7 +970,7 @@ namespace Esiur.Net.IIP
void IIPRequestUpdateAttributes(uint callback, uint resourceId, byte[] attributes, bool clearAttributes = false) void IIPRequestUpdateAttributes(uint callback, uint resourceId, byte[] attributes, bool clearAttributes = false)
{ {
Warehouse.Get(resourceId).Then(r => Warehouse.GetById(resourceId).Then(r =>
{ {
if (r == null) if (r == null)
{ {
@ -1028,7 +1035,7 @@ namespace Esiur.Net.IIP
void IIPRequestTemplateFromResourceId(uint callback, uint resourceId) void IIPRequestTemplateFromResourceId(uint callback, uint resourceId)
{ {
Warehouse.Get(resourceId).Then((r) => Warehouse.GetById(resourceId).Then((r) =>
{ {
if (r != null) if (r != null)
SendReply(IIPPacket.IIPPacketAction.TemplateFromResourceId, callback) SendReply(IIPPacket.IIPPacketAction.TemplateFromResourceId, callback)
@ -1078,7 +1085,7 @@ namespace Esiur.Net.IIP
{ {
//Console.WriteLine("IIPRequestInvokeFunction " + callback + " " + resourceId + " " + index); //Console.WriteLine("IIPRequestInvokeFunction " + callback + " " + resourceId + " " + index);
Warehouse.Get(resourceId).Then((r) => Warehouse.GetById(resourceId).Then((r) =>
{ {
if (r != null) if (r != null)
{ {
@ -1235,7 +1242,7 @@ namespace Esiur.Net.IIP
void IIPRequestInvokeFunctionNamedArguments(uint callback, uint resourceId, byte index, byte[] content) void IIPRequestInvokeFunctionNamedArguments(uint callback, uint resourceId, byte index, byte[] content)
{ {
Warehouse.Get(resourceId).Then((r) => Warehouse.GetById(resourceId).Then((r) =>
{ {
if (r != null) if (r != null)
{ {
@ -1382,7 +1389,7 @@ namespace Esiur.Net.IIP
void IIPRequestGetProperty(uint callback, uint resourceId, byte index) void IIPRequestGetProperty(uint callback, uint resourceId, byte index)
{ {
Warehouse.Get(resourceId).Then((r) => Warehouse.GetById(resourceId).Then((r) =>
{ {
if (r != null) if (r != null)
{ {
@ -1429,7 +1436,7 @@ namespace Esiur.Net.IIP
void IIPRequestInquireResourceHistory(uint callback, uint resourceId, DateTime fromDate, DateTime toDate) void IIPRequestInquireResourceHistory(uint callback, uint resourceId, DateTime fromDate, DateTime toDate)
{ {
Warehouse.Get(resourceId).Then((r) => Warehouse.GetById(resourceId).Then((r) =>
{ {
if (r != null) if (r != null)
{ {
@ -1465,7 +1472,7 @@ namespace Esiur.Net.IIP
void IIPRequestGetPropertyIfModifiedSince(uint callback, uint resourceId, byte index, ulong age) void IIPRequestGetPropertyIfModifiedSince(uint callback, uint resourceId, byte index, ulong age)
{ {
Warehouse.Get(resourceId).Then((r) => Warehouse.GetById(resourceId).Then((r) =>
{ {
if (r != null) if (r != null)
{ {
@ -1511,7 +1518,7 @@ namespace Esiur.Net.IIP
void IIPRequestSetProperty(uint callback, uint resourceId, byte index, byte[] content) void IIPRequestSetProperty(uint callback, uint resourceId, byte index, byte[] content)
{ {
Warehouse.Get(resourceId).Then((r) => Warehouse.GetById(resourceId).Then((r) =>
{ {
if (r != null) if (r != null)
{ {

View File

@ -259,25 +259,33 @@ namespace Esiur.Net
public virtual void Send(byte[] msg) public virtual void Send(byte[] msg)
{ {
//Console.WriteLine("TXX " + msg.Length);
try try
{ {
//if (!connected)
//{
//Console.WriteLine("not connected");
// return;
//}
if (sock != null) if (sock != null)
{ {
lastAction = DateTime.Now; lastAction = DateTime.Now;
sock.Send(msg); 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
{
} }
} }

View File

@ -150,6 +150,12 @@ namespace Esiur.Net.Packets
set; set;
} }
public bool Bulk
{
get;
set;
}
public IIPPacketEvent Event public IIPPacketEvent Event
{ {
get; 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 ResourceId { get; set; }
public uint NewResourceId { get; set; } public uint NewResourceId { get; set; }
//public uint ParentId { get; set; } //public uint ParentId { get; set; }
@ -249,11 +262,11 @@ namespace Esiur.Net.Packets
CallbackId = data.GetUInt32(offset); CallbackId = data.GetUInt32(offset);
offset += 4; offset += 4;
} }
else else // response or reply
{ {
PreviousAction = Action; PreviousAction = Action;
Action = (IIPPacketAction)(data[offset++] & 0x3f); Action = (IIPPacketAction)(data[offset] & 0x1f);
Bulk = (data[offset++] & 0x20) == 0x20;
if (NotEnough(offset, ends, 4)) if (NotEnough(offset, ends, 4))
return -dataLengthNeeded; return -dataLengthNeeded;
@ -371,8 +384,21 @@ namespace Esiur.Net.Packets
if (NotEnough(offset, ends, 4)) if (NotEnough(offset, ends, 4))
return -dataLengthNeeded; return -dataLengthNeeded;
ResourceId = data.GetUInt32(offset); if (Bulk)
offset += 4; {
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) else if (Action == IIPPacketAction.ReattachResource)
{ {
@ -628,35 +654,74 @@ namespace Esiur.Net.Packets
|| Action == IIPPacketAction.ReattachResource) || Action == IIPPacketAction.ReattachResource)
{ {
if (NotEnough(offset, ends, 26)) if (Bulk)
return -dataLengthNeeded; {
if (NotEnough(offset, ends, 26))
return -dataLengthNeeded;
ClassId = data.GetGuid(offset); ClassId = data.GetGuid(offset);
offset += 16; offset += 16;
ResourceAge = data.GetUInt64(offset); ResourceAge = data.GetUInt64(offset);
offset += 8; offset += 8;
uint cl = data.GetUInt16(offset); uint cl = data.GetUInt16(offset);
offset += 2; offset += 2;
if (NotEnough(offset, ends, cl)) if (NotEnough(offset, ends, cl))
return -dataLengthNeeded; return -dataLengthNeeded;
ResourceLink = data.GetString(offset, cl); ResourceLink = data.GetString(offset, cl);
offset += cl; offset += cl;
if (NotEnough(offset, ends, 4)) if (NotEnough(offset, ends, 4))
return -dataLengthNeeded; return -dataLengthNeeded;
cl = data.GetUInt32(offset); cl = data.GetUInt32(offset);
offset += 4; offset += 4;
if (NotEnough(offset, ends, cl)) if (NotEnough(offset, ends, cl))
return -dataLengthNeeded; return -dataLengthNeeded;
Content = data.Clip(offset, cl); Content = data.Clip(offset, cl);
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<IIPPacketAttachInfo>();
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) else if (Action == IIPPacketAction.DetachResource)
{ {

View File

@ -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;
}
}
}

View File

@ -59,5 +59,9 @@ namespace Esiur.Net.Sockets
AsyncReply<ISocket> Accept(); AsyncReply<ISocket> Accept();
IPEndPoint RemoteEndPoint { get; } IPEndPoint RemoteEndPoint { get; }
IPEndPoint LocalEndPoint { get; } IPEndPoint LocalEndPoint { get; }
void Hold();
void Unhold();
} }
} }

View File

@ -339,5 +339,15 @@ namespace Esiur.Net.Sockets
return reply; return reply;
} }
public void Hold()
{
throw new NotImplementedException();
}
public void Unhold()
{
throw new NotImplementedException();
}
} }
} }

View File

@ -42,6 +42,8 @@ namespace Esiur.Net.Sockets
Socket sock; Socket sock;
byte[] receiveBuffer; byte[] receiveBuffer;
bool held;
ArraySegment<byte> receiveBufferSegment; ArraySegment<byte> receiveBufferSegment;
NetworkBuffer receiveNetworkBuffer = new NetworkBuffer(); NetworkBuffer receiveNetworkBuffer = new NetworkBuffer();
@ -241,9 +243,12 @@ namespace Esiur.Net.Sockets
if (sendBufferQueue.Count > 0) if (sendBufferQueue.Count > 0)
{ {
byte[] data = sendBufferQueue.Dequeue();
lock (sendLock) lock (sendLock)
{
byte[] data = sendBufferQueue.Dequeue();
//Console.WriteLine(Encoding.UTF8.GetString(data));
sock.SendAsync(new ArraySegment<byte>(data), SocketFlags.None).ContinueWith(DataSent); sock.SendAsync(new ArraySegment<byte>(data), SocketFlags.None).ContinueWith(DataSent);
}
} }
else else
{ {
@ -340,22 +345,57 @@ namespace Esiur.Net.Sockets
public void Send(byte[] message, int offset, int size) public void Send(byte[] message, int offset, int size)
{ {
//sock.Blocking =
//sock.Send(message, offset, size, SocketFlags.None);
//return;
if (sock.Connected) if (sock.Connected)
lock (sendLock) lock (sendLock)
{ {
if (asyncSending)
if (asyncSending || held)
{ {
sendBufferQueue.Enqueue(message.Clip((uint)offset, (uint)size)); sendBufferQueue.Enqueue(message.Clip((uint)offset, (uint)size));
} }
else else
{ {
asyncSending = true; asyncSending = true;
sock.SendAsync(new ArraySegment<byte>(message, offset, size), SocketFlags.None).ContinueWith(DataSent); sock.BeginSend(message, offset, size, SocketFlags.None, PacketSent, null);
//sock.SendAsync(new ArraySegment<byte>(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) public bool Trigger(ResourceTrigger trigger)
{ {
@ -394,5 +434,16 @@ namespace Esiur.Net.Sockets
return reply; return reply;
} }
public void Hold()
{
held = true;
}
public void Unhold()
{
DataSent(null);
held = false;
}
} }
} }

View File

@ -44,7 +44,10 @@ namespace Esiur.Net.Sockets
ISocket sock; ISocket sock;
NetworkBuffer receiveNetworkBuffer = new NetworkBuffer(); NetworkBuffer receiveNetworkBuffer = new NetworkBuffer();
NetworkBuffer sendNetworkBuffer = new NetworkBuffer();
object sendLock = new object(); object sendLock = new object();
bool held;
public event ISocketReceiveEvent OnReceive; public event ISocketReceiveEvent OnReceive;
public event ISocketConnectEvent OnConnect; public event ISocketConnectEvent OnConnect;
@ -206,12 +209,19 @@ namespace Esiur.Net.Sockets
{ {
lock(sendLock) lock(sendLock)
{ {
totalSent += message.Length; if (held)
//Console.WriteLine("TX " + message.Length +"/"+totalSent);// + " " + DC.ToHex(message, 0, (uint)size)); {
sendNetworkBuffer.Write(message);
}
else
{
totalSent += message.Length;
//Console.WriteLine("TX " + message.Length +"/"+totalSent);// + " " + DC.ToHex(message, 0, (uint)size));
pkt_send.Message = message; pkt_send.Message = message;
if (pkt_send.Compose()) if (pkt_send.Compose())
sock.Send(pkt_send.Data); sock.Send(pkt_send.Data);
}
} }
} }
@ -220,13 +230,20 @@ namespace Esiur.Net.Sockets
{ {
lock (sendLock) lock (sendLock)
{ {
totalSent += size; if (held)
//Console.WriteLine("TX " + size + "/"+totalSent);// + " " + DC.ToHex(message, 0, (uint)size)); {
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]; pkt_send.Message = new byte[size];
Buffer.BlockCopy(message, offset, pkt_send.Message, 0, size); Buffer.BlockCopy(message, offset, pkt_send.Message, 0, size);
if (pkt_send.Compose()) if (pkt_send.Compose())
sock.Send(pkt_send.Data); sock.Send(pkt_send.Data);
}
} }
} }
@ -262,5 +279,35 @@ namespace Esiur.Net.Sockets
{ {
throw new NotImplementedException(); 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);
}
}
} }
} }

View File

@ -12,6 +12,7 @@ namespace Esiur.Proxy
{ {
static Dictionary<Type, Type> cache = new Dictionary<Type, Type>(); static Dictionary<Type, Type> cache = new Dictionary<Type, Type>();
#if NETSTANDARD #if NETSTANDARD
static MethodInfo modifyMethod = typeof(Instance).GetTypeInfo().GetMethod("Modified"); static MethodInfo modifyMethod = typeof(Instance).GetTypeInfo().GetMethod("Modified");
static MethodInfo instanceGet = typeof(IResource).GetTypeInfo().GetProperty("Instance").GetGetMethod(); static MethodInfo instanceGet = typeof(IResource).GetTypeInfo().GetProperty("Instance").GetGetMethod();
@ -74,7 +75,7 @@ namespace Esiur.Proxy
TypeAttributes.Public | TypeAttributes.Class, type); TypeAttributes.Public | TypeAttributes.Class, type);
foreach (PropertyInfo propertyInfo in props) 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); var propertyBuilder = typeBuilder.DefineProperty(pi.Name, PropertyAttributes.None, pi.PropertyType, null);
@ -108,24 +110,51 @@ namespace Esiur.Proxy
builder.DefineParameter(1, ParameterAttributes.None, "value"); builder.DefineParameter(1, ParameterAttributes.None, "value");
ILGenerator g = builder.GetILGenerator(); 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 callModified = g.DefineLabel();
Label exitMethod = g.DefineLabel(); Label exitMethod = g.DefineLabel();
/*
IL_0000: ldarg.0 // IL_0000: ldarg.0
IL_0001: call instance class [Esiur]Esiur.Resource.Instance [Esiur]Esiur.Resource.Resource::get_Instance() //IL_0001: call instance class [Esiur]Esiur.Resource.Instance [Esiur]Esiur.Resource.Resource::get_Instance()
// (no C# code) //// (no C# code)
IL_0006: dup //IL_0006: dup
IL_0007: brtrue.s IL_000c //IL_0007: brtrue.s IL_000c
IL_0009: pop //IL_0009: pop
// } //// }
IL_000a: br.s IL_0017 //IL_000a: br.s IL_0017
// (no C# code) //// (no C# code)
IL_000c: ldstr "Level3" //IL_000c: ldstr "Level3"
IL_0011: call instance void [Esiur]Esiur.Resource.Instance::Modified(string) //IL_0011: call instance void [Esiur]Esiur.Resource.Instance::Modified(string)
IL_0016: nop //IL_0016: nop
IL_0017: ret //IL_0017: ret
*/
// Add IL code for set method // Add IL code for set method
g.Emit(OpCodes.Nop); g.Emit(OpCodes.Nop);
@ -133,13 +162,13 @@ namespace Esiur.Proxy
g.Emit(OpCodes.Ldarg_1); g.Emit(OpCodes.Ldarg_1);
g.Emit(OpCodes.Call, pi.GetSetMethod()); g.Emit(OpCodes.Call, pi.GetSetMethod());
/*
IL_0000: ldarg.0 // IL_0000: ldarg.0
IL_0001: call instance class [Esiur]Esiur.Resource.Instance [Esiur]Esiur.Resource.Resource::get_Instance() // IL_0001: call instance class [Esiur]Esiur.Resource.Instance [Esiur]Esiur.Resource.Resource::get_Instance()
IL_0006: ldstr "Level3" // IL_0006: ldstr "Level3"
IL_000b: callvirt instance void [Esiur]Esiur.Resource.Instance::Modified(string) //IL_000b: callvirt instance void [Esiur]Esiur.Resource.Instance::Modified(string)
IL_0010: ret //IL_0010: ret
*/
// Call property changed for object // Call property changed for object
g.Emit(OpCodes.Nop); g.Emit(OpCodes.Nop);
@ -158,6 +187,11 @@ namespace Esiur.Proxy
g.MarkLabel(exitMethod); g.MarkLabel(exitMethod);
g.Emit(OpCodes.Ret); g.Emit(OpCodes.Ret);
propertyBuilder.SetSetMethod(builder); propertyBuilder.SetSetMethod(builder);
// create get method
*/
} }
} }

View File

@ -388,12 +388,15 @@ namespace Esiur.Resource
#endif #endif
*/ */
IResource res; //if (pt.Serilize)
if (resource.TryGetTarget(out res)) //{
{ IResource res;
var rt = pt.Info.GetValue(res, null); if (resource.TryGetTarget(out res))
props.Add(new PropertyValue(rt, ages[pt.Index], modificationDates[pt.Index])); {
} var rt = pt.Serilize ? pt.Info.GetValue(res, null) : null;
props.Add(new PropertyValue(rt, ages[pt.Index], modificationDates[pt.Index]));
}
//}
} }
return props.ToArray(); return props.ToArray();

View File

@ -35,6 +35,7 @@ namespace Esiur.Resource
[AttributeUsage(AttributeTargets.Property)] [AttributeUsage(AttributeTargets.Property)]
public class ResourceProperty : System.Attribute public class ResourceProperty : System.Attribute
{ {
bool serialize;
string readExpansion; string readExpansion;
string writeExpansion; string writeExpansion;
// bool recordable; // bool recordable;
@ -47,6 +48,8 @@ namespace Esiur.Resource
public StorageMode Storage => storage; public StorageMode Storage => storage;
public bool Serialize => serialize;
public string ReadExpansion public string ReadExpansion
{ {
get 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.readExpansion = readExpansion;
this.writeExpansion = writeExpansion; this.writeExpansion = writeExpansion;
this.storage = storage; this.storage = storage;
this.serialize = serialize;
} }
} }
} }

View File

@ -24,6 +24,10 @@ namespace Esiur.Resource.Template
set; set;
} }
public bool Serilize
{
get;set;
}
//bool ReadOnly; //bool ReadOnly;
//IIPTypes::DataType ReturnType; //IIPTypes::DataType ReturnType;
public PropertyPermission Permission { public PropertyPermission Permission {

View File

@ -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); var pt = new PropertyTemplate(this, i++, pi.Name, ps[0].ReadExpansion, ps[0].WriteExpansion, ps[0].Storage);
pt.Info = pi; pt.Info = pi;
pt.Serilize = ps[0].Serialize;
properties.Add(pt); properties.Add(pt);
} }
} }

View File

@ -84,7 +84,7 @@ namespace Esiur.Resource
/// </summary> /// </summary>
/// <param name="id">Instance Id</param> /// <param name="id">Instance Id</param>
/// <returns></returns> /// <returns></returns>
public static AsyncReply<IResource> Get(uint id) public static AsyncReply<IResource> GetById(uint id)
{ {
if (resources.ContainsKey(id)) if (resources.ContainsKey(id))
{ {
@ -317,9 +317,6 @@ namespace Esiur.Resource
/// <returns>Resource instance.</returns> /// <returns>Resource instance.</returns>
public static AsyncReply<IResource> Get(string path, object attributes = null, IResource parent = null, IPermissionsManager manager = null) public static AsyncReply<IResource> Get(string path, object attributes = null, IResource parent = null, IPermissionsManager manager = null)
{ {
var rt = new AsyncReply<IResource>(); var rt = new AsyncReply<IResource>();
// Should we create a new store ? // Should we create a new store ?
@ -528,7 +525,7 @@ namespace Esiur.Resource
var toBeRemoved = resources.Values.Where(x => { var toBeRemoved = resources.Values.Where(x => {
IResource r; IResource r;
return x.TryGetTarget(out r) && r.Instance.Store == resource; return x.TryGetTarget(out r) && r.Instance.Store == resource;
}); }).ToArray();
foreach (var o in toBeRemoved) foreach (var o in toBeRemoved)
{ {