4using System.Threading.Tasks;
15 internal class JsonRpcServerRequest : IDisposable
17 public JsonRpcServerRequest?[]? BatchRequests =
null;
18 public Dictionary<string, object?>? ResponseObject =
null;
19 public Dictionary<string, object?>[]? ResponseArray =
null;
20 public object? Response =
null;
21 public Dictionary<string, object?>? ParametersObj =
null;
22 public JsonRpcMethodInfo? MethodInfo =
null;
23 public Array? ParametersArray =
null;
24 public string JsonVersion =
string.Empty;
25 public object? Id =
null;
26 public int? ErrorCode =
null;
27 public int StatusCode = 204;
28 public string StatusMessage =
"No Content";
29 public string? ErrorMessage =
null;
30 public object? Result =
null;
31 public bool IsResult =
false;
32 public bool IsError =
false;
34 public void SetError(
int ErrorCode,
string ErrorMessage,
int StatusCode,
37 this.ErrorCode = ErrorCode;
38 this.ErrorMessage = ErrorMessage;
39 this.StatusCode = StatusCode;
40 this.StatusMessage = StatusMessage;
45 if (this.Result is IDisposable Disposable)
48 if (!(this.BatchRequests is
null))
50 int i, c = this.BatchRequests.Length;
52 for (i = 0; i < c; i++)
53 this.BatchRequests[i]?.Dispose();
55 this.BatchRequests =
null;
68 public async Task<bool> BuildResponse(JsonRpcWebService WebService,
69 HttpRequest HttpRequest, HttpResponse HttpResponse)
71 bool HasSniffer = HttpRequest.Server.HasSniffers;
77 this.SetError(-32600,
"Missing id attribute.",
78 BadRequestException.Code, BadRequestException.StatusMessage);
82 IJsonRpcClientRequest? Request = WebService.PopClientRequest(this.Id.ToString());
85 this.SetError(-32600,
"Id attribute not recognized or obsolete.",
86 NotFoundException.Code, NotFoundException.StatusMessage);
90 await Request.ReportResult(this.Result);
93 else if (this.IsError && !(this.Id is
null))
95 IJsonRpcClientRequest? Request = WebService.PopClientRequest(this.Id.ToString());
98 this.SetError(-32600,
"Id attribute not recognized or obsolete.",
99 NotFoundException.Code, NotFoundException.StatusMessage);
103 await Request.ReportError(this.ErrorCode, this.ErrorMessage ??
"Unable to perform request.");
107 if (this.BatchRequests is
null)
109 this.ResponseObject =
new Dictionary<string, object?>();
111 if (!
string.IsNullOrEmpty(this.JsonVersion))
112 this.ResponseObject[
"jsonrpc"] = this.JsonVersion;
114 if (!(this.Id is
null))
115 this.ResponseObject[
"id"] = this.Id;
117 if (this.MethodInfo is
null && !this.ErrorCode.HasValue)
119 this.SetError(-32600,
"Missing method.",
120 BadRequestException.Code, BadRequestException.StatusMessage);
123 if (!this.ErrorCode.HasValue)
127 int i, c = this.MethodInfo!.NrArguments;
128 int NrParametersSet = 0;
129 object?[]? Parameters =
null;
131 if (!(this.ParametersObj is
null))
133 if (!this.MethodInfo.TryBuildRequest(
134 this.Id?.ToString() ??
string.Empty,
135 this.ParametersObj,
null, out
string? Reason,
138 this.SetError(-32602, Reason,
139 BadRequestException.Code, BadRequestException.StatusMessage);
142 else if (!(this.ParametersArray is
null))
144 if (this.ParametersArray.Length != c -
this.MethodInfo.NrSpecialArguments)
146 this.SetError(-32602,
"Invalid number of parameters.",
147 BadRequestException.Code, BadRequestException.StatusMessage);
151 Parameters =
new object?[c];
153 for (i = 0; i < c; i++)
155 object? Value = this.ParametersArray.GetValue(i);
156 ProtectedMethodArgumentInfo ArgumentInfo = this.MethodInfo.Arguments[i];
157 Type ExpectedType = ArgumentInfo.Parameter.ParameterType;
160 if (ParameterType == ExpectedType)
161 Parameters[i] = Value;
163 Parameters[i] = Converted;
164 else if (ArgumentInfo.HasDefaultValue &&
165 Value is Dictionary<string, object?> Dictionary &&
166 Dictionary.Count == 0)
168 Parameters[i] = ArgumentInfo.DefaultValue;
172 this.SetError(-32602,
"Parameter " + (i + 1).
ToString() +
174 ", Expected: " + ExpectedType.FullName,
175 BadRequestException.Code, BadRequestException.StatusMessage);
183 Parameters =
new object?[c];
185 if (NrParametersSet != c - this.MethodInfo.NrSpecialArguments)
187 foreach (ProtectedMethodArgumentInfo Argument
in this.MethodInfo.Arguments)
189 if (!Argument.IsSpecialArgument &&
190 Argument.HasDefaultValue)
192 Parameters[Argument.Parameter.Position] = Argument.DefaultValue;
198 if (NrParametersSet != c - this.MethodInfo.NrSpecialArguments)
200 this.SetError(-32600,
"Missing required parameters.",
201 BadRequestException.Code, BadRequestException.StatusMessage);
205 if (!this.ErrorCode.HasValue)
207 Parameters ??=
new object?[c];
209 if (this.MethodInfo.NrSpecialArguments > 0)
211 if (this.MethodInfo.RequestArgument.HasValue)
212 Parameters[this.MethodInfo.RequestArgument.Value] = HttpRequest;
214 if (this.MethodInfo.ResponseArgument.HasValue)
215 Parameters[this.MethodInfo.ResponseArgument.Value] = HttpResponse;
217 if (this.MethodInfo.IdArgument.HasValue)
218 Parameters[this.MethodInfo.IdArgument.Value] = this.Id;
223 StringBuilder sb =
new StringBuilder();
226 sb.Append(this.MethodInfo.Method.Name);
229 foreach (
object? P
in Parameters)
241 HttpRequest.Server.Information(sb.ToString());
244 IUser User = HttpRequest.User;
245 bool Encrypted = HttpRequest.Encrypted;
246 int Strength = HttpRequest.CipherStrength;
248 if (this.MethodInfo.RequiresAuthentication && User is
null)
250 HttpAuthenticationScheme[] Schemes = this.MethodInfo.AuthenticationMechanisms ?? Array.Empty<HttpAuthenticationScheme>();
252 foreach (HttpAuthenticationScheme Scheme
in Schemes)
254 if (Scheme.RequireEncryption &&
255 (!Encrypted || Strength < Scheme.MinStrength))
260 if (Scheme.UserSessions && HttpRequest.Session is
null)
261 HttpRequest.GetSessionFromCookie();
263 User = await Scheme.IsAuthenticated(HttpRequest);
266 HttpRequest.User = User;
273 List<string> Challenges =
new List<string>();
275 foreach (HttpAuthenticationScheme Scheme
in Schemes)
277 if (Scheme.RequireEncryption &&
278 (!Encrypted || Strength < Scheme.MinStrength))
283 foreach (
string Challenge
in Scheme.GetChallenges(HttpRequest))
284 Challenges.Add(Challenge);
287 await HttpResponse.SendResponse(
new UnauthorizedException(
288 Challenges.ToArray()));
292 foreach (
string Privilege
in this.MethodInfo.RequiredPrivileges)
296 await HttpResponse.SendResponse(ForbiddenException.AccessDenied(
297 HttpRequest.Resource.ResourceName,
305 this.MethodInfo.Method.Invoke(WebService, Parameters));
309 if (this.Result is
null)
310 HttpRequest.Server.Information(
"Result: null");
312 HttpRequest.Server.Information(
"Result: void");
315 HttpRequest.Server.Information(
"Result: " +
320 if (HttpResponse.ResponseSent)
327 HttpRequest.Server.Exception(ex);
330 InternalServerErrorException.Code, InternalServerErrorException.StatusMessage);
334 if (this.ErrorCode.HasValue)
336 this.ResponseObject[
"error"] =
new Dictionary<string, object>()
338 {
"code", this.ErrorCode.Value },
339 {
"message", this.ErrorMessage ?? string.Empty }
343 this.ResponseObject[
"result"] =
new Dictionary<string, object>();
345 this.ResponseObject[
"result"] = this.Result;
347 this.Response = this.ResponseObject;
349 if (!(this.Id is
null) && this.StatusCode == 204)
351 this.StatusCode = 200;
352 this.StatusMessage =
"OK";
357 int i, c = this.BatchRequests.Length;
360 for (i = 0; i < c; i++)
362 if (!(this.BatchRequests[i]!.Id is
null))
366 this.ResponseArray =
new Dictionary<string, object?>[d];
368 for (i = j = 0; i < c; i++)
370 JsonRpcServerRequest Request = this.BatchRequests[i]!;
372 if (await Request.BuildResponse(WebService, HttpRequest, HttpResponse))
375 if (!(Request.Id is
null))
376 this.ResponseArray[j++] = Request.ResponseObject!;
379 this.Response = this.ResponseArray;
381 if (this.StatusCode == 204)
383 this.StatusCode = 200;
384 this.StatusMessage =
"OK";
Static class managing the application event log. Applications and services log events on this static ...
static Exception UnnestException(Exception Exception)
Unnests an exception, to extract the relevant inner exception.
Class managing a script expression.
static bool IsVoid(Type ResultType)
Checks if a result object type is equal to void (i.e. its type equal to System.Threading....
static bool TryConvert(object Value, Type DesiredType, bool AcceptInformationLoss, out object Result)
Tries to convert an object Value to an object of type DesiredType .
static bool IsNullOrVoid(object Result)
Checks if a result object value is equal to null or void (i.e. its type equal to System....
static string ToExpressionString(object Value)
Converts an object to a string, that can be parsed as part of an expression.
Base class for all nodes in a parsed script tree.
static async Task< object > WaitPossibleTask(object Result)
Waits for any asynchronous process to terminate.
bool HasPrivilege(string Privilege)
If the object has a given privilege.
Basic interface for a user.
string UserName
User Name.
ParameterType
Type of parameter.
delegate string ToString(IElement Element)
Delegate for callback methods that convert an element value to a string.