Example #1
0
        public IObservable <JsonResponse <T> > Invoke <T>(string method, object[] args)
        {
            var req = new AustinHarris.JsonRpc.JsonRequest()
            {
                Method = method,
                Params = args
            };

            return(InvokeRequest <T>(req));
        }
Example #2
0
        public IObservable <JsonResponse <T> > InvokeSingleArgument <T>(string method, object arg)
        {
            var req = new AustinHarris.JsonRpc.JsonRequest()
            {
                Method = method,
                Params = new object[] { arg }
            };

            return(InvokeRequest <T>(req));
        }
Example #3
0
        public IObservable <JsonResponse <T> > InvokeWithScheduler <T>(string method, object[] args, IScheduler scheduler)
        {
            var req = new AustinHarris.JsonRpc.JsonRequest()
            {
                Method = method,
                Params = args
            };

            return(InvokeRequestWithScheduler <T>(req, scheduler));
        }
        private JsonRpcException PreProcess(JsonRequest rpc, object context)
        {
            // Useful for logging or authentication using the context.

            if(!string.Equals(rpc.Method, "RequiresCredentials",StringComparison.CurrentCultureIgnoreCase))
                return null;
                        
            // If this is using the ASP.Net handler then the context will contain the httpRequest
            // you could use that for cookies or IP authentication.

            // Here we will just check that the first parameter is a magic Key
            // DO NOT do this type of thing in production code. You would be better just checking the parameter inside the JsonRpcMethod.
            var j = rpc.Params as Newtonsoft.Json.Linq.JArray;
            if (j == null 
                || j[0] == null
                || j[0].Type != Newtonsoft.Json.Linq.JTokenType.String
                || !string.Equals(j[0].ToString(), "GoodPassword", StringComparison.CurrentCultureIgnoreCase)
                ) return new JsonRpcException(-2, "This exception was thrown using: JsonRpcTest.Global.PreProcess, Not Authenticated", null);

            return null;
        }
Example #5
0
        /// <summary>
        /// Sets a new difficulty to the miner and sends it.
        /// </summary>
        public void SetDifficulty(float difficulty)
        {
            if (Difficulty == difficulty) // if new difficulty is the same with current one,
                return; // just skip.

            PreviousDifficulty = Difficulty; // store the previous difficulty (so we can still accept shares targeted for last difficulty when vardiff sets a new difficulty).
            Difficulty = difficulty;

            var notification = new JsonRequest
            {
                Id = null,
                Method = "mining.set_difficulty",
                Params = new List<object>{ Difficulty }
            };

            Send(notification); //send the difficulty update message.
            _storageLayer.UpdateDifficulty(this); // store the new difficulty within persistance layer.
        }
Example #6
0
        private void Send(JsonRequest request)
        {
            var json = JsonConvert.SerializeObject(request) + "\n";

            var data = Encoding.UTF8.GetBytes(json);
            Connection.Send(data);

            _packetLogger.Verbose("tx: {0}", data.ToEncodedString().PrettifyJson());
        }
Example #7
0
        /// <summary>
        /// Sends a mining-job to miner.
        /// </summary>
        public void SendJob(IJob job)
        {
            var notification = new JsonRequest
            {
                Id = null,
                Method = "mining.notify",
                Params = job
            };

            Send(notification);
        }
Example #8
0
        /// <summary>
        /// Sends message of the day to miner.
        /// </summary>
        public void SendMessage(string message)
        {
            var notification = new JsonRequest
            {
                Id = null,
                Method = "client.show_message",
                Params = new List<object> { message }
            };

            Send(notification);
        }
Example #9
0
        public void TestJsonpWithHttpGet()
        {
            string method = "internal.echo";
            string input = "Echo this sucka";
            string id = "1";
            string callbackName = "myCallback";
            object[] parameters = new object[1];
            parameters[0] = input;

            JsonRequest jsonParameters = new JsonRequest()
            {
                Method = method,
                Params = parameters,
                Id = id
            };
            var serailaizedParameters = Newtonsoft.Json.JsonConvert.SerializeObject(jsonParameters);
            string uri = string.Format("{0}?jsonrpc={1}&callback={2}", remoteUri, serailaizedParameters, callbackName, id);

            WebRequest request = WebRequest.Create(uri);
            WebResponse response = request.GetResponse();
            StreamReader reader = new StreamReader(response.GetResponseStream());

            var regexPattern = callbackName + @"\({.*}\)";

            var result = reader.ReadToEnd().Trim();

            Assert.IsTrue(Regex.IsMatch(result, regexPattern));
        }
Example #10
0
        public void TestJsonPWithHttpPost()
        {
            string method = "internal.echo";
            string input = "Echo this sucka";
            string id = "1";
            string callbackName = "myCallback";
            object[] parameters = new object[1];
            parameters[0] = input;

            JsonRequest jsonParameters = new JsonRequest()
            {
                Method = method,
                Params = parameters,
                Id = id
            };

            var serailaizedParameters = Newtonsoft.Json.JsonConvert.SerializeObject(jsonParameters);
            var postData = string.Format("jsonrpc={0}&callback={1}", serailaizedParameters, callbackName);

            WebRequest request = WebRequest.Create(remoteUri);
            request.ContentType = "application/x-www-form-urlencoded";
            request.Method = "POST";

            byte[] bytes = System.Text.Encoding.ASCII.GetBytes(postData);
            request.ContentLength = bytes.Length;

            using (Stream stream = request.GetRequestStream())
            {
                stream.Write(bytes, 0, bytes.Length);
                stream.Close();
            }

            WebResponse response = request.GetResponse();
            StreamReader reader = new StreamReader(response.GetResponseStream());
            //myCallback({"jsonrpc":"2.0","result":"Echo this sucka","id":"1"})
            var regexPattern = callbackName + @"\({.*}\)";
            var result = reader.ReadToEnd().Trim();

            Assert.IsTrue(Regex.IsMatch(result, regexPattern));
        }
Example #11
0
 private JsonRpcException ProcessException(JsonRequest req,JsonRpcException ex)
 {
     if(externalErrorHandler!=null)
         return externalErrorHandler(req,ex);
     return ex;
 }
Example #12
0
        /// <summary>
        /// Sends difficulty to the miner.
        /// </summary>
        public void SendDifficulty()
        {
            var notification = new JsonRequest
            {
                Id = null,
                Method = "mining.set_difficulty",
                Params = new Difficulty(Difficulty)
            };

            var json = JsonConvert.SerializeObject(notification) + "\n";

            var data = Encoding.UTF8.GetBytes(json);
            Connection.Send(data);

            _logger.Verbose("tx: {0}", data.ToEncodedString().PrettifyJson());
        }
Example #13
0
        /// <summary>
        /// Sends a mining-job to miner.
        /// </summary>
        public void SendJob(JobNotification jobNotification)
        {
            var notification = new JsonRequest
            {
                Id = null,
                Method = "mining.notify",
                Params = jobNotification
            };

            //Params = new JobNotification()
            //{
            //    Id = "2b50",
            //    PreviousBlockHash = "8f0472e229d7f803642efac67a3daeabbe9bda7ac7872ea19e3978cf3e65261d",
            //    CoinbaseInitial = "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff2703c33a07062f503253482f047028a25208",
            //    CoinbaseFinal = "0d2f7374726174756d506f6f6c2f0000000001fe7aaa2a010000001976a9145b771921a9b47ee8104da7e4710b5f633d95fa7388ac00000000",
            //    MerkleBranches = new List<object>
            //    {
            //        "795ec58b7ebf9522ad15b76207c8f40e569cfd478c2e2c30bfa06c8a6d24609d",
            //        "e76544a1b9d7550280c49bf965d5882c65f8cd4b9711202cc9bd311f76b438ac",
            //        "01acd5a2a3142d735e4847a5b512aef35f22f67eb2d7be1f4dcdfca3c4031a43",
            //        "4c561433d42406ca777fb1aa730a6b96317ca68c2341b5f0f52afc2ae1b6235d"
            //    },
            //    BlockVersion = "00000002",
            //    NetworkDifficulty = "1b1d88f6",
            //    nTime = "52a22871",
            //    CleanJobs = false
            //}

            var json = JsonConvert.SerializeObject(notification) + "\n";

            var data = Encoding.UTF8.GetBytes(json);
            this.Connection.Send(data);

            Log.Verbose("RPC-client send:\n{0}", data.ToEncodedString());
        }
Example #14
0
 private JsonRpcException PreProcess(JsonRequest request, object context)
 {
     return(externalPreProcessingHandler?.Invoke(request, context));
 }
Example #15
0
        protected JsonResponse handleJsonRpcRequest(String method, Object[] parameters, string uniqueID)
        {
            try
            {
                JsonRequest request = new JsonRequest
                {
                    Method = method,
                    Params = parameters,
                    Id = uniqueID
                };
                JArray jsonParams = request.Params as JArray;
                JsonResponse jsonResponse = null;

                // create a JSON string from the request object
                String requestString = JsonConvert.SerializeObject(request, new JsonSerializerSettings
                {
                    ReferenceLoopHandling = ReferenceLoopHandling.Serialize
                });

                Trace.TraceInformation("sending request: " + requestString);
                // attempting to send the request via the writer to
                // the JSON-RPC server might throw an IOException
                if (writer != null)
                {
                    writer.Write(requestString);
                    // flush the stream to make sure the request is sent via the socket
                    writer.Flush();
                }

                // try to receive a response via the reader
                if (reader != null)
                {
                    var response = jsonSerializer.Deserialize(reader, typeof(JsonResponse));
                    // check whether a response has been received
                    if (response != null)
                    {
                        jsonResponse = (JsonResponse)response;
                        // (re-)serialize the response for informational purposes
                        String responseString = JsonConvert.SerializeObject(jsonResponse);

                        Trace.TraceInformation("received response: " + responseString);
                    }
                    else
                    {
                        // connection to JSON-RPC server is lost
                        Trace.TraceInformation("server connection dropped");
                        establishSocketConnection();
                    }
                }
                else
                {
                    // connection to JSON-RPC server is lost
                    Trace.TraceInformation("server connection dropped");
                    establishSocketConnection();
                }
                return jsonResponse;
            }
            catch (Exception ex)
            {
                Trace.TraceInformation("There was an error while handling a JSONRCP request, was the server shutting down? Error reads: " + ex.Message);
                return null;
            }
        }
Example #16
0
        /// <summary>
        /// Sends a mining-job to miner.
        /// </summary>
        public void SendJob(IJob job)
        {
            var notification = new JsonRequest
            {
                Id = null,
                Method = "mining.notify",
                Params = job
            };

            var json = JsonConvert.SerializeObject(notification) + "\n";

            var data = Encoding.UTF8.GetBytes(json);
            Connection.Send(data);

            Log.ForContext<StratumMiner>().Verbose("Send:\n{0}", data.ToEncodedString().PrettifyJson());
        }
Example #17
0
 private AustinHarris.JsonRpc.JsonRpcException OnJsonRpcException(AustinHarris.JsonRpc.JsonRequest rpc, AustinHarris.JsonRpc.JsonRpcException ex)
 {
     return(ex);
 }
Example #18
0
        /// <summary>
        /// Invokes a method to handle a JsonRpc request.
        /// </summary>
        /// <param name="Rpc">JsonRpc Request to be processed</param>
        /// <param name="RpcContext">Optional context that will be available from within the jsonRpcMethod.</param>
        /// <returns></returns>
        public JsonResponse Handle(JsonRequest Rpc, Object RpcContext = null)
        {
            AddRpcContext(RpcContext);

            var preProcessingException = PreProcess(Rpc, RpcContext);

            if (preProcessingException != null)
            {
                JsonResponse response = new JsonResponse()
                {
                    Error = preProcessingException,
                    Id    = Rpc.Id
                };
                //callback is called - if it is empty then nothing will be done
                //return response always- if callback is empty or not
                return(PostProcess(Rpc, response, RpcContext));
            }

            SMDService metadata = null;
            Delegate   handle   = null;

            if (this.MetaData.Services.TryGetValue(Rpc.Method, out metadata))
            {
                handle = metadata.dele;
            }
            else if (metadata == null)
            {
                JsonResponse response = new JsonResponse()
                {
                    Result = null,
                    Error  = new JsonRpcException(-32601, "Method not found", "The method does not exist / is not available."),
                    Id     = Rpc.Id
                };
                return(PostProcess(Rpc, response, RpcContext));
            }

            object[] parameters          = null;
            bool     expectsRefException = false;
            var      metaDataParamCount  = metadata.parameters.Count(x => x != null);


            var loopCt   = 0;
            var getCount = Rpc.Params as ICollection;

            if (getCount != null)
            {
                loopCt = getCount.Count;
            }

            var paramCount = loopCt;

            if (paramCount == metaDataParamCount - 1 && metadata.parameters[metaDataParamCount - 1].ObjectType.Name.Equals(Name_of_JSONRPCEXCEPTION))
            {
                paramCount++;
                expectsRefException = true;
            }
            parameters = new object[paramCount];

            if (Rpc.Params is Newtonsoft.Json.Linq.JArray)
            {
                var jarr = ((Newtonsoft.Json.Linq.JArray)Rpc.Params);
                for (int i = 0; i < loopCt && i < metadata.parameters.Length; i++)
                {
                    parameters[i] = CleanUpParameter(jarr[i], metadata.parameters[i]);
                }
            }
            else if (Rpc.Params is Newtonsoft.Json.Linq.JObject)
            {
                var asDict = Rpc.Params as IDictionary <string, Newtonsoft.Json.Linq.JToken>;
                for (int i = 0; i < loopCt && i < metadata.parameters.Length; i++)
                {
                    if (asDict.ContainsKey(metadata.parameters[i].Name) == true)
                    {
                        parameters[i] = CleanUpParameter(asDict[metadata.parameters[i].Name], metadata.parameters[i]);
                        continue;
                    }
                    else
                    {
                        var foundDefault = metadata.defaultValues
                                           .FirstOrDefault(defaul => defaul.Name == metadata.parameters[i].Name);
                        if (foundDefault != null)
                        {
                            parameters[i] = foundDefault.Value;
                            continue;
                        }

                        JsonResponse response = new JsonResponse()
                        {
                            Error = ProcessException(Rpc,
                                                     new JsonRpcException(-32602,
                                                                          "Invalid params",
                                                                          string.Format("Named parameter '{0}' was not present.",
                                                                                        metadata.parameters[i].Name)
                                                                          )),
                            Id = Rpc.Id
                        };
                        return(PostProcess(Rpc, response, RpcContext));
                    }
                }
            }

            // Optional Parameter support
            // check if we still miss parameters compared to metadata which may include optional parameters.
            // if the rpc-call didn't supply a value for an optional parameter, we should be assinging the default value of it.
            if (parameters.Length < metaDataParamCount && metadata.defaultValues.Length > 0)                   // rpc call didn't set values for all optional parameters, so we need to assign the default values for them.
            {
                var suppliedParamsCount = parameters.Length;                                                   // the index we should start storing default values of optional parameters.
                var missingParamsCount  = metaDataParamCount - parameters.Length;                              // the amount of optional parameters without a value set by rpc-call.
                Array.Resize(ref parameters, parameters.Length + missingParamsCount);                          // resize the array to include all optional parameters.

                for (int paramIndex = parameters.Length - 1, defaultIndex = metadata.defaultValues.Length - 1; // fill missing parameters from the back
                     paramIndex >= suppliedParamsCount && defaultIndex >= 0;                                   // to don't overwrite supplied ones.
                     paramIndex--, defaultIndex--)
                {
                    parameters[paramIndex] = metadata.defaultValues[defaultIndex].Value;
                }

                if (missingParamsCount > metadata.defaultValues.Length)
                {
                    JsonResponse response = new JsonResponse
                    {
                        Error = ProcessException(Rpc,
                                                 new JsonRpcException(-32602,
                                                                      "Invalid params",
                                                                      string.Format(
                                                                          "Number of default parameters {0} not sufficient to fill all missing parameters {1}",
                                                                          metadata.defaultValues.Length, missingParamsCount)
                                                                      )),
                        Id = Rpc.Id
                    };
                    return(PostProcess(Rpc, response, RpcContext));
                }
            }

            if (parameters.Length != metaDataParamCount)
            {
                JsonResponse response = new JsonResponse()
                {
                    Error = ProcessException(Rpc,
                                             new JsonRpcException(-32602,
                                                                  "Invalid params",
                                                                  string.Format("Expecting {0} parameters, and received {1}",
                                                                                metadata.parameters.Length,
                                                                                parameters.Length)
                                                                  )),
                    Id = Rpc.Id
                };
                return(PostProcess(Rpc, response, RpcContext));
            }

            try
            {
                var results = handle.DynamicInvoke(parameters);

                var          last             = parameters.LastOrDefault();
                var          contextException = RpcGetAndRemoveRpcException();
                JsonResponse response         = null;
                if (contextException != null)
                {
                    response = new JsonResponse()
                    {
                        Error = ProcessException(Rpc, contextException), Id = Rpc.Id
                    };
                }
                else if (expectsRefException && last != null && last is JsonRpcException)
                {
                    response = new JsonResponse()
                    {
                        Error = ProcessException(Rpc, last as JsonRpcException), Id = Rpc.Id
                    };
                }
                else
                {
                    response = new JsonResponse()
                    {
                        Result = results
                    };
                }
                return(PostProcess(Rpc, response, RpcContext));
            }
            catch (Exception ex)
            {
                JsonResponse response;
                if (ex is TargetParameterCountException)
                {
                    response = new JsonResponse()
                    {
                        Error = ProcessException(Rpc, new JsonRpcException(-32602, "Invalid params", ex))
                    };
                    return(PostProcess(Rpc, response, RpcContext));
                }

                // We really dont care about the TargetInvocationException, just pass on the inner exception
                if (ex is JsonRpcException)
                {
                    response = new JsonResponse()
                    {
                        Error = ProcessException(Rpc, ex as JsonRpcException)
                    };
                    return(PostProcess(Rpc, response, RpcContext));
                }
                if (ex.InnerException != null && ex.InnerException is JsonRpcException)
                {
                    response = new JsonResponse()
                    {
                        Error = ProcessException(Rpc, ex.InnerException as JsonRpcException)
                    };
                    return(PostProcess(Rpc, response, RpcContext));
                }
                else if (ex.InnerException != null)
                {
                    response = new JsonResponse()
                    {
                        Error = ProcessException(Rpc, new JsonRpcException(-32603, "Internal Error", ex.InnerException))
                    };
                    return(PostProcess(Rpc, response, RpcContext));
                }

                response = new JsonResponse()
                {
                    Error = ProcessException(Rpc, new JsonRpcException(-32603, "Internal Error", ex))
                };
                return(PostProcess(Rpc, response, RpcContext));
            }
            finally
            {
                RemoveRpcContext();
            }
        }
Example #19
0
        private JsonResponse PostProcess(Action<JsonResponse> callback, JsonRequest request, JsonResponse response, object context)
        {
            if (externalPostProcessingHandler != null)
            {
                try
                {
                    JsonRpcException exception = externalPostProcessingHandler(request, response, context);
                    if (exception != null)
                    {
                        response = new JsonResponse() { Error = exception };
                    }
                }
                catch (Exception ex)
                {
                    response = new JsonResponse() { Error = ProcessException(request, new JsonRpcException(-32603, "Internal Error", ex)) };
                }
            }

            if (callback != null)
                callback.Invoke(response);

            return response;
        }
Example #20
0
            public JsonRpcException PreProcess(JsonRequest rpc, object context)
            {
                run++;

                this.rpc = rpc;
                this.context = context;

                return null;
            }
Example #21
0
        /// <summary>
        /// Invokes a method to handle a JsonRpc request.
        /// </summary>
        /// <param name="Rpc">JsonRpc Request to be processed</param>
        /// <param name="RpcContext">Optional context that will be available from within the jsonRpcMethod.</param>
        /// <returns></returns>
        public JsonResponse Handle(JsonRequest Rpc, Object RpcContext = null, Action<JsonResponse> callback = null)
        {
            //empty delegate declaration if callback is not provided
            if (null == callback)
            {
                callback = delegate(JsonResponse a) { };
            }

            AddRpcContext(RpcContext);

            var preProcessingException = PreProcess(Rpc, RpcContext);
            if (preProcessingException != null)
            {
                JsonResponse response = new JsonResponse()
                {
                    Error = preProcessingException,
                    Id = Rpc.Id
                };
                //callback is called - if it is empty then nothing will be done
                callback.Invoke(response);
                //return response always- if callback is empty or not
                return response;
            }

            SMDService metadata = null;
            Delegate handle = null;
            var haveDelegate = this.Handlers.TryGetValue(Rpc.Method, out handle);
            var haveMetadata = this.MetaData.Services.TryGetValue(Rpc.Method, out metadata);

            if (haveDelegate == false || haveMetadata == false || metadata == null || handle == null)
            {
                JsonResponse response = new JsonResponse()
                {
                    Result = null,
                    Error = new JsonRpcException(-32601, "Method not found", "The method does not exist / is not available."),
                    Id = Rpc.Id
                };
                callback.Invoke(response);
                return response;
            }

            bool isJObject = Rpc.Params is Newtonsoft.Json.Linq.JObject;
            bool isJArray = Rpc.Params is Newtonsoft.Json.Linq.JArray;
            object[] parameters = null;
            bool expectsRefException = false;
            var metaDataParamCount = metadata.parameters.Count(x => x != null);

            var getCount = Rpc.Params as ICollection;
            var loopCt = 0;

            if (getCount != null)
            {
                loopCt = getCount.Count;
            }

            var paramCount = loopCt;
            if (paramCount == metaDataParamCount - 1 && metadata.parameters[metaDataParamCount - 1].ObjectType.Name.Contains(typeof(JsonRpcException).Name))
            {
                paramCount++;
                expectsRefException = true;
            }
            parameters = new object[paramCount];

            if (isJArray)
            {
                var jarr = ((Newtonsoft.Json.Linq.JArray)Rpc.Params);
                //var loopCt = jarr.Count;
                //var pCount = loopCt;
                //if (pCount == metaDataParamCount - 1 && metadata.parameters[metaDataParamCount].GetType() == typeof(JsonRpcException))
                //    pCount++;
                //parameters = new object[pCount];
                for (int i = 0; i < loopCt; i++)
                {
                    parameters[i] = CleanUpParameter(jarr[i], metadata.parameters[i]);
                }
            }
            else if (isJObject)
            {
                var jo = Rpc.Params as Newtonsoft.Json.Linq.JObject;
                //var loopCt = jo.Count;
                //var pCount = loopCt;
                //if (pCount == metaDataParamCount - 1 && metadata.parameters[metaDataParamCount].GetType() == typeof(JsonRpcException))
                //    pCount++;
                //parameters = new object[pCount];
                var asDict = jo as IDictionary<string, Newtonsoft.Json.Linq.JToken>;
                for (int i = 0; i < loopCt; i++)
                {
                    if (asDict.ContainsKey(metadata.parameters[i].Name) == false)
                    {
                        JsonResponse response = new JsonResponse()
                        {
                            Error = ProcessException(Rpc,
                            new JsonRpcException(-32602,
                                "Invalid params",
                                string.Format("Named parameter '{0}' was not present.",
                                                metadata.parameters[i].Name)
                                )),
                            Id = Rpc.Id
                        };
                        callback.Invoke(response);
                        return response;
                    }
                    parameters[i] = CleanUpParameter(jo[metadata.parameters[i].Name], metadata.parameters[i]);
                }
            }

            // Optional Parameter support
            // check if we still miss parameters compared to metadata which may include optional parameters.
            // if the rpc-call didn't supply a value for an optional parameter, we should be assinging the default value of it.
            if (parameters.Length < metaDataParamCount && metadata.defaultValues.Length > 0) // rpc call didn't set values for all optional parameters, so we need to assign the default values for them.
            {
                var suppliedParamsCount = parameters.Length; // the index we should start storing default values of optional parameters.
                var missingParamsCount = metaDataParamCount - parameters.Length; // the amount of optional parameters without a value set by rpc-call.
                Array.Resize(ref parameters, parameters.Length + missingParamsCount); // resize the array to include all optional parameters.

                for (int paramIndex = parameters.Length - 1, defaultIndex = metadata.defaultValues.Length - 1;     // fill missing parameters from the back 
                    paramIndex >= suppliedParamsCount && defaultIndex >= 0;                                        // to don't overwrite supplied ones.
                    paramIndex--, defaultIndex--)
                {
                    parameters[paramIndex] = metadata.defaultValues[defaultIndex].Value;
                }

                if (missingParamsCount > metadata.defaultValues.Length)
                {
                    JsonResponse response = new JsonResponse
                    {
                        Error = ProcessException(Rpc,
                            new JsonRpcException(-32602,
                                "Invalid params",
                                string.Format(
                                    "Number of default parameters {0} not sufficient to fill all missing parameters {1}",
                                    metadata.defaultValues.Length, missingParamsCount)
                                )),
                        Id = Rpc.Id
                    };
                    callback.Invoke(response);
                    return response;
                }
            }

            if (parameters.Length != metaDataParamCount)
            {
                JsonResponse response = new JsonResponse()
                {
                    Error = ProcessException(Rpc,
                    new JsonRpcException(-32602,
                        "Invalid params",
                        string.Format("Expecting {0} parameters, and received {1}",
                                        metadata.parameters.Length,
                                        parameters.Length)
                        )),
                    Id = Rpc.Id
                };
                callback.Invoke(response);
                return response;
            }

            try
            {
                //callback is stored to thread's local storage in order to get it directly from concrete JsonRpcService method implementation
                //where callback is just returned from method
               Thread.SetData(Thread.GetNamedDataSlot(THREAD_CALLBACK_SLOT_NAME), callback);
               
                
                var results = handle.DynamicInvoke(parameters);
                
                var last = parameters.LastOrDefault();
                JsonRpcException contextException;
                if (Task.CurrentId.HasValue && RpcExceptions.TryRemove(Task.CurrentId.Value, out contextException))
                {
                    JsonResponse response = new JsonResponse() { Error = ProcessException(Rpc, contextException), Id = Rpc.Id };
                    callback.Invoke(response);
                    return response;
                }
                if (expectsRefException && last != null && last is JsonRpcException)
                {
                    JsonResponse response = new JsonResponse() { Error = ProcessException(Rpc, last as JsonRpcException), Id = Rpc.Id };
                    callback.Invoke(response);
                    return response;
                }
                //return response, if callback is set (method is asynchronous) - result could be empty string and future result operations
                //will be processed in the callback
                return new JsonResponse() { Result = results };
            }
            catch (Exception ex)
            {
                JsonResponse response;
                if (ex is TargetParameterCountException)
                {
                    response = new JsonResponse() { Error = ProcessException(Rpc, new JsonRpcException(-32602, "Invalid params", ex)) };
                    callback.Invoke(response);
                    return response;
                }

                // We really dont care about the TargetInvocationException, just pass on the inner exception
                if (ex is JsonRpcException)
                {
                    response = new JsonResponse() { Error = ProcessException(Rpc, ex as JsonRpcException) };
                    callback.Invoke(response);
                    return response;
                }
                if (ex.InnerException != null && ex.InnerException is JsonRpcException)
                {
                    response = new JsonResponse() { Error = ProcessException(Rpc, ex.InnerException as JsonRpcException) };
                    callback.Invoke(response);
                    return response;
                }
                else if (ex.InnerException != null)
                {
                    response = new JsonResponse() { Error = ProcessException(Rpc, new JsonRpcException(-32603, "Internal Error", ex.InnerException)) };
                    callback.Invoke(response);
                    return response;
                }

                response = new JsonResponse() { Error = ProcessException(Rpc, new JsonRpcException(-32603, "Internal Error", ex)) };
                callback.Invoke(response);
                return response;
            }
            finally
            {
                RemoveRpcContext();
            }
        }
Example #22
0
        /// <summary>
        /// Invokes a method to handle a JsonRpc request.
        /// </summary>
        /// <param name="Rpc">JsonRpc Request to be processed</param>
        /// <param name="RpcContext">Optional context that will be available from within the jsonRpcMethod.</param>
        /// <returns></returns>
        public JsonResponse Handle(JsonRequest Rpc, Object RpcContext = null)
        {
            AddRpcContext(RpcContext);

            var preProcessingException = PreProcess(Rpc, RpcContext);
            if (preProcessingException != null)
            {
                return new JsonResponse() { Error = preProcessingException,
                    Id = Rpc.Id };
            }

            SMDService metadata = null;
            Delegate handle = null;
            var haveDelegate = this.Handlers.TryGetValue(Rpc.Method, out handle);
            var haveMetadata = this.MetaData.Services.TryGetValue(Rpc.Method, out metadata);

            if (haveDelegate == false || haveMetadata == false || metadata == null || handle == null)
            {
                return new JsonResponse() { Result = null, Error = new JsonRpcException(-32601, "Method not found", "The method does not exist / is not available."), Id = Rpc.Id };
            }
            if (Rpc.Params is ICollection == false)
            {
                return new JsonResponse()
                {
                    Result = null,
                    Error = new JsonRpcException(-32602,
                        "Invalid params", "The number of parameters could not be counted"),
                    Id = Rpc.Id
                };
            }

            bool isJObject = Rpc.Params is Newtonsoft.Json.Linq.JObject;
            bool isJArray = Rpc.Params is Newtonsoft.Json.Linq.JArray;
            object[] parameters = null;
            bool expectsRefException = false;
            var metaDataParamCount = metadata.parameters.Count(x => x != null);
            
            var getCount = Rpc.Params as ICollection;
            var loopCt = getCount.Count;
            var paramCount = loopCt;
            if (paramCount == metaDataParamCount - 1 && metadata.parameters[metaDataParamCount-1].ObjectType.Name.Contains(typeof(JsonRpcException).Name))
            {
                paramCount++;
                expectsRefException = true;
            }
            parameters = new object[paramCount];

            if (isJArray)
            {
                var jarr = ((Newtonsoft.Json.Linq.JArray)Rpc.Params);
                //var loopCt = jarr.Count;
                //var pCount = loopCt;
                //if (pCount == metaDataParamCount - 1 && metadata.parameters[metaDataParamCount].GetType() == typeof(JsonRpcException))
                //    pCount++;
                //parameters = new object[pCount];
                for (int i = 0; i < loopCt; i++)
                {
                    parameters[i] = CleanUpParameter(jarr[i], metadata.parameters[i]);
                }                
            }
            else if (isJObject)
            {
                var jo = Rpc.Params as Newtonsoft.Json.Linq.JObject;
                //var loopCt = jo.Count;
                //var pCount = loopCt;
                //if (pCount == metaDataParamCount - 1 && metadata.parameters[metaDataParamCount].GetType() == typeof(JsonRpcException))
                //    pCount++;
                //parameters = new object[pCount];
                var asDict = jo as IDictionary<string, Newtonsoft.Json.Linq.JToken>;
                for (int i = 0; i < loopCt; i++)
                {
                    if (asDict.ContainsKey(metadata.parameters[i].Name) == false)
                    {
                        return new JsonResponse()
                        {
                            Error = ProcessException(Rpc,
                            new JsonRpcException(-32602,
                                "Invalid params",
                                string.Format("Named parameter '{0}' was not present.",
                                                metadata.parameters[i].Name)
                                ))
                                ,Id = Rpc.Id
                        };
                    }
                    parameters[i] = CleanUpParameter(jo[metadata.parameters[i].Name], metadata.parameters[i]);
                }
            }

            // Optional Parameter support
            // check if we still miss parameters compared to metadata which may include optional parameters.
            // if the rpc-call didn't supply a value for an optional parameter, we should be assinging the default value of it.
            if (parameters.Length < metaDataParamCount && metadata.defaultValues.Length > 0) // rpc call didn't set values for all optional parameters, so we need to assign the default values for them.
            {
                var paramIndex = parameters.Length; // the index we should start storing default values of optional parameters.
                var missingParamsCount = metaDataParamCount - parameters.Length; // the amount of optional parameters without a value set by rpc-call.
                Array.Resize(ref parameters, parameters.Length + missingParamsCount); // resize the array to include all optional parameters.

                // we need to add in reverse order as parameters can appear after all required parameters.
                // as some of the optional parameters could already have assigned their values in rpc-call,
                // by starting from the end we can make sure we only add the required default values.
                for (int k = missingParamsCount; k > 0; k--)
                {
                    var optionalParamIndex = k - 1; // the index of the optional parameter we will be currently setting a default value.
                    parameters[paramIndex] = metadata.defaultValues[optionalParamIndex].Value; // set the default value for the optional parameter that rpc-call didn't set a value for.
                    paramIndex++;
                    paramCount++; // we need to increase the paramCount by one each time we add default-value for an optional parameter that rpc-call didn't set a value for.
                }
            }
            
            if (parameters.Length != metaDataParamCount)
            {
                return new JsonResponse()
                {
                    Error = ProcessException(Rpc,
                    new JsonRpcException(-32602,
                        "Invalid params",
                        string.Format("Expecting {0} parameters, and received {1}",
                                        metadata.parameters.Length,
                                        parameters.Length)
                        )),
                    Id = Rpc.Id
                };
            }

            try
            {
                var results = handle.DynamicInvoke(parameters);
                var last = parameters.Length>0 ? parameters[paramCount - 1]:null;
                JsonRpcException contextException;
                if (Task.CurrentId.HasValue && RpcExceptions.TryRemove(Task.CurrentId.Value, out contextException))
                {
                    return new JsonResponse() { Error = ProcessException(Rpc, contextException), Id = Rpc.Id };
                }
                if (expectsRefException && last != null && last is JsonRpcException)
                {
                    return new JsonResponse() { Error = ProcessException(Rpc, last as JsonRpcException), Id = Rpc.Id };
                }

                return new JsonResponse() { Result = results };
            }
            catch (Exception ex)
            {
                if (ex is TargetParameterCountException)
                {
                    return new JsonResponse() { Error = ProcessException(Rpc, new JsonRpcException(-32602, "Invalid params", ex)) };
                }

                // We really dont care about the TargetInvocationException, just pass on the inner exception
                if (ex is JsonRpcException)
                {
                    return new JsonResponse() { Error = ProcessException(Rpc, ex as JsonRpcException) };
                }
                if (ex.InnerException != null && ex.InnerException is JsonRpcException)
                {
                    return new JsonResponse() { Error = ProcessException(Rpc, ex.InnerException as JsonRpcException) };
                }
                else if (ex.InnerException != null)
                {
                    return new JsonResponse() { Error = ProcessException(Rpc, new JsonRpcException(-32603, "Internal Error", ex.InnerException)) };
                }

                return new JsonResponse() { Error = ProcessException(Rpc, new JsonRpcException(-32603, "Internal Error", ex)) };
            }
            finally
            {
                RemoveRpcContext();
            }
        }
Example #23
0
            public JsonRpcException PostProcess(JsonRequest rpc, JsonResponse response, object context)
            {
                run++;

                this.rpc = rpc;
                this.response = response;
                this.context = context;

                if (changeResponse_)
                {
                    return new JsonRpcException(-123, "Test error", null);
                }
                return null;
            }
Example #24
0
 private JsonRpcException PreProcess(JsonRequest request, object context)
 {
     if (externalPreProcessingHandler == null)
         return null;
     return externalPreProcessingHandler(request, context);
 }
Example #25
0
        public IObservable <JsonResponse <T> > Invoke <T>(JsonRequest jsonRpc, IScheduler scheduler)
        {
            var res = Observable.Create <JsonResponse <T> >((obs) =>
                                                            scheduler.Schedule(() => {
                WebRequest req = null;
                try
                {
                    int myId;
                    lock (idLock)
                    {
                        myId = ++id;
                    }
                    jsonRpc.Id      = myId.ToString();
                    req             = HttpWebRequest.Create(new Uri(ServiceEndpoint, "?callid=" + myId.ToString()));
                    req.Method      = "Post";
                    req.ContentType = "application/json-rpc";
                }
                catch (Exception ex)
                {
                    obs.OnError(ex);
                }

                var ar = req.BeginGetRequestStream(new AsyncCallback((iar) =>
                {
                    HttpWebRequest request = null;

                    try
                    {
                        request    = (HttpWebRequest)iar.AsyncState;
                        var stream = new StreamWriter(req.EndGetRequestStream(iar));
                        var json   = Newtonsoft.Json.JsonConvert.SerializeObject(jsonRpc);
                        stream.Write(json);

                        stream.Close();
                    }
                    catch (Exception ex)
                    {
                        obs.OnError(ex);
                    }

                    var rar = req.BeginGetResponse(new AsyncCallback((riar) =>
                    {
                        JsonResponse <T> rjson = null;
                        string sstream         = "";
                        try
                        {
                            var request1 = (HttpWebRequest)riar.AsyncState;
                            var resp     = (HttpWebResponse)request1.EndGetResponse(riar);

                            using (var rstream = new StreamReader(CopyAndClose(resp.GetResponseStream())))
                            {
                                sstream = rstream.ReadToEnd();
                            }

                            rjson = Newtonsoft.Json.JsonConvert.DeserializeObject <JsonResponse <T> >(sstream);
                        }
                        catch (Exception ex)
                        {
                            Debug.WriteLine(ex.Message);
                            Debugger.Break();
                        }

                        if (rjson == null)
                        {
                            if (!string.IsNullOrEmpty(sstream))
                            {
                                JObject jo = Newtonsoft.Json.JsonConvert.DeserializeObject(sstream) as JObject;
                                obs.OnError(new Exception(jo["Error"].ToString()));
                            }
                            else
                            {
                                obs.OnError(new Exception("Empty response"));
                            }
                        }

                        obs.OnNext(rjson);
                        obs.OnCompleted();
                    }), request);
                }), req);
            }));

            return(res);
        }