Esempio n. 1
0
        /// <summary>
        /// JSON-RPC2リクエストを送信する。
        /// </summary>
        /// <param name="method">メソッド名。</param>
        /// <param name="param">引数のJSONオブジェクト(MiniJSONで変換可能な型のみ)。</param>
        /// <returns>メソッドの戻り値。</returns>
        public IObservable <string> Call(string method, object param = null)
        {
            return(Observable.Defer(() =>
            {
                // リトライされた場合もIDは変える
                var id = this.GenerateId();
                var json = new JsonRpc2Request(method, param, id).ToJson();

                var subject = new Subject <object>();
                this.callback[id] = subject;

                this.Send(json)
                .Subscribe(_ => { }, (ex) =>
                {
                    this.callback.Remove(id);
                    subject.OnError(ex);
                });

                // タイムアウトチェック用のタイマーもセットする
                if (this.Timeout > 0)
                {
                    Observable.Timer(TimeSpan.FromMilliseconds(this.Timeout)).Subscribe(_ =>
                    {
                        Subject <object> sub;
                        if (this.callback.TryGetValue(id, out sub))
                        {
                            this.callback.Remove(id);
                            sub.OnError(new JsonRpc2Exception((int)JsonRpc2Exception.ErrorCode.InternalError, "RPC response timeouted. (" + json + ")"));
                        }
                    });
                }

                return subject.Select((s) => (string)s);
            }));
        }
Esempio n. 2
0
        /// <summary>
        /// JSON-RPC2リクエスト/レスポンスを処理する。
        /// </summary>
        /// <param name="json">リクエスト/レスポンスのJSON文字列。</param>
        /// <returns>レスポンスのJSON文字列。通知やレスポンス無しの場合はnull。</returns>
        private async Task <JsonRpc2Response> DoMethodOrCallback(string json)
        {
            // TODO: バッチリクエスト/レスポンスには未対応

            // レスポンス/リクエストかチェック
            JsonRpc2Response res;
            JsonRpc2Request  req;

            if (JsonRpc2Response.TryParse(json, out res))
            {
                // ※ intのIDしか送ってないのでintのIDしか返ってこない想定
                var id = (int)(long)res.Id;
                Subject <object> subject;
                if (this.callback.TryGetValue(id, out subject))
                {
                    if (res.Error != null)
                    {
                        subject.OnError(res.Error);
                    }
                    else
                    {
                        subject.OnNext(Json.Serialize(res.Result));
                        subject.OnCompleted();
                    }

                    this.callback.Remove(id);
                }

                return(null);
            }
            else if (JsonRpc2Request.TryParse(json, out req))
            {
                // リクエストの場合はハンドラーに任せる
                try
                {
                    var result = await this.RequestHandler(req.Method, req.Params, req.Id, this);

                    if (req.Id != null)
                    {
                        return(new JsonRpc2Response(result, req.Id));
                    }

                    return(null);
                }
                catch (Exception ex)
                {
                    return(new JsonRpc2Response(JsonRpc2Exception.Convert(ex), req.Id));
                }
            }

            throw new JsonRpc2Exception(JsonRpc2Exception.ErrorCode.ParseError);
        }
Esempio n. 3
0
            /// <summary>
            /// MiniJSONのオブジェクトをJSON-RPC2リクエストとして解析する。
            /// </summary>
            /// <param name="json">JSONオブジェクト。</param>
            /// <param name="request">解析したリクエスト。</param>
            /// <returns>解析できた場合true。</returns>
            public static bool TryParse(object json, out JsonRpc2Request request)
            {
                request = null;

                var req = json as IDictionary <string, object>;

                if (req == null)
                {
                    return(false);
                }

                // 以下methodだけ必須。他はあれば取得(jsonrpcのバージョンチェックはしない)
                object method;

                if (!req.TryGetValue("method", out method) || method == null)
                {
                    return(false);
                }

                object jsonrpcObj;
                var    jsonrpc = "";

                if (req.TryGetValue("jsonrpc", out jsonrpcObj) && jsonrpcObj != null)
                {
                    jsonrpc = jsonrpcObj.ToString();
                }

                object param;

                req.TryGetValue("params", out param);
                object id;

                req.TryGetValue("id", out id);

                request = new JsonRpc2Request(method.ToString(), param, id)
                {
                    Jsonrpc = jsonrpc
                };
                return(true);
            }
Esempio n. 4
0
 /// <summary>
 /// JSON文字列をJSON-RPC2リクエストとして解析する。
 /// </summary>
 /// <param name="json">JSON文字列。</param>
 /// <param name="request">解析したリクエスト。</param>
 /// <returns>解析できた場合true。</returns>
 public static bool TryParse(string json, out JsonRpc2Request request)
 {
     return(TryParse(Json.Deserialize(json), out request));
 }