diff --git a/Application.cs b/Application.cs index 494fafe..4785c60 100644 --- a/Application.cs +++ b/Application.cs @@ -9,6 +9,8 @@ using System.Net; using ln.application.service; using ln.http.resources; using ln.types.btree; +using ln.types.rpc; +using ln.application.slots; namespace ln.application { @@ -24,8 +26,11 @@ namespace ln.application public int ApplicationContextTimeout { get; set; } = 1200; + public RPCContainer RPCContainer { get; } = new RPCContainer(); + public BinarySlotContainer BinarySlots { get; } = new BinarySlotContainer(); - MappingBTree applicationContexts = new MappingBTree((x)=>x.ContextID); + + MappingBTree applicationContexts = new MappingBTree((x)=>x.ContextID); public Application() { diff --git a/ApplicationWebSocket.cs b/ApplicationWebSocket.cs index 1ede16d..47b74ed 100644 --- a/ApplicationWebSocket.cs +++ b/ApplicationWebSocket.cs @@ -1,104 +1,147 @@ using System; -using ln.http.resources.websocket; -using ln.http.resources; using ln.http.websocket; -using System.Collections.Generic; using ln.json; using ln.logging; using ln.types.rpc; -using System.Linq; -using System.IO; +using ln.http; +using System.Collections.Generic; +using ln.application.slots; namespace ln.application { - public class ApplicationWebSocket : WebsocketResource + public class ApplicationWebSocket : WebSocket { - public WebSocket[] CurrentWebSockets + public IApplicationInterface ApplicationInterface { get; } + + Dictionary> messageConverters = new Dictionary>(); + + public ApplicationWebSocket(IApplicationInterface applicationInterface,HttpRequest httpRequest) + :base(httpRequest) { - get - { - lock (currentWebSockets) - { - return currentWebSockets.ToArray(); - } - } - } - HashSet currentWebSockets = new HashSet(); - - public RPCContainer RPCContainer { get; private set; } - - - public ApplicationWebSocket(Resource container, string name,RPCContainer rpcContainer) - :this(container,name) - { - RPCContainer = rpcContainer; + ApplicationInterface = applicationInterface; } - public ApplicationWebSocket(Resource container,string name) - :base(container,name) - { - Connection += WebSocketInterface_Connection; - } + public void AddMessageConverter(string messageType, Func converter) + { + messageConverters[messageType] = converter; + } - void WebSocketInterface_Connection(WebsocketResource webSocketResource, ln.http.websocket.WebSocket webSocket, WSREvent ev) - { - lock (currentWebSockets) - { - switch (ev) - { - case WSREvent.CONNECT: - currentWebSockets.Add(webSocket); - break; - case WSREvent.CLOSE: - case WSREvent.ERROR: - currentWebSockets.Remove(webSocket); - break; - } - } - } + public Func FindConverter(string messageType) + { + return messageConverters[messageType]; + } - public void Broadcast(JSONObject json) - { - Broadcast(json.ToString()); - } + public override bool Received(string textMessage) + { + JSONObject json = (JSONObject)JSONParser.Parse(textMessage); - public void Broadcast(String text) - { - foreach (WebSocket webSocket in CurrentWebSockets) - { - try - { - webSocket.Send(text); - } - catch (IOException) - { } + if (!json.ContainsKey("id")) + { + Logging.Log(LogLevel.WARNING, "ApplicatioNWebSocket received json message without id"); + return false; } - } - public override void MessageReceived(WebSocketResourceRequestContext requestContext, string textMessage) + long messageID = (long)json["id"].ToNative(); + + if (!json.ContainsKey("type")) + { + SendError(messageID, "type missing", "ApplicationWebSocket received message without 'type' attribute"); + return false; + } + + string messageType = json["type"].ToNative() as string; + JSONValue message = json.ContainsKey("message") ? json["message"] : JSONNull.Instance; + + return ReceivedMessage(messageID,messageType,message); + } + + public virtual bool ReceivedMessage(long messageId,string messageType,JSONValue message) + { + try + { + object convertedMessage = FindConverter(messageType)(message); + return ReceivedMessage(messageId, messageType, convertedMessage); + } catch (Exception e) + { + Logging.Log(e); + SendError(messageId, e.ToString(), e.InnerException.ToString()); + return false; + } + } + + public virtual bool ReceivedMessage(long messageId, string messageType, object message) + { + switch (messageType) + { + case "RPCCall": + SendMessage(messageId, ApplicationInterface.RPCContainer.Invoke(message as RPCCall)); + return true; + case "SlotRequest": + SlotAllocation slotAllocation = ApplicationInterface.BinarySlots.RequestSlot(message as SlotRequest); + return true; + default: + return false; + } + } + + public override bool Received(byte[] binaryMessage) + { + return base.Received(binaryMessage); + } + + public void SendMessage(long messageID, object message) + { + string messageType = message.GetType().Name; + JSONObject jsonMessage = JSONObject.From(message); + + SendMessage(messageID, messageType, jsonMessage); + } + public virtual void SendMessage(long messageID,string messageType,JSONObject message) + { + JSONObject messageFrame = new JSONObject(); + messageFrame["id"] = new JSONNumber(messageID); + messageFrame["type"] = new JSONString(messageType); + messageFrame["message"] = message; + + Send(messageFrame.ToString()); + } + + public virtual void SendError(long messageId, string error, string cause) => SendError(messageId, error, cause, null); + public virtual void SendError(long messageId, string error,string cause,JSONValue details) + { + JSONObject failed = new JSONObject(); + failed["message"] = new JSONString(error); + failed["cause"] = new JSONString(cause); + failed["details"] = details; + + Logging.Log(LogLevel.WARNING, "ApplicationWebSocket sends error: {0}\n{1}",error,cause); + SendMessage(messageId, "error", failed); + } + + public void a() { - try - { - Logging.Log(LogLevel.DEBUGDETAIL, "ApplicationWebSocket: Received: {0}",textMessage); - JSONObject json = (JSONObject)JSONParser.Parse(textMessage); - RPCCall rpcCall = json.ToObject(); + //try + //{ + // Logging.Log(LogLevel.DEBUGDETAIL, "ApplicationWebSocket: Received: {0}",textMessage); + + // RPCCall rpcCall = json.ToObject(); - RPCResult rpcResult = Invoke(rpcCall); - string resultText = JSONObject.From(rpcResult).ToString(); + // RPCResult rpcResult = Invoke(rpcCall); + // string resultText = JSONObject.From(rpcResult).ToString(); - Logging.Log(LogLevel.DEBUGDETAIL, "ApplicationWebSocket: Sending: {0}", resultText); - requestContext.WebSocket.Send(resultText); + // Logging.Log(LogLevel.DEBUGDETAIL, "ApplicationWebSocket: Sending: {0}", resultText); + // requestContext.WebSocket.Send(resultText); - } - catch (Exception e) - { - Logging.Log(e); - } + //} + //catch (Exception e) + //{ + // Logging.Log(e); + //} } public virtual RPCResult Invoke(RPCCall call) { RPCResult result = null; - result = RPCContainer.Invoke(call); + result = ApplicationInterface.RPCContainer.Invoke(call); return result; } } diff --git a/IApplicationInterface.cs b/IApplicationInterface.cs index e5bdc31..4ed9105 100644 --- a/IApplicationInterface.cs +++ b/IApplicationInterface.cs @@ -5,6 +5,8 @@ using ln.application.service; using ln.http.resources; using ln.http; using ln.types; +using ln.types.rpc; +using ln.application.slots; namespace ln.application { public interface IApplicationInterface @@ -15,5 +17,8 @@ namespace ln.application ResourceApplication HTTPApplication { get; } ServiceContainer ServiceContainer { get; } + RPCContainer RPCContainer { get; } + BinarySlotContainer BinarySlots { get; } + } } diff --git a/ln.application.csproj b/ln.application.csproj index 37447cb..fbd815e 100644 --- a/ln.application.csproj +++ b/ln.application.csproj @@ -39,6 +39,10 @@ + + + + @@ -65,15 +69,85 @@ + PreserveNewest - + PreserveNewest - + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + PreserveNewest diff --git a/ln.application.demo/ApplicationDemo.cs b/ln.application.demo/ApplicationDemo.cs new file mode 100644 index 0000000..6988846 --- /dev/null +++ b/ln.application.demo/ApplicationDemo.cs @@ -0,0 +1,50 @@ +// /** +// * File: ApplicationDemo.cs +// * Author: haraldwolff +// * +// * This file and it's content is copyrighted by the Author and / or copyright holder. +// * Any use wihtout proper permission is illegal and may lead to legal actions. +// * +// * +// **/ +using System; +using ln.http.resources; +using ln.application.service; +using ln.http; +using ln.http.listener; +namespace ln.application.demo +{ + public class ApplicationDemo : Application + { + public override void PrepareStart() + { + base.PrepareStart(); + + ServiceContainer.Add(ServiceDefinition.From(true)); + } + + class ApplicationService : ApplicationServiceBase + { + + public ApplicationService() : base("core") { } + + + public override void ServiceMain(IApplicationInterface applicationInterface) + { + DirectoryResource directoryResource = new DirectoryResource(new string[] { "../../www", "www" }); + directoryResource.DefaultResource = directoryResource.GetResource("demo.html"); + directoryResource.FallBackResource = directoryResource.DefaultResource; + + CurrentApplicationInterface.HTTPApplication.RootResource = directoryResource; + + //applicationInterface.HttpServer.AddListener(new HttpsListener(8443)); + + base.ServiceMain(applicationInterface); + } + + + } + + + } +} diff --git a/ln.application.demo/Program.cs b/ln.application.demo/Program.cs new file mode 100644 index 0000000..08d22ed --- /dev/null +++ b/ln.application.demo/Program.cs @@ -0,0 +1,21 @@ +// /** +// * File: Program.cs +// * Author: haraldwolff +// * +// * This file and it's content is copyrighted by the Author and / or copyright holder. +// * Any use wihtout proper permission is illegal and may lead to legal actions. +// * +// * +// **/ +using System; + +namespace ln.application.demo +{ + class MainClass + { + public static void Main(string[] args) + { + new ApplicationDemo().Start(args); + } + } +} diff --git a/ln.application.demo/Properties/AssemblyInfo.cs b/ln.application.demo/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..719313c --- /dev/null +++ b/ln.application.demo/Properties/AssemblyInfo.cs @@ -0,0 +1,35 @@ +// /** +// * File: AssemblyInfo.cs +// * Author: haraldwolff +// * +// * This file and it's content is copyrighted by the Author and / or copyright holder. +// * Any use wihtout proper permission is illegal and may lead to legal actions. +// * +// * +// **/ +using System.Reflection; +using System.Runtime.CompilerServices; + +// Information about this assembly is defined by the following attributes. +// Change them to the values specific to your project. + +[assembly: AssemblyTitle("ln.application.demo")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". +// The form "{Major}.{Minor}.*" will automatically update the build and revision, +// and "{Major}.{Minor}.{Build}.*" will update just the revision. + +[assembly: AssemblyVersion("1.0.*")] + +// The following attributes are used to specify the signing key for the assembly, +// if desired. See the Mono documentation for more information about signing. + +//[assembly: AssemblyDelaySign(false)] +//[assembly: AssemblyKeyFile("")] diff --git a/ln.application.demo/ln.application.demo.csproj b/ln.application.demo/ln.application.demo.csproj new file mode 100644 index 0000000..315b530 --- /dev/null +++ b/ln.application.demo/ln.application.demo.csproj @@ -0,0 +1,71 @@ + + + + Debug + AnyCPU + {2CBEE2D5-C4D4-4DBD-8AA4-B54E99812808} + Exe + ln.application.demo + ln.application.demo + v4.7 + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + true + + + true + bin\Release + prompt + 4 + true + + + + + + + + + + + + {44AA3A50-7214-47F2-9D60-6FF34C0FE6D3} + ln.application + + + {CEEEEB41-3059-46A2-A871-2ADE22C013D9} + ln.http + + + {F9086FE4-8925-42FF-A59C-607341604293} + ln.http.resources + + + {D9342117-3249-4D8B-87C9-51A50676B158} + ln.json + + + {D471A566-9FB6-41B2-A777-3C32874ECD0E} + ln.logging + + + {AD0267BB-F08C-4BE1-A88D-010D49041761} + ln.templates + + + {8D9AB9A5-E513-4BA7-A450-534F6456BF28} + ln.types + + + + + + + \ No newline at end of file diff --git a/ln.application.sln b/ln.application.sln new file mode 100644 index 0000000..1528e81 --- /dev/null +++ b/ln.application.sln @@ -0,0 +1,59 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ln.application", "ln.application.csproj", "{44AA3A50-7214-47F2-9D60-6FF34C0FE6D3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ln.http", "..\ln.http\ln.http.csproj", "{CEEEEB41-3059-46A2-A871-2ADE22C013D9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ln.http.resources", "..\ln.http.resources\ln.http.resources.csproj", "{F9086FE4-8925-42FF-A59C-607341604293}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ln.json", "..\ln.json\ln.json.csproj", "{D9342117-3249-4D8B-87C9-51A50676B158}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ln.logging", "..\ln.logging\ln.logging.csproj", "{D471A566-9FB6-41B2-A777-3C32874ECD0E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ln.templates", "..\ln.templates\ln.templates.csproj", "{AD0267BB-F08C-4BE1-A88D-010D49041761}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ln.types", "..\ln.types\ln.types.csproj", "{8D9AB9A5-E513-4BA7-A450-534F6456BF28}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ln.application.demo", "ln.application.demo\ln.application.demo.csproj", "{2CBEE2D5-C4D4-4DBD-8AA4-B54E99812808}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {44AA3A50-7214-47F2-9D60-6FF34C0FE6D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {44AA3A50-7214-47F2-9D60-6FF34C0FE6D3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {44AA3A50-7214-47F2-9D60-6FF34C0FE6D3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {44AA3A50-7214-47F2-9D60-6FF34C0FE6D3}.Release|Any CPU.Build.0 = Release|Any CPU + {CEEEEB41-3059-46A2-A871-2ADE22C013D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CEEEEB41-3059-46A2-A871-2ADE22C013D9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CEEEEB41-3059-46A2-A871-2ADE22C013D9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CEEEEB41-3059-46A2-A871-2ADE22C013D9}.Release|Any CPU.Build.0 = Release|Any CPU + {F9086FE4-8925-42FF-A59C-607341604293}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F9086FE4-8925-42FF-A59C-607341604293}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F9086FE4-8925-42FF-A59C-607341604293}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F9086FE4-8925-42FF-A59C-607341604293}.Release|Any CPU.Build.0 = Release|Any CPU + {D9342117-3249-4D8B-87C9-51A50676B158}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D9342117-3249-4D8B-87C9-51A50676B158}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D9342117-3249-4D8B-87C9-51A50676B158}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D9342117-3249-4D8B-87C9-51A50676B158}.Release|Any CPU.Build.0 = Release|Any CPU + {D471A566-9FB6-41B2-A777-3C32874ECD0E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D471A566-9FB6-41B2-A777-3C32874ECD0E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D471A566-9FB6-41B2-A777-3C32874ECD0E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D471A566-9FB6-41B2-A777-3C32874ECD0E}.Release|Any CPU.Build.0 = Release|Any CPU + {AD0267BB-F08C-4BE1-A88D-010D49041761}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AD0267BB-F08C-4BE1-A88D-010D49041761}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AD0267BB-F08C-4BE1-A88D-010D49041761}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AD0267BB-F08C-4BE1-A88D-010D49041761}.Release|Any CPU.Build.0 = Release|Any CPU + {8D9AB9A5-E513-4BA7-A450-534F6456BF28}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8D9AB9A5-E513-4BA7-A450-534F6456BF28}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8D9AB9A5-E513-4BA7-A450-534F6456BF28}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8D9AB9A5-E513-4BA7-A450-534F6456BF28}.Release|Any CPU.Build.0 = Release|Any CPU + {2CBEE2D5-C4D4-4DBD-8AA4-B54E99812808}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2CBEE2D5-C4D4-4DBD-8AA4-B54E99812808}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2CBEE2D5-C4D4-4DBD-8AA4-B54E99812808}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2CBEE2D5-C4D4-4DBD-8AA4-B54E99812808}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/service/ApplicationServiceBase.cs b/service/ApplicationServiceBase.cs index be9b061..306b74b 100644 --- a/service/ApplicationServiceBase.cs +++ b/service/ApplicationServiceBase.cs @@ -49,7 +49,17 @@ namespace ln.application.service return serviceBase; } - public virtual void ServiceMain(IApplicationInterface applicationInterface) => throw new NotImplementedException(); + public virtual void ServiceMain(IApplicationInterface applicationInterface) + { + Ready(); + while (!StopRequested) + { + lock (Thread.CurrentThread) + { + Monitor.Wait(Thread.CurrentThread); + } + } + } public virtual bool Start(IApplicationInterface applicationInterface, String[] arguments) { diff --git a/slots/BinarySlot.cs b/slots/BinarySlot.cs new file mode 100644 index 0000000..9b75c03 --- /dev/null +++ b/slots/BinarySlot.cs @@ -0,0 +1,19 @@ +// /** +// * File: BinarySlot.cs +// * Author: haraldwolff +// * +// * This file and it's content is copyrighted by the Author and / or copyright holder. +// * Any use wihtout proper permission is illegal and may lead to legal actions. +// * +// * +// **/ +using System; +namespace ln.application.slots +{ + public class BinarySlot + { + public BinarySlot() + { + } + } +} diff --git a/slots/BinarySlotContainer.cs b/slots/BinarySlotContainer.cs new file mode 100644 index 0000000..3656994 --- /dev/null +++ b/slots/BinarySlotContainer.cs @@ -0,0 +1,28 @@ +// /** +// * File: BinarySlotContainer.cs +// * Author: haraldwolff +// * +// * This file and it's content is copyrighted by the Author and / or copyright holder. +// * Any use wihtout proper permission is illegal and may lead to legal actions. +// * +// * +// **/ +using System; +using ln.types.btree; +namespace ln.application.slots +{ + public class BinarySlotContainer + { + BTree slots = new BTree(); + + public BinarySlotContainer() + { + } + + public SlotAllocation RequestSlot(SlotRequest slotRequest) + { + return null; + } + + } +} diff --git a/slots/SlotAllocation.cs b/slots/SlotAllocation.cs new file mode 100644 index 0000000..2c045d0 --- /dev/null +++ b/slots/SlotAllocation.cs @@ -0,0 +1,22 @@ +// /** +// * File: SlotAllocation.cs +// * Author: haraldwolff +// * +// * This file and it's content is copyrighted by the Author and / or copyright holder. +// * Any use wihtout proper permission is illegal and may lead to legal actions. +// * +// * +// **/ +using System; +namespace ln.application.slots +{ + public class SlotAllocation + { + public long maxchunksize; + public byte[] slotidentifier; + + public SlotAllocation() + { + } + } +} diff --git a/slots/SlotRequest.cs b/slots/SlotRequest.cs new file mode 100644 index 0000000..12e7719 --- /dev/null +++ b/slots/SlotRequest.cs @@ -0,0 +1,22 @@ +// /** +// * File: SlotRequest.cs +// * Author: haraldwolff +// * +// * This file and it's content is copyrighted by the Author and / or copyright holder. +// * Any use wihtout proper permission is illegal and may lead to legal actions. +// * +// * +// **/ +using System; +namespace ln.application.slots +{ + public class SlotRequest + { + public long datasize; + public long chunksize; + + public SlotRequest() + { + } + } +} diff --git a/www b/www index 0de72ab..d1663cb 160000 --- a/www +++ b/www @@ -1 +1 @@ -Subproject commit 0de72abc3d46603c95f6986cc8add6cbd0066ea8 +Subproject commit d1663cbbbe0d91631c4bd6b7b0f7228621329705