Start working on rust compile step
This commit is contained in:
10
crates/libjrpc/templates/CSharp/CSharp.csproj
Normal file
10
crates/libjrpc/templates/CSharp/CSharp.csproj
Normal file
@ -0,0 +1,10 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<LangVersion>10.0</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
170
crates/libjrpc/templates/CSharp/JRpcClient.cs
Normal file
170
crates/libjrpc/templates/CSharp/JRpcClient.cs
Normal file
@ -0,0 +1,170 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace __NAMESPACE__;
|
||||
|
||||
public class JRpcClient
|
||||
{
|
||||
private JRpcTransport Transport;
|
||||
private IDictionary<string, TaskCompletionSource<JsonNode?>> Requests;
|
||||
private int? Timeout = null;
|
||||
|
||||
public JRpcClient(JRpcTransport transport, int? timeout = null)
|
||||
{
|
||||
this.Transport = transport;
|
||||
this.Timeout = timeout;
|
||||
this.Requests = new Dictionary<string, TaskCompletionSource<JsonNode?>>();
|
||||
|
||||
this.Transport.OnPacket += this.HandlePacket;
|
||||
}
|
||||
|
||||
private void HandlePacket(string packet)
|
||||
{
|
||||
try
|
||||
{
|
||||
var parsed = JsonNode.Parse(packet);
|
||||
if (parsed == null || (string?)parsed["jsonrpc"] != "2.0")
|
||||
return;
|
||||
|
||||
if (parsed["method"] != null)
|
||||
{ // Request or Notification
|
||||
if (parsed["id"] != null) // Requests are not supported on the Client
|
||||
return;
|
||||
//TODO: implement Notifications
|
||||
}
|
||||
else if (parsed["id"] != null && parsed["method"] == null)
|
||||
{
|
||||
// Response
|
||||
//TODO: Somehow remove this warning, since it has no meaning in this context.
|
||||
// ID has to be something, that was checked before
|
||||
var id = (string)parsed["id"]!;
|
||||
|
||||
var task = this.Requests[id];
|
||||
if (task == null)
|
||||
return; //This Request was not from here
|
||||
|
||||
if (parsed["error"] != null)
|
||||
{
|
||||
var err = parsed["error"].Deserialize<JRpcError>();
|
||||
if (err == null)
|
||||
{
|
||||
task.SetException(new JRpcException("Internal Server Error"));
|
||||
}
|
||||
else
|
||||
{
|
||||
task.SetException(err.ToException());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
task.SetResult(parsed["result"]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Ignoring invalid packet!
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
//TODO: Maybe log exception, but don't break!
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<JsonNode?> SendRequestRaw(string method, JsonArray param)
|
||||
{
|
||||
var id = Guid.NewGuid().ToString();
|
||||
var request = new JsonObject
|
||||
{
|
||||
["jsonrpc"] = "2.0",
|
||||
["id"] = id,
|
||||
["method"] = method,
|
||||
["params"] = param
|
||||
};
|
||||
|
||||
var task = new TaskCompletionSource<JsonNode?>();
|
||||
this.Requests.Add(id, task);
|
||||
|
||||
try
|
||||
{
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
await this.Transport.Write(request.ToJsonString());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
task.SetException(e);
|
||||
}
|
||||
});
|
||||
|
||||
if (this.Timeout.HasValue)
|
||||
{
|
||||
if (await Task.WhenAny(task.Task, Task.Delay(this.Timeout.Value)) == task.Task)
|
||||
{
|
||||
return await task.Task;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new JRpcTimeoutException();
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
return await task.Task;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.Requests.Remove(id);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<TResult?> SendRequest<TResult>(string method, JsonArray param)
|
||||
{
|
||||
var result = await this.SendRequestRaw(method, param);
|
||||
return result.Deserialize<TResult>();
|
||||
}
|
||||
|
||||
public async void SendNotification(string method, JsonArray param)
|
||||
{
|
||||
var not = new JsonObject
|
||||
{
|
||||
["jsonrpc"] = "2.0",
|
||||
["method"] = method,
|
||||
["params"] = param,
|
||||
};
|
||||
|
||||
await this.Transport.Write(not.ToJsonString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class JRpcError
|
||||
{
|
||||
public int code { get; set; }
|
||||
public string? message { get; set; }
|
||||
public JsonNode? data { get; set; }
|
||||
|
||||
public JRpcException ToException()
|
||||
{
|
||||
return new JRpcException(this.message!);
|
||||
}
|
||||
}
|
||||
|
||||
public class JRpcException : Exception
|
||||
{
|
||||
public JRpcException(string message) : base(message) { }
|
||||
}
|
||||
|
||||
public class JRpcTimeoutException : JRpcException
|
||||
{
|
||||
public JRpcTimeoutException() : base("Request Timeout") { }
|
||||
}
|
199
crates/libjrpc/templates/CSharp/JRpcServer.cs
Normal file
199
crates/libjrpc/templates/CSharp/JRpcServer.cs
Normal file
@ -0,0 +1,199 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace __NAMESPACE__;
|
||||
|
||||
public class JRpcServer<TContext>
|
||||
{
|
||||
public IDictionary<string, JRpcService<TContext>> Services;
|
||||
|
||||
public JRpcServer()
|
||||
{
|
||||
this.Services = new Dictionary<string, JRpcService<TContext>>();
|
||||
}
|
||||
|
||||
public void AddService(JRpcService<TContext> service)
|
||||
{
|
||||
this.Services.Add(service.Name, service);
|
||||
}
|
||||
|
||||
public JRpcServerSession<TContext> GetSession(JRpcTransport transport, TContext context)
|
||||
{
|
||||
return new JRpcServerSession<TContext>(this, transport, context);
|
||||
}
|
||||
}
|
||||
|
||||
public class JRpcServerSession<TContext>
|
||||
{
|
||||
public JRpcServer<TContext> Server { get; private set; }
|
||||
public JRpcTransport Transport { get; private set; }
|
||||
public TContext Context { get; private set; }
|
||||
|
||||
public JRpcServerSession(JRpcServer<TContext> server, JRpcTransport transport, TContext context)
|
||||
{
|
||||
this.Server = server;
|
||||
this.Transport = transport;
|
||||
this.Context = context;
|
||||
|
||||
this.Transport.OnPacket += this.HandlePacket;
|
||||
}
|
||||
|
||||
private void HandlePacket(string packet)
|
||||
{
|
||||
try
|
||||
{
|
||||
var parsed = JsonNode.Parse(packet);
|
||||
if (parsed == null || (string?)parsed["jsonrpc"] != "2.0")
|
||||
return;
|
||||
|
||||
if (parsed["method"] != null) // Request or Notification
|
||||
{
|
||||
var id = (string?)parsed["id"];
|
||||
var splitted = ((string)parsed["method"]!).Split(".", 2);
|
||||
var serviceName = splitted[0];
|
||||
var functionName = splitted[1];
|
||||
|
||||
if (serviceName == null || functionName == null)
|
||||
{
|
||||
if (id != null)
|
||||
{
|
||||
var response = new JsonObject
|
||||
{
|
||||
["jsonrpc"] = "2.0",
|
||||
["id"] = id,
|
||||
["error"] = new JsonObject
|
||||
{
|
||||
["code"] = -32700,
|
||||
["message"] = "Method not found!",
|
||||
}
|
||||
};
|
||||
_ = this.Transport.Write(response.ToJsonString()!);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var service = this.Server.Services[serviceName];
|
||||
if (service == null)
|
||||
{
|
||||
if (id != null)
|
||||
{
|
||||
var response = new JsonObject
|
||||
{
|
||||
["jsonrpc"] = "2.0",
|
||||
["id"] = id,
|
||||
["error"] = new JsonObject
|
||||
{
|
||||
["code"] = -32700,
|
||||
["message"] = "Method not found!",
|
||||
}
|
||||
};
|
||||
_ = this.Transport.Write(response.ToJsonString()!);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!service.Functions.Contains(functionName))
|
||||
{
|
||||
if (id != null)
|
||||
{
|
||||
var response = new JsonObject
|
||||
{
|
||||
["jsonrpc"] = "2.0",
|
||||
["id"] = id,
|
||||
["error"] = new JsonObject
|
||||
{
|
||||
["code"] = -32700,
|
||||
["message"] = "Method not found!",
|
||||
}
|
||||
};
|
||||
_ = this.Transport.Write(response.ToJsonString()!);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(parsed["params"] is JsonArray || parsed["params"] is JsonObject))
|
||||
{
|
||||
if (id != null)
|
||||
{
|
||||
var response = new JsonObject
|
||||
{
|
||||
["jsonrpc"] = "2.0",
|
||||
["id"] = id,
|
||||
["error"] = new JsonObject
|
||||
{
|
||||
["code"] = -32602,
|
||||
["message"] = "Invalid Parameters!",
|
||||
}
|
||||
};
|
||||
_ = this.Transport.Write(response.ToJsonString()!);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
_ = service.HandleRequest(functionName, parsed["params"]!, this.Context).ContinueWith(result =>
|
||||
{
|
||||
if (id != null)
|
||||
{
|
||||
var response = new JsonObject
|
||||
{
|
||||
["jsonrpc"] = "2.0",
|
||||
["id"] = id,
|
||||
["error"] = result.IsFaulted ? new JsonObject
|
||||
{
|
||||
["code"] = -32603,
|
||||
["message"] = result.Exception!.InnerException!.Message
|
||||
} : null,
|
||||
["result"] = !result.IsFaulted ? result.Result : null,
|
||||
};
|
||||
_ = this.Transport.Write(response.ToJsonString()!);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
//TODO: implement Notifications
|
||||
}
|
||||
else
|
||||
{
|
||||
// Ignoring everyting else. Don't care!
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
//TODO: Maybe log exception, but don't break!
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public async void SendNotification(string method, JsonArray param)
|
||||
{
|
||||
var not = new JsonObject
|
||||
{
|
||||
["jsonrpc"] = "2.0",
|
||||
["method"] = method,
|
||||
["params"] = param,
|
||||
};
|
||||
|
||||
await this.Transport.Write(not.ToJsonString());
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class JRpcService<TContext>
|
||||
{
|
||||
public abstract string Name { get; }
|
||||
|
||||
public HashSet<string> Functions = new HashSet<string>();
|
||||
|
||||
|
||||
protected void RegisterFunction(string name)
|
||||
{
|
||||
this.Functions.Add(name);
|
||||
}
|
||||
|
||||
public abstract Task<JsonNode?> HandleRequest(string function, JsonNode param, TContext context);
|
||||
// public abstract Task HandleNotification(string notification, JsonNode param);
|
||||
}
|
15
crates/libjrpc/templates/CSharp/JRpcTransport.cs
Normal file
15
crates/libjrpc/templates/CSharp/JRpcTransport.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace __NAMESPACE__;
|
||||
|
||||
public delegate void NotifyPacket(string data);
|
||||
|
||||
public abstract class JRpcTransport {
|
||||
public event NotifyPacket? OnPacket;
|
||||
public abstract Task Write(string data);
|
||||
|
||||
// TODO: Spend some time finding a better permission, but it is fine for now
|
||||
public void SendPacketEvent(string data) {
|
||||
this.OnPacket?.Invoke(data);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user