mirror of
https://github.com/Icinga/icinga2.git
synced 2025-04-08 17:05:25 +02:00
De-coupled JSON parsing from the Netstring class.
This commit is contained in:
parent
7b03f52e99
commit
cdcac0d903
@ -57,6 +57,8 @@
|
||||
#include <typeinfo>
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
|
||||
#if defined(__APPLE__) && defined(__MACH__)
|
||||
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
|
@ -17,8 +17,6 @@
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
******************************************************************************/
|
||||
|
||||
#include <functional>
|
||||
#include <algorithm>
|
||||
#include "i2-base.h"
|
||||
|
||||
using namespace icinga;
|
||||
|
@ -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<EndpointManager>(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<Endpoint::Ptr>::iterator i = m_Endpoints.begin(); i != m_Endpoints.end(); i++)
|
||||
for (vector<Endpoint::Ptr>::iterator i = m_Endpoints.begin(); i != m_Endpoints.end(); i++)
|
||||
{
|
||||
SendUnicastRequest(sender, *i, request, fromLocal);
|
||||
}
|
||||
@ -156,7 +160,7 @@ void EndpointManager::ForEachEndpoint(function<int (const NewEndpointEventArgs&)
|
||||
NewEndpointEventArgs neea;
|
||||
neea.Source = shared_from_this();
|
||||
|
||||
list<Endpoint::Ptr>::iterator prev, i;
|
||||
vector<Endpoint::Ptr>::iterator prev, i;
|
||||
for (i = m_Endpoints.begin(); i != m_Endpoints.end(); ) {
|
||||
prev = i;
|
||||
i++;
|
||||
@ -168,7 +172,7 @@ void EndpointManager::ForEachEndpoint(function<int (const NewEndpointEventArgs&)
|
||||
|
||||
Endpoint::Ptr EndpointManager::GetEndpointByIdentity(string identity) const
|
||||
{
|
||||
list<Endpoint::Ptr>::const_iterator i;
|
||||
vector<Endpoint::Ptr>::const_iterator i;
|
||||
for (i = m_Endpoints.begin(); i != m_Endpoints.end(); i++) {
|
||||
if ((*i)->GetIdentity() == identity)
|
||||
return *i;
|
||||
|
@ -33,8 +33,8 @@ class I2_ICINGA_API EndpointManager : public Object
|
||||
string m_Identity;
|
||||
shared_ptr<SSL_CTX> m_SSLContext;
|
||||
|
||||
list<JsonRpcServer::Ptr> m_Servers;
|
||||
list<Endpoint::Ptr> m_Endpoints;
|
||||
vector<JsonRpcServer::Ptr> m_Servers;
|
||||
vector<Endpoint::Ptr> m_Endpoints;
|
||||
|
||||
void RegisterServer(JsonRpcServer::Ptr server);
|
||||
void UnregisterServer(JsonRpcServer::Ptr server);
|
||||
|
@ -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;
|
||||
|
@ -18,6 +18,7 @@
|
||||
******************************************************************************/
|
||||
|
||||
#include "i2-jsonrpc.h"
|
||||
#include <cJSON.h>
|
||||
|
||||
using namespace icinga;
|
||||
|
||||
@ -26,6 +27,18 @@ Message::Message(void)
|
||||
m_Dictionary = make_shared<Dictionary>();
|
||||
}
|
||||
|
||||
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<Dictionary>();
|
||||
|
||||
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<Dictionary>(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;
|
||||
|
@ -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;
|
||||
|
@ -17,67 +17,12 @@
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
******************************************************************************/
|
||||
|
||||
#include <cstdio>
|
||||
#include "i2-jsonrpc.h"
|
||||
#include <cJSON.h>
|
||||
|
||||
using namespace icinga;
|
||||
|
||||
Dictionary::Ptr Netstring::GetDictionaryFromJson(json_t *json)
|
||||
{
|
||||
Dictionary::Ptr dictionary = make_shared<Dictionary>();
|
||||
|
||||
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<Dictionary>(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);
|
||||
}
|
||||
|
@ -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<Netstring> Ptr;
|
||||
typedef weak_ptr<Netstring> 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);
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user