From ab32aa4f71e3cd3bf949f625b248dcad3ad9d717 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Mon, 16 Apr 2012 16:27:41 +0200 Subject: [PATCH] Refactored JSON/message code. --- base/application.cpp | 2 +- base/exception.h | 7 +- components/configrpc/configrpccomponent.cpp | 3 +- icinga.sln | 7 + icinga/endpoint.cpp | 27 ++- icinga/endpoint.h | 15 +- icinga/endpointmanager.cpp | 34 ++-- icinga/endpointmanager.h | 3 +- icinga/i2-icinga.h | 1 + icinga/jsonrpcendpoint.cpp | 27 +++ icinga/jsonrpcendpoint.h | 14 +- icinga/virtualendpoint.cpp | 57 +++---- icinga/virtualendpoint.h | 21 ++- jsonrpc/i2-jsonrpc.h | 4 +- jsonrpc/jsonrpc.vcxproj | 36 +++- jsonrpc/jsonrpcclient.cpp | 14 +- jsonrpc/jsonrpcclient.h | 4 +- jsonrpc/jsonrpcmessage.cpp | 167 ------------------ jsonrpc/jsonrpcmessage.h | 56 ------- jsonrpc/jsonrpcrequest.message | 5 + jsonrpc/jsonrpcresponse.message | 5 + jsonrpc/netstring.cpp | 11 +- jsonrpc/netstring.h | 4 +- msgc/msgc.cpp | 177 ++++++++++++++++++++ msgc/msgc.vcxproj | 82 +++++++++ 25 files changed, 474 insertions(+), 309 deletions(-) delete mode 100644 jsonrpc/jsonrpcmessage.cpp delete mode 100644 jsonrpc/jsonrpcmessage.h create mode 100644 jsonrpc/jsonrpcrequest.message create mode 100644 jsonrpc/jsonrpcresponse.message create mode 100644 msgc/msgc.cpp create mode 100644 msgc/msgc.vcxproj diff --git a/base/application.cpp b/base/application.cpp index b125335e4..ace02930c 100644 --- a/base/application.cpp +++ b/base/application.cpp @@ -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 +} diff --git a/base/exception.h b/base/exception.h index d454f79e3..5cb7f41fe 100644 --- a/base/exception.h +++ b/base/exception.h @@ -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 */ diff --git a/components/configrpc/configrpccomponent.cpp b/components/configrpc/configrpccomponent.cpp index 2f6d88282..2d9ac1fb0 100644 --- a/components/configrpc/configrpccomponent.cpp +++ b/components/configrpc/configrpccomponent.cpp @@ -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(); + Message::Ptr params = message->GetParams(); string name, type; if (!message->GetParamString("name", &name)) diff --git a/icinga.sln b/icinga.sln index b165bd7f1..58e5c3854 100644 --- a/icinga.sln +++ b/icinga.sln @@ -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 diff --git a/icinga/endpoint.cpp b/icinga/endpoint.cpp index b7c61b157..63c2c9b99 100644 --- a/icinga/endpoint.cpp +++ b/icinga/endpoint.cpp @@ -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()); } diff --git a/icinga/endpoint.h b/icinga/endpoint.h index c02ad6959..92b0ab661 100644 --- a/icinga/endpoint.h +++ b/icinga/endpoint.h @@ -9,18 +9,23 @@ class EndpointManager; class I2_ICINGA_API Endpoint : public Object { private: - bool m_Connected; + set m_MethodSinks; + set m_MethodSources; public: typedef shared_ptr Ptr; typedef weak_ptr 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; }; } diff --git a/icinga/endpointmanager.cpp b/icinga/endpointmanager.cpp index 3eb1c072f..f8de5a48d 100644 --- a/icinga/endpointmanager.cpp +++ b/icinga/endpointmanager.cpp @@ -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::iterator i = m_Endpoints.begin(); i != m_Endpoints.end(); i++) - { - Endpoint::Ptr endpoint = *i; + throw NotImplementedException(); +} - if (endpoint == source) - continue; +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 */ - endpoint->SendMessage(source, message); - } + string method; + if (!request->GetMethod(&method)) + throw InvalidArgumentException(); + + for (list::iterator i = m_Endpoints.begin(); i != m_Endpoints.end(); i++) + { + Endpoint::Ptr endpoint = *i; + + if (endpoint == sender) + continue; + + if (endpoint->IsMethodSink(method)) + endpoint->SendRequest(sender, request); } } diff --git a/icinga/endpointmanager.h b/icinga/endpointmanager.h index 6d0f1f0e6..4c5e43c66 100644 --- a/icinga/endpointmanager.h +++ b/icinga/endpointmanager.h @@ -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); }; } diff --git a/icinga/i2-icinga.h b/icinga/i2-icinga.h index cd37106b4..8b2a0f68e 100644 --- a/icinga/i2-icinga.h +++ b/icinga/i2-icinga.h @@ -3,6 +3,7 @@ #include #include +#include #ifdef I2_ICINGA_BUILD # define I2_ICINGA_API I2_EXPORT diff --git a/icinga/jsonrpcendpoint.cpp b/icinga/jsonrpcendpoint.cpp index 22bbf7ddb..140a04e31 100644 --- a/icinga/jsonrpcendpoint.cpp +++ b/icinga/jsonrpcendpoint.cpp @@ -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); +} diff --git a/icinga/jsonrpcendpoint.h b/icinga/jsonrpcendpoint.h index ffced0d14..6f037e97f 100644 --- a/icinga/jsonrpcendpoint.h +++ b/icinga/jsonrpcendpoint.h @@ -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 */ diff --git a/icinga/virtualendpoint.cpp b/icinga/virtualendpoint.cpp index 081be6869..560a6cd97 100644 --- a/icinga/virtualendpoint.cpp +++ b/icinga/virtualendpoint.cpp @@ -2,47 +2,42 @@ using namespace icinga; -VirtualEndpoint::VirtualEndpoint() -{ - SetConnected(true); -} - -void VirtualEndpoint::RegisterMethodHandler(string method, function callback) +void VirtualEndpoint::RegisterMethodHandler(string method, function callback) { m_MethodHandlers[method] += callback; + + RegisterMethodSink(method); } -void VirtualEndpoint::UnregisterMethodHandler(string method, function callback) +void VirtualEndpoint::UnregisterMethodHandler(string method, function callback) { // TODO: implement - //m_Methods[method] -= callback; + //m_MethodHandlers[method] -= callback; + //UnregisterMethodSink(method); + + throw NotImplementedException(); } -void VirtualEndpoint::RegisterMethodSource(string method) +void VirtualEndpoint::SendRequest(Endpoint::Ptr sender, JsonRpcRequest::Ptr request) { - m_MethodSources.push_front(method); + string method; + if (!request->GetMethod(&method)) + return; + + map >::iterator i = m_MethodHandlers.find(method); + + if (i == m_MethodHandlers.end()) + throw InvalidArgumentException(); + + NewRequestEventArgs::Ptr nrea = make_shared(); + nrea->Source = shared_from_this(); + nrea->Sender = sender; + nrea->Request = request; + i->second(nrea); } -void VirtualEndpoint::UnregisterMethodSource(string method) +void VirtualEndpoint::SendResponse(Endpoint::Ptr sender, JsonRpcResponse::Ptr response) { - m_MethodSources.remove(method); -} - -void VirtualEndpoint::SendMessage(Endpoint::Ptr source, JsonRpcMessage::Ptr message) -{ - map >::iterator i; - i = m_MethodHandlers.find(message->GetMethod()); - - if (i == m_MethodHandlers.end()) { - JsonRpcMessage::Ptr response = make_shared(); - response->SetVersion("2.0"); - response->SetError("Unknown method."); - response->SetID(message->GetID()); - source->SendMessage(static_pointer_cast(shared_from_this()), response); - } - - NewMessageEventArgs::Ptr nmea = make_shared(); - 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(); } diff --git a/icinga/virtualendpoint.h b/icinga/virtualendpoint.h index 18fc3eecb..c7c150683 100644 --- a/icinga/virtualendpoint.h +++ b/icinga/virtualendpoint.h @@ -4,25 +4,32 @@ namespace icinga { +struct I2_JSONRPC_API NewRequestEventArgs : public EventArgs +{ + typedef shared_ptr Ptr; + typedef weak_ptr WeakPtr; + + Endpoint::Ptr Sender; + JsonRpcRequest::Ptr Request; +}; + class I2_ICINGA_API VirtualEndpoint : public Endpoint { private: - map< string, Event > m_MethodHandlers; - list m_MethodSources; + map< string, Event > m_MethodHandlers; public: typedef shared_ptr Ptr; typedef weak_ptr WeakPtr; - VirtualEndpoint(); - - virtual void RegisterMethodHandler(string method, function callback); - virtual void UnregisterMethodHandler(string method, function callback); + void RegisterMethodHandler(string method, function callback); + void UnregisterMethodHandler(string method, function 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); }; } diff --git a/jsonrpc/i2-jsonrpc.h b/jsonrpc/i2-jsonrpc.h index a9962f22f..b7ced984e 100644 --- a/jsonrpc/i2-jsonrpc.h +++ b/jsonrpc/i2-jsonrpc.h @@ -11,8 +11,10 @@ # 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" diff --git a/jsonrpc/jsonrpc.vcxproj b/jsonrpc/jsonrpc.vcxproj index c1d632b75..83fe30436 100644 --- a/jsonrpc/jsonrpc.vcxproj +++ b/jsonrpc/jsonrpc.vcxproj @@ -13,16 +13,48 @@ - + + + - + + + + + + Document + "$(OutputPath)\msgc" %(Identity) + "$(OutputPath)\msgc" %(Identity) + Compiling %(Identity) + Compiling %(Identity) + %(Filename).cpp %(Filename).h + %(Filename).cpp %(Filename).h + + + + + + + Document + %(Filename).cpp %(Filename).h + %(Filename).cpp %(Filename).h + Compiling %(Identity) + Compiling %(Identity) + "$(OutputPath)\msgc" %(Identity) + "$(OutputPath)\msgc" %(Identity) + + + + + + {8DD52FAC-ECEE-48C2-B266-E7C47ED485F8} Win32Proj diff --git a/jsonrpc/jsonrpcclient.cpp b/jsonrpc/jsonrpcclient.cpp index e449b33e9..45f10dae6 100644 --- a/jsonrpc/jsonrpcclient.cpp +++ b/jsonrpc/jsonrpcclient.cpp @@ -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(); - msg->SetJSON(json); NewMessageEventArgs::Ptr nea = make_shared(); nea->Source = shared_from_this(); - nea->Message = msg; + nea->Message = message; OnNewMessage(nea); } diff --git a/jsonrpc/jsonrpcclient.h b/jsonrpc/jsonrpcclient.h index 9e4f7cedb..bafe381e7 100644 --- a/jsonrpc/jsonrpcclient.h +++ b/jsonrpc/jsonrpcclient.h @@ -9,7 +9,7 @@ struct I2_JSONRPC_API NewMessageEventArgs : public EventArgs typedef shared_ptr Ptr; typedef weak_ptr WeakPtr; - JsonRpcMessage::Ptr Message; + Message::Ptr Message; }; class I2_JSONRPC_API JsonRpcClient : public TCPClient @@ -21,7 +21,7 @@ public: typedef shared_ptr Ptr; typedef weak_ptr 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 index a5fbeb55e..000000000 --- a/jsonrpc/jsonrpcmessage.cpp +++ /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 index f6b97f700..000000000 --- a/jsonrpc/jsonrpcmessage.h +++ /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 Ptr; - typedef weak_ptr 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 index 000000000..5fee1a2e9 --- /dev/null +++ b/jsonrpc/jsonrpcrequest.message @@ -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 index 000000000..60cbeb775 --- /dev/null +++ b/jsonrpc/jsonrpcresponse.message @@ -0,0 +1,5 @@ +JsonRpcResponse : Message + JsonRpc : string + Result : string + Error : string + ID : string diff --git a/jsonrpc/netstring.cpp b/jsonrpc/netstring.cpp index d357bd8b1..a5a9515a4 100644 --- a/jsonrpc/netstring.cpp +++ b/jsonrpc/netstring.cpp @@ -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(object); } -void Netstring::WriteJSONToFIFO(FIFO::Ptr fifo, cJSON *object) +void Netstring::WriteMessageToFIFO(FIFO::Ptr fifo, Message::Ptr message) { char *json; + shared_ptr 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); diff --git a/jsonrpc/netstring.h b/jsonrpc/netstring.h index d5c382bd7..e33c0f8da 100644 --- a/jsonrpc/netstring.h +++ b/jsonrpc/netstring.h @@ -14,8 +14,8 @@ public: typedef shared_ptr Ptr; typedef weak_ptr 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 index 000000000..f85551852 --- /dev/null +++ b/msgc/msgc.cpp @@ -0,0 +1,177 @@ +#include +#include +#include +#include +#include +#include + +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] << " " << 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 index 000000000..63e633455 --- /dev/null +++ b/msgc/msgc.vcxproj @@ -0,0 +1,82 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {4F00EE82-B829-4872-B8F0-C1A8D86C94B4} + Win32Proj + msgc + + + + Application + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + true + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + + + + + \ No newline at end of file