示例#1
0
        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();
 }
示例#3
0
        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
示例#4
0
        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 }));
        }
示例#6
0
 private RpcCall CreateCall(string methodName, string targetPeerID,
                            RpcRetryStrategy retry = RpcRetryStrategy.Retry) => new RpcCall
 {
     Method        = RpcMethod.Create(methodName),
     RetryStrategy = retry,
     RemotePeerID  = targetPeerID
 };
示例#7
0
        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);
        }
示例#8
0
 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 });
        }
示例#10
0
        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);
        }
示例#12
0
 public void WriteReturn(RpcMethod method, BinaryWriter bw, object value)
 {
     switch (method.MethodId)
     {
     case 1:
         bw.Write((Boolean)value);
         break;
     }
 }
示例#13
0
 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;
     }
 }
示例#14
0
 public void Dispatch(IRpcImplInstnce impl, RpcMethod method, ServiceImplementStub.SendResult cont)
 {
     switch (method.MethodId)
     {
     case 1:
         ((ILogic2CliImpl)impl).ServerMessageOk();
         break;
     }
 }
示例#15
0
        public RpcMethod Read(BinaryReader br)
        {
            RpcMethod method = new RpcMethod();

            method.MethodId = br.ReadUInt32();
            switch (method.MethodId)
            {
            case 1:
                break;
            }
            return(method);
        }
示例#16
0
        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);
        }
示例#17
0
        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);
            }
        }
示例#18
0
        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);
        }
示例#20
0
        /// <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);
        }
示例#21
0
 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;
     }
 }
示例#22
0
        /// <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);
        }
示例#23
0
 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);
             }
         }
     }
 }
示例#24
0
        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);
        }
示例#25
0
        /// <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);
        }
示例#26
0
        /// <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);
        }
示例#27
0
        } = 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);
示例#28
0
 public void addRpcMethod(string name, RpcMethod method)
 {
     RPCHandler [name] = method;
 }
示例#29
0
		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;
		}
示例#30
0
        /// <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);
        }
示例#31
0
        /// <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);
        }
示例#32
0
 /// <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(),
示例#33
0
		/// <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;
		}