Refactored JSON/message code.

This commit is contained in:
Gunnar Beutner 2012-04-16 16:27:41 +02:00
parent 40b45c3d91
commit ab32aa4f71
25 changed files with 474 additions and 309 deletions

View 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 */

View 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))

View 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

View 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());
}

View 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;
};
}

View 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();
}
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<Endpoint::Ptr>::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);
}
}

View 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);
};
}

View 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

View 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);
}

View File

@ -6,7 +6,19 @@ 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);
};
}

View 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);
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<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::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<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();
}

View 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);
};
}

View File

@ -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"

View File

@ -13,16 +13,48 @@
<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>

View 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);
}

View 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);

View File

@ -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");
}

View File

@ -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 */

View File

@ -0,0 +1,5 @@
JsonRpcRequest : Message
JsonRpc : string
Method : string
Params : Message
ID : string

View File

@ -0,0 +1,5 @@
JsonRpcResponse : Message
JsonRpc : string
Result : string
Error : string
ID : string

View 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);

View 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);
};
}

177
msgc/msgc.cpp Normal file
View File

@ -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;
}

82
msgc/msgc.vcxproj Normal file
View File

@ -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>