diff --git a/base/i2-base.h b/base/i2-base.h index 1d58c5083..771708887 100644 --- a/base/i2-base.h +++ b/base/i2-base.h @@ -57,6 +57,8 @@ #include #include #include +#include +#include #if defined(__APPLE__) && defined(__MACH__) # pragma GCC diagnostic ignored "-Wdeprecated-declarations" diff --git a/base/timer.cpp b/base/timer.cpp index 5efae4983..2cda9debb 100644 --- a/base/timer.cpp +++ b/base/timer.cpp @@ -17,8 +17,6 @@ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * ******************************************************************************/ -#include -#include #include "i2-base.h" using namespace icinga; diff --git a/icinga/endpointmanager.cpp b/icinga/endpointmanager.cpp index f49a81e8a..83e2f7b88 100644 --- a/icinga/endpointmanager.cpp +++ b/icinga/endpointmanager.cpp @@ -68,7 +68,7 @@ void EndpointManager::AddConnection(string node, string service) void EndpointManager::RegisterServer(JsonRpcServer::Ptr server) { - m_Servers.push_front(server); + m_Servers.push_back(server); server->OnNewClient += bind_weak(&EndpointManager::NewClientHandler, shared_from_this()); } @@ -86,7 +86,9 @@ int EndpointManager::NewClientHandler(const NewClientEventArgs& ncea) void EndpointManager::UnregisterServer(JsonRpcServer::Ptr server) { - m_Servers.remove(server); + m_Servers.erase( + remove(m_Servers.begin(), m_Servers.end(), server), + m_Servers.end()); // TODO: unbind event } @@ -96,7 +98,7 @@ void EndpointManager::RegisterEndpoint(Endpoint::Ptr endpoint) throw InvalidArgumentException("Identity must be empty."); endpoint->SetEndpointManager(static_pointer_cast(shared_from_this())); - m_Endpoints.push_front(endpoint); + m_Endpoints.push_back(endpoint); NewEndpointEventArgs neea; neea.Source = shared_from_this(); @@ -106,7 +108,9 @@ void EndpointManager::RegisterEndpoint(Endpoint::Ptr endpoint) void EndpointManager::UnregisterEndpoint(Endpoint::Ptr endpoint) { - m_Endpoints.remove(endpoint); + m_Endpoints.erase( + remove(m_Endpoints.begin(), m_Endpoints.end(), endpoint), + m_Endpoints.end()); } void EndpointManager::SendUnicastRequest(Endpoint::Ptr sender, Endpoint::Ptr recipient, const JsonRpcRequest& request, bool fromLocal) @@ -123,7 +127,7 @@ void EndpointManager::SendUnicastRequest(Endpoint::Ptr sender, Endpoint::Ptr rec throw InvalidArgumentException("Missing 'method' parameter."); if (recipient->IsMethodSink(method)) { - Application::Log(sender->GetAddress() + " -> " + recipient->GetAddress() + ": " + method); + //Application::Log(sender->GetAddress() + " -> " + recipient->GetAddress() + ": " + method); recipient->ProcessRequest(sender, request); } } @@ -145,7 +149,7 @@ void EndpointManager::SendMulticastRequest(Endpoint::Ptr sender, const JsonRpcRe if (!request.GetMethod(&method)) throw InvalidArgumentException("Message is missing the 'method' property."); - for (list::iterator i = m_Endpoints.begin(); i != m_Endpoints.end(); i++) + for (vector::iterator i = m_Endpoints.begin(); i != m_Endpoints.end(); i++) { SendUnicastRequest(sender, *i, request, fromLocal); } @@ -156,7 +160,7 @@ void EndpointManager::ForEachEndpoint(function::iterator prev, i; + vector::iterator prev, i; for (i = m_Endpoints.begin(); i != m_Endpoints.end(); ) { prev = i; i++; @@ -168,7 +172,7 @@ void EndpointManager::ForEachEndpoint(function::const_iterator i; + vector::const_iterator i; for (i = m_Endpoints.begin(); i != m_Endpoints.end(); i++) { if ((*i)->GetIdentity() == identity) return *i; diff --git a/icinga/endpointmanager.h b/icinga/endpointmanager.h index 96ececa79..b866a83f8 100644 --- a/icinga/endpointmanager.h +++ b/icinga/endpointmanager.h @@ -33,8 +33,8 @@ class I2_ICINGA_API EndpointManager : public Object string m_Identity; shared_ptr m_SSLContext; - list m_Servers; - list m_Endpoints; + vector m_Servers; + vector m_Endpoints; void RegisterServer(JsonRpcServer::Ptr server); void UnregisterServer(JsonRpcServer::Ptr server); diff --git a/jsonrpc/jsonrpcclient.cpp b/jsonrpc/jsonrpcclient.cpp index 46391948e..0f12adf6e 100644 --- a/jsonrpc/jsonrpcclient.cpp +++ b/jsonrpc/jsonrpcclient.cpp @@ -33,18 +33,21 @@ void JsonRpcClient::Start(void) void JsonRpcClient::SendMessage(const Message& message) { - Netstring::WriteMessageToFIFO(GetSendQueue(), message); + Netstring::WriteStringToFIFO(GetSendQueue(), message.ToJsonString()); } int JsonRpcClient::DataAvailableHandler(const EventArgs&) { for (;;) { try { + string jsonString; Message message; - if (!Netstring::ReadMessageFromFIFO(GetRecvQueue(), &message)) + if (!Netstring::ReadStringFromFIFO(GetRecvQueue(), &jsonString)) break; + message = Message(jsonString); + NewMessageEventArgs nea; nea.Source = shared_from_this(); nea.Message = message; diff --git a/jsonrpc/message.cpp b/jsonrpc/message.cpp index b6dc68c0a..f25ff7ec7 100644 --- a/jsonrpc/message.cpp +++ b/jsonrpc/message.cpp @@ -18,6 +18,7 @@ ******************************************************************************/ #include "i2-jsonrpc.h" +#include using namespace icinga; @@ -26,6 +27,18 @@ Message::Message(void) m_Dictionary = make_shared(); } +Message::Message(string jsonString) +{ + json_t *json = cJSON_Parse(jsonString.c_str()); + + if (!json) + throw InvalidArgumentException("Invalid JSON string"); + + m_Dictionary = GetDictionaryFromJson(json); + + cJSON_Delete(json); +} + Message::Message(const Dictionary::Ptr& dictionary) { m_Dictionary = dictionary; @@ -36,6 +49,80 @@ Message::Message(const Message& message) m_Dictionary = message.GetDictionary(); } +Dictionary::Ptr Message::GetDictionaryFromJson(json_t *json) +{ + Dictionary::Ptr dictionary = make_shared(); + + for (cJSON *i = json->child; i != NULL; i = i->next) { + switch (i->type) { + case cJSON_Number: + dictionary->SetProperty(i->string, i->valueint); + break; + case cJSON_String: + dictionary->SetProperty(i->string, i->valuestring); + break; + case cJSON_Object: + dictionary->SetProperty(i->string, GetDictionaryFromJson(i)); + break; + default: + break; + } + } + + return dictionary; +} + +json_t *Message::GetJsonFromDictionary(const Dictionary::Ptr& dictionary) +{ + cJSON *json; + string valueString; + Dictionary::Ptr valueDictionary; + + json = cJSON_CreateObject(); + + for (DictionaryIterator i = dictionary->Begin(); i != dictionary->End(); i++) { + switch (i->second.GetType()) { + case VariantInteger: + cJSON_AddNumberToObject(json, i->first.c_str(), i->second.GetInteger()); + break; + case VariantString: + valueString = i->second.GetString(); + cJSON_AddStringToObject(json, i->first.c_str(), valueString.c_str()); + break; + case VariantObject: + valueDictionary = dynamic_pointer_cast(i->second.GetObject()); + + if (valueDictionary) + cJSON_AddItemToObject(json, i->first.c_str(), GetJsonFromDictionary(valueDictionary)); + default: + break; + } + } + + return json; +} + +string Message::ToJsonString(void) const +{ + json_t *json = GetJsonFromDictionary(m_Dictionary); + char *jsonString; + string result; + +#ifdef _DEBUG + jsonString = cJSON_Print(json); +#else /* _DEBUG */ + jsonString = cJSON_PrintUnformatted(json); +#endif /* _DEBUG */ + + cJSON_Delete(json); + + result = jsonString; + + free(jsonString); + + return result; +} + Dictionary::Ptr Message::GetDictionary(void) const { return m_Dictionary; diff --git a/jsonrpc/message.h b/jsonrpc/message.h index d77b0f12c..ddca1dcf8 100644 --- a/jsonrpc/message.h +++ b/jsonrpc/message.h @@ -20,19 +20,29 @@ #ifndef MESSAGE_H #define MESSAGE_H +struct cJSON; + namespace icinga { +typedef ::cJSON json_t; + class I2_JSONRPC_API Message { private: Dictionary::Ptr m_Dictionary; + static Dictionary::Ptr GetDictionaryFromJson(json_t *json); + static json_t *GetJsonFromDictionary(const Dictionary::Ptr& dictionary); + public: Message(void); + Message(string json); Message(const Dictionary::Ptr& dictionary); Message(const Message& message); + string ToJsonString(void) const; + Dictionary::Ptr GetDictionary(void) const; bool GetPropertyString(string key, string *value) const; diff --git a/jsonrpc/netstring.cpp b/jsonrpc/netstring.cpp index c05ba7925..307f16b5d 100644 --- a/jsonrpc/netstring.cpp +++ b/jsonrpc/netstring.cpp @@ -17,67 +17,12 @@ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * ******************************************************************************/ -#include #include "i2-jsonrpc.h" -#include using namespace icinga; -Dictionary::Ptr Netstring::GetDictionaryFromJson(json_t *json) -{ - Dictionary::Ptr dictionary = make_shared(); - - for (cJSON *i = json->child; i != NULL; i = i->next) { - switch (i->type) { - case cJSON_Number: - dictionary->SetProperty(i->string, i->valueint); - break; - case cJSON_String: - dictionary->SetProperty(i->string, i->valuestring); - break; - case cJSON_Object: - dictionary->SetProperty(i->string, GetDictionaryFromJson(i)); - break; - default: - break; - } - } - - return dictionary; -} - -json_t *Netstring::GetJsonFromDictionary(const Dictionary::Ptr& dictionary) -{ - cJSON *json; - string valueString; - Dictionary::Ptr valueDictionary; - - json = cJSON_CreateObject(); - - for (DictionaryIterator i = dictionary->Begin(); i != dictionary->End(); i++) { - switch (i->second.GetType()) { - case VariantInteger: - cJSON_AddNumberToObject(json, i->first.c_str(), i->second.GetInteger()); - break; - case VariantString: - valueString = i->second.GetString(); - cJSON_AddStringToObject(json, i->first.c_str(), valueString.c_str()); - break; - case VariantObject: - valueDictionary = dynamic_pointer_cast(i->second.GetObject()); - - if (valueDictionary) - cJSON_AddItemToObject(json, i->first.c_str(), GetJsonFromDictionary(valueDictionary)); - default: - break; - } - } - - return json; -} - /* based on https://github.com/PeterScott/netstring-c/blob/master/netstring.c */ -bool Netstring::ReadMessageFromFIFO(FIFO::Ptr fifo, Message *message) +bool Netstring::ReadStringFromFIFO(FIFO::Ptr fifo, string *str) { size_t buffer_length = fifo->GetSize(); char *buffer = (char *)fifo->GetReadBuffer(); @@ -113,45 +58,22 @@ bool Netstring::ReadMessageFromFIFO(FIFO::Ptr fifo, Message *message) if (buffer[i + len] != ',') throw InvalidArgumentException("Invalid Netstring (missing ,)"); - /* nuke the comma delimiter */ - buffer[i + len] = '\0'; - cJSON *object = cJSON_Parse(&buffer[i]); - - if (object == NULL) { - /* restore the comma */ - buffer[i + len] = ','; - throw InvalidArgumentException("Invalid JSON string"); - } + *str = string(&buffer[i], &buffer[i + len]); /* remove the data from the fifo */ fifo->Read(NULL, i + len + 1); - *message = Message(GetDictionaryFromJson(object)); - cJSON_Delete(object); return true; } -void Netstring::WriteMessageToFIFO(FIFO::Ptr fifo, const Message& message) +void Netstring::WriteStringToFIFO(FIFO::Ptr fifo, const string& str) { - char *json; - cJSON *object = GetJsonFromDictionary(message.GetDictionary()); - size_t len; - -#ifdef _DEBUG - json = cJSON_Print(object); -#else /* _DEBUG */ - json = cJSON_PrintUnformatted(object); -#endif /* _DEBUG */ - - cJSON_Delete(object); - - len = strlen(json); + unsigned long len = str.size(); char strLength[50]; sprintf(strLength, "%lu:", (unsigned long)len); fifo->Write(strLength, strlen(strLength)); - fifo->Write(json, len); - free(json); + fifo->Write(str.c_str(), len); fifo->Write(",", 1); } diff --git a/jsonrpc/netstring.h b/jsonrpc/netstring.h index 732fcad87..4f264ccd1 100644 --- a/jsonrpc/netstring.h +++ b/jsonrpc/netstring.h @@ -20,28 +20,17 @@ #ifndef NETSTRING_H #define NETSTRING_H -struct cJSON; - namespace icinga { -typedef ::cJSON json_t; - class I2_JSONRPC_API Netstring : public Object { -private: - size_t m_Length; - void *m_Data; - - static Dictionary::Ptr GetDictionaryFromJson(json_t *json); - static json_t *GetJsonFromDictionary(const Dictionary::Ptr& dictionary); - public: typedef shared_ptr Ptr; typedef weak_ptr WeakPtr; - static bool ReadMessageFromFIFO(FIFO::Ptr fifo, Message *message); - static void WriteMessageToFIFO(FIFO::Ptr fifo, const Message& message); + static bool ReadStringFromFIFO(FIFO::Ptr fifo, string *message); + static void WriteStringToFIFO(FIFO::Ptr fifo, const string& message); }; }