From b72110c9302c9fca113d74b12c6cb30e1b3f83aa Mon Sep 17 00:00:00 2001 From: cxl Date: Fri, 20 May 2016 13:32:19 +0000 Subject: [PATCH] Core/Rpc: rpc.EndRpc - preliminary reply to request git-svn-id: svn://ultimatepp.org/upp/trunk@9850 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- uppsrc/Core/Rpc/Rpc.h | 12 +- uppsrc/Core/Rpc/imp/Client.cpp | 4 +- uppsrc/Core/Rpc/imp/Server.cpp | 226 ++++++++++++++++++++++----------- uppsrc/Core/Rpc/legacy.h | 6 - 4 files changed, 162 insertions(+), 86 deletions(-) diff --git a/uppsrc/Core/Rpc/Rpc.h b/uppsrc/Core/Rpc/Rpc.h index a1989b4eb..189f9f273 100644 --- a/uppsrc/Core/Rpc/Rpc.h +++ b/uppsrc/Core/Rpc/Rpc.h @@ -205,6 +205,8 @@ struct RpcGet { String ToString() const { return v.ToString(); } }; +struct XmlRpcDo; + struct RpcData { String peeraddr; ValueArray in; @@ -235,8 +237,15 @@ struct RpcData { void operator=(const T& x) { out.Clear(); operator<<(x); } void Reset() { in.Clear(); out.Clear(); ii = 0; } + + void EndRpc(); - RpcData() { ii = 0; } + RpcData() { ii = 0; rpc = NULL; } + +private: + friend struct XmlRpcDo; + + XmlRpcDo *rpc; }; String FormatXmlRpcValue(const Value& value); @@ -256,7 +265,6 @@ struct RpcError { }; void SetRpcMethodFilter(String (*filter)(const String& methodname)); -String RpcExecute(const String& request, const char *group, const char *peeraddr); bool RpcPerform(TcpSocket& http, const char *group); bool RpcServerLoop(int port, const char *group = NULL); diff --git a/uppsrc/Core/Rpc/imp/Client.cpp b/uppsrc/Core/Rpc/imp/Client.cpp index f490ccd71..ccdf06e52 100644 --- a/uppsrc/Core/Rpc/imp/Client.cpp +++ b/uppsrc/Core/Rpc/imp/Client.cpp @@ -75,6 +75,8 @@ Value JsonRpcData(const Value& v) return v; } +String RpcExecute(const String& request_); + RpcGet RpcRequest::Execute() { if(!shouldExecute) @@ -129,7 +131,7 @@ RpcGet RpcRequest::Execute() String response; New(); if(shorted) - response = RpcExecute(request, "", "127.0.0.1"); + response = RpcExecute(request); else response = Post(request).Execute(); if(sLogRpcCalls) { diff --git a/uppsrc/Core/Rpc/imp/Server.cpp b/uppsrc/Core/Rpc/imp/Server.cpp index ba50bcd33..df778d0e3 100644 --- a/uppsrc/Core/Rpc/imp/Server.cpp +++ b/uppsrc/Core/Rpc/imp/Server.cpp @@ -93,38 +93,69 @@ bool CallRpcMethod(RpcData& data, const char *group, String methodname, const St return true; } -String DoXmlRpc(const String& request, const char *group, const char *peeraddr, String& methodname) +struct XmlRpcDo { + TcpSocket& http; + RpcData data; + String request; + String group; + String methodname; + Value id; + bool json; + + String XmlResult(); + String DoXmlRpc(); + String JsonRpcError(int code, const char *text, const Value& id); + String JsonResult(); + String ProcessJsonRpc(const Value& v); + String DoJsonRpc(); + String RpcExecute(); + void RpcResponse(const String& r); + void EndRpc(); + bool Perform(); + + XmlRpcDo(TcpSocket& http, const char *group); +}; + +XmlRpcDo::XmlRpcDo(TcpSocket& http, const char *group) +: http(http), group(group) +{ + data.rpc = this; +} + +String XmlRpcDo::XmlResult() +{ + String r = XmlHeader(); + r << "\r\n"; + if(IsValueArray(data.out)) { + ValueArray va = data.out; + if(va.GetCount() && IsError(va[0])) { + LLOG("ProcessingError"); + String e = GetErrorText(data.out[0]); + if(rpc_trace) + *rpc_trace << "Processing error: " << e << '\n'; + return FormatXmlRpcError(RPC_SERVER_PROCESSING_ERROR, "Processing error: " + e); + } + r << FormatXmlRpcParams(data.out); + } + r << "\r\n\r\n"; + return r; +} + +String XmlRpcDo::DoXmlRpc() { XmlParser p(request); - RpcData data; try { - String r = XmlHeader(); - r << "\r\n"; p.ReadPI(); p.PassTag("methodCall"); p.PassTag("methodName"); methodname = p.ReadText(); p.PassEnd(); - data.peeraddr = peeraddr; data.in = ParseXmlRpcParams(p); - if(CallRpcMethod(data, group, methodname, request)) { - if(IsValueArray(data.out)) { - ValueArray va = data.out; - if(va.GetCount() && IsError(va[0])) { - LLOG("ProcessingError"); - String e = GetErrorText(data.out[0]); - if(rpc_trace) - *rpc_trace << "Processing error: " << e << '\n'; - return FormatXmlRpcError(RPC_SERVER_PROCESSING_ERROR, "Processing error: " + e); - } - r << FormatXmlRpcParams(data.out); - } - r << "\r\n\r\n"; - } - else + if(!CallRpcMethod(data, group, methodname, request)) return FormatXmlRpcError(RPC_UNKNOWN_METHOD_ERROR, "\'" + methodname + "\' method is unknown"); - p.PassEnd(); - return r; + if(!data.rpc) + return Null; + return XmlResult(); } catch(RpcError e) { LLOG("Processing error: " << e.text); @@ -147,7 +178,7 @@ String DoXmlRpc(const String& request, const char *group, const char *peeraddr, return Null; } -String JsonRpcError(int code, const char *text, const Value& id) +String XmlRpcDo::JsonRpcError(int code, const char *text, const Value& id) { Json m; m("jsonrpc", "2.0"); @@ -159,42 +190,48 @@ String JsonRpcError(int code, const char *text, const Value& id) return m; } -String ProcessJsonRpc(const Value& v, const char *group, const char *peeraddr, const String& request, String& methodname) +String XmlRpcDo::JsonResult() +{ + if(IsValueArray(data.out)) { + ValueArray va = data.out; + Value result = Null; + if(va.GetCount()) { + if(IsError(va[0])) { + LLOG("ProcessingError"); + String e = GetErrorText(data.out[0]); + if(rpc_trace) + *rpc_trace << "Processing error: " << e << '\n'; + return JsonRpcError(RPC_SERVER_PROCESSING_ERROR, "Processing error: " + e, id); + } + result = JsonRpcData(va[0]); + } + Json json; + json("jsonrpc", "2.0"); + if(result.Is()) + json.CatRaw("result", result.To().json); + else + json("result", result); + json("id", id); + return json; + } + return JsonRpcError(RPC_UNKNOWN_METHOD_ERROR, "Method not found", id); +} + +String XmlRpcDo::ProcessJsonRpc(const Value& v) { LLOG("Parsed JSON request: " << v); - Value id = v["id"]; + id = v["id"]; methodname = AsString(v["method"]); Value param = v["params"]; - RpcData data; - data.peeraddr = peeraddr; if(param.Is()) data.in_map = param; else data.in = param; try { if(CallRpcMethod(data, group, methodname, request)) { - if(IsValueArray(data.out)) { - ValueArray va = data.out; - Value result = Null; - if(va.GetCount()) { - if(IsError(va[0])) { - LLOG("ProcessingError"); - String e = GetErrorText(data.out[0]); - if(rpc_trace) - *rpc_trace << "Processing error: " << e << '\n'; - return JsonRpcError(RPC_SERVER_PROCESSING_ERROR, "Processing error: " + e, id); - } - result = JsonRpcData(va[0]); - } - Json json; - json("jsonrpc", "2.0"); - if(result.Is()) - json.CatRaw("result", result.To().json); - else - json("result", result); - json("id", id); - return json; - } + if(!data.rpc) + return Null; + return JsonResult(); } return JsonRpcError(RPC_UNKNOWN_METHOD_ERROR, "Method not found", id); } @@ -212,16 +249,16 @@ String ProcessJsonRpc(const Value& v, const char *group, const char *peeraddr, c } } -String DoJsonRpc(const String& request, const char *group, const char *peeraddr, String& methodname) +String XmlRpcDo::DoJsonRpc() { try { Value v = ParseJSON(request); if(v.Is()) - return ProcessJsonRpc(v, group, peeraddr, request, methodname); + return ProcessJsonRpc(v); if(v.Is()) { JsonArray a; for(int i = 0; i < v.GetCount(); i++) - a.CatRaw(ProcessJsonRpc(v[i], group, peeraddr, request, methodname)); + a.CatRaw(ProcessJsonRpc(v[i])); return v.GetCount() ? ~a : String(); } } @@ -229,17 +266,23 @@ String DoJsonRpc(const String& request, const char *group, const char *peeraddr, return AsJSON(JsonRpcError(RPC_SERVER_JSON_ERROR, "Parse error", Null)); } -String RpcExecute(const String& request, const char *group, const char *peeraddr, bool& json) +String XmlRpcDo::RpcExecute() { - CParser p(request); + json = false; + try { + CParser p(request); + json = p.Char('{') || p.Char('['); + } + catch(CParser::Error) {} + String r; - json = p.Char('{') || p.Char('['); String mn; TimeStop tm; if(json) - r = DoJsonRpc(request, group, peeraddr, mn); + r = DoJsonRpc(); else - r = DoXmlRpc(request, group, peeraddr, mn); + r = DoXmlRpc(); + if(rpc_trace) { mn << " (" << tm.Elapsed() << " ms)"; if(rpc_trace_level == 0) @@ -259,35 +302,50 @@ String RpcExecute(const String& request, const char *group, const char *peeraddr return r; } -String RpcExecute(const String& request, const char *group, const char *peeraddr) +void XmlRpcDo::RpcResponse(const String& r) { - bool dummy; - return RpcExecute(request, group, peeraddr, dummy); + LLOG("--------- Server response:\n" << r << "============="); + String response; + String ts = WwwFormat(GetUtcTime()); + response << + "HTTP/1.0 200 OK\r\n" + "Date: " << ts << "\r\n" + "Server: U++ RPC server\r\n" + "Content-Length: " << r.GetCount() << "\r\n" + "Connection: close\r\n" + "Content-Type: application/" << (json ? "json" : "xml") << "\r\n\r\n" + << r; + LLOG(response); + if(r.GetCount()) + http.Put(response); } -bool RpcPerform(TcpSocket& http, const char *group) +void XmlRpcDo::EndRpc() +{ + RpcResponse(json ? JsonResult() : XmlResult()); +} + +void RpcData::EndRpc() +{ + if(rpc) { + rpc->EndRpc(); + rpc = NULL; + } +} + +bool XmlRpcDo::Perform() { LLOG("=== Accepted connection ==================================================="); HttpHeader hdr; if(hdr.Read(http) && hdr.GetMethod() == "POST") { int len = atoi(hdr["content-length"]); if(len > 0 && len < 1024 * 1024 * 1024) { - bool json; - String r = RpcExecute(http.GetAll(len), group, http.GetPeerAddr(), json); - LLOG("--------- Server response:\n" << r << "============="); - String response; - String ts = WwwFormat(GetUtcTime()); - response << - "HTTP/1.0 200 OK\r\n" - "Date: " << ts << "\r\n" - "Server: U++ RPC server\r\n" - "Content-Length: " << r.GetCount() << "\r\n" - "Connection: close\r\n" - "Content-Type: application/" << (json ? "json" : "xml") << "\r\n\r\n" - << r; - LLOG(response); - if(r.GetCount()) - http.Put(response); + request = http.GetAll(len); + data.peeraddr = http.GetPeerAddr(); + data.rpc = this; + String r = RpcExecute(); + if(data.rpc) + RpcResponse(r); return true; } } @@ -296,6 +354,20 @@ bool RpcPerform(TcpSocket& http, const char *group) return false; } +bool RpcPerform(TcpSocket& http, const char *group) +{ + return XmlRpcDo(http, group).Perform(); +} + +String RpcExecute(const String& request_) +{ + HttpRequest dummy; + XmlRpcDo h(dummy, ""); + h.request = request_; + h.data.peeraddr = "127.0.0.1"; + return h.RpcExecute(); +} + bool RpcServerLoop(int port, const char *group) { TcpSocket rpc; diff --git a/uppsrc/Core/Rpc/legacy.h b/uppsrc/Core/Rpc/legacy.h index 93257238c..e43d58170 100644 --- a/uppsrc/Core/Rpc/legacy.h +++ b/uppsrc/Core/Rpc/legacy.h @@ -27,12 +27,6 @@ void SetXmlRpcMethodFilter(String (*filter)(const String& methodname)) SetRpcMethodFilter(filter); } -inline -String XmlRpcExecute(const String& request, const char *group, const char *peeraddr) -{ - return RpcExecute(request, group, peeraddr); -} - inline bool XmlRpcPerform(TcpSocket& http, const char *group) {