aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ShiftOS.Objects/MudAttributes.cs43
-rw-r--r--ShiftOS.Objects/ShiftOS.Objects.csproj1
-rw-r--r--ShiftOS.Server/Program.cs218
-rw-r--r--ShiftOS.Server/RemoteTerminal.cs70
-rw-r--r--ShiftOS.Server/SaveManager.cs88
-rw-r--r--ShiftOS.Server/ShiftOS.Server.csproj2
6 files changed, 318 insertions, 104 deletions
diff --git a/ShiftOS.Objects/MudAttributes.cs b/ShiftOS.Objects/MudAttributes.cs
new file mode 100644
index 0000000..b3b7380
--- /dev/null
+++ b/ShiftOS.Objects/MudAttributes.cs
@@ -0,0 +1,43 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using attribute = System.Attribute;
+
+namespace ShiftOS.Objects
+{
+ [AttributeUsage(AttributeTargets.Method)]
+ public class MudRequestAttribute : attribute
+ {
+ /// <summary>
+ /// This attribute can be used on a static method to make the multi-user domain server software see this method as a MUD request handler.
+ /// </summary>
+ /// <param name="rName">The header ID of the request this method should handle.</param>
+ public MudRequestAttribute(string rName)
+ {
+ RequestName = rName;
+ }
+
+ public string RequestName { get; private set; }
+ }
+
+ [AttributeUsage(AttributeTargets.Method)]
+ public class MudResponseAttribute : attribute
+ {
+ /// <summary>
+ /// Clients will look for static methods marked with this attribute and run them first. If no attribute is found with the given header ID, the client may invoke a delegate with the message information.
+ /// </summary>
+ /// <param name="rName">The header ID of the response that this method will handle.</param>
+ public MudResponseAttribute(string rName)
+ {
+ ResponseName = rName;
+ }
+
+ public string ResponseName { get; private set; }
+ }
+
+
+}
+
diff --git a/ShiftOS.Objects/ShiftOS.Objects.csproj b/ShiftOS.Objects/ShiftOS.Objects.csproj
index b82a40a..867c540 100644
--- a/ShiftOS.Objects/ShiftOS.Objects.csproj
+++ b/ShiftOS.Objects/ShiftOS.Objects.csproj
@@ -47,6 +47,7 @@
<Compile Include="ClientSave.cs" />
<Compile Include="Job.cs" />
<Compile Include="Legion.cs" />
+ <Compile Include="MudAttributes.cs" />
<Compile Include="Objects.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Save.cs" />
diff --git a/ShiftOS.Server/Program.cs b/ShiftOS.Server/Program.cs
index 352214d..b06b9d5 100644
--- a/ShiftOS.Server/Program.cs
+++ b/ShiftOS.Server/Program.cs
@@ -35,10 +35,19 @@ using System.Net;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.IO.Compression;
+using System.Reflection;
namespace ShiftOS.Server
{
+ public class MudException : Exception
+ {
+ public MudException(string message) : base(message)
+ {
+
+ }
+ }
+
/// <summary>
/// Program.
/// </summary>
@@ -187,8 +196,8 @@ namespace ShiftOS.Server
server.Start(IPAddress.Loopback, 13370);
}
-
- server.OnStopped += (o, a) =>
+ ClientDispatcher = new Server.MudClientDispatcher(server);
+ server.OnStopped += (o, a) =>
{
Console.WriteLine("Server stopping.");
@@ -262,120 +271,67 @@ namespace ShiftOS.Server
try
{
- Console.WriteLine($@"Message received from {msg.GUID}: {msg.Name}
-
-Contents:
-{msg.Contents}");
-
- if (!string.IsNullOrWhiteSpace(msg.Contents))
- {
- try
- {
- //It's gotta be JSON.
- if (msg.Contents.StartsWith("{"))
- {
- args = JsonConvert.DeserializeObject<Dictionary<string, object>>(msg.Contents);
- }
- }
- catch
- {
- //Damnit, we were wrong.
- args = null;
- }
- }
-
- switch (msg.Name)
- {
- case "usr_getcp":
+ Console.WriteLine($@"[{DateTime.Now}] Message received from {msg.GUID}: {msg.Name}");
- break;
- case "usr_takecp":
- if (args["username"] != null && args["password"] != null && args["amount"] != null && args["yourusername"] != null)
+ foreach (var asmFile in Directory.GetFiles(Environment.CurrentDirectory))
+ {
+ if (asmFile.EndsWith(".exe") || asmFile.EndsWith(".dll"))
+ {
+ try
{
- string userName = args["username"] as string;
- string passw = args["password"] as string;
- int amount = (int)args["amount"];
-
- if (Directory.Exists("saves"))
+ var asm = Assembly.LoadFile(asmFile);
+ foreach (var type in asm.GetTypes())
{
- foreach (var saveFile in Directory.GetFiles("saves"))
+ foreach (var method in type.GetMethods(BindingFlags.Public | BindingFlags.Static))
{
- var saveFileContents = JsonConvert.DeserializeObject<Save>(ReadEncFile(saveFile));
- if (saveFileContents.Username == userName && saveFileContents.Password == passw)
+ foreach (var attrib in method.GetCustomAttributes(false))
{
- saveFileContents.Codepoints += amount;
- WriteEncFile(saveFile, JsonConvert.SerializeObject(saveFileContents, Formatting.Indented));
- server.DispatchAll(new NetObject("stop_being_drunk_michael", new ServerMessage
- {
- Name = "update_your_cp",
- GUID = "server",
- Contents = $@"{{
- username: ""{userName}"",
- amount: -{amount}
-}}"
- }));
- server.DispatchTo(new Guid(msg.GUID), new NetObject("argh", new ServerMessage
+ if (attrib is MudRequestAttribute)
{
- Name = "update_your_cp",
- GUID = "server",
- Contents = $@"{{
- username: ""{args["yourusername"]}"",
- amount: {amount}
-}}"
- }));
- return;
+ if ((attrib as MudRequestAttribute).RequestName == msg.Name)
+ {
+ try
+ {
+ object contents = msg.Contents;
+ try
+ {
+ contents = JsonConvert.DeserializeObject<Dictionary<string, object>>(msg.Contents);
+ }
+ catch
+ {
+
+ }
+
+ method?.Invoke(null, new[] { msg.GUID, contents });
+ }
+ catch (MudException mEx)
+ {
+ ClientDispatcher.DispatchTo("Error", msg.GUID, mEx);
+ }
+ catch
+ {
+ Console.WriteLine($@"[{DateTime.Now}] {method.Name}: Missing guid and content parameters, request handler NOT RAN.");
+ }
+ return;
+ }
+ }
}
}
}
}
- server.DispatchTo(new Guid(msg.GUID), new NetObject("no", new ServerMessage
- {
- Name = "user_cp_not_found",
- GUID = "Server",
- }));
- break;
- case "trm_handshake_accept":
- if(args["guid"] != null && args["target"] != null)
- {
- server.DispatchTo(new Guid(args["target"] as string), new NetObject("hold_it", new ServerMessage
- {
- Name = "trm_handshake_guid",
- GUID = args["guid"] as string
- }));
- }
- break;
- case "trm_handshake_request":
- if(args["username"] != null && args["password"] != null && args["sysname"] != null)
- {
- server.DispatchAll(new NetObject("hold_my_hand", new ServerMessage
- {
- Name = "handshake_from",
- GUID = msg.GUID,
- Contents = JsonConvert.SerializeObject(args)
- }));
- }
- break;
- case "trm_handshake_stop":
- if(args["guid"] != null)
- {
- server.DispatchTo(new Guid(args["guid"] as string), new NetObject("trm_handshake_stop", new ServerMessage
- {
- Name = "trm_handshake_stop",
- GUID = msg.GUID
- }));
- }
- break;
- case "write":
- if(args["guid"] != null && args["text"] != null)
+ catch (Exception ex)
{
- server.DispatchTo(new Guid(args["guid"] as string), new NetObject("pleaseWrite", new ServerMessage
- {
- Name = "pleasewrite",
- GUID = "server",
- Contents = args["text"] as string
- }));
+ Console.WriteLine($"[{DateTime.Now}] Exception while handling request {msg.Name}: {ex}");
+ return;
}
- break;
+ }
+ }
+
+ ClientDispatcher.DispatchTo("Error", msg.GUID, new MudRequestHandlerNotFoundException());
+
+
+ switch (msg.Name)
+ {
case "trm_invcmd":
Console.WriteLine("Before arg check");
args = JsonConvert.DeserializeObject<Dictionary<string, object>>(msg.Contents);
@@ -1388,6 +1344,8 @@ The page you requested at was not found on this multi-user domain."
/// </summary>
public static Dictionary<string, string> MUDHackPasswords = new Dictionary<string, string>();
+ public static MudClientDispatcher ClientDispatcher { get; private set; }
+
/// <summary>
/// Stop this instance.
/// </summary>
@@ -1495,7 +1453,59 @@ The page you requested at was not found on this multi-user domain."
}
}
+ public class MudRequestHandlerNotFoundException : MudException
+ {
+ public MudRequestHandlerNotFoundException() : base("The request handler for this request couldn't be found.")
+ {
+
+ }
+ }
+
+ public class MudClientDispatcher
+ {
+ public NetObjectServer Server { get; private set; }
+
+ public MudClientDispatcher(NetObjectServer srv)
+ {
+ Server = srv;
+ DispatcherGUID = Guid.NewGuid().ToString();
+ Console.WriteLine($"[{DateTime.Now}] <ClientDispatcher> Dispatcher started.");
+ }
+
+ public string DispatcherGUID { get; private set; }
+ public void Broadcast(string msgHeader, object contents)
+ {
+ Server.DispatchAll(new NetObject
+ {
+ Name = "broadcast",
+ Object = new ServerMessage
+ {
+ Name = msgHeader,
+ GUID = DispatcherGUID,
+ Contents = JsonConvert.SerializeObject(contents)
+ }
+ });
+ }
+
+ public void DispatchTo(string msgName, string cGuid, object mContents)
+ {
+ if(Server.Clients.Contains(new Guid(cGuid)))
+ {
+ Server.DispatchTo(new Guid(cGuid), new NetObject("dispatch", new ServerMessage
+ {
+ Name = msgName,
+ GUID = DispatcherGUID,
+ Contents = JsonConvert.SerializeObject(mContents)
+ }));
+ Console.WriteLine($"[{DateTime.Now}] <ClientDispatcher> Dispatching to {cGuid}: {msgName}.");
+ }
+ else
+ {
+ Console.WriteLine($"[{DateTime.Now}] <ClientDispatcher> Client \"{cGuid}\" not found on server. Possibly a connection drop.");
+ }
+ }
+ }
}
// Uncommenting by Michael \ No newline at end of file
diff --git a/ShiftOS.Server/RemoteTerminal.cs b/ShiftOS.Server/RemoteTerminal.cs
new file mode 100644
index 0000000..d28cf8a
--- /dev/null
+++ b/ShiftOS.Server/RemoteTerminal.cs
@@ -0,0 +1,70 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using ShiftOS.Objects;
+using Newtonsoft.Json;
+using NetSockets;
+
+namespace ShiftOS.Server
+{
+ public static class RemoteTerminal
+ {
+ [MudRequest("trm_handshake_accept")]
+ public static void AcceptHandshake(string guid, object contents)
+ {
+ var args = contents as Dictionary<string, object>;
+ if (args["guid"] != null && args["target"] != null)
+ {
+
+ Program.ClientDispatcher.Server.DispatchTo(new Guid(args["target"] as string), new NetObject("hold_it", new ServerMessage
+ {
+ Name = "trm_handshake_guid",
+ GUID = args["guid"] as string
+ }));
+ }
+ }
+
+ [MudRequest("trm_handshake_request")]
+ public static void RequestHandshake(string guid, object contents)
+ {
+ var args = contents as Dictionary<string, object>;
+ if (args["username"] != null && args["password"] != null && args["sysname"] != null)
+ {
+ Program.ClientDispatcher.Server.DispatchAll(new NetObject("hold_my_hand", new ServerMessage
+ {
+ Name = "handshake_from",
+ GUID = guid,
+ Contents = JsonConvert.SerializeObject(args)
+ }));
+ }
+ }
+
+ [MudRequest("trm_handshake_stop")]
+ public static void StopSession(string guid, object contents)
+ {
+ var args = contents as Dictionary<string, object>;
+ if (args["guid"] != null)
+ {
+ Program.ClientDispatcher.Server.DispatchTo(new Guid(args["guid"] as string), new NetObject("trm_handshake_stop", new ServerMessage
+ {
+ Name = "trm_handshake_stop",
+ GUID = guid
+ }));
+ }
+
+ }
+
+ [MudRequest("write")]
+ public static void WriteText(string guid, object contents)
+ {
+ var args = contents as Dictionary<string, object>;
+ if (args["guid"] != null && args["text"] != null)
+ {
+ Program.ClientDispatcher.DispatchTo("pleasewrite", args["guid"] as string, args["text"]);
+ }
+
+ }
+ }
+}
diff --git a/ShiftOS.Server/SaveManager.cs b/ShiftOS.Server/SaveManager.cs
new file mode 100644
index 0000000..4bca36d
--- /dev/null
+++ b/ShiftOS.Server/SaveManager.cs
@@ -0,0 +1,88 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using ShiftOS.Objects;
+using System.IO;
+using Newtonsoft.Json;
+
+namespace ShiftOS.Server
+{
+ public static class SaveManager
+ {
+ [MudRequest("usr_getcp")]
+ public static void GetCodepoints(string guid, object contents)
+ {
+ var args = contents as Dictionary<string, object>;
+ if (!args.ContainsKey("username"))
+ throw new MudException("No 'username' argument supplied.");
+
+ foreach(var savefile in Directory.GetFiles("saves"))
+ {
+ var save = ReadSave(savefile);
+ if(save.Username == args["username"] as string)
+ {
+ Program.ClientDispatcher.DispatchTo("usr_codepoints", guid, save.Codepoints);
+ return;
+ }
+ }
+
+ throw new MudException("User " + args["username"] as string + " not found on this multi-user domain.");
+
+ }
+
+ [MudRequest("usr_takecp")]
+ public static void TakeCodepoints(string guid, object contents)
+ {
+ var args = contents as Dictionary<string, object>;
+ if (args["username"] != null && args["password"] != null && args["amount"] != null && args["yourusername"] != null)
+ {
+ string userName = args["username"] as string;
+ string passw = args["password"] as string;
+ int cpAmount = (int)args["amount"];
+
+ if (Directory.Exists("saves"))
+ {
+ foreach (var saveFile in Directory.GetFiles("saves"))
+ {
+ var saveFileContents = JsonConvert.DeserializeObject<Save>(ReadEncFile(saveFile));
+ if (saveFileContents.Username == userName && saveFileContents.Password == passw)
+ {
+ saveFileContents.Codepoints += cpAmount;
+ WriteEncFile(saveFile, JsonConvert.SerializeObject(saveFileContents, Formatting.Indented));
+ Program.ClientDispatcher.Broadcast("update_your_cp", new {
+ username = userName,
+ amount = -cpAmount
+ });
+ Program.ClientDispatcher.DispatchTo("update_your_cp", guid, new
+ {
+ username = args["yourusername"].ToString(),
+ amount = cpAmount
+ });
+ return;
+ }
+ }
+ }
+ }
+
+ }
+
+ private static Save ReadSave(string fPath)
+ {
+ return Newtonsoft.Json.JsonConvert.DeserializeObject<Save>(ReadEncFile(fPath));
+ }
+
+
+ private static string ReadEncFile(string fPath)
+ {
+ return Encryption.Decrypt(File.ReadAllText(fPath));
+ }
+
+ private static void WriteEncFile(string fPath, string contents)
+ {
+ File.WriteAllText(fPath, Encryption.Encrypt(contents));
+ }
+
+ }
+}
diff --git a/ShiftOS.Server/ShiftOS.Server.csproj b/ShiftOS.Server/ShiftOS.Server.csproj
index d68aa3e..8654d82 100644
--- a/ShiftOS.Server/ShiftOS.Server.csproj
+++ b/ShiftOS.Server/ShiftOS.Server.csproj
@@ -60,6 +60,8 @@
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
+ <Compile Include="RemoteTerminal.cs" />
+ <Compile Include="SaveManager.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />