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)
{