]> granicus.if.org Git - icinga2/commitdiff
Refactored JSON/message code.
authorGunnar Beutner <gunnar.beutner@netways.de>
Mon, 16 Apr 2012 14:27:41 +0000 (16:27 +0200)
committerGunnar Beutner <gunnar.beutner@netways.de>
Mon, 16 Apr 2012 14:27:41 +0000 (16:27 +0200)
25 files changed:
base/application.cpp
base/exception.h
components/configrpc/configrpccomponent.cpp
icinga.sln
icinga/endpoint.cpp
icinga/endpoint.h
icinga/endpointmanager.cpp
icinga/endpointmanager.h
icinga/i2-icinga.h
icinga/jsonrpcendpoint.cpp
icinga/jsonrpcendpoint.h
icinga/virtualendpoint.cpp
icinga/virtualendpoint.h
jsonrpc/i2-jsonrpc.h
jsonrpc/jsonrpc.vcxproj
jsonrpc/jsonrpcclient.cpp
jsonrpc/jsonrpcclient.h
jsonrpc/jsonrpcmessage.cpp [deleted file]
jsonrpc/jsonrpcmessage.h [deleted file]
jsonrpc/jsonrpcrequest.message [new file with mode: 0644]
jsonrpc/jsonrpcresponse.message [new file with mode: 0644]
jsonrpc/netstring.cpp
jsonrpc/netstring.h
msgc/msgc.cpp [new file with mode: 0644]
msgc/msgc.vcxproj [new file with mode: 0644]

index b125335e4f7932b4aa67b03943c8101ad14a24e1..ace02930cb09ddd0f1c13e6fa7338ec8bd468e45 100644 (file)
@@ -422,4 +422,4 @@ int application_main(int argc, char **argv, Application *instance)
        assert(Object::ActiveObjects == 0);
 
        return result;
-}
\ No newline at end of file
+}
index d454f79e339a63a6f312ab5098191873cdf480a0..5cb7f41fe22be2cda243a14aa888e10840fcc1ba 100644 (file)
@@ -21,8 +21,6 @@ public:
        string GetMessage(void) const;
 };
 
-}
-
 #define DEFINE_EXCEPTION_CLASS(klass)                                                          \
        class klass : public Exception                                                                  \
        {                                                                                                                               \
@@ -39,4 +37,9 @@ public:
                }                                                                                                                       \
        };
 
+DEFINE_EXCEPTION_CLASS(NotImplementedException);
+DEFINE_EXCEPTION_CLASS(InvalidArgumentException);
+
+}
+
 #endif /* EXCEPTION_H */
index 2f6d882829e76b4ccee995e75f639ba6c92e3b8c..2d9ac1fb05b29e722d5aebf70447f06288eb0fea 100644 (file)
@@ -183,7 +183,8 @@ int ConfigRpcComponent::RemoteObjectUpdatedHandler(NewMessageEventArgs::Ptr ea)
 
 int ConfigRpcComponent::RemoteObjectRemovedHandler(NewMessageEventArgs::Ptr ea)
 {
-       JsonRpcMessage::Ptr message = ea->Message;
+       JsonRpcRequest::Ptr message = ea->Message->Cast<JsonRpcRequest>();
+       Message::Ptr params = message->GetParams();
        string name, type;
        
        if (!message->GetParamString("name", &name))
index b165bd7f1a0f39d81b781bca8ff81433d71fe95c..58e5c385459055a1fb31cf20357a14c1aed9a8e7 100644 (file)
@@ -6,6 +6,7 @@ EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jsonrpc", "jsonrpc\jsonrpc.vcxproj", "{8DD52FAC-ECEE-48C2-B266-E7C47ED485F8}"
        ProjectSection(ProjectDependencies) = postProject
                {66BED474-C33F-48F9-90BA-BBCFEDC006B8} = {66BED474-C33F-48F9-90BA-BBCFEDC006B8}
+               {4F00EE82-B829-4872-B8F0-C1A8D86C94B4} = {4F00EE82-B829-4872-B8F0-C1A8D86C94B4}
                {9C92DA90-FD53-43A9-A244-90F2E8AF9677} = {9C92DA90-FD53-43A9-A244-90F2E8AF9677}
        EndProjectSection
 EndProject
@@ -32,6 +33,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "configrpc", "components\con
                {C1FC77E1-04A4-481B-A78B-2F7AF489C2F8} = {C1FC77E1-04A4-481B-A78B-2F7AF489C2F8}
        EndProjectSection
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "msgc", "msgc\msgc.vcxproj", "{4F00EE82-B829-4872-B8F0-C1A8D86C94B4}"
+EndProject
 Global
        GlobalSection(SolutionConfigurationPlatforms) = preSolution
                Debug|Win32 = Debug|Win32
@@ -66,6 +69,10 @@ Global
                {697C6D7E-3109-484C-A7AF-384D28711610}.Debug|Win32.Build.0 = Debug|Win32
                {697C6D7E-3109-484C-A7AF-384D28711610}.Release|Win32.ActiveCfg = Release|Win32
                {697C6D7E-3109-484C-A7AF-384D28711610}.Release|Win32.Build.0 = Release|Win32
+               {4F00EE82-B829-4872-B8F0-C1A8D86C94B4}.Debug|Win32.ActiveCfg = Debug|Win32
+               {4F00EE82-B829-4872-B8F0-C1A8D86C94B4}.Debug|Win32.Build.0 = Debug|Win32
+               {4F00EE82-B829-4872-B8F0-C1A8D86C94B4}.Release|Win32.ActiveCfg = Release|Win32
+               {4F00EE82-B829-4872-B8F0-C1A8D86C94B4}.Release|Win32.Build.0 = Release|Win32
        EndGlobalSection
        GlobalSection(SolutionProperties) = preSolution
                HideSolutionNode = FALSE
index b7c61b157f02b604ed285818ef411282ca707ecd..63c2c9b9958e98d627233e4df99cdf5eda49c040 100644 (file)
@@ -2,17 +2,32 @@
 
 using namespace icinga;
 
-Endpoint::Endpoint(void)
+void Endpoint::RegisterMethodSink(string method)
 {
-       m_Connected = false;
+       m_MethodSinks.insert(method);
 }
 
-void Endpoint::SetConnected(bool connected)
+void Endpoint::UnregisterMethodSink(string method)
 {
-       m_Connected = connected;
+       m_MethodSinks.erase(method);
 }
 
-bool Endpoint::GetConnected(void)
+bool Endpoint::IsMethodSink(string method)
 {
-       return m_Connected;
+       return (m_MethodSinks.find(method) != m_MethodSinks.end());
+}
+
+void Endpoint::RegisterMethodSource(string method)
+{
+       m_MethodSources.insert(method);
+}
+
+void Endpoint::UnregisterMethodSource(string method)
+{
+       m_MethodSources.erase(method);
+}
+
+bool Endpoint::IsMethodSource(string method)
+{
+       return (m_MethodSources.find(method) != m_MethodSinks.end());
 }
index c02ad6959333f5f1452ddf5ab1c66ef100e60655..92b0ab661a4f8c37dfc3e0704baa8385299d9079 100644 (file)
@@ -9,18 +9,23 @@ class EndpointManager;
 class I2_ICINGA_API Endpoint : public Object
 {
 private:
-       bool m_Connected;
+       set<string> m_MethodSinks;
+       set<string> m_MethodSources;
 
 public:
        typedef shared_ptr<Endpoint> Ptr;
        typedef weak_ptr<Endpoint> WeakPtr;
 
-       Endpoint(void);
+       void RegisterMethodSink(string method);
+       void UnregisterMethodSink(string method);
+       bool IsMethodSink(string method);
 
-       virtual void SetConnected(bool connected);
-       virtual bool GetConnected(void);
+       void RegisterMethodSource(string method);
+       void UnregisterMethodSource(string method);
+       bool IsMethodSource(string method);
 
-       virtual void SendMessage(Endpoint::Ptr source, JsonRpcMessage::Ptr message) = 0;
+       virtual void SendRequest(Endpoint::Ptr sender, JsonRpcRequest::Ptr message) = 0;
+       virtual void SendResponse(Endpoint::Ptr sender, JsonRpcResponse::Ptr message) = 0;
 };
 
 }
index 3eb1c072fe431efed3164a961616ad101b353e7a..f8de5a48dce1711f9ec0e4be6355fb3475748b8c 100644 (file)
@@ -121,19 +121,31 @@ void EndpointManager::UnregisterEndpoint(Endpoint::Ptr endpoint)
        m_Endpoints.remove(endpoint);
 }
 
-void EndpointManager::SendMessage(Endpoint::Ptr source, Endpoint::Ptr destination, JsonRpcMessage::Ptr message)
+void EndpointManager::SendAnycastRequest(Endpoint::Ptr sender, JsonRpcRequest::Ptr request)
 {
-       if (destination) {
-               destination->SendMessage(source, message);
-       } else {
-               for (list<Endpoint::Ptr>::iterator i = m_Endpoints.begin(); i != m_Endpoints.end(); i++)
-               {
-                       Endpoint::Ptr endpoint = *i;
+       throw NotImplementedException();
+}
+
+void EndpointManager::SendMulticastRequest(Endpoint::Ptr sender, JsonRpcRequest::Ptr request)
+{
+#ifdef _DEBUG
+       string id;
+       if (request->GetID(&id))
+               throw InvalidArgumentException("Multicast requests must not have an ID.");
+#endif /* _DEBUG */
+
+       string method;
+       if (!request->GetMethod(&method))
+               throw InvalidArgumentException();
+
+       for (list<Endpoint::Ptr>::iterator i = m_Endpoints.begin(); i != m_Endpoints.end(); i++)
+       {
+               Endpoint::Ptr endpoint = *i;
 
-                       if (endpoint == source)
-                               continue;
+               if (endpoint == sender)
+                       continue;
 
-                       endpoint->SendMessage(source, message);
-               }
+               if (endpoint->IsMethodSink(method))
+                       endpoint->SendRequest(sender, request);
        }
 }
index 6d0f1f0e6e079d6b0c3dfa30694e17caa453151a..4c5e43c6635f1a538561651fec1eada253b3c004 100644 (file)
@@ -37,7 +37,8 @@ public:
        void RegisterEndpoint(Endpoint::Ptr endpoint);
        void UnregisterEndpoint(Endpoint::Ptr endpoint);
 
-       void SendMessage(Endpoint::Ptr source, Endpoint::Ptr destination, JsonRpcMessage::Ptr message);
+       void SendAnycastRequest(Endpoint::Ptr sender, JsonRpcRequest::Ptr request);
+       void SendMulticastRequest(Endpoint::Ptr sender, JsonRpcRequest::Ptr request);
 };
 
 }
index cd37106b47fa0b4201930f2347556ecb100c26a6..8b2a0f68e3335ecb3474c1f6704b462063361d12 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <i2-base.h>
 #include <i2-jsonrpc.h>
+#include <set>
 
 #ifdef I2_ICINGA_BUILD
 #      define I2_ICINGA_API I2_EXPORT
index 22bbf7ddb27000d1d29e3efbda68c3e55f67d3e8..140a04e318c1cf11161e0884f4d4c6d874875f51 100644 (file)
@@ -1,3 +1,30 @@
 #include "i2-icinga.h"
 
 using namespace icinga;
+
+JsonRpcClient::Ptr JsonRpcEndpoint::GetClient(void)
+{
+       return m_Client;
+}
+
+void JsonRpcEndpoint::SetClient(JsonRpcClient::Ptr client)
+{
+       m_Client = client;
+}
+
+bool JsonRpcEndpoint::IsConnected(void) const
+{
+       return (m_Client.get() != NULL);
+}
+
+void JsonRpcEndpoint::SendRequest(Endpoint::Ptr sender, JsonRpcRequest::Ptr message)
+{
+       if (IsConnected())
+               m_Client->SendMessage(message);
+}
+
+void JsonRpcEndpoint::SendResponse(Endpoint::Ptr sender, JsonRpcResponse::Ptr message)
+{
+       if (IsConnected())
+               m_Client->SendMessage(message);
+}
index ffced0d143dd59b147364ddc7bdc647ba1663538..6f037e97fb74a1cd5ef978c36705cf4f2a501273 100644 (file)
@@ -6,9 +6,21 @@ namespace icinga
 
 class I2_ICINGA_API JsonRpcEndpoint : public Endpoint
 {
+private:
+       JsonRpcClient::Ptr m_Client;
+
+       bool IsConnected(void) const;
+
 public:
+       JsonRpcEndpoint(void);
+
+       JsonRpcClient::Ptr GetClient(void);
+       void SetClient(JsonRpcClient::Ptr client);
+
+       virtual void SendRequest(Endpoint::Ptr sender, JsonRpcRequest::Ptr message);
+       virtual void SendResponse(Endpoint::Ptr sender, JsonRpcResponse::Ptr message);
 };
 
 }
 
-#endif /* JSONRPCENDPOINT_H */
\ No newline at end of file
+#endif /* JSONRPCENDPOINT_H */
index 081be6869c8abc58665de293e17e76408c7ac639..560a6cd977accaee59fb850057b5cf9681097018 100644 (file)
@@ -2,47 +2,42 @@
 
 using namespace icinga;
 
-VirtualEndpoint::VirtualEndpoint()
-{
-       SetConnected(true);
-}
-
-void VirtualEndpoint::RegisterMethodHandler(string method, function<int (NewMessageEventArgs::Ptr)> callback)
+void VirtualEndpoint::RegisterMethodHandler(string method, function<int (NewRequestEventArgs::Ptr)> callback)
 {
        m_MethodHandlers[method] += callback;
+
+       RegisterMethodSink(method);
 }
 
-void VirtualEndpoint::UnregisterMethodHandler(string method, function<int (NewMessageEventArgs::Ptr)> callback)
+void VirtualEndpoint::UnregisterMethodHandler(string method, function<int (NewRequestEventArgs::Ptr)> callback)
 {
        // TODO: implement
-       //m_Methods[method] -= callback;
-}
+       //m_MethodHandlers[method] -= callback;
+       //UnregisterMethodSink(method);
 
-void VirtualEndpoint::RegisterMethodSource(string method)
-{
-       m_MethodSources.push_front(method);
+       throw NotImplementedException();
 }
 
-void VirtualEndpoint::UnregisterMethodSource(string method)
+void VirtualEndpoint::SendRequest(Endpoint::Ptr sender, JsonRpcRequest::Ptr request)
 {
-       m_MethodSources.remove(method);
+       string method;
+       if (!request->GetMethod(&method))
+               return;
+
+       map<string, Event<NewRequestEventArgs::Ptr> >::iterator i = m_MethodHandlers.find(method);
+
+       if (i == m_MethodHandlers.end())
+               throw InvalidArgumentException();
+
+       NewRequestEventArgs::Ptr nrea = make_shared<NewRequestEventArgs>();
+       nrea->Source = shared_from_this();
+       nrea->Sender = sender;
+       nrea->Request = request;
+       i->second(nrea);
 }
 
-void VirtualEndpoint::SendMessage(Endpoint::Ptr source, JsonRpcMessage::Ptr message)
+void VirtualEndpoint::SendResponse(Endpoint::Ptr sender, JsonRpcResponse::Ptr response)
 {
-       map<string, Event<NewMessageEventArgs::Ptr> >::iterator i;
-       i = m_MethodHandlers.find(message->GetMethod());
-
-       if (i == m_MethodHandlers.end()) {
-               JsonRpcMessage::Ptr response = make_shared<JsonRpcMessage>();
-               response->SetVersion("2.0");
-               response->SetError("Unknown method.");
-               response->SetID(message->GetID());
-               source->SendMessage(static_pointer_cast<Endpoint>(shared_from_this()), response);
-       }
-
-       NewMessageEventArgs::Ptr nmea = make_shared<NewMessageEventArgs>();
-       nmea->Source = shared_from_this();
-       nmea->Message = message;
-       i->second(nmea);
+       // TODO: figure out which request this response belongs to and notify the caller
+       throw NotImplementedException();
 }
index 18fc3eecb6c12a9f5302a34389005400492fcd75..c7c1506835b5ad499c9c4cf9ee991eff64a869d1 100644 (file)
@@ -4,25 +4,32 @@
 namespace icinga
 {
 
+struct I2_JSONRPC_API NewRequestEventArgs : public EventArgs
+{
+       typedef shared_ptr<NewRequestEventArgs> Ptr;
+       typedef weak_ptr<NewRequestEventArgs> WeakPtr;
+
+       Endpoint::Ptr Sender;
+       JsonRpcRequest::Ptr Request;
+};
+
 class I2_ICINGA_API VirtualEndpoint : public Endpoint
 {
 private:
-       map< string, Event<NewMessageEventArgs::Ptr> > m_MethodHandlers;
-       list<string> m_MethodSources;
+       map< string, Event<NewRequestEventArgs::Ptr> > m_MethodHandlers;
 
 public:
        typedef shared_ptr<VirtualEndpoint> Ptr;
        typedef weak_ptr<VirtualEndpoint> WeakPtr;
 
-       VirtualEndpoint();
-
-       virtual void RegisterMethodHandler(string method, function<int (NewMessageEventArgs::Ptr)> callback);
-       virtual void UnregisterMethodHandler(string method, function<int (NewMessageEventArgs::Ptr)> callback);
+       void RegisterMethodHandler(string method, function<int (NewRequestEventArgs::Ptr)> callback);
+       void UnregisterMethodHandler(string method, function<int (NewRequestEventArgs::Ptr)> callback);
 
        virtual void RegisterMethodSource(string method);
        virtual void UnregisterMethodSource(string method);
 
-       virtual void SendMessage(Endpoint::Ptr source, JsonRpcMessage::Ptr message);
+       virtual void SendRequest(Endpoint::Ptr sender, JsonRpcRequest::Ptr message);
+       virtual void SendResponse(Endpoint::Ptr sender, JsonRpcResponse::Ptr message);
 };
 
 }
index a9962f22facc5f0902cf95518bf04811cc8853a3..b7ced984e51668148c0a55f01cf6a71d5c264c71 100644 (file)
 #      define I2_JSONRPC_API I2_IMPORT
 #endif /* I2_JSONRPC_BUILD */
 
+#include "message.h"
 #include "netstring.h"
-#include "jsonrpcmessage.h"
+#include "jsonrpcrequest.h"
+#include "jsonrpcresponse.h"
 #include "jsonrpcclient.h"
 #include "jsonrpcserver.h"
 
index c1d632b7513aa6faa18d46dcc64baef3afa3aa8d..83fe30436d95e655774a9c21f8cbdd91dc068904 100644 (file)
   <ItemGroup>
     <ClInclude Include="i2-jsonrpc.h" />
     <ClInclude Include="jsonrpcclient.h" />
-    <ClInclude Include="jsonrpcmessage.h" />
+    <ClInclude Include="jsonrpcrequest.h" />
+    <ClInclude Include="jsonrpcresponse.h" />
     <ClInclude Include="jsonrpcserver.h" />
+    <ClInclude Include="message.h" />
     <ClInclude Include="netstring.h" />
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="jsonrpcclient.cpp" />
-    <ClCompile Include="jsonrpcmessage.cpp" />
+    <ClCompile Include="jsonrpcrequest.cpp" />
+    <ClCompile Include="jsonrpcresponse.cpp" />
     <ClCompile Include="jsonrpcserver.cpp" />
+    <ClCompile Include="message.cpp" />
     <ClCompile Include="netstring.cpp" />
   </ItemGroup>
+  <ItemGroup>
+    <CustomBuild Include="jsonrpcrequest.message">
+      <FileType>Document</FileType>
+      <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">"$(OutputPath)\msgc" %(Identity)</Command>
+      <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">"$(OutputPath)\msgc" %(Identity)</Command>
+      <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Compiling %(Identity)</Message>
+      <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Compiling %(Identity)</Message>
+      <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(Filename).cpp %(Filename).h</Outputs>
+      <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(Filename).cpp %(Filename).h</Outputs>
+      <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+      </AdditionalInputs>
+      <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+      </AdditionalInputs>
+    </CustomBuild>
+    <CustomBuild Include="jsonrpcresponse.message">
+      <FileType>Document</FileType>
+      <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(Filename).cpp %(Filename).h</Outputs>
+      <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(Filename).cpp %(Filename).h</Outputs>
+      <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Compiling %(Identity)</Message>
+      <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Compiling %(Identity)</Message>
+      <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">"$(OutputPath)\msgc" %(Identity)</Command>
+      <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">"$(OutputPath)\msgc" %(Identity)</Command>
+      <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+      </AdditionalInputs>
+      <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+      </AdditionalInputs>
+    </CustomBuild>
+  </ItemGroup>
   <PropertyGroup Label="Globals">
     <ProjectGuid>{8DD52FAC-ECEE-48C2-B266-E7C47ED485F8}</ProjectGuid>
     <Keyword>Win32Proj</Keyword>
index e449b33e925492cfbdca9b1824cfe75d1355de3b..45f10dae6b17b1cfbeebd4bae4c30b628087c0ee 100644 (file)
@@ -9,32 +9,30 @@ void JsonRpcClient::Start(void)
        OnDataAvailable += bind_weak(&JsonRpcClient::DataAvailableHandler, shared_from_this());
 }
 
-void JsonRpcClient::SendMessage(JsonRpcMessage::Ptr message)
+void JsonRpcClient::SendMessage(Message::Ptr message)
 {
-       Netstring::WriteJSONToFIFO(GetSendQueue(), message->GetJSON());
+       Netstring::WriteMessageToFIFO(GetSendQueue(), message);
 }
 
 int JsonRpcClient::DataAvailableHandler(EventArgs::Ptr ea)
 {
-       cJSON *json;
+       Message::Ptr message;
 
        while (true) {
                try {
-                       json = Netstring::ReadJSONFromFIFO(GetRecvQueue());
+                       message = Netstring::ReadMessageFromFIFO(GetRecvQueue());
                } catch (const exception&) {
                        Close();
 
                        return 1;
                }
        
-               if (json == NULL)
+               if (message.get() == NULL)
                        break;
 
-               JsonRpcMessage::Ptr msg = make_shared<JsonRpcMessage>();
-               msg->SetJSON(json);
                NewMessageEventArgs::Ptr nea = make_shared<NewMessageEventArgs>();
                nea->Source = shared_from_this();
-               nea->Message = msg;
+               nea->Message = message;
                OnNewMessage(nea);
        }
 
index 9e4f7cedb212965e324f0bcacda75145a73812fe..bafe381e7b20a8f4c03fc3cfd520414e6b082bfe 100644 (file)
@@ -9,7 +9,7 @@ struct I2_JSONRPC_API NewMessageEventArgs : public EventArgs
        typedef shared_ptr<NewMessageEventArgs> Ptr;
        typedef weak_ptr<NewMessageEventArgs> WeakPtr;
 
-       JsonRpcMessage::Ptr Message;
+       Message::Ptr Message;
 };
 
 class I2_JSONRPC_API JsonRpcClient : public TCPClient
@@ -21,7 +21,7 @@ public:
        typedef shared_ptr<JsonRpcClient> Ptr;
        typedef weak_ptr<JsonRpcClient> WeakPtr;
 
-       void SendMessage(JsonRpcMessage::Ptr message);
+       void SendMessage(Message::Ptr message);
 
        virtual void Start(void);
 
diff --git a/jsonrpc/jsonrpcmessage.cpp b/jsonrpc/jsonrpcmessage.cpp
deleted file mode 100644 (file)
index a5fbeb5..0000000
+++ /dev/null
@@ -1,167 +0,0 @@
-#include "i2-jsonrpc.h"
-
-using namespace icinga;
-
-JsonRpcMessage::JsonRpcMessage(void)
-{
-       m_JSON = NULL;
-}
-
-JsonRpcMessage::~JsonRpcMessage(void)
-{
-       cJSON_Delete(m_JSON);
-}
-
-void JsonRpcMessage::SetJSON(cJSON *object)
-{
-       cJSON_Delete(m_JSON);
-       m_JSON = object;
-}
-
-cJSON *JsonRpcMessage::GetJSON(void)
-{
-       return m_JSON;
-}
-
-void JsonRpcMessage::InitJson(void)
-{
-       if (m_JSON == NULL)
-               m_JSON = cJSON_CreateObject();
-}
-
-void JsonRpcMessage::SetFieldObject(const char *field, cJSON *object)
-{
-       if (m_JSON == NULL && object == NULL)
-               return;
-
-       InitJson();
-
-       cJSON_DeleteItemFromObject(m_JSON, field);
-
-       if (object != NULL)
-               cJSON_AddItemToObject(m_JSON, field, object);
-}
-
-cJSON *JsonRpcMessage::GetFieldObject(const char *field)
-{
-       if (m_JSON == NULL)
-               return NULL;
-
-       return cJSON_GetObjectItem(m_JSON, field);
-}
-
-void JsonRpcMessage::SetFieldString(const char *field, const string& value)
-{
-       cJSON *object = cJSON_CreateString(value.c_str());
-       SetFieldObject(field, object);
-}
-
-string JsonRpcMessage::GetFieldString(const char *field)
-{
-       cJSON *object = GetFieldObject(field);
-
-       if (object == NULL || object->type != cJSON_String)
-               return string();
-
-       return string(object->valuestring);
-}
-
-void JsonRpcMessage::SetVersion(const string& version)
-{
-       SetFieldString("version", version);
-}
-
-string JsonRpcMessage::GetVersion(void)
-{
-       return GetFieldString("jsonrpc");
-}
-
-void JsonRpcMessage::SetID(const string& id)
-{
-       SetFieldString("id", id);
-}
-
-string JsonRpcMessage::GetID(void)
-{
-       return GetFieldString("id");
-}
-
-void JsonRpcMessage::SetMethod(const string& method)
-{
-       SetFieldString("method", method);
-}
-
-string JsonRpcMessage::GetMethod(void)
-{
-       return GetFieldString("method");
-}
-
-void JsonRpcMessage::ClearParams(void)
-{
-       SetFieldObject("params", NULL);
-}
-
-cJSON *JsonRpcMessage::GetParams(void)
-{
-       cJSON *object = GetFieldObject("params");
-
-       if (object == NULL) {
-               object = cJSON_CreateObject();
-               cJSON_AddItemToObject(m_JSON, "params", object);
-       }
-
-       return object;
-}
-
-void JsonRpcMessage::SetParam(const string& name, const string& value)
-{
-}
-
-cJSON *JsonRpcMessage::GetParam(const string& name)
-{
-       cJSON *params = GetFieldObject("params");
-
-       if (params == NULL)
-               return NULL;
-
-       return cJSON_GetObjectItem(params, name.c_str());
-}
-
-bool JsonRpcMessage::GetParamString(const string name, string *value)
-{
-       cJSON *param = GetParam(name);
-
-       if (param == NULL || param->type != cJSON_String)
-               return false;
-
-       *value = param->valuestring;
-
-       return true;
-}
-
-void JsonRpcMessage::ClearResult(void)
-{
-       SetFieldObject("result", NULL);
-}
-
-cJSON *JsonRpcMessage::GetResult(void)
-{
-       cJSON *object = GetFieldObject("result");
-
-       if (object == NULL) {
-               object = cJSON_CreateObject();
-               cJSON_AddItemToObject(m_JSON, "result", object);
-       }
-
-       return object;
-}
-
-void JsonRpcMessage::SetError(const string& error)
-{
-       SetFieldString("error", error);
-}
-
-string JsonRpcMessage::GetError(void)
-{
-       return GetFieldString("error");
-}
diff --git a/jsonrpc/jsonrpcmessage.h b/jsonrpc/jsonrpcmessage.h
deleted file mode 100644 (file)
index f6b97f7..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-#ifndef JSONRPCMESSAGE_H
-#define JSONRPCMESSAGE_H
-
-namespace icinga
-{
-
-class I2_JSONRPC_API JsonRpcMessage : public Object
-{
-private:
-       cJSON *m_JSON;
-
-       void InitJson(void);
-
-       void SetFieldString(const char *field, const string& value);
-       string GetFieldString(const char *field);
-
-       void ClearField(const char *field);
-       void SetFieldObject(const char *field, cJSON *object);
-       cJSON *GetFieldObject(const char *field);
-
-public:
-       typedef shared_ptr<JsonRpcMessage> Ptr;
-       typedef weak_ptr<JsonRpcMessage> WeakPtr;
-
-       JsonRpcMessage(void);
-       ~JsonRpcMessage(void);
-
-       void SetJSON(cJSON *object);
-       cJSON *GetJSON(void);
-       
-       void SetVersion(const string& version);
-       string GetVersion(void);
-
-       void SetID(const string& id);
-       string GetID(void);
-
-       void SetMethod(const string& method);
-       string GetMethod(void);
-
-       void ClearParams(void);
-       cJSON *GetParams(void);
-
-       void SetParam(const string& name, const string& value);
-       cJSON *GetParam(const string& name);
-       bool GetParamString(const string name, string *value);
-
-       void ClearResult();
-       cJSON *GetResult(void);
-
-       void SetError(const string& error);
-       string GetError(void);
-};
-
-}
-
-#endif /* JSONRPCMESSAGE_H */
diff --git a/jsonrpc/jsonrpcrequest.message b/jsonrpc/jsonrpcrequest.message
new file mode 100644 (file)
index 0000000..5fee1a2
--- /dev/null
@@ -0,0 +1,5 @@
+JsonRpcRequest : Message
+       JsonRpc : string
+       Method : string
+       Params : Message
+       ID : string
diff --git a/jsonrpc/jsonrpcresponse.message b/jsonrpc/jsonrpcresponse.message
new file mode 100644 (file)
index 0000000..60cbeb7
--- /dev/null
@@ -0,0 +1,5 @@
+JsonRpcResponse : Message
+       JsonRpc : string
+       Result : string
+       Error : string
+       ID : string
index d357bd8b10a1235b2d6bf75725f210a4cf4bf5c7..a5a9515a4d4dd80da47c974268c7dc2362811c0f 100644 (file)
@@ -4,7 +4,7 @@
 using namespace icinga;
 
 /* based on https://github.com/PeterScott/netstring-c/blob/master/netstring.c */
-cJSON *Netstring::ReadJSONFromFIFO(FIFO::Ptr fifo)
+Message::Ptr Netstring::ReadMessageFromFIFO(FIFO::Ptr fifo)
 {
        size_t buffer_length = fifo->GetSize();
        char *buffer = (char *)fifo->GetReadBuffer();
@@ -53,18 +53,19 @@ cJSON *Netstring::ReadJSONFromFIFO(FIFO::Ptr fifo)
        /* remove the data from the fifo */
        fifo->Read(NULL, i + len + 1);
 
-       return object;
+       return make_shared<Message>(object);
 }
 
-void Netstring::WriteJSONToFIFO(FIFO::Ptr fifo, cJSON *object)
+void Netstring::WriteMessageToFIFO(FIFO::Ptr fifo, Message::Ptr message)
 {
        char *json;
+       shared_ptr<cJSON> object = message->GetJson();
        size_t len;
 
 #ifdef _DEBUG
-       json = cJSON_Print(object);
+       json = cJSON_Print(object.get());
 #else /* _DEBUG */
-       json = cJSON_PrintUnformatted(object);
+       json = cJSON_PrintUnformatted(object.get());
 #endif /* _DEBUG */
 
        len = strlen(json);
index d5c382bd7c16cef1bfa7509c82f7f712e67ee03c..e33c0f8da87f66ed18e09a87dabc4508fcebd01a 100644 (file)
@@ -14,8 +14,8 @@ public:
        typedef shared_ptr<Netstring> Ptr;
        typedef weak_ptr<Netstring> WeakPtr;
 
-       static cJSON *ReadJSONFromFIFO(FIFO::Ptr fifo);
-       static void WriteJSONToFIFO(FIFO::Ptr fifo, cJSON *object);
+       static Message::Ptr ReadMessageFromFIFO(FIFO::Ptr fifo);
+       static void WriteMessageToFIFO(FIFO::Ptr fifo, Message::Ptr message);
 };
 
 }
diff --git a/msgc/msgc.cpp b/msgc/msgc.cpp
new file mode 100644 (file)
index 0000000..f855518
--- /dev/null
@@ -0,0 +1,177 @@
+#include <cstdlib>
+#include <cctype>
+#include <iostream>
+#include <algorithm>
+#include <fstream>
+#include <string>
+
+using namespace std;
+
+void trim(string& str, const char *whitespace = "\r\n\t ")
+{
+       string::size_type pos;
+
+       pos = str.find_first_not_of(whitespace);
+       if (pos != string::npos)
+               str.erase(0, pos);
+
+       pos = str.find_last_not_of(whitespace);
+       if (pos != string::npos)
+               str.erase(pos + 1);
+}
+
+int main(int argc, char **argv)
+{
+       if (argc < 2) {
+               cerr << "Syntax: " << argv[0] << " <file.message>" << endl;
+               return EXIT_FAILURE;
+       }
+
+       char *pos;
+       pos = strrchr(argv[1], '.');
+
+       if (pos == NULL || strcmp(pos, ".message") != 0) {
+               cerr << "Input filename must have the '.message' extension." << endl;
+               return EXIT_FAILURE;
+       }
+
+       char *headername, *implname;
+       headername = strdup(argv[1]);
+       strcpy(&(headername[pos - argv[1]]), ".h");
+
+       implname = strdup(argv[1]);
+       strcpy(&(implname[pos - argv[1]]), ".cpp");
+
+       fstream inputfp, headerfp, implfp;
+
+       inputfp.open(argv[1], fstream::in);
+       headerfp.open(headername, fstream::out | fstream::trunc);
+       implfp.open(implname, fstream::out | fstream::trunc);
+
+       string line;
+       string klass, klassupper, base;
+       bool hasclass = false;
+
+       while (true) {
+               getline(inputfp, line);
+
+               if (inputfp.fail())
+                       break;
+
+               if (!hasclass) {
+                       string::size_type index = line.find(':');
+
+                       if (index == string::npos) {
+                               cerr << "Must specify class and base name." << endl;
+                               return EXIT_FAILURE;
+                       }
+
+                       klass = line.substr(0, index);
+                       trim(klass);
+
+                       klassupper = klass;
+                       transform(klassupper.begin(), klassupper.end(), klassupper.begin(), toupper);
+
+                       base = line.substr(index + 1);
+                       trim(base);
+
+                       cout << "Class: '" << klass << "' (inherits from: '" << base << "')" << endl;
+
+                       headerfp        << "#ifndef " << klassupper << "_H" << endl
+                                               << "#define " << klassupper << "_H" << endl
+                                               << endl
+                                               << "namespace icinga" << endl
+                                               << "{" << endl
+                                               << endl
+                                               << "class " << klass << " : public " << base << endl
+                                               << "{" << endl
+                                               << endl
+                                               << "public:" << endl
+                                               << "\ttypedef shared_ptr<" << klass << "> Ptr;" << endl
+                                               << "\ttypedef weak_ptr<" << klass << "> WeakPtr;" << endl
+                                               << endl
+                                               << "\t" << klass << "(void) : " << base << "() { }" << endl
+                                               << "\t" << klass << "(const Message::Ptr& message) : " << base << "(message) { }" << endl
+                                               << endl;
+
+                       implfp          << "#include \"i2-jsonrpc.h\"" << endl
+                                               << "#include \"" << headername << "\"" << endl
+                                               << endl
+                                               << "using namespace icinga;" << endl
+                                               << endl;
+
+                       hasclass = true;
+               } else {
+                       string::size_type index = line.find(':');
+
+                       if (index == string::npos) {
+                               cerr << "Must specify type and property name." << endl;
+                               return EXIT_FAILURE;
+                       }
+
+                       string prop = line.substr(0, index);
+                       trim(prop);
+
+                       string type = line.substr(index + 1);
+                       trim(type);
+
+                       string typeaccessor = type;
+                       typeaccessor[0] = toupper(typeaccessor[0]);
+
+                       string rawtype = type;
+
+                       /* assume it's a reference type if we don't know the type */
+                       if (type != "int" && type != "string") {
+                               type = type + "::Ptr";
+                               typeaccessor = "Message";
+                       }
+
+                       cout << "Property: '" << prop << "' (Type: '" << type << "')" << endl;
+
+                       headerfp        << endl
+                                               << "\tbool Get" << prop << "(" << type << " *value);" << endl
+                                               << "\tvoid Set" << prop << "(const " << type << "& value);" << endl;
+
+                       implfp          << "bool " << klass << "::Get" << prop << "(" << type << " *value)" << endl
+                                               << "{" << endl;
+
+                       if (typeaccessor == "Message") {
+                               implfp          << "\tMessage::Ptr message;" << endl
+                                                       << endl
+                                                       << "\tif (!GetProperty" << typeaccessor << "(\"" << prop << "\", &message))" << endl
+                                                       << "\treturn false;" << endl
+                                                       << endl
+                                                       << "\t*value = message->Cast<" + rawtype + ">();" << endl
+                                                       << "return true;" << endl
+                                                       << endl;
+                       } else {
+                               implfp          << "\treturn GetProperty" << typeaccessor << "(\"" << prop << "\", value);" << endl;
+                       }
+       
+                       implfp          << "}" << endl
+                                               << endl;
+
+                       implfp          << "void " << klass << "::Set" << prop << "(const " << type << "& value)" << endl
+                                               << "{" << endl
+                                               << "\tSetProperty" << typeaccessor << "(\"" << prop << "\", value);" << endl
+                                               << "}" << endl
+                                               << endl;
+               }
+       }
+
+       headerfp        << endl
+                               << "};" << endl
+                               << endl
+                               << "}" << endl
+                               << endl
+                               << "#endif /* " << klassupper << "_H */" << endl;
+
+       inputfp.close();
+       headerfp.close();
+       implfp.close();
+
+       free(headername);
+       free(implname);
+
+       return EXIT_SUCCESS;
+}
diff --git a/msgc/msgc.vcxproj b/msgc/msgc.vcxproj
new file mode 100644 (file)
index 0000000..63e6334
--- /dev/null
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{4F00EE82-B829-4872-B8F0-C1A8D86C94B4}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <RootNamespace>msgc</RootNamespace>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <LinkIncremental>false</LinkIncremental>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="msgc.cpp" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file