icinga2/jsonrpc/netstring.cpp

158 lines
4.8 KiB
C++
Raw Normal View History

/******************************************************************************
* Icinga 2 *
* Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/) *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software Foundation *
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
******************************************************************************/
2012-03-28 13:24:49 +02:00
#include <cstdio>
#include "i2-jsonrpc.h"
#include <cJSON.h>
2012-03-28 13:24:49 +02:00
using namespace icinga;
Dictionary::Ptr Netstring::GetDictionaryFromJson(json_t *json)
2012-04-18 15:22:25 +02:00
{
Dictionary::Ptr dictionary = make_shared<Dictionary>();
for (cJSON *i = json->child; i != NULL; i = i->next) {
switch (i->type) {
case cJSON_Number:
2012-04-20 13:49:04 +02:00
dictionary->SetProperty(i->string, i->valueint);
2012-04-18 15:22:25 +02:00
break;
case cJSON_String:
2012-04-20 13:49:04 +02:00
dictionary->SetProperty(i->string, i->valuestring);
2012-04-18 15:22:25 +02:00
break;
case cJSON_Object:
2012-04-20 13:49:04 +02:00
dictionary->SetProperty(i->string, GetDictionaryFromJson(i));
2012-04-18 15:22:25 +02:00
break;
default:
break;
}
}
return dictionary;
}
json_t *Netstring::GetJsonFromDictionary(const Dictionary::Ptr& dictionary)
2012-04-18 15:22:25 +02:00
{
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)
2012-04-18 15:22:25 +02:00
cJSON_AddItemToObject(json, i->first.c_str(), GetJsonFromDictionary(valueDictionary));
default:
break;
}
}
return json;
}
2012-03-28 13:24:49 +02:00
/* based on https://github.com/PeterScott/netstring-c/blob/master/netstring.c */
2012-04-18 15:22:25 +02:00
bool Netstring::ReadMessageFromFIFO(FIFO::Ptr fifo, Message *message)
2012-03-28 13:24:49 +02:00
{
size_t buffer_length = fifo->GetSize();
2012-03-28 21:20:13 +02:00
char *buffer = (char *)fifo->GetReadBuffer();
2012-03-28 13:24:49 +02:00
/* minimum netstring length is 3 */
if (buffer_length < 3)
2012-04-18 15:22:25 +02:00
return false;
2012-03-28 13:24:49 +02:00
/* no leading zeros allowed */
if (buffer[0] == '0' && isdigit(buffer[1]))
2012-04-18 15:22:25 +02:00
throw InvalidArgumentException("Invalid netstring (leading zero)");
2012-03-28 13:24:49 +02:00
size_t len, i;
len = 0;
for (i = 0; i < buffer_length && isdigit(buffer[i]); i++) {
/* length specifier must have at most 9 characters */
if (i >= 9)
throw InvalidArgumentException("Length specifier must not exceed 9 characters");
2012-03-28 13:24:49 +02:00
len = len * 10 + (buffer[i] - '0');
}
/* make sure the buffer is large enough */
if (i + len + 1 >= buffer_length)
2012-04-18 15:22:25 +02:00
return false;
2012-03-28 13:24:49 +02:00
/* check for the colon delimiter */
if (buffer[i++] != ':')
2012-04-18 15:22:25 +02:00
throw InvalidArgumentException("Invalid Netstring (missing :)");
2012-03-28 13:24:49 +02:00
/* check for the comma delimiter after the string */
if (buffer[i + len] != ',')
2012-04-18 15:22:25 +02:00
throw InvalidArgumentException("Invalid Netstring (missing ,)");
2012-03-28 13:24:49 +02:00
2012-03-28 21:20:13 +02:00
/* nuke the comma delimiter */
buffer[i + len] = '\0';
cJSON *object = cJSON_Parse(&buffer[i]);
if (object == NULL) {
/* restore the comma */
buffer[i + len] = ',';
2012-04-18 15:22:25 +02:00
throw InvalidArgumentException("Invalid JSON string");
2012-03-28 21:20:13 +02:00
}
2012-03-28 13:24:49 +02:00
/* remove the data from the fifo */
fifo->Read(NULL, i + len + 1);
2012-04-18 15:22:25 +02:00
*message = Message(GetDictionaryFromJson(object));
cJSON_Delete(object);
return true;
2012-03-28 13:24:49 +02:00
}
2012-04-18 15:22:25 +02:00
void Netstring::WriteMessageToFIFO(FIFO::Ptr fifo, const Message& message)
2012-03-28 13:24:49 +02:00
{
char *json;
2012-04-18 15:22:25 +02:00
cJSON *object = GetJsonFromDictionary(message.GetDictionary());
size_t len;
#ifdef _DEBUG
2012-04-18 15:22:25 +02:00
json = cJSON_Print(object);
#else /* _DEBUG */
2012-04-18 15:22:25 +02:00
json = cJSON_PrintUnformatted(object);
#endif /* _DEBUG */
2012-04-18 15:22:25 +02:00
cJSON_Delete(object);
len = strlen(json);
2012-03-28 13:24:49 +02:00
char strLength[50];
2012-04-18 15:22:25 +02:00
sprintf(strLength, "%lu:", (unsigned long)len);
2012-03-28 13:24:49 +02:00
fifo->Write(strLength, strlen(strLength));
2012-03-28 21:20:13 +02:00
fifo->Write(json, len);
free(json);
2012-03-28 13:24:49 +02:00
fifo->Write(",", 1);
}