From df0777ffedc8e54c881b14f65a01d7b03178af52 Mon Sep 17 00:00:00 2001
From: Markus Frank <Markus.Frank@cern.ch>
Date: Thu, 17 Mar 2022 21:18:38 +0100
Subject: [PATCH] Fixes to property RPC

---
 .../src/interactive/PropertyManip.cpp         |   2 +-
 .../Dataflow/src/interactive/PropertyManip.h  |   4 +-
 Online/RPC/include/RPC/JSONRPC.h              |   4 +
 Online/RPC/src/JSONRPC.cpp                    |  13 +
 Online/RPCServer/include/RPC/DimClient.h      |   9 +-
 Online/RPCServer/include/RPC/DimRequest.h     |   2 +-
 Online/RPCServer/include/RPC/DimServer.h      |  10 +-
 Online/RPCServer/src/DimClient.cpp            |  98 ++++---
 Online/RPCServer/src/DimRequest.cpp           |   2 +-
 Online/RPCServer/src/DimServer.cpp            | 256 ++++++++++--------
 Online/RPCServer/src/HttpDimRpcBridge.h       |  19 +-
 Online/RPCServer/src/HttpXmlRpcHandler.cpp    |   2 +-
 Online/RPCServer/tests/src/RODomainRPC.cpp    |   2 +-
 .../tests/src/test_dimxmlrpc_client.cpp       |   2 +-
 .../tests/src/test_dimxmlrpc_server.cpp       |   2 +-
 15 files changed, 256 insertions(+), 171 deletions(-)

diff --git a/Online/Dataflow/src/interactive/PropertyManip.cpp b/Online/Dataflow/src/interactive/PropertyManip.cpp
index 5e4c5b881..808336473 100644
--- a/Online/Dataflow/src/interactive/PropertyManip.cpp
+++ b/Online/Dataflow/src/interactive/PropertyManip.cpp
@@ -90,7 +90,7 @@ void PropertyManip::startServices()  {
     dimSvcID = ::dis_add_service(svc.c_str(),"C",0,0,feedProperties,(long)this);
   }
   if ( 0 == rpc )   {
-    rpc = new xmlrpc::DimServer(RTL::processName());
+    rpc = new rpc::DimServer(RTL::processName());
     rpc->setDebug(true);
     rpc->define("clients",            xmlrpc::Call(this).make(&PropertyManip::clients));
     rpc->define("allProperties",      xmlrpc::Call(this).make(&PropertyManip::allProperties));
diff --git a/Online/Dataflow/src/interactive/PropertyManip.h b/Online/Dataflow/src/interactive/PropertyManip.h
index 3e8840cc2..71b205cf9 100644
--- a/Online/Dataflow/src/interactive/PropertyManip.h
+++ b/Online/Dataflow/src/interactive/PropertyManip.h
@@ -50,7 +50,7 @@ namespace Online  {
   class PropertyManip : public DataflowComponent  {
   protected:
     /// Definition of the clients collection type
-    typedef std::vector<std::string>             Clients;
+    typedef std::vector<std::string>          Clients;
     /// Definition of the property collection type
     typedef std::vector<rpc::ObjectProperty>  Properties;
  
@@ -70,7 +70,7 @@ namespace Online  {
     /// Dim buffer allocation reservation
     int          dimMemSize = 1024*1024*2;
     /// Reference to the RPC object
-    xmlrpc::DimServer* rpc = 0;
+    rpc::DimServer* rpc = 0;
 
   protected:
     /// Start all DIM publishing services
diff --git a/Online/RPC/include/RPC/JSONRPC.h b/Online/RPC/include/RPC/JSONRPC.h
index 893081981..8921d1997 100644
--- a/Online/RPC/include/RPC/JSONRPC.h
+++ b/Online/RPC/include/RPC/JSONRPC.h
@@ -178,6 +178,8 @@ public:
   void check();
 
 public:
+  /// Default constructor
+  MethodResponse();
   /// Default constructor
   MethodResponse(int id);
   /// Initializing constructor with existing json object
@@ -232,6 +234,8 @@ public:
   static MethodResponse makeFault(int id, int code);
   /// Set fault information in case of failure
   static MethodResponse makeFault(int id, int code, const std::string& reason);
+  /// Set fault information in case of failure
+  static MethodResponse makeFault(int code, const std::string& reason);
   /// Access return value data element by true type
   template <typename T> T data()   const;
 };
diff --git a/Online/RPC/src/JSONRPC.cpp b/Online/RPC/src/JSONRPC.cpp
index 0f2414561..49ef2fd86 100644
--- a/Online/RPC/src/JSONRPC.cpp
+++ b/Online/RPC/src/JSONRPC.cpp
@@ -524,6 +524,12 @@ size_t MethodCall::numArgs() const   {
   return this->root.at("params").size();
 }
 
+/// Initializing constructor
+MethodResponse::MethodResponse()
+{
+  this->root = json_h::object({{"jsonrpc", "2.0"},{"id",0}});
+}
+
 /// Initializing constructor
 MethodResponse::MethodResponse(int id)
 {
@@ -659,6 +665,13 @@ MethodResponse MethodResponse::makeFault(int id, int code, const string& reason)
   return resp;
 }
 
+/// Set fault information in case of failure
+MethodResponse MethodResponse::makeFault(int code, const string& reason)   {
+  MethodResponse resp(0);
+  resp.root["error"] = json_h::object({{"code",code},{"message", reason}});
+  return resp;
+}
+
 /// Decode the response of a server
 MethodResponse MethodResponse::decode(const string& json_text)   {
   return MethodResponse(json_text);
diff --git a/Online/RPCServer/include/RPC/DimClient.h b/Online/RPCServer/include/RPC/DimClient.h
index a70e15b64..c45c73a43 100644
--- a/Online/RPCServer/include/RPC/DimClient.h
+++ b/Online/RPCServer/include/RPC/DimClient.h
@@ -17,13 +17,14 @@
 
 // Framework include files
 #include <RPC/XMLRPC.h>
+#include <RPC/JSONRPC.h>
 #include <RPC/DimRequest.h>
 
 // C/C++ include files
 #include <memory>
 
 /// Namespace for the dimrpc based implementation
-namespace xmlrpc  {
+namespace rpc  {
 
   ///  XMLRPC Client class based on DIM
   /**
@@ -65,7 +66,9 @@ namespace xmlrpc  {
     /// Connect client to given URI
     virtual std::vector<unsigned char> request(const std::string& call)  const;
     /// Connect client to given URI
-    virtual MethodResponse call(const MethodCall& call)  const;
+    virtual xmlrpc::MethodResponse call(const xmlrpc::MethodCall& call)  const;
+    /// Connect client to given URI
+    virtual jsonrpc::MethodResponse call(const jsonrpc::MethodCall& call)  const;
   };
-}       // End namespace xmlrpc
+}       // End namespace rpc
 #endif  /* RPC_DIMCLIENT_H       */
diff --git a/Online/RPCServer/include/RPC/DimRequest.h b/Online/RPCServer/include/RPC/DimRequest.h
index 837071d93..444bb8521 100644
--- a/Online/RPCServer/include/RPC/DimRequest.h
+++ b/Online/RPCServer/include/RPC/DimRequest.h
@@ -16,7 +16,7 @@
 #define RPC_DIMREQUEST_H
 
 /// Namespace for the dimrpc based implementation
-namespace xmlrpc {
+namespace rpc {
 
   ///  XMLRPC request structure for DIM servers and clients
   /**
diff --git a/Online/RPCServer/include/RPC/DimServer.h b/Online/RPCServer/include/RPC/DimServer.h
index b5948d9e3..e27608216 100644
--- a/Online/RPCServer/include/RPC/DimServer.h
+++ b/Online/RPCServer/include/RPC/DimServer.h
@@ -21,12 +21,14 @@
 // C/C++ include files
 #include <string>
 
+namespace xmlrpc  {  class Call;  }
+namespace jsonrpc {  class Call;  }
+
 /// Namespace for the dim based xmlrpc implementation
-namespace xmlrpc  {
+namespace rpc  {
 
   /// Forward declarations
   class DimRequest;
-  class Call;
   
   ///  XMLRPC Server class
   /**
@@ -65,7 +67,9 @@ namespace xmlrpc  {
     void stop();
 
     /// Bind a callback to a function
-    void define(const std::string& name, const Call& call);
+    void define(const std::string& name, const xmlrpc::Call& call);
+    /// Bind a callback to a function
+    void define(const std::string& name, const jsonrpc::Call& call);
     /// Remove a callback from the xmlrpc interface
     void remove(const std::string& name);
 
diff --git a/Online/RPCServer/src/DimClient.cpp b/Online/RPCServer/src/DimClient.cpp
index 23214fe79..9b07fa5f7 100644
--- a/Online/RPCServer/src/DimClient.cpp
+++ b/Online/RPCServer/src/DimClient.cpp
@@ -22,7 +22,8 @@
 #include <condition_variable>
 
 /// Namespace for the dimrpc based implementation
-namespace xmlrpc  {
+namespace rpc  {
+
   class DimClient::Handler  {
   public:
     /// Lock for the conditions variable
@@ -53,10 +54,12 @@ namespace xmlrpc  {
     void open(const std::string& server_name, const std::string& dns_name);
     /// Access name
     std::string name()  const;
-    /// Execute RPC call
-    MethodResponse call(const MethodCall& call);
     /// Connect client to given URI and execute RPC request
     std::vector<unsigned char> request(const void* call, size_t len);
+    /// Execute RPC call
+    xmlrpc::MethodResponse call(const xmlrpc::MethodCall& call);
+    /// Execute RPC call
+    jsonrpc::MethodResponse call(const jsonrpc::MethodCall& call);
   };
 }
 //==========================================================================
@@ -75,8 +78,8 @@ namespace xmlrpc  {
 #endif
 
 using namespace std;
+using namespace rpc;
 using namespace dd4hep;
-using namespace xmlrpc;
 
 namespace {
   vector<unsigned char> to_vector(const char* data)   {
@@ -205,43 +208,56 @@ vector<unsigned char> DimClient::Handler::request(const void* req, size_t length
   throw runtime_error(str.str());
 }
 
-/// Execute RPC call
-MethodResponse DimClient::Handler::call(const MethodCall& request)   {
-  using namespace chrono;
-  stringstream str;
-  try  {
-    string req = request.str();
-    MethodResponse mr;
+namespace {
+
+  template <typename RESPONSE, typename CALL>
+  RESPONSE do_rpc(DimClient::Handler* client, const CALL& request)   {
+    using namespace chrono;
+    stringstream str;
     try  {
-      mr = MethodResponse::decode(this->request(req.c_str(), req.length()));
+      string req = request.str();
+      RESPONSE mr;
+      try  {
+	mr = RESPONSE::decode(client->request(req.c_str(), req.length()));
+      }
+      catch(const std::exception& e)   {
+	std::error_code errcode(errno, std::system_category());
+	mr = RESPONSE::makeFault(errcode.value(),e.what());
+      }
+      catch( ... )   {
+	std::error_code errcode(errno, std::system_category());
+	mr = RESPONSE::makeFault(errcode.value(),errcode.message());
+      }
+      if ( client->debug > 1 )  {
+	printout(INFO,"RPCClient","Handling response: %s",mr.str().c_str());
+      }
+      else if ( client->debug > 0 )  {
+	printout(INFO,"RPCClient","Handling response [Length:%ld bytes]",mr.str().length());
+      }
+      if ( !mr.isFault() )   {
+	return mr;
+      }
+      str << "XMLRPC fault [" << mr.faultCode() << "]: " << mr.faultString();
     }
     catch(const std::exception& e)   {
-      std::error_code errcode(errno, std::system_category());
-      mr = MethodResponse::makeFault(errcode.value(),e.what());
+      str << e.what();
     }
     catch( ... )   {
       std::error_code errcode(errno, std::system_category());
-      mr = MethodResponse::makeFault(errcode.value(),errcode.message());
-    }
-    if ( debug>1 )  {
-      printout(INFO,"RPCClient","Handling response: %s",mr.str().c_str());
+      str << "RPC fault [" << errcode.value() << "] (UNKOWN Exception): " << errcode.message();
     }
-    else if ( debug>0 )  {
-      printout(INFO,"RPCClient","Handling response [Length:%ld bytes]",mr.str().length());
-    }
-    if ( !mr.isFault() )   {
-      return mr;
-    }
-    str << "XMLRPC fault [" << mr.faultCode() << "]: " << mr.faultString();
-  }
-  catch(const std::exception& e)   {
-    str << e.what();
+    throw runtime_error(str.str());
   }
-  catch( ... )   {
-    std::error_code errcode(errno, std::system_category());
-    str << "XMLRPC fault [" << errcode.value() << "] (UNKOWN Exception): " << errcode.message();
-  }
-  throw runtime_error(str.str());
+}
+
+/// Execute RPC call
+xmlrpc::MethodResponse DimClient::Handler::call(const xmlrpc::MethodCall& request)   {
+  return do_rpc<xmlrpc::MethodResponse,xmlrpc::MethodCall>(this, request);
+}
+
+/// Execute RPC call
+jsonrpc::MethodResponse DimClient::Handler::call(const jsonrpc::MethodCall& request)   {
+  return do_rpc<jsonrpc::MethodResponse,jsonrpc::MethodCall>(this, request);
 }
 
 /// Initializing constructor
@@ -288,11 +304,6 @@ void DimClient::open(const string& server_name, const string& dns_name, int tmo)
   open(server_name, dns_name);
 }
 
-/// Execute RPC call
-MethodResponse DimClient::call(const MethodCall& call)  const {
-  return implementation->call(call);
-}
-
 /// Execute RPC call
 vector<unsigned char> DimClient::request(const string& call)  const {
   return implementation->request(call.c_str(), call.length());
@@ -302,3 +313,14 @@ vector<unsigned char> DimClient::request(const string& call)  const {
 vector<unsigned char> DimClient::request(const void* call, size_t len)  const  {
   return implementation->request(call, len);
 }
+
+/// Execute RPC call
+xmlrpc::MethodResponse DimClient::call(const xmlrpc::MethodCall& call)  const {
+  return implementation->call(call);
+}
+
+/// Execute RPC call
+jsonrpc::MethodResponse DimClient::call(const jsonrpc::MethodCall& call)  const {
+  return implementation->call(call);
+}
+
diff --git a/Online/RPCServer/src/DimRequest.cpp b/Online/RPCServer/src/DimRequest.cpp
index c01eb3128..648983e02 100644
--- a/Online/RPCServer/src/DimRequest.cpp
+++ b/Online/RPCServer/src/DimRequest.cpp
@@ -19,7 +19,7 @@
 // C/C++ include files
 #include <mutex>
 
-int xmlrpc::DimRequest::newID()   {
+int rpc::DimRequest::newID()   {
   static std::mutex mid_lock;
   std::lock_guard<std::mutex> lk(mid_lock);
   return ++mid;
diff --git a/Online/RPCServer/src/DimServer.cpp b/Online/RPCServer/src/DimServer.cpp
index 11d7b6ce6..225dedec2 100644
--- a/Online/RPCServer/src/DimServer.cpp
+++ b/Online/RPCServer/src/DimServer.cpp
@@ -23,7 +23,9 @@
 #include <map>
 
 /// Namespace for the dimrpc based implementation
-namespace xmlrpc  {
+namespace rpc  {
+
+  class Dimrequest;
 
   ///  XMLRPC Client class based on DIM
   /**
@@ -44,15 +46,19 @@ namespace xmlrpc  {
     void open(const std::string& server, const std::string& dns);
     /// Handle client request
     void handle(const DimRequest* request);
+    /// Update client about result
+    int update_client(const DimRequest* req, std::string&& rep);
 
   public:
     /// Definition of the XMLRPC callback map
-    typedef std::map<std::string,Call> Calls;
+    typedef std::map<std::string,xmlrpc::Call>  XmlCalls;
+    typedef std::map<std::string,jsonrpc::Call> JsonCalls;
 
     /// Object Lock to ensure we have no race conditions when editing the call-map
     std::mutex                        lock;
     /// The map of registered XML-RPC calls
-    Calls                             calls;
+    XmlCalls                          xml_calls;
+    JsonCalls                         json_calls;
     /// Bind default callback to all successfully handled functions.
     std::vector<Callback>             onHandled;
     /// Bind default callback to all unhandled functions.
@@ -75,6 +81,7 @@ namespace xmlrpc  {
 //==========================================================================
 
 #include <RPC/XMLRPC.h>
+#include <RPC/JSONRPC.h>
 #include <RPC/DimRequest.h>
 #include <XML/Printout.h>
 #include <unistd.h>
@@ -92,24 +99,25 @@ namespace xmlrpc  {
 #include <iostream>
 #include <stdexcept>
 
+using namespace rpc;
 using namespace std;
-using namespace xmlrpc;
 typedef std::lock_guard<std::mutex>  Lock;
 
 // Framework include files
 #include "RPC/DimRequest.h"
 
+
 namespace {
   void handle_request(void* tag, void* buffer, int* size)   {
     if ( tag && buffer && size )   {
-      DimServer::Handler* server = *(DimServer::Handler**)tag;
-      server->handle((DimRequest*)buffer);
+      rpc::DimServer::Handler* server = *(rpc::DimServer::Handler**)tag;
+      server->handle((rpc::DimRequest*)buffer);
     }
     return;
   }
   void feed_result(void* tag, void** buffer, int* size, int* first)   {
-    DimServer::Handler* server = *(DimServer::Handler**)tag;
-    DimRequest* msg = server->response.get();
+    rpc::DimServer::Handler* server = *(rpc::DimServer::Handler**)tag;
+    rpc::DimRequest* msg = server->response.get();
     if ( (first && *first) || !msg )  {
       static int empty = 0;
       *buffer = &empty;
@@ -118,7 +126,7 @@ namespace {
     }
     msg = server->response.get();
     *buffer = msg;
-    *size =   msg->size+sizeof(DimRequest);
+    *size =   msg->size+sizeof(rpc::DimRequest);
   }
 }
 
@@ -147,103 +155,115 @@ void DimServer::Handler::open(const std::string& server,const std::string& dns)
   }
 }
 
-/// Handle client request
-void DimServer::Handler::handle(const DimRequest* req)    {
-  char client_name[256];
-  const void* args[] = { req, 0 };
-  const DimRequest* rq = req;
-  MethodResponse mr;
-  try  {
-    const char* data = req->data;
-    if ( req->magic == DimRequest::MAGIC )  {
-      if ( req->size <= 0 )  {
-        // ERROR: call user callbacks
-        for (const auto& c : onError )
-          c.execute(args);
-        mr = MethodResponse::makeFault(EINVAL, "Invalid DIM-XML-RPC: Bad command length.");
-        return;
+namespace  {
+  template <typename RESPONSE, typename CALL, typename CALLS>
+  std::string handle_rpc(DimServer::Handler* srv, CALLS& calls, const char* data)    {
+    using namespace xmlrpc;
+    const void* args[] = { data, 0 };
+    RESPONSE mr;
+    try  {
+      CALL   call(data);
+      string method = call.method();
+      const auto& callback = calls.find(method);
+      if ( callback == calls.end() )   {
+	mr = RESPONSE::makeFault(EOPNOTSUPP,"RPC call not supported.");
+	// Unhandled call: call user callbacks
+	for (const auto& cb : srv->onUnhandled )
+	  cb.execute(args);
+      }
+      else  {
+	const auto& c = (*callback).second;
+	mr = c.execute(call);
+	// Successfully handled call: call user callbacks
+	for (const auto& cb : srv->onHandled )
+	  cb.execute(args);
       }
     }
-    else if ( req->magic == *(unsigned int*)"<method" )  {
-      rq = 0;
-      data = (const char*)req;
-    }
-    
-    MethodCall call(data);
-    string method = call.method();
-    const auto& callback = calls.find(method);
-    if ( callback == calls.end() )   {
-      mr = MethodResponse::makeFault(EOPNOTSUPP);
-      // Unhandled call: call user callbacks
-      for (const auto& cb : onUnhandled )
-        cb.execute(args);
+    catch(const std::exception& e)    {
+      mr = RESPONSE::makeFault(EINVAL, e.what());
+      // ERROR: call user callbacks
+      for (const auto& cb : srv->onError )
+	cb.execute(args);
     }
-    else  {
-      const Call& c = (*callback).second;
-      mr = c.execute(call);
-      // Successfully handled call: call user callbacks
-      for (const auto& cb : onHandled )
-        cb.execute(args);
+    catch(...)    {
+      mr = RESPONSE::makeFault(EINVAL, "DIM-RPC: Unknown exception during RPC execution");
+      // ERROR: call user callbacks
+      for (const auto& c : srv->onError )
+	c.execute(args);
     }
+    return mr.str();
   }
-  catch(const std::exception& e)    {
-    mr = MethodResponse::makeFault(EINVAL,e.what());
-    // ERROR: call user callbacks
-    for (const auto& cb : onError )
-      cb.execute(args);
-  }
-  catch(...)    {
-    mr = MethodResponse::makeFault(EINVAL,"DIM-RPC: Unknown exception during RPC execution");
-    // ERROR: call user callbacks
-    for (const auto& c : onError )
+}
+
+/// Handle client request
+void DimServer::Handler::handle(const DimRequest* req)    {
+  string response;
+  const char* data = req->data;
+  if ( req->magic == DimRequest::MAGIC && req->size <= 0 )  {
+    const void* args[] = { req, 0 };
+    for (const auto& c : this->onError )
       c.execute(args);
+    response = "Invalid DIM-RPC: Bad command length.";
+  }
+#if 0 // This should not be necessary!
+  const DimRequest* rq = req;
+  if ( req->magic == *(unsigned int*)"<method" )  {
+    rq = 0;
+    data = (const char*)req;
   }
-  int    num_client = 0;
-  if ( rq )  {
-    int    pid[] = { ::dis_get_client(client_name), 0, 0};
-    string used;
-    string rep = mr.str();
-    size_t len = rep.length()+sizeof(DimRequest);
-    Lock   lck(lock);  {
-      if ( response_len < len )  {
-        response.reset((DimRequest*)::operator new(response_len=len));
+#endif
+  else if ( *(int*)data == *(int*)"<?xml version" )
+    response = handle_rpc<xmlrpc::MethodResponse,xmlrpc::MethodCall>(this, xml_calls, data);
+  else if ( data[0] == '{' && data[1] == '"' )
+    response = handle_rpc<jsonrpc::MethodResponse,jsonrpc::MethodCall>(this, json_calls, data);
+  this->update_client(req, std::move(response));
+}
+
+int DimServer::Handler::update_client(const DimRequest* req, string&& answer)    {
+  char client_name[256];
+  int num_client = 0;
+  int    pid[] = { ::dis_get_client(client_name), 0, 0};
+  string used;
+  size_t len = answer.length()+sizeof(DimRequest);
+  Lock   lck(lock);  {
+    if ( response_len < len )  {
+      response.reset((DimRequest*)::operator new(response_len=len));
+    }
+    response->pid      = req->pid;
+    response->host     = req->host;
+    response->mid      = req->mid;
+    switch(req->encoding)   {
+    case DimRequest::COMPRESSION_GZIP:
+    case DimRequest::COMPRESSION_DEFLATE:  {
+      vector<unsigned char> buff(http::compress::compress("gzip deflate",
+							  http::compress::to_vector(answer),
+							  used));
+      if ( buff.size() < len && ::tolower(used[0]) == 'g' )   {
+	response->encoding = DimRequest::COMPRESSION_GZIP;
+	response->size     = buff.size();
+	::memcpy(response->data, buff.data(), buff.size());
       }
-      response->pid      = rq->pid;
-      response->host     = rq->host;
-      response->mid      = rq->mid;
-      switch(rq->encoding)   {
-      case DimRequest::COMPRESSION_GZIP:
-      case DimRequest::COMPRESSION_DEFLATE:  {
-	vector<unsigned char> buff(http::compress::compress("gzip deflate",
-							    http::compress::to_vector(rep),
-							    used));
-	if ( buff.size() < len && ::tolower(used[0]) == 'g' )   {
-	  response->encoding = DimRequest::COMPRESSION_GZIP;
-	  response->size     = buff.size();
-	  ::memcpy(response->data, buff.data(), buff.size());
-	}
-	else if ( buff.size() < len && ::tolower(used[0]) == 'd' )   {
-	  response->encoding = DimRequest::COMPRESSION_DEFLATE;
-	  response->size     = buff.size();
-	  ::memcpy(response->data, buff.data(), buff.size());
-	}
-	else  {
-	  response->size     = rep.length();
-	  response->encoding = DimRequest::COMPRESSION_NONE;
-	  ::memcpy(response->data, rep.c_str(),rep.length());
-	  break;
-	}
-	break;
+      else if ( buff.size() < len && ::tolower(used[0]) == 'd' )   {
+	response->encoding = DimRequest::COMPRESSION_DEFLATE;
+	response->size     = buff.size();
+	::memcpy(response->data, buff.data(), buff.size());
       }
-      case DimRequest::COMPRESSION_NONE:
-      default:
-	response->encoding = rq->encoding;
-	response->size     = rep.length();
-	::memcpy(response->data, rep.c_str(),rep.length());
+      else  {
+	response->size     = answer.length();
+	response->encoding = DimRequest::COMPRESSION_NONE;
+	::memcpy(response->data, answer.c_str(), answer.length());
 	break;
       }
-      num_client = ::dis_selective_update_service(response_id,pid);
+      break;
+    }
+    case DimRequest::COMPRESSION_NONE:
+    default:
+      response->encoding = req->encoding;
+      response->size     = answer.length();
+      ::memcpy(response->data, answer.c_str(),answer.length());
+      break;
     }
+    num_client = ::dis_selective_update_service(response_id,pid);
   }
   if ( debug )   {
     cout << "+++++ HTTP Request   pid:" << std::hex << req->pid
@@ -252,13 +272,12 @@ void DimServer::Handler::handle(const DimRequest* req)    {
          << " Size:"  << int(req->size) << endl;
     if ( debug > 1 ) cout << " Data:" << req->data << endl;
     cout << "*****" << endl;
-    if ( rq )  {
-      cout << "+++++ HTTP Response No.Clients: " << num_client
-	   << " (" << client_name << ") "
-	   << " Size:" << int(response->size) << endl;
-      if ( debug > 1 ) cout << " Data:" << response->data << "|data-end|" << endl;
-    }
+    cout << "+++++ HTTP Response No.Clients: " << num_client
+	 << " (" << client_name << ") "
+	 << " Size:" << int(response->size) << endl;
+    if ( debug > 1 ) cout << " Data:" << response->data << "|data-end|" << endl;
   }
+  return num_client;
 }
 
 /// Initializing constructor
@@ -293,15 +312,27 @@ void DimServer::start(bool detached)   {
 /// Stop the xmlrpc service
 void DimServer::stop()   {
   Lock lock(implementation->lock);
-  implementation->calls.clear();
+  implementation->json_calls.clear();
+  implementation->xml_calls.clear();
+}
+
+/// Bind a callback to a function
+void DimServer::define(const string& name, const xmlrpc::Call& call)   {
+  Lock lock(implementation->lock);
+  auto i = implementation->xml_calls.find(name);
+  if ( i == implementation->xml_calls.end() )  {
+    implementation->xml_calls.insert(make_pair(name,call));
+    return;
+  }
+  throw runtime_error("The RPC call "+name+" is already registered to the RPC interface.");
 }
 
 /// Bind a callback to a function
-void DimServer::define(const string& name, const Call& call)   {
+void DimServer::define(const string& name, const jsonrpc::Call& call)   {
   Lock lock(implementation->lock);
-  auto i = implementation->calls.find(name);
-  if ( i == implementation->calls.end() )  {
-    implementation->calls.insert(make_pair(name,call));
+  auto i = implementation->json_calls.find(name);
+  if ( i == implementation->json_calls.end() )  {
+    implementation->json_calls.insert(make_pair(name,call));
     return;
   }
   throw runtime_error("The RPC call "+name+" is already registered to the RPC interface.");
@@ -310,9 +341,18 @@ void DimServer::define(const string& name, const Call& call)   {
 /// Remove a callback from the xmlrpc interface
 void DimServer::remove(const string& name)   {
   Lock lock(implementation->lock);
-  auto i = implementation->calls.find(name);
-  if ( i == implementation->calls.end() )  {
-    implementation->calls.erase(i);
+  bool found = false;
+  auto i = implementation->xml_calls.find(name);
+  if ( i == implementation->xml_calls.end() )  {
+    implementation->xml_calls.erase(i);
+    found = true;
+  }
+  auto j = implementation->json_calls.find(name);
+  if ( j == implementation->json_calls.end() )  {
+    implementation->json_calls.erase(j);
+    found = true;
+  }
+  if ( found )   {
     return;
   }
   throw runtime_error("The RPC call "+name+" is not registered to the RPC interface.");
diff --git a/Online/RPCServer/src/HttpDimRpcBridge.h b/Online/RPCServer/src/HttpDimRpcBridge.h
index 2ef52b3c0..0063108db 100644
--- a/Online/RPCServer/src/HttpDimRpcBridge.h
+++ b/Online/RPCServer/src/HttpDimRpcBridge.h
@@ -19,7 +19,7 @@
 #include <mutex>
 #include <condition_variable>
 
-namespace xmlrpc {
+namespace rpc {
 
   class HttpDimBridgeHandler : public rpc::HttpRpcHandler  {
   public:
@@ -44,7 +44,6 @@ namespace xmlrpc {
     /// Debug flag
     int                        debug = 0;
 
-
     /// Standard constructor
     HttpDimBridgeHandler(const std::string& srv, int dbg = false);
     /// Standard destructor
@@ -57,7 +56,7 @@ namespace xmlrpc {
 }
 
 namespace   {
-  static xmlrpc::DimRequest proc;
+  static rpc::DimRequest proc;
 
   void rpc_callback(void* tag, int* code)  {
     if ( tag && code )  {}
@@ -65,14 +64,14 @@ namespace   {
 
   void feed_result(void* tag, void* buffer, int* size)   {
     if ( tag && buffer && size && *size )   {
-      xmlrpc::HttpDimBridgeHandler* client = *(xmlrpc::HttpDimBridgeHandler**)tag;
-      xmlrpc::DimRequest* msg = (xmlrpc::DimRequest*)buffer;
+      rpc::HttpDimBridgeHandler* client = *(rpc::HttpDimBridgeHandler**)tag;
+      rpc::DimRequest* msg = (rpc::DimRequest*)buffer;
       if ( msg->pid == proc.pid )  {
         if ( msg->host == proc.host )  {
           if ( msg->mid == client->message_id )  {
             unique_lock<mutex> lk(client->lock);
             if ( !client->ready )  {
-	      client->encoding = xmlrpc::DimRequest::COMPRESSION_NONE;
+	      client->encoding = rpc::DimRequest::COMPRESSION_NONE;
               try  {
 		client->response.clear();
 		client->encoding = msg->encoding;
@@ -99,7 +98,7 @@ namespace   {
 }
 
 /// Standard constructor
-xmlrpc::HttpDimBridgeHandler::HttpDimBridgeHandler(const std::string& server_name,int dbg)
+rpc::HttpDimBridgeHandler::HttpDimBridgeHandler(const std::string& server_name,int dbg)
 : debug(dbg)
 {
   /// Initialize structure
@@ -124,13 +123,13 @@ xmlrpc::HttpDimBridgeHandler::HttpDimBridgeHandler(const std::string& server_nam
 }
 
 /// Standard destructor
-xmlrpc::HttpDimBridgeHandler::~HttpDimBridgeHandler()  {
+rpc::HttpDimBridgeHandler::~HttpDimBridgeHandler()  {
   if ( response_id != -1 ) ::dic_release_service(response_id);
 }
 
 /// Execute RPC call
-xmlrpc::HttpDimBridgeHandler::continue_action
-xmlrpc::HttpDimBridgeHandler::handle_request(const http::Request& req, http::Reply& rep)   {
+rpc::HttpDimBridgeHandler::continue_action
+rpc::HttpDimBridgeHandler::handle_request(const http::Request& req, http::Reply& rep)   {
   using namespace chrono;
   stringstream str;
   try  {
diff --git a/Online/RPCServer/src/HttpXmlRpcHandler.cpp b/Online/RPCServer/src/HttpXmlRpcHandler.cpp
index 20c842b6e..b3215d40b 100644
--- a/Online/RPCServer/src/HttpXmlRpcHandler.cpp
+++ b/Online/RPCServer/src/HttpXmlRpcHandler.cpp
@@ -202,7 +202,7 @@ void rpc::HttpXmlRpcHandler::handle_bridge_request(const std::string& dns,
 	Lock lck(lock);
 	auto i = dimBridge.handlers.find(server);
 	if ( i == dimBridge.handlers.end() )  {
-	  auto ptr = std::make_unique<xmlrpc::HttpDimBridgeHandler>(server, debug);
+	  auto ptr = std::make_unique<rpc::HttpDimBridgeHandler>(server, debug);
 	  h = ptr.get();
 	  dimBridge.handlers.emplace(server, std::move(ptr));
 	}
diff --git a/Online/RPCServer/tests/src/RODomainRPC.cpp b/Online/RPCServer/tests/src/RODomainRPC.cpp
index b2bf2aa78..ad9c848d5 100644
--- a/Online/RPCServer/tests/src/RODomainRPC.cpp
+++ b/Online/RPCServer/tests/src/RODomainRPC.cpp
@@ -322,7 +322,7 @@ RODomainRPC::RODomainRPC(int argc, char** argv) : m_print(LIB_RTL_WARNING)  {
 	});
     }
     else    {
-      setupServer(this, new xmlrpc::DimServer(m_name, to))->setDebug(debug);
+      setupServer(this, new rpc::DimServer(m_name, to))->setDebug(debug);
     }
   }
   PartitionListener p(this,"Subfarms","*",true);
diff --git a/Online/RPCServer/tests/src/test_dimxmlrpc_client.cpp b/Online/RPCServer/tests/src/test_dimxmlrpc_client.cpp
index 3e5c93485..467e44a34 100644
--- a/Online/RPCServer/tests/src/test_dimxmlrpc_client.cpp
+++ b/Online/RPCServer/tests/src/test_dimxmlrpc_client.cpp
@@ -17,7 +17,7 @@
 
 /// Framework includes
 #define Callable         DimCallable
-#define CallableHandler  xmlrpc::DimClient
+#define CallableHandler  rpc::DimClient
 
 #include "RPC/DimClient.h"
 #include "Objects.h"
diff --git a/Online/RPCServer/tests/src/test_dimxmlrpc_server.cpp b/Online/RPCServer/tests/src/test_dimxmlrpc_server.cpp
index 06b255665..459c0ba6c 100644
--- a/Online/RPCServer/tests/src/test_dimxmlrpc_server.cpp
+++ b/Online/RPCServer/tests/src/test_dimxmlrpc_server.cpp
@@ -45,7 +45,7 @@ extern "C" int test_dimxmlrpc_server(int argc, char** argv)   {
       help_server();
   }
 
-  xmlrpc::DimServer server(name,dns);
+  rpc::DimServer server(name,dns);
   server.setDebug(debug != 0);
   printout(INFO,"DIM-SERVE","TEST> Starting test DIM-XMLRPC server: %s:%s\n",dns.c_str(),name.c_str());
   return call_server(argc, argv, server);
-- 
GitLab