private async Task <bool> IsAuthorizedAsync(RpcMethod rpcMethod, HttpContext httpContext) { if (rpcMethod.AuthorizeDataList.Any()) { if (rpcMethod.AllowAnonymous) { this.logger?.LogDebug("Skipping authorization. Allow anonymous specified for method."); } else { this.logger?.LogDebug($"Running authorization for method."); AuthorizationPolicy policy = await AuthorizationPolicy.CombineAsync(this.policyProvider, rpcMethod.AuthorizeDataList); bool passed = await this.authorizationService.AuthorizeAsync(httpContext.User, policy); if (!passed) { this.logger?.LogInformation($"Authorization failed for user '{httpContext.User.Identity.Name}'."); return(false); } else { this.logger?.LogDebug($"Authoization was successful for user '{httpContext.User.Identity.Name}'."); } } } else { this.logger?.LogDebug("Skipping authorization. None configured for method."); } return(true); }
public RpcRequest(RpcMethod rpcMethod) { Params= new string[0]; JsonRpc = "2.0"; Id = 68; Method = rpcMethod.ToJsonMethodName(); }
public async Task <T> ExecuteOnRemotePeer <T>(string?remotePeerID, string methodName, params object[] methodParameters) { // Enqueue in the corresponding channel and await call try { var method = new RpcMethod(methodName, methodParameters); var call = PrepareCall(remotePeerID, method); var channel = GetChannel(remotePeerID); if (channel == null) { string msg = remotePeerID != null ? $"No client with ID {remotePeerID} connected" : "No connection to server"; // The given client is not connected. If the command is retryable and if // a backlog is registered, remember it. if (call.IsRetryable() && Settings.Backlog != null) { await RpcQueue.AddToBacklogIfApplicable(call, Settings.Backlog); msg += ", but adding the call to the backlog"; } throw new Exception(msg); } var result = await channel.Run(call); if (result.Failure != null) { throw new RpcException(result.Failure); } else if (result.ReturnValue != null) { return(Serializer.Deserialize <T>(result.ReturnValue)); } else { return(default !); // void methods are called with T = object, thus null
private async Task <bool> IsAuthorizedAsync(RpcMethod rpcMethod, IRouteContext routeContext) { if (rpcMethod.AuthorizeDataListClass.Any() || rpcMethod.AuthorizeDataListMethod.Any()) { if (rpcMethod.AllowAnonymousOnClass || rpcMethod.AllowAnonymousOnMethod) { this.logger?.LogDebug("Skipping authorization. Allow anonymous specified for method."); } else { this.logger?.LogDebug($"Running authorization for method."); bool passedAuth = await this.CheckAuthorize(rpcMethod.AuthorizeDataListClass, routeContext); if (passedAuth) { passedAuth = await this.CheckAuthorize(rpcMethod.AuthorizeDataListMethod, routeContext); } if (passedAuth) { this.logger?.LogDebug($"Authorization was successful for user '{routeContext.User.Identity.Name}'."); } else { this.logger?.LogInformation($"Authorization failed for user '{routeContext.User.Identity.Name}'."); return(false); } } } else { this.logger?.LogDebug("Skipping authorization. None configured for class or method."); } return(true); }
public async Task <byte[]?> Execute(RpcMethod method, RpcPeerInfo callingPeer) { var div = Div.FromMethod(method); byte ret = (byte)(div.dividend / div.divisor); // Yes, may throw div/0 exception return(await Task.FromResult(new byte[] { ret })); }
private RpcCall CreateCall(string methodName, string targetPeerID, RpcRetryStrategy retry = RpcRetryStrategy.Retry) => new RpcCall { Method = RpcMethod.Create(methodName), RetryStrategy = retry, RemotePeerID = targetPeerID };
public RpcMethod Read(BinaryReader br) { RpcMethod method = new RpcMethod(); method.MethodId = br.ReadUInt32(); switch (method.MethodId) { case 1: method.Args = new object[3]; if (br.ReadByte() == (byte)SerializeObjectMark.Common) { method.Args[0] = br.ReadString(); } if (br.ReadByte() == (byte)SerializeObjectMark.Common) { method.Args[1] = br.ReadString(); } if (br.ReadByte() == (byte)SerializeObjectMark.Common) { method.Args[2] = br.ReadBytes(br.ReadInt32()); } break; } return(method); }
public RpcRequest(RpcMethod rpcMethod) { Params = new string[0]; JsonRpc = "2.0"; Id = 68; Method = rpcMethod.ToJsonMethodName(); }
public async Task <byte[]?> Execute(RpcMethod method, RpcPeerInfo callingPeer) { await Task.Delay(delaysMs[callIndex % delaysMs.Count]); callIndex++; return(new byte[] { 42 }); }
public RpcMessageTest() { // Create RpcMethod test data with parameters testMethod = new RpcMethod { ID = 13, Name = "Hi", Parameters = new List <byte[]> { new byte[] { 100, 101 }, new byte[] { 255 } } }; testMethodBytes = new byte[] { (byte)'1', (byte)'M', 13, 0, 0, 0, 0, 0, 0, 0, // Header, ID (byte)'H', (byte)'i', (byte)';', 2, // Method name "Hi", 2 Parameters 2, 0, 0, 0, 100, 101, // 1st parameter: 2 bytes: 100 and 101 1, 0, 0, 0, 255 }; // 2st parameter: 1 byte // Create RpcMethod test data without parameters testMethod_NoParams = new RpcMethod { ID = 1, Name = "Hey" }; testMethodBytes_NoParams = new byte[] { (byte)'1', (byte)'M', 1, 0, 0, 0, 0, 0, 0, 0, // Header, ID (byte)'H', (byte)'e', (byte)'y', (byte)';', 0 // Method name "Hey", 0 Parameters }; // Create RpcResult test data (successful state) testResultSuccess = new RpcResult { MethodID = 300, ReturnValue = new byte[] { 200, 201, 202 } }; testResultSuccessBytes = new byte[] { (byte)'1', (byte)'R', 0x2C, 0x01, 0, 0, 0, 0, 0, 0, (byte)'S', // Header, ID, Success 3, 0, 0, 0, 200, 201, 202 }; // Return value: 3 bytes // Create RpcResult test data (failure state with message) testResultFailure = new RpcResult { MethodID = 65536, Failure = new RpcFailure { Type = RpcFailureType.Timeout, Message = "Oh" } }; testResultFailureBytes = new byte[] { (byte)'1', (byte)'R', 0x00, 0x00, 0x01, 0, 0, 0, 0, 0, (byte)'F', // Header, ID, Failure (byte)'T', (byte)'i', (byte)'m', (byte)'e', (byte)'o', (byte)'u', (byte)'t', (byte)';', // Timeout 2, 0, 0, 0, (byte)'O', (byte)'h' // Message }; // Return value: 3 bytes // Create RpcResult test data (failure state without message) testResultFailure_NoMessage = new RpcResult { MethodID = 65536, Failure = new RpcFailure { Type = RpcFailureType.Other } }; testResultFailureBytes_NoMessage = new byte[] { (byte)'1', (byte)'R', 0x00, 0x00, 0x01, 0, 0, 0, 0, 0, (byte)'F', // Header, ID, Failure (byte)'O', (byte)'t', (byte)'h', (byte)'e', (byte)'r', (byte)';', // Timeout 0, 0, 0, 0 // No message }; // Return value: 3 bytes }
public RpcResponseBase InvokeRequest(RpcRequest request, RpcRoute route) { try { if (request == null) { throw new ArgumentNullException(nameof(request)); } if (route == null) { throw new ArgumentNullException(nameof(route)); } } catch (ArgumentNullException ex) // Dont want to throw any exceptions when doing async requests { return(this.GetUnknownExceptionReponse(request, ex)); } this.Logger?.LogVerbose($"Invoking request with id '{request.Id}'"); RpcResponseBase rpcResponse; try { if (!string.Equals(request.JsonRpcVersion, "2.0")) { throw new RpcInvalidRequestException("Request must be jsonrpc version '2.0'"); } object[] parameterList; RpcMethod rpcMethod = this.GetMatchingMethod(route, request, out parameterList); this.Logger?.LogVerbose($"Attempting to invoke method '{request.Method}'"); object result = rpcMethod.Invoke(parameterList); this.Logger?.LogVerbose($"Finished invoking method '{request.Method}'"); rpcResponse = new RpcResultResponse(request.Id, result); } catch (RpcException ex) { this.Logger?.LogError("An Rpc error occurred. Returning an Rpc error response", ex); RpcError error = new RpcError(ex); rpcResponse = new RpcErrorResponse(request.Id, error); } catch (Exception ex) { rpcResponse = this.GetUnknownExceptionReponse(request, ex); } if (request.Id != null) { this.Logger?.LogVerbose($"Finished request with id '{request.Id}'"); //Only give a response if there is an id return(rpcResponse); } this.Logger?.LogVerbose($"Finished request with no id. Not returning a response"); return(null); }
public void WriteReturn(RpcMethod method, BinaryWriter bw, object value) { switch (method.MethodId) { case 1: bw.Write((Boolean)value); break; } }
public void Dispatch(IRpcImplInstnce impl, RpcMethod method, ServiceImplementStub.SendResult cont) { switch (method.MethodId) { case 1: ((IScene2CliImpl)impl).SyncPosition((Int32)(method.Args[0]), (Int32)(method.Args[1])); break; } }
public void Dispatch(IRpcImplInstnce impl, RpcMethod method, ServiceImplementStub.SendResult cont) { switch (method.MethodId) { case 1: ((ILogic2CliImpl)impl).ServerMessageOk(); break; } }
public RpcMethod Read(BinaryReader br) { RpcMethod method = new RpcMethod(); method.MethodId = br.ReadUInt32(); switch (method.MethodId) { case 1: break; } return(method); }
private object InvokeMethod(MethodInfo p, RpcMethod method, params object[] args) { object r = null; try { r = p.Invoke(_binds[method.Interface], args); } catch (Exception ex) { Singleton <ExceptionStack> .Instance.Push(ex); } return(r); }
private async Task <T> Post <T>(RpcMethod method, string[] parameters = null) { using (var client = new JsonServiceClient(baseUrl)) { var command = new RpcCommand { Method = method, Params = parameters }; var response = await client.PostAsync(command); var rpcresult = response.FromJson <RpcResult <T> >(); return(rpcresult.result); } }
public RpcMethod Read(BinaryReader br) { RpcMethod method = new RpcMethod(); method.MethodId = br.ReadUInt32(); switch (method.MethodId) { case 1: method.Args = new object[2]; method.Args[0] = br.ReadInt32(); method.Args[1] = br.ReadInt32(); break; } return(method); }
private static List <RpcMethod> GetRpcMethods(RpcRoute route) { List <RpcMethod> rpcMethods = new List <RpcMethod>(); foreach (Type type in route.GetClasses()) { MethodInfo[] publicMethods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly); foreach (MethodInfo publicMethod in publicMethods) { RpcMethod rpcMethod = new RpcMethod(type, route, publicMethod); rpcMethods.Add(rpcMethod); } } return(rpcMethods); }
/// <summary> /// Gets all the predefined Rpc methods for a Rpc route /// </summary> /// <param name="route">The route to get Rpc methods for</param> /// <param name="serviceProvider">(Optional) IoC Container for rpc method controllers</param> /// <param name="jsonSerializerSettings">Json serialization settings that will be used in serialization and deserialization for rpc requests</param> /// <returns>List of Rpc methods for the specified Rpc route</returns> private static List <RpcMethod> GetRpcMethods(RpcRoute route, IServiceProvider serviceProvider = null, JsonSerializerSettings jsonSerializerSettings = null) { List <RpcMethod> rpcMethods = new List <RpcMethod>(); foreach (Type type in route.GetClasses()) { MethodInfo[] publicMethods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance); foreach (MethodInfo publicMethod in publicMethods) { RpcMethod rpcMethod = new RpcMethod(type, route, publicMethod, serviceProvider, jsonSerializerSettings); rpcMethods.Add(rpcMethod); } } return(rpcMethods); }
public void WriteReturn(RpcMethod method, BinaryWriter bw, object value) { switch (method.MethodId) { case 1: if (value == null) { bw.Write((byte)SerializeObjectMark.IsNull); } else { bw.Write((byte)SerializeObjectMark.Common); ((ServerList)value).Write(bw); } break; } }
/// <summary> /// Gets all the predefined Rpc methods for a Rpc route /// </summary> /// <param name="route">The route to get Rpc methods for</param> /// <param name="serviceProvider">(Optional) IoC Container for rpc method controllers</param> /// <param name="jsonSerializerSettings">Json serialization settings that will be used in serialization and deserialization for rpc requests</param> /// <returns>List of Rpc methods for the specified Rpc route</returns> private static List <RpcMethod> GetRpcMethods(RpcRoute route, IServiceProvider serviceProvider = null, JsonSerializerSettings jsonSerializerSettings = null) { List <RpcMethod> rpcMethods = new List <RpcMethod>(); foreach (RouteCriteria routeCriteria in route.RouteCriteria) { foreach (Type type in routeCriteria.Types) { List <MethodInfo> publicMethods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance) //Ignore ToString, GetHashCode and Equals .Where(m => m.DeclaringType != typeof(object)) .ToList(); foreach (MethodInfo publicMethod in publicMethods) { RpcMethod rpcMethod = new RpcMethod(type, route, publicMethod, serviceProvider, jsonSerializerSettings); rpcMethods.Add(rpcMethod); } } } return(rpcMethods); }
internal RpcMethodCollection(AdsMethodEntry[] coll) { this._list = new List <IRpcMethod>(); this._dict = new Dictionary <string, IRpcMethod>(StringComparer.OrdinalIgnoreCase); if (coll != null) { for (int i = 0; i < coll.Length; i++) { IRpcMethod item = new RpcMethod(coll[i]); if (!this.Contains(item)) { this.Add(item); } else { object[] args = new object[] { item.Name }; TwinCAT.Ads.Module.Trace.TraceWarning("RpcMethod '{0}' already contained in collection. Double definition in AdsMethodEntry", args); } } } }
public object CallMethod <Interface>(string methodname, params object[] args) where Interface : class { mre.Reset(); var m = new RpcMethod { Interface = typeof(Interface).Name, Name = methodname, Args = args.ToList() }; sender.Write(Serializer.Serialize(m)); mre.WaitOne(); if (Singleton <ExceptionStack> .Instance.Any()) { throw Singleton <ExceptionStack> .Instance.Pop(); } return(ReturnValue); }
/// <summary> /// Finds the matching Rpc method for the current request /// </summary> /// <param name="route">Rpc route for the current request</param> /// <param name="request">Current Rpc request</param> /// <param name="parameterList">Paramter list parsed from the request</param> /// <param name="serviceProvider">(Optional)IoC Container for rpc method controllers</param> /// <param name="jsonSerializerSettings">Json serialization settings that will be used in serialization and deserialization for rpc requests</param> /// <returns>The matching Rpc method to the current request</returns> private RpcMethod GetMatchingMethod(RpcRoute route, RpcRequest request, out object[] parameterList, IServiceProvider serviceProvider = null, JsonSerializerSettings jsonSerializerSettings = null) { if (route == null) { throw new ArgumentNullException(nameof(route)); } if (request == null) { throw new ArgumentNullException(nameof(request)); } this.logger?.LogDebug($"Attempting to match Rpc request to a method '{request.Method}'"); List <RpcMethod> methods = DefaultRpcInvoker.GetRpcMethods(route, serviceProvider, jsonSerializerSettings); //Case insenstive check for hybrid approach. Will check for case sensitive if there is ambiguity methods = methods .Where(m => string.Equals(m.Method, request.Method, StringComparison.OrdinalIgnoreCase)) .ToList(); RpcMethod rpcMethod = null; parameterList = null; int originalMethodCount = methods.Count; if (methods.Count > 0) { List <RpcMethod> potentialMatches = new List <RpcMethod>(); foreach (RpcMethod method in methods) { bool matchingMethod; if (request.ParameterMap != null) { matchingMethod = method.HasParameterSignature(request.ParameterMap, out parameterList); } else { matchingMethod = method.HasParameterSignature(request.ParameterList, out parameterList); } if (matchingMethod) { potentialMatches.Add(method); } } if (potentialMatches.Count > 1) { //Try to remove ambiguity with case sensitive check potentialMatches = potentialMatches .Where(m => string.Equals(m.Method, request.Method, StringComparison.Ordinal)) .ToList(); if (potentialMatches.Count != 1) { this.logger?.LogError("More than one method matched the rpc request. Unable to invoke due to ambiguity."); throw new RpcMethodNotFoundException(); } } if (potentialMatches.Count == 1) { rpcMethod = potentialMatches.First(); } } if (rpcMethod == null) { this.logger?.LogError("No methods matched request."); throw new RpcMethodNotFoundException(); } this.logger?.LogDebug("Request was matched to a method"); return(rpcMethod); }
/// <summary> /// Call the incoming Rpc request method and gives the appropriate response /// </summary> /// <param name="request">Rpc request</param> /// <param name="route">Rpc route that applies to the current request</param> /// <param name="httpContext">The context of the current http request</param> /// <param name="jsonSerializerSettings">Json serialization settings that will be used in serialization and deserialization for rpc requests</param> /// <returns>An Rpc response for the request</returns> public async Task <RpcResponse> InvokeRequestAsync(RpcRequest request, RpcRoute route, IRouteContext routeContext, JsonSerializerSettings jsonSerializerSettings = null) { try { if (request == null) { throw new ArgumentNullException(nameof(request)); } if (route == null) { throw new ArgumentNullException(nameof(route)); } } catch (ArgumentNullException ex) // Dont want to throw any exceptions when doing async requests { return(this.GetUnknownExceptionReponse(request, ex)); } this.logger?.LogDebug($"Invoking request with id '{request.Id}'"); RpcResponse rpcResponse; try { if (!string.Equals(request.JsonRpcVersion, JsonRpcContants.JsonRpcVersion)) { throw new RpcInvalidRequestException($"Request must be jsonrpc version '{JsonRpcContants.JsonRpcVersion}'"); } object[] parameterList; RpcMethod rpcMethod = this.GetMatchingMethod(route, request, out parameterList, routeContext.RequestServices, jsonSerializerSettings); bool isAuthorized = await this.IsAuthorizedAsync(rpcMethod, routeContext); if (isAuthorized) { this.logger?.LogDebug($"Attempting to invoke method '{request.Method}'"); object result = await rpcMethod.InvokeAsync(parameterList); this.logger?.LogDebug($"Finished invoking method '{request.Method}'"); JsonSerializer jsonSerializer = JsonSerializer.Create(jsonSerializerSettings); if (result is IRpcMethodResult) { this.logger?.LogTrace($"Result is {nameof(IRpcMethodResult)}."); rpcResponse = ((IRpcMethodResult)result).ToRpcResponse(request.Id, obj => JToken.FromObject(obj, jsonSerializer)); } else { this.logger?.LogTrace($"Result is plain object."); JToken resultJToken = result != null?JToken.FromObject(result, jsonSerializer) : null; rpcResponse = new RpcResponse(request.Id, resultJToken); } } else { var authError = new RpcError(RpcErrorCode.InvalidRequest, "Unauthorized"); rpcResponse = new RpcResponse(request.Id, authError); } } catch (RpcException ex) { this.logger?.LogException(ex, "An Rpc error occurred. Returning an Rpc error response"); RpcError error = new RpcError(ex, this.serverConfig.Value.ShowServerExceptions); rpcResponse = new RpcResponse(request.Id, error); } catch (Exception ex) { rpcResponse = this.GetUnknownExceptionReponse(request, ex); } if (request.Id != null) { this.logger?.LogDebug($"Finished request with id '{request.Id}'"); //Only give a response if there is an id return(rpcResponse); } this.logger?.LogDebug($"Finished request with no id. Not returning a response"); return(null); }
} = null !; // Will be set when a method is called /// <summary> /// Implement this method to map the encoded RPC methods to /// the real methods in this class. Thrown exceptions are catched /// and the calling peer gets notified about a /// <see cref="RpcFailureType.RemoteException"> failure. /// If successfull, returns a task with the encoded result or null /// if the method has no return type (void). /// If the given command name is undefined in this implementation, returns null /// (not a Task with value null, but null itself!). /// </summary> public abstract Task <byte[]?>?Execute(RpcMethod method);
public void addRpcMethod(string name, RpcMethod method) { RPCHandler [name] = method; }
private async Task<bool> IsAuthorizedAsync(RpcMethod rpcMethod, HttpContext httpContext) { if (rpcMethod.AuthorizeDataList.Any()) { if (rpcMethod.AllowAnonymous) { this.logger?.LogDebug("Skipping authorization. Allow anonymous specified for method."); } else { this.logger?.LogDebug($"Running authorization for method."); AuthorizationPolicy policy = await AuthorizationPolicy.CombineAsync(this.policyProvider, rpcMethod.AuthorizeDataList); bool passed = await this.authorizationService.AuthorizeAsync(httpContext.User, policy); if (!passed) { this.logger?.LogInformation($"Authorization failed for user '{httpContext.User.Identity.Name}'."); return false; } else { this.logger?.LogDebug($"Authoization was successful for user '{httpContext.User.Identity.Name}'."); } } } else { this.logger?.LogDebug("Skipping authorization. None configured for method."); } return true; }
/// <summary> /// Call the incoming Rpc request method and gives the appropriate response /// </summary> /// <param name="request">Rpc request</param> /// <param name="route">Rpc route that applies to the current request</param> /// <param name="serviceProvider">(Optional)IoC Container for rpc method controllers</param> /// <param name="jsonSerializerSettings">Json serialization settings that will be used in serialization and deserialization for rpc requests</param> /// <returns>An Rpc response for the request</returns> public RpcResponse InvokeRequest(RpcRequest request, RpcRoute route, IServiceProvider serviceProvider = null, JsonSerializerSettings jsonSerializerSettings = null) { try { if (request == null) { throw new ArgumentNullException(nameof(request)); } if (route == null) { throw new ArgumentNullException(nameof(route)); } } catch (ArgumentNullException ex) // Dont want to throw any exceptions when doing async requests { return(this.GetUnknownExceptionReponse(request, ex)); } this.Logger?.LogDebug($"Invoking request with id '{request.Id}'"); RpcResponse rpcResponse; try { if (!string.Equals(request.JsonRpcVersion, JsonRpcContants.JsonRpcVersion)) { throw new RpcInvalidRequestException($"Request must be jsonrpc version '{JsonRpcContants.JsonRpcVersion}'"); } object[] parameterList; RpcMethod rpcMethod = this.GetMatchingMethod(route, request, out parameterList, serviceProvider, jsonSerializerSettings); this.Logger?.LogDebug($"Attempting to invoke method '{request.Method}'"); object result = rpcMethod.Invoke(parameterList); this.Logger?.LogDebug($"Finished invoking method '{request.Method}'"); JsonSerializer jsonSerializer = JsonSerializer.Create(jsonSerializerSettings); JToken resultJToken = result != null?JToken.FromObject(result, jsonSerializer) : null; rpcResponse = new RpcResponse(request.Id, resultJToken); } catch (RpcException ex) { this.Logger?.LogException(ex, "An Rpc error occurred. Returning an Rpc error response"); RpcError error = new RpcError(ex, this.ShowServerExceptions); rpcResponse = new RpcResponse(request.Id, error); } catch (Exception ex) { rpcResponse = this.GetUnknownExceptionReponse(request, ex); } if (request.Id != null) { this.Logger?.LogDebug($"Finished request with id '{request.Id}'"); //Only give a response if there is an id return(rpcResponse); } this.Logger?.LogDebug($"Finished request with no id. Not returning a response"); return(null); }
/// <summary> /// Finds the matching Rpc method for the current request /// </summary> /// <param name="route">Rpc route for the current request</param> /// <param name="request">Current Rpc request</param> /// <param name="parameterList">Paramter list parsed from the request</param> /// <param name="serviceProvider">(Optional)IoC Container for rpc method controllers</param> /// <param name="jsonSerializerSettings">Json serialization settings that will be used in serialization and deserialization for rpc requests</param> /// <returns>The matching Rpc method to the current request</returns> private RpcMethod GetMatchingMethod(RpcRoute route, RpcRequest request, out object[] parameterList, IServiceProvider serviceProvider = null, JsonSerializerSettings jsonSerializerSettings = null) { if (route == null) { throw new ArgumentNullException(nameof(route)); } if (request == null) { throw new ArgumentNullException(nameof(request)); } this.Logger?.LogDebug($"Attempting to match Rpc request to a method '{request.Method}'"); List <RpcMethod> methods = DefaultRpcInvoker.GetRpcMethods(route, serviceProvider, jsonSerializerSettings); methods = methods .Where(m => string.Equals(m.Method, request.Method, StringComparison.OrdinalIgnoreCase)) .ToList(); RpcMethod rpcMethod = null; parameterList = null; if (methods.Count > 1) { foreach (RpcMethod method in methods) { bool matchingMethod; if (request.ParameterMap != null) { matchingMethod = method.HasParameterSignature(request.ParameterMap, out parameterList); } else { matchingMethod = method.HasParameterSignature(request.ParameterList); parameterList = request.ParameterList; } if (matchingMethod) { if (rpcMethod != null) //If already found a match { throw new RpcAmbiguousMethodException(); } rpcMethod = method; } } } else if (methods.Count == 1) { //Only signature check for methods that have the same name for performance reasons rpcMethod = methods.First(); if (request.ParameterMap != null) { bool signatureMatch = rpcMethod.TryParseParameterList(request.ParameterMap, out parameterList); if (!signatureMatch) { throw new RpcMethodNotFoundException(); } } else { parameterList = request.ParameterList; } } if (rpcMethod == null) { throw new RpcMethodNotFoundException(); } this.Logger?.LogDebug("Request was matched to a method"); return(rpcMethod); }
/// <summary> /// Mapping of <see cref="RpcMethod"/> to real method calls (just boilerplate code; /// we could auto-generate this method later in .NET 5 with source generators) /// </summary> public override Task <byte[]?>?Execute(RpcMethod method) => method.Name switch { "ReceiveMessage" => ReceiveMessage(method.GetParam <string>(0), method.GetParam <string>(1)).Serialize(),
/// <summary> /// Gets all the predefined Rpc methods for a Rpc route /// </summary> /// <param name="route">The route to get Rpc methods for</param> /// <param name="serviceProvider">(Optional) IoC Container for rpc method controllers</param> /// <param name="jsonSerializerSettings">Json serialization settings that will be used in serialization and deserialization for rpc requests</param> /// <returns>List of Rpc methods for the specified Rpc route</returns> private static List<RpcMethod> GetRpcMethods(RpcRoute route, IServiceProvider serviceProvider = null, JsonSerializerSettings jsonSerializerSettings = null) { List<RpcMethod> rpcMethods = new List<RpcMethod>(); foreach (RouteCriteria routeCriteria in route.RouteCriteria) { foreach (Type type in routeCriteria.Types) { MethodInfo[] publicMethods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance); foreach (MethodInfo publicMethod in publicMethods) { RpcMethod rpcMethod = new RpcMethod(type, route, publicMethod, serviceProvider, jsonSerializerSettings); rpcMethods.Add(rpcMethod); } } } return rpcMethods; }