char *debugging = getenv("_DEBUG");
m_Debugging = (debugging && strtol(debugging, NULL, 10) != 0);
+#ifdef _WIN32
+ if (IsDebuggerPresent())
+ m_Debugging = true;
+#endif /* _WIN32 */
+
m_ShuttingDown = false;
m_ConfigHive = make_shared<ConfigHive>();
}
fd_set readfds, writefds, exceptfds;
int nfds = -1;
+ Timer::CallExpiredTimers();
+
FD_ZERO(&readfds);
FD_ZERO(&writefds);
FD_ZERO(&exceptfds);
nfds = fd;
}
- long sleep;
-
- do {
- Timer::CallExpiredTimers();
- sleep = (long)(Timer::GetNextCall() - time(NULL));
- } while (sleep <= 0);
+ long sleep = (long)(Timer::GetNextCall() - time(NULL));
if (m_ShuttingDown)
break;
else if (ready == 0)
continue;
- EventArgs::Ptr ea = make_shared<EventArgs>();
- ea->Source = shared_from_this();
+ EventArgs ea;
+ ea.Source = shared_from_this();
list<Socket::WeakPtr>::iterator prev, i;
for (i = Socket::Sockets.begin(); i != Socket::Sockets.end(); ) {
throw ComponentLoadException("Loadable module does not contain CreateComponent function");
component = Component::Ptr(pCreateComponent());
- component->SetApplication(static_pointer_cast<Application>(shared_from_this()));
component->SetConfig(componentConfig);
+ RegisterComponent(component);
+ return component;
+}
+
+void Application::RegisterComponent(Component::Ptr component)
+{
+ component->SetApplication(static_pointer_cast<Application>(shared_from_this()));
m_Components[component->GetName()] = component;
component->Start();
-
- return component;
}
-Component::Ptr Application::GetComponent(const string& name)
+void Application::UnregisterComponent(Component::Ptr component)
{
- map<string, Component::Ptr>::iterator ci = m_Components.find(name);
-
- if (ci == m_Components.end())
- return Component::Ptr();
+ string name = component->GetName();
- return ci->second;
+ Log("Unloading component '%s'", name.c_str());
+ map<string, Component::Ptr>::iterator i = m_Components.find(name);
+ if (i != m_Components.end()) {
+ m_Components.erase(i);
+ component->Stop();
+ }
}
-void Application::UnloadComponent(const string& name)
+Component::Ptr Application::GetComponent(const string& name)
{
map<string, Component::Ptr>::iterator ci = m_Components.find(name);
if (ci == m_Components.end())
- return;
-
- Log("Unloading component '%s'", name.c_str());
-
- Component::Ptr component = ci->second;
- component->Stop();
- m_Components.erase(ci);
+ return Component::Ptr();
- // TODO: unload DLL
+ return ci->second;
}
void Application::Log(const char *format, ...)
try {
result = Application::Instance->Main(args);
} catch (const Exception& ex) {
- cout << "---" << endl;
+ cerr << "---" << endl;
string klass = typeid(ex).name();
}
#endif /* HAVE_GCC_ABI_DEMANGLE */
- cout << "Exception: " << klass << endl;
- cout << "Message: " << ex.GetMessage() << endl;
+ cerr << "Exception: " << klass << endl;
+ cerr << "Message: " << ex.GetMessage() << endl;
return EXIT_FAILURE;
}
ConfigHive::Ptr GetConfigHive(void);
shared_ptr<Component> LoadComponent(const string& path, const ConfigObject::Ptr& componentConfig);
- void UnloadComponent(const string& name);
+ void RegisterComponent(shared_ptr<Component> component);
+ void UnregisterComponent(shared_ptr<Component> component);
shared_ptr<Component> GetComponent(const string& name);
void AddComponentSearchDir(const string& componentDirectory);
<ClCompile Include="configcollection.cpp" />
<ClCompile Include="confighive.cpp" />
<ClCompile Include="configobject.cpp" />
+ <ClCompile Include="dictionary.cpp" />
<ClCompile Include="exception.cpp" />
<ClCompile Include="fifo.cpp" />
<ClCompile Include="memory.cpp" />
<ClCompile Include="thread.cpp" />
<ClCompile Include="timer.cpp" />
<ClCompile Include="unix.cpp" />
+ <ClCompile Include="variant.cpp" />
<ClCompile Include="win32.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="configobject.h" />
<ClInclude Include="cxx11-compat.h" />
<ClInclude Include="delegate.h" />
+ <ClInclude Include="dictionary.h" />
<ClInclude Include="event.h" />
<ClInclude Include="exception.h" />
<ClInclude Include="fifo.h" />
<ClInclude Include="thread.h" />
<ClInclude Include="timer.h" />
<ClInclude Include="unix.h" />
+ <ClInclude Include="variant.h" />
<ClInclude Include="win32.h" />
</ItemGroup>
<ItemGroup>
{
Objects[object->GetName()] = object;
- ConfigObjectEventArgs::Ptr ea = make_shared<ConfigObjectEventArgs>();
- ea->Source = object;
+ ConfigObjectEventArgs ea;
+ ea.Source = object;
OnObjectCreated(ea);
ConfigHive::Ptr hive = m_Hive.lock();
if (oi != Objects.end()) {
Objects.erase(oi);
- ConfigObjectEventArgs::Ptr ea = make_shared<ConfigObjectEventArgs>();
- ea->Source = object;
+ ConfigObjectEventArgs ea;
+ ea.Source = object;
OnObjectRemoved(ea);
ConfigHive::Ptr hive = m_Hive.lock();
return oi->second;
}
-void ConfigCollection::ForEachObject(function<int (ConfigObjectEventArgs::Ptr)> callback)
+void ConfigCollection::ForEachObject(function<int (const ConfigObjectEventArgs&)> callback)
{
+ ConfigObjectEventArgs ea;
+
for (ObjectIterator oi = Objects.begin(); oi != Objects.end(); oi++) {
- ConfigObjectEventArgs::Ptr ea = make_shared<ConfigObjectEventArgs>();
- ea->Source = oi->second;
+ ea.Source = oi->second;
callback(ea);
}
}
void RemoveObject(const ConfigObject::Ptr& object);
ConfigObject::Ptr GetObject(const string& name = string());
- void ForEachObject(function<int (ConfigObjectEventArgs::Ptr)> callback);
+ void ForEachObject(function<int (const ConfigObjectEventArgs&)> callback);
- Event<ConfigObjectEventArgs::Ptr> OnObjectCreated;
- Event<ConfigObjectEventArgs::Ptr> OnObjectRemoved;
- Event<ConfigObjectEventArgs::Ptr> OnPropertyChanged;
+ Event<ConfigObjectEventArgs> OnObjectCreated;
+ Event<ConfigObjectEventArgs> OnObjectRemoved;
+ Event<ConfigObjectEventArgs> OnPropertyChanged;
};
}
return ci->second;
}
-void ConfigHive::ForEachObject(const string& type, function<int (ConfigObjectEventArgs::Ptr)> callback)
+void ConfigHive::ForEachObject(const string& type, function<int (const ConfigObjectEventArgs&)> callback)
{
CollectionIterator ci = Collections.find(type);
ConfigObject::Ptr GetObject(const string& collection, const string& name = string());
ConfigCollection::Ptr GetCollection(const string& collection);
- void ForEachObject(const string& type, function<int (ConfigObjectEventArgs::Ptr)> callback);
+ void ForEachObject(const string& type, function<int (const ConfigObjectEventArgs&)> callback);
- Event<ConfigObjectEventArgs::Ptr> OnObjectCreated;
- Event<ConfigObjectEventArgs::Ptr> OnObjectRemoved;
- Event<ConfigObjectEventArgs::Ptr> OnPropertyChanged;
+ Event<ConfigObjectEventArgs> OnObjectCreated;
+ Event<ConfigObjectEventArgs> OnObjectRemoved;
+ Event<ConfigObjectEventArgs> OnPropertyChanged;
};
}
ConfigHive::Ptr hive = m_Hive.lock();
if (hive) {
- ConfigObjectEventArgs::Ptr ea = make_shared<ConfigObjectEventArgs>();
- ea->Source = shared_from_this();
- ea->Property = name;
+ ConfigObjectEventArgs ea;
+ ea.Source = shared_from_this();
+ ea.Property = name;
string oldValue;
if (GetProperty(name, &oldValue))
- ea->OldValue = oldValue;
+ ea.OldValue = oldValue;
hive->GetCollection(m_Type)->OnPropertyChanged(ea);
hive->OnPropertyChanged(ea);
--- /dev/null
+#include "i2-base.h"
+
+using namespace icinga;
+
+bool Dictionary::GetValueVariant(string key, Variant *value)
+{
+ DictionaryIterator i = m_Data.find(key);
+
+ if (i == m_Data.end())
+ return false;
+
+ *value = i->second;
+
+ return true;
+}
+
+void Dictionary::SetValueVariant(string key, const Variant& value)
+{
+ m_Data.erase(key);
+ m_Data[key] = value;
+}
+
+bool Dictionary::GetValueString(string key, string *value)
+{
+ Variant data;
+
+ if (!GetValueVariant(key, &data))
+ return false;
+
+ *value = data;
+ return true;
+}
+
+void Dictionary::SetValueString(string key, const string& value)
+{
+ SetValueVariant(key, Variant(value));
+}
+
+bool Dictionary::GetValueInteger(string key, long *value)
+{
+ Variant data;
+
+ if (!GetValueVariant(key, &data))
+ return false;
+
+ *value = data;
+ return true;
+}
+
+void Dictionary::SetValueInteger(string key, long value)
+{
+ SetValueVariant(key, Variant(value));
+}
+
+bool Dictionary::GetValueDictionary(string key, Dictionary::Ptr *value)
+{
+ Dictionary::Ptr dictionary;
+ Variant data;
+
+ if (!GetValueVariant(key, &data))
+ return false;
+
+ dictionary = dynamic_pointer_cast<Dictionary>(data.GetObject());
+
+ if (dictionary == NULL)
+ throw InvalidArgumentException();
+
+ *value = dictionary;
+
+ return true;
+}
+
+void Dictionary::SetValueDictionary(string key, const Dictionary::Ptr& value)
+{
+ SetValueVariant(key, Variant(value));
+}
+
+bool Dictionary::GetValueObject(string key, Object::Ptr *value)
+{
+ Variant data;
+
+ if (!GetValueVariant(key, &data))
+ return false;
+
+ *value = data;
+ return true;
+}
+
+void Dictionary::SetValueObject(string key, const Object::Ptr& value)
+{
+ SetValueVariant(key, Variant(value));
+}
+
+DictionaryIterator Dictionary::Begin(void)
+{
+ return m_Data.begin();
+}
+
+DictionaryIterator Dictionary::End(void)
+{
+ return m_Data.end();
+}
--- /dev/null
+#ifndef DICTIONARY_H
+#define DICTIONARY_H
+
+namespace icinga
+{
+
+typedef map<string, Variant>::iterator DictionaryIterator;
+
+class I2_BASE_API Dictionary : public Object
+{
+private:
+ map<string, Variant> m_Data;
+
+public:
+ typedef shared_ptr<Dictionary> Ptr;
+ typedef weak_ptr<Dictionary> WeakPtr;
+
+ bool GetValueVariant(string key, Variant *value);
+ void SetValueVariant(string key, const Variant& value);
+
+ bool GetValueString(string key, string *value);
+ void SetValueString(string key, const string& value);
+
+ bool GetValueInteger(string key, long *value);
+ void SetValueInteger(string key, long value);
+
+ bool GetValueDictionary(string key, Dictionary::Ptr *value);
+ void SetValueDictionary(string key, const Dictionary::Ptr& value);
+
+ bool GetValueObject(string key, Object::Ptr *value);
+ void SetValueObject(string key, const Object::Ptr& value);
+
+ DictionaryIterator Begin(void);
+ DictionaryIterator End(void);
+};
+
+}
+
+#endif /* DICTIONARY_H */
namespace icinga
{
-struct I2_BASE_API EventArgs : public Object
+struct I2_BASE_API EventArgs
{
- typedef shared_ptr<EventArgs> Ptr;
- typedef weak_ptr<EventArgs> WeakPtr;
-
Object::Ptr Source;
};
class Event
{
public:
- typedef function<int (TArgs)> DelegateType;
+ typedef function<int (const TArgs&)> DelegateType;
private:
list<DelegateType> m_Delegates;
#include "memory.h"
#include "delegate.h"
#include "event.h"
+#include "variant.h"
+#include "dictionary.h"
#include "timer.h"
#include "fifo.h"
#include "socket.h"
void Socket::Start(void)
{
+ assert(m_FD != INVALID_SOCKET);
+
OnException += bind_weak(&Socket::ExceptionEventHandler, shared_from_this());
Sockets.push_front(static_pointer_cast<Socket>(shared_from_this()));
/* nobody can possibly have a valid event subscription when the destructor has been called */
if (!from_dtor) {
- EventArgs::Ptr ea = make_shared<EventArgs>();
- ea->Source = shared_from_this();
+ EventArgs ea;
+ ea.Source = shared_from_this();
OnClosed(ea);
}
}
return result;
}
-int Socket::ExceptionEventHandler(EventArgs::Ptr ea)
+int Socket::ExceptionEventHandler(const EventArgs& ea)
{
int opt;
socklen_t optlen = sizeof(opt);
}
if (opt != 0) {
- SocketErrorEventArgs::Ptr ea = make_shared<SocketErrorEventArgs>();
- ea->Code = opt;
- ea->Message = FormatErrorCode(ea->Code);
- OnError(ea);
+ SocketErrorEventArgs sea;
+ sea.Code = opt;
+ sea.Message = FormatErrorCode(sea.Code);
+ OnError(sea);
Close();
}
private:
SOCKET m_FD;
- int ExceptionEventHandler(EventArgs::Ptr ea);
+ int ExceptionEventHandler(const EventArgs& ea);
protected:
string FormatErrorCode(int errorCode);
static void CloseAllSockets(void);
- Event<EventArgs::Ptr> OnReadable;
- Event<EventArgs::Ptr> OnWritable;
- Event<EventArgs::Ptr> OnException;
+ Event<EventArgs> OnReadable;
+ Event<EventArgs> OnWritable;
+ Event<EventArgs> OnException;
- Event<SocketErrorEventArgs::Ptr> OnError;
- Event<EventArgs::Ptr> OnClosed;
+ Event<SocketErrorEventArgs> OnError;
+ Event<EventArgs> OnClosed;
virtual bool WantsToRead(void) const;
virtual bool WantsToWrite(void) const;
#else /* _WIN32 */
if (rc < 0 && errno != EINPROGRESS) {
#endif /* _WIN32 */
- SocketErrorEventArgs::Ptr ea = make_shared<SocketErrorEventArgs>();
+ SocketErrorEventArgs sea;
#ifdef _WIN32
- ea->Code = WSAGetLastError();
+ sea.Code = WSAGetLastError();
#else /* _WIN32 */
- ea->Code = errno;
+ sea.Code = errno;
#endif /* _WIN32 */
- ea->Message = FormatErrorCode(ea->Code);
+ sea.Message = FormatErrorCode(sea.Code);
- OnError(ea);
+ OnError(sea);
Close();
}
return m_PeerPort;
}
-int TCPClient::ReadableEventHandler(EventArgs::Ptr ea)
+int TCPClient::ReadableEventHandler(const EventArgs& ea)
{
int rc;
if (rc <= 0) {
if (rc < 0) {
- SocketErrorEventArgs::Ptr ea = make_shared<SocketErrorEventArgs>();
+ SocketErrorEventArgs sea;
#ifdef _WIN32
- ea->Code = WSAGetLastError();
+ sea.Code = WSAGetLastError();
#else /* _WIN32 */
- ea->Code = errno;
+ sea.Code = errno;
#endif /* _WIN32 */
- ea->Message = FormatErrorCode(ea->Code);
+ sea.Message = FormatErrorCode(sea.Code);
- OnError(ea);
+ OnError(sea);
}
Close();
m_RecvQueue->Write(NULL, rc);
- EventArgs::Ptr dea = make_shared<EventArgs>();
- dea->Source = shared_from_this();
+ EventArgs dea;
+ dea.Source = shared_from_this();
OnDataAvailable(dea);
return 0;
}
-int TCPClient::WritableEventHandler(EventArgs::Ptr ea)
+int TCPClient::WritableEventHandler(const EventArgs& ea)
{
int rc;
if (rc <= 0) {
if (rc < 0) {
- SocketErrorEventArgs::Ptr ea = make_shared<SocketErrorEventArgs>();
+ SocketErrorEventArgs sea;
#ifdef _WIN32
- ea->Code = WSAGetLastError();
+ sea.Code = WSAGetLastError();
#else /* _WIN32 */
- ea->Code = errno;
+ sea.Code = errno;
#endif /* _WIN32 */
- ea->Message = FormatErrorCode(ea->Code);
+ sea.Message = FormatErrorCode(sea.Code);
- OnError(ea);
+ OnError(sea);
}
Close();
FIFO::Ptr m_SendQueue;
FIFO::Ptr m_RecvQueue;
- int ReadableEventHandler(EventArgs::Ptr ea);
- int WritableEventHandler(EventArgs::Ptr ea);
+ int ReadableEventHandler(const EventArgs& ea);
+ int WritableEventHandler(const EventArgs& ea);
public:
typedef shared_ptr<TCPClient> Ptr;
virtual bool WantsToRead(void) const;
virtual bool WantsToWrite(void) const;
- Event<EventArgs::Ptr> OnDataAvailable;
+ Event<EventArgs> OnDataAvailable;
};
}
Start();
}
-int TCPServer::ReadableEventHandler(EventArgs::Ptr ea)
+int TCPServer::ReadableEventHandler(const EventArgs& ea)
{
int fd;
sockaddr_in addr;
fd = accept(GetFD(), (sockaddr *)&addr, &addrlen);
- NewClientEventArgs::Ptr nea = make_shared<NewClientEventArgs>();
- nea->Source = shared_from_this();
- nea->Client = static_pointer_cast<TCPSocket>(m_ClientFactory());
- nea->Client->SetFD(fd);
- nea->Client->Start();
+ if (fd == INVALID_SOCKET) {
+#ifdef _WIN32
+ if (WSAGetLastError() == WSAEWOULDBLOCK)
+#else /* _WIN32 */
+ if (errno == EINPROGRESS)
+#endif /* _WIN32 */
+ return 0;
+
+ SocketErrorEventArgs sea;
+#ifdef _WIN32
+ sea.Code = WSAGetLastError();
+#else /* _WIN32 */
+ sea.Code = errno;
+#endif /* _WIN32 */
+ sea.Message = FormatErrorCode(sea.Code);
+
+ OnError(sea);
+
+ Close();
+ }
+
+ NewClientEventArgs nea;
+ nea.Source = shared_from_this();
+ nea.Client = static_pointer_cast<TCPSocket>(m_ClientFactory());
+ nea.Client->SetFD(fd);
+ nea.Client->Start();
OnNewClient(nea);
return 0;
class I2_BASE_API TCPServer : public TCPSocket
{
private:
- int ReadableEventHandler(EventArgs::Ptr ea);
+ int ReadableEventHandler(const EventArgs& ea);
factory_function m_ClientFactory;
void Listen(void);
- Event<NewClientEventArgs::Ptr> OnNewClient;
+ Event<NewClientEventArgs> OnNewClient;
virtual bool WantsToRead(void) const;
};
int fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd == INVALID_SOCKET) {
- SocketErrorEventArgs::Ptr ea = make_shared<SocketErrorEventArgs>();
+ SocketErrorEventArgs sea;
#ifdef _WIN32
- ea->Code = WSAGetLastError();
+ sea.Code = WSAGetLastError();
#else /* _WIN32 */
- ea->Code = errno;
+ sea.Code = errno;
#endif /* _WIN32 */
- ea->Message = FormatErrorCode(ea->Code);
- OnError(ea);
+ sea.Message = FormatErrorCode(sea.Code);
+ OnError(sea);
}
SetFD(fd);
int rc = ::bind(GetFD(), (sockaddr *)&sin, sizeof(sin));
if (rc < 0) {
- SocketErrorEventArgs::Ptr ea = make_shared<SocketErrorEventArgs>();
+ SocketErrorEventArgs sea;
#ifdef _WIN32
- ea->Code = WSAGetLastError();
+ sea.Code = WSAGetLastError();
#else /* _WIN32 */
- ea->Code = errno;
+ sea.Code = errno;
#endif /* _WIN32 */
- ea->Message = FormatErrorCode(ea->Code);
+ sea.Message = FormatErrorCode(sea.Code);
- OnError(ea);
+ OnError(sea);
Close();
}
* the timer that originally invoked the delegate */
void Timer::Call(void)
{
- TimerEventArgs::Ptr ea = make_shared<TimerEventArgs>();
- ea->Source = shared_from_this();
- ea->UserArgs = m_UserArgs;
- OnTimerExpired(ea);
+ TimerEventArgs tea;
+ tea.Source = shared_from_this();
+ tea.UserArgs = m_UserArgs;
+ OnTimerExpired(tea);
}
void Timer::SetInterval(unsigned int interval)
return m_Interval;
}
-void Timer::SetUserArgs(const EventArgs::Ptr& userArgs)
+void Timer::SetUserArgs(const EventArgs& userArgs)
{
m_UserArgs = userArgs;
}
-EventArgs::Ptr Timer::GetUserArgs(void) const
+EventArgs Timer::GetUserArgs(void) const
{
return m_UserArgs;
}
typedef shared_ptr<TimerEventArgs> Ptr;
typedef weak_ptr<TimerEventArgs> WeakPtr;
- EventArgs::Ptr UserArgs;
+ EventArgs UserArgs;
};
class I2_BASE_API Timer : public Object
{
private:
- EventArgs::Ptr m_UserArgs;
+ EventArgs m_UserArgs;
unsigned int m_Interval;
time_t m_Next;
void SetInterval(unsigned int interval);
unsigned int GetInterval(void) const;
- void SetUserArgs(const EventArgs::Ptr& userArgs);
- EventArgs::Ptr GetUserArgs(void) const;
+ void SetUserArgs(const EventArgs& userArgs);
+ EventArgs GetUserArgs(void) const;
static time_t GetNextCall(void);
static void CallExpiredTimers(void);
void Reschedule(time_t next);
- Event<TimerEventArgs::Ptr> OnTimerExpired;
+ Event<TimerEventArgs> OnTimerExpired;
};
}
--- /dev/null
+#include "i2-base.h"
+
+using namespace icinga;
+
+Variant::Variant(void) : m_Type(VariantEmpty)
+{
+}
+
+Variant::Variant(long value) : m_Type(VariantInteger), m_IntegerValue(value)
+{
+}
+
+Variant::Variant(string value) : m_Type(VariantString), m_StringValue(value)
+{
+}
+
+Variant::Variant(Object::Ptr value) : m_Type(VariantObject), m_ObjectValue(value)
+{
+}
+
+void Variant::Convert(VariantType newType) const
+{
+ if (newType == m_Type)
+ return;
+
+ throw NotImplementedException();
+}
+
+VariantType Variant::GetType(void) const
+{
+ return m_Type;
+}
+
+long Variant::GetInteger(void) const
+{
+ Convert(VariantInteger);
+
+ return m_IntegerValue;
+}
+
+string Variant::GetString(void) const
+{
+ Convert(VariantString);
+
+ return m_StringValue;
+}
+
+Object::Ptr Variant::GetObject(void) const
+{
+ Convert(VariantObject);
+
+ return m_ObjectValue;
+}
+
+Variant::operator long(void) const
+{
+ return GetInteger();
+}
+
+Variant::operator string(void) const
+{
+ return GetString();
+}
+
+Variant::operator Object::Ptr(void) const
+{
+ return GetObject();
+}
--- /dev/null
+#ifndef VARIANT_H
+#define VARIANT_H
+
+namespace icinga
+{
+
+enum I2_BASE_API VariantType
+{
+ VariantEmpty,
+ VariantInteger,
+ VariantString,
+ VariantObject
+};
+
+class I2_BASE_API Variant
+{
+private:
+ mutable long m_IntegerValue;
+ mutable string m_StringValue;
+ mutable Object::Ptr m_ObjectValue;
+
+ mutable VariantType m_Type;
+
+ void Convert(VariantType newType) const;
+
+public:
+ Variant(void);
+ Variant(long value);
+ Variant(string value);
+ Variant(Object::Ptr value);
+
+ VariantType GetType(void) const;
+
+ long GetInteger(void) const;
+ string GetString(void) const;
+ Object::Ptr GetObject(void) const;
+
+ operator long(void) const;
+ operator string(void) const;
+ operator Object::Ptr(void) const;
+};
+
+}
+
+#endif /* VARIANT_H */
\ No newline at end of file
// TODO: implement
}
-JsonRpcMessage::Ptr ConfigRpcComponent::MakeObjectMessage(const ConfigObject::Ptr& object, string method, bool includeProperties)
+JsonRpcRequest ConfigRpcComponent::MakeObjectMessage(const ConfigObject::Ptr& object, string method, bool includeProperties)
{
- JsonRpcMessage::Ptr msg = make_shared<JsonRpcMessage>();
- msg->SetVersion("2.0");
- msg->SetMethod(method);
- cJSON *params = msg->GetParams();
+ JsonRpcRequest msg;
+ msg.SetVersion("2.0");
+ msg.SetMethod(method);
- string name = object->GetName();
- cJSON_AddStringToObject(params, "name", name.c_str());
+ Message params;
+ msg.SetParams(params);
- string type = object->GetType();
- cJSON_AddStringToObject(params, "type", type.c_str());
+ params.GetDictionary()->SetValueString("name", object->GetName());
+ params.GetDictionary()->SetValueString("type", object->GetType());
if (includeProperties) {
- cJSON *properties = cJSON_CreateObject();
- cJSON_AddItemToObject(params, "properties", properties);
+ Message properties;
+ params.GetDictionary()->SetValueDictionary("properties", properties.GetDictionary());
for (ConfigObject::ParameterIterator pi = object->Properties.begin(); pi != object->Properties.end(); pi++) {
- cJSON_AddStringToObject(properties, pi->first.c_str(), pi->second.c_str());
+ properties.GetDictionary()->SetValueString(pi->first, pi->second);
}
}
return msg;
}
-int ConfigRpcComponent::FetchObjectsHandler(NewMessageEventArgs::Ptr ea)
+int ConfigRpcComponent::FetchObjectsHandler(const NewRequestEventArgs& ea)
{
- JsonRpcClient::Ptr client = static_pointer_cast<JsonRpcClient>(ea->Source);
+ Endpoint::Ptr client = ea.Sender;
ConfigHive::Ptr configHive = GetIcingaApplication()->GetConfigHive();
for (ConfigHive::CollectionIterator ci = configHive->Collections.begin(); ci != configHive->Collections.end(); ci++) {
ConfigCollection::Ptr collection = ci->second;
for (ConfigCollection::ObjectIterator oi = collection->Objects.begin(); oi != collection->Objects.end(); oi++) {
- JsonRpcMessage::Ptr msg = MakeObjectMessage(oi->second, "config::ObjectCreated", true);
- client->SendMessage(msg);
+ client->ProcessRequest(m_ConfigRpcEndpoint, MakeObjectMessage(oi->second, "config::ObjectCreated", true));
}
}
return 0;
}
-int ConfigRpcComponent::LocalObjectCreatedHandler(ConfigObjectEventArgs::Ptr ea)
+int ConfigRpcComponent::LocalObjectCreatedHandler(const ConfigObjectEventArgs& ea)
{
- ConfigObject::Ptr object = static_pointer_cast<ConfigObject>(ea->Source);
+ ConfigObject::Ptr object = static_pointer_cast<ConfigObject>(ea.Source);
int replicate = 0;
object->GetPropertyInteger("replicate", &replicate);
if (replicate) {
EndpointManager::Ptr mgr = GetIcingaApplication()->GetEndpointManager();
- mgr->SendMessage(m_ConfigRpcEndpoint, Endpoint::Ptr(), MakeObjectMessage(object, "config::ObjectCreated", true));
+ mgr->SendMulticastRequest(m_ConfigRpcEndpoint, MakeObjectMessage(object, "config::ObjectCreated", true));
}
return 0;
}
-int ConfigRpcComponent::LocalObjectRemovedHandler(ConfigObjectEventArgs::Ptr ea)
+int ConfigRpcComponent::LocalObjectRemovedHandler(const ConfigObjectEventArgs& ea)
{
- ConfigObject::Ptr object = static_pointer_cast<ConfigObject>(ea->Source);
+ ConfigObject::Ptr object = static_pointer_cast<ConfigObject>(ea.Source);
int replicate = 0;
object->GetPropertyInteger("replicate", &replicate);
if (replicate) {
EndpointManager::Ptr mgr = GetIcingaApplication()->GetEndpointManager();
- mgr->SendMessage(m_ConfigRpcEndpoint, Endpoint::Ptr(), MakeObjectMessage(object, "config::ObjectRemoved", false));
+ mgr->SendMulticastRequest(m_ConfigRpcEndpoint, MakeObjectMessage(object, "config::ObjectRemoved", false));
}
return 0;
}
-int ConfigRpcComponent::LocalPropertyChangedHandler(ConfigObjectEventArgs::Ptr ea)
+int ConfigRpcComponent::LocalPropertyChangedHandler(const ConfigObjectEventArgs& ea)
{
- ConfigObject::Ptr object = static_pointer_cast<ConfigObject>(ea->Source);
+ ConfigObject::Ptr object = static_pointer_cast<ConfigObject>(ea.Source);
int replicate = 0;
object->GetPropertyInteger("replicate", &replicate);
if (replicate) {
- JsonRpcMessage::Ptr msg = MakeObjectMessage(object, "config::PropertyChanged", false);
- cJSON *params = msg->GetParams();
+ JsonRpcRequest msg = MakeObjectMessage(object, "config::PropertyChanged", false);
+ Message params;
+ msg.SetParams(params);
- cJSON *properties = cJSON_CreateObject();
- cJSON_AddItemToObject(params, "properties", properties);
+ Message properties;
+ params.GetDictionary()->SetValueDictionary("properties", properties.GetDictionary());
string value;
- object->GetProperty(ea->Property, &value);
+ object->GetProperty(ea.Property, &value);
- cJSON_AddStringToObject(properties, ea->Property.c_str(), value.c_str());
+ properties.GetDictionary()->SetValueString(ea.Property, value);
EndpointManager::Ptr mgr = GetIcingaApplication()->GetEndpointManager();
- mgr->SendMessage(m_ConfigRpcEndpoint, Endpoint::Ptr(), msg);
+ mgr->SendMulticastRequest(m_ConfigRpcEndpoint, msg);
}
return 0;
}
-int ConfigRpcComponent::RemoteObjectUpdatedHandler(NewMessageEventArgs::Ptr ea)
+int ConfigRpcComponent::RemoteObjectUpdatedHandler(const NewRequestEventArgs& ea)
{
- JsonRpcMessage::Ptr message = ea->Message;
- string name, type, value;
+ JsonRpcRequest message = ea.Request;
bool was_null = false;
- if (!message->GetParamString("name", &name))
+ Message params;
+ if (!message.GetParams(¶ms))
return 0;
- if (!message->GetParamString("type", &type))
+ string name;
+ if (!params.GetDictionary()->GetValueString("name", &name))
+ return 0;
+
+ string type;
+ if (!params.GetDictionary()->GetValueString("type", &type))
return 0;
ConfigHive::Ptr configHive = GetIcingaApplication()->GetConfigHive();
object = make_shared<ConfigObject>(type, name);
}
- cJSON *properties = message->GetParam("properties");
-
- if (properties != NULL) {
- for (cJSON *prop = properties->child; prop != NULL; prop = prop->next) {
- if (prop->type != cJSON_String)
- continue;
+ Dictionary::Ptr properties;
+ if (!params.GetDictionary()->GetValueDictionary("properties", &properties))
+ return 0;
- object->SetProperty(prop->string, prop->valuestring);
- }
+ for (DictionaryIterator i = properties->Begin(); i != properties->End(); i++) {
+ object->SetProperty(i->first, i->second);
}
if (was_null)
return 0;
}
-int ConfigRpcComponent::RemoteObjectRemovedHandler(NewMessageEventArgs::Ptr ea)
+int ConfigRpcComponent::RemoteObjectRemovedHandler(const NewRequestEventArgs& ea)
{
- JsonRpcRequest::Ptr message = ea->Message->Cast<JsonRpcRequest>();
- Message::Ptr params = message->GetParams();
- string name, type;
+ JsonRpcRequest message = ea.Request;
- if (!message->GetParamString("name", &name))
+ Message params;
+ if (!message.GetParams(¶ms))
+ return 0;
+
+ string name;
+ if (!params.GetDictionary()->GetValueString("name", &name))
return 0;
- if (!message->GetParamString("type", &type))
+ string type;
+ if (!params.GetDictionary()->GetValueString("type", &type))
return 0;
ConfigHive::Ptr configHive = GetIcingaApplication()->GetConfigHive();
IcingaApplication::Ptr GetIcingaApplication(void);
- int FetchObjectsHandler(NewMessageEventArgs::Ptr ea);
+ int LocalObjectCreatedHandler(const ConfigObjectEventArgs& ea);
+ int LocalObjectRemovedHandler(const ConfigObjectEventArgs& ea);
+ int LocalPropertyChangedHandler(const ConfigObjectEventArgs& ea);
- int LocalObjectCreatedHandler(ConfigObjectEventArgs::Ptr ea);
- int LocalObjectRemovedHandler(ConfigObjectEventArgs::Ptr ea);
- int LocalPropertyChangedHandler(ConfigObjectEventArgs::Ptr ea);
+ int FetchObjectsHandler(const NewRequestEventArgs& ea);
+ int RemoteObjectUpdatedHandler(const NewRequestEventArgs& ea);
+ int RemoteObjectRemovedHandler(const NewRequestEventArgs& ea);
- int RemoteObjectUpdatedHandler(NewMessageEventArgs::Ptr ea);
- int RemoteObjectRemovedHandler(NewMessageEventArgs::Ptr ea);
-
- JsonRpcMessage::Ptr MakeObjectMessage(const ConfigObject::Ptr& object, string method, bool includeProperties);
+ JsonRpcRequest MakeObjectMessage(const ConfigObject::Ptr& object, string method, bool includeProperties);
public:
virtual string GetName(void);
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
{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
{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
using namespace icinga;
+EndpointManager::Ptr Endpoint::GetEndpointManager(void) const
+{
+ return m_EndpointManager;
+}
+
+void Endpoint::SetEndpointManager(EndpointManager::Ptr manager)
+{
+ m_EndpointManager = manager;
+}
+
void Endpoint::RegisterMethodSink(string method)
{
m_MethodSinks.insert(method);
m_MethodSinks.erase(method);
}
-bool Endpoint::IsMethodSink(string method)
+bool Endpoint::IsMethodSink(string method) const
{
return (m_MethodSinks.find(method) != m_MethodSinks.end());
}
+void Endpoint::ForeachMethodSink(function<int (const NewMethodEventArgs&)> callback)
+{
+ for (set<string>::iterator i = m_MethodSinks.begin(); i != m_MethodSinks.end(); i++) {
+ NewMethodEventArgs nmea;
+ nmea.Source = shared_from_this();
+ nmea.Method = *i;
+ callback(nmea);
+ }
+}
+
void Endpoint::RegisterMethodSource(string method)
{
m_MethodSources.insert(method);
m_MethodSources.erase(method);
}
-bool Endpoint::IsMethodSource(string method)
+bool Endpoint::IsMethodSource(string method) const
{
return (m_MethodSources.find(method) != m_MethodSinks.end());
}
+
+void Endpoint::ForeachMethodSource(function<int (const NewMethodEventArgs&)> callback)
+{
+ for (set<string>::iterator i = m_MethodSources.begin(); i != m_MethodSources.end(); i++) {
+ NewMethodEventArgs nmea;
+ nmea.Source = shared_from_this();
+ nmea.Method = *i;
+ callback(nmea);
+ }
+}
class EndpointManager;
+struct I2_ICINGA_API NewMethodEventArgs : public EventArgs
+{
+ string Method;
+};
+
class I2_ICINGA_API Endpoint : public Object
{
private:
set<string> m_MethodSinks;
set<string> m_MethodSources;
+ shared_ptr<EndpointManager> m_EndpointManager;
+
public:
typedef shared_ptr<Endpoint> Ptr;
typedef weak_ptr<Endpoint> WeakPtr;
+ shared_ptr<EndpointManager> GetEndpointManager(void) const;
+ void SetEndpointManager(shared_ptr<EndpointManager> manager);
+
void RegisterMethodSink(string method);
void UnregisterMethodSink(string method);
- bool IsMethodSink(string method);
+ bool IsMethodSink(string method) const;
void RegisterMethodSource(string method);
void UnregisterMethodSource(string method);
- bool IsMethodSource(string method);
+ bool IsMethodSource(string method) const;
+
+ virtual bool IsLocal(void) const = 0;
+
+ virtual void ProcessRequest(Endpoint::Ptr sender, const JsonRpcRequest& message) = 0;
+ virtual void ProcessResponse(Endpoint::Ptr sender, const JsonRpcResponse& message) = 0;
+
+ Event<NewMethodEventArgs> OnNewMethodSink;
+ Event<NewMethodEventArgs> OnNewMethodSource;
- virtual void SendRequest(Endpoint::Ptr sender, JsonRpcRequest::Ptr message) = 0;
- virtual void SendResponse(Endpoint::Ptr sender, JsonRpcResponse::Ptr message) = 0;
+ void ForeachMethodSink(function<int (const NewMethodEventArgs&)> callback);
+ void ForeachMethodSource(function<int (const NewMethodEventArgs&)> callback);
};
}
server->Start();
}
-void EndpointManager::AddConnection(string host, short port)
+void EndpointManager::AddConnection(string host, unsigned short port)
{
- JsonRpcClient::Ptr client = make_shared<JsonRpcClient>();
- RegisterClient(client);
+ JsonRpcEndpoint::Ptr endpoint = make_shared<JsonRpcEndpoint>();
+ RegisterEndpoint(endpoint);
- client->MakeSocket();
- client->Connect(host, port);
- client->Start();
+ endpoint->Connect(host, port);
}
void EndpointManager::RegisterServer(JsonRpcServer::Ptr server)
server->OnNewClient += bind_weak(&EndpointManager::NewClientHandler, shared_from_this());
}
-void EndpointManager::UnregisterServer(JsonRpcServer::Ptr server)
-{
- m_Servers.remove(server);
- // TODO: unbind event
-}
-
-void EndpointManager::RegisterClient(JsonRpcClient::Ptr client)
-{
- m_Clients.push_front(client);
- client->OnNewMessage += bind_weak(&EndpointManager::NewMessageHandler, shared_from_this());
- client->OnClosed += bind_weak(&EndpointManager::CloseClientHandler, shared_from_this());
- client->OnError += bind_weak(&EndpointManager::ErrorClientHandler, shared_from_this());
-}
-
-void EndpointManager::UnregisterClient(JsonRpcClient::Ptr client)
+int EndpointManager::NewClientHandler(const NewClientEventArgs& ncea)
{
- m_Clients.remove(client);
- // TODO: unbind event
-}
+ JsonRpcEndpoint::Ptr endpoint = make_shared<JsonRpcEndpoint>();
+ RegisterEndpoint(endpoint);
-int EndpointManager::NewClientHandler(NewClientEventArgs::Ptr ncea)
-{
- JsonRpcClient::Ptr client = static_pointer_cast<JsonRpcClient>(ncea->Client);
- RegisterClient(client);
+ endpoint->SetClient(static_pointer_cast<JsonRpcClient>(ncea.Client));
return 0;
}
-int EndpointManager::CloseClientHandler(EventArgs::Ptr ea)
-{
- JsonRpcClient::Ptr client = static_pointer_cast<JsonRpcClient>(ea->Source);
- UnregisterClient(client);
-
- if (client->GetPeerHost() != string()) {
- Timer::Ptr timer = make_shared<Timer>();
- timer->SetInterval(30);
- timer->SetUserArgs(ea);
- timer->OnTimerExpired += bind_weak(&EndpointManager::ReconnectClientHandler, shared_from_this());
- timer->Start();
- m_ReconnectTimers.push_front(timer);
- }
-
- return 0;
-}
-
-int EndpointManager::ErrorClientHandler(SocketErrorEventArgs::Ptr ea)
-{
- cout << "Error occured for JSON-RPC socket: Code=" << ea->Code << "; Message=" << ea->Message << endl;
-
- return 0;
-}
-
-int EndpointManager::ReconnectClientHandler(TimerEventArgs::Ptr ea)
-{
- JsonRpcClient::Ptr client = static_pointer_cast<JsonRpcClient>(ea->UserArgs->Source);
- Timer::Ptr timer = static_pointer_cast<Timer>(ea->Source);
-
- AddConnection(client->GetPeerHost(), client->GetPeerPort());
-
- timer->Stop();
- m_ReconnectTimers.remove(timer);
-
- return 0;
-}
-
-int EndpointManager::NewMessageHandler(NewMessageEventArgs::Ptr nmea)
+void EndpointManager::UnregisterServer(JsonRpcServer::Ptr server)
{
-// TODO: implement
-
- return 0;
+ m_Servers.remove(server);
+ // TODO: unbind event
}
void EndpointManager::RegisterEndpoint(Endpoint::Ptr endpoint)
{
+ endpoint->SetEndpointManager(static_pointer_cast<EndpointManager>(shared_from_this()));
m_Endpoints.push_front(endpoint);
+
+ endpoint->OnNewMethodSink += bind_weak(&EndpointManager::NewMethodSinkHandler, shared_from_this());
+ endpoint->ForeachMethodSink(bind(&EndpointManager::NewMethodSinkHandler, this, _1));
+
+ endpoint->OnNewMethodSource += bind_weak(&EndpointManager::NewMethodSourceHandler, shared_from_this());
+ endpoint->ForeachMethodSource(bind(&EndpointManager::NewMethodSourceHandler, this, _1));
}
void EndpointManager::UnregisterEndpoint(Endpoint::Ptr endpoint)
m_Endpoints.remove(endpoint);
}
-void EndpointManager::SendAnycastRequest(Endpoint::Ptr sender, JsonRpcRequest::Ptr request)
+void EndpointManager::SendAnycastRequest(Endpoint::Ptr sender, const JsonRpcRequest& request, bool fromLocal)
{
throw NotImplementedException();
}
-void EndpointManager::SendMulticastRequest(Endpoint::Ptr sender, JsonRpcRequest::Ptr request)
+void EndpointManager::SendMulticastRequest(Endpoint::Ptr sender, const JsonRpcRequest& request, bool fromLocal)
{
#ifdef _DEBUG
string id;
- if (request->GetID(&id))
+ if (request.GetID(&id))
throw InvalidArgumentException("Multicast requests must not have an ID.");
#endif /* _DEBUG */
string method;
- if (!request->GetMethod(&method))
+ if (!request.GetMethod(&method))
throw InvalidArgumentException();
for (list<Endpoint::Ptr>::iterator i = m_Endpoints.begin(); i != m_Endpoints.end(); i++)
if (endpoint == sender)
continue;
+ /* send non-local messages to just the local endpoints */
+ if (!fromLocal && !endpoint->IsLocal())
+ continue;
+
if (endpoint->IsMethodSink(method))
- endpoint->SendRequest(sender, request);
+ endpoint->ProcessRequest(sender, request);
+ }
+}
+
+int EndpointManager::NewMethodSinkHandler(const NewMethodEventArgs& ea)
+{
+ Endpoint::Ptr sender = static_pointer_cast<Endpoint>(ea.Source);
+
+ if (!sender->IsLocal())
+ return 0;
+
+ JsonRpcRequest request;
+ request.SetVersion("2.0");
+ request.SetMethod("message::Subscribe");
+
+ Message params;
+ params.GetDictionary()->SetValueString("method", ea.Method);
+ request.SetParams(params);
+
+ SendMulticastRequest(sender, request);
+
+ return 0;
+}
+
+int EndpointManager::NewMethodSourceHandler(const NewMethodEventArgs& ea)
+{
+ Endpoint::Ptr sender = static_pointer_cast<Endpoint>(ea.Source);
+
+ if (!sender->IsLocal())
+ return 0;
+
+ JsonRpcRequest request;
+ request.SetVersion("2.0");
+ request.SetMethod("message::Provide");
+
+ Message params;
+ params.GetDictionary()->SetValueString("method", ea.Method);
+ request.SetParams(params);
+
+ SendMulticastRequest(sender, request);
+
+ return 0;
+}
+
+void EndpointManager::ForeachEndpoint(function<int (Endpoint::Ptr)> callback)
+{
+ for (list<Endpoint::Ptr>::iterator i = m_Endpoints.begin(); i != m_Endpoints.end(); i++) {
+ callback(*i);
}
}
class I2_ICINGA_API EndpointManager : public Object
{
list<JsonRpcServer::Ptr> m_Servers;
- list<JsonRpcClient::Ptr> m_Clients;
- list<Timer::Ptr> m_ReconnectTimers;
list<Endpoint::Ptr> m_Endpoints;
string m_Identity;
- int NewClientHandler(NewClientEventArgs::Ptr ncea);
- int CloseClientHandler(EventArgs::Ptr ea);
- int ErrorClientHandler(SocketErrorEventArgs::Ptr ea);
- int ReconnectClientHandler(TimerEventArgs::Ptr ea);
- int NewMessageHandler(NewMessageEventArgs::Ptr nmea);
-
- void RegisterClient(JsonRpcClient::Ptr server);
- void UnregisterClient(JsonRpcClient::Ptr server);
-
void RegisterServer(JsonRpcServer::Ptr server);
void UnregisterServer(JsonRpcServer::Ptr server);
+ int NewClientHandler(const NewClientEventArgs& ncea);
+
+ int NewMethodSinkHandler(const NewMethodEventArgs& ea);
+ int NewMethodSourceHandler(const NewMethodEventArgs& ea);
+
public:
typedef shared_ptr<EndpointManager> Ptr;
typedef weak_ptr<EndpointManager> WeakPtr;
string GetIdentity(void) const;
void AddListener(unsigned short port);
- void AddConnection(string host, short port);
+ void AddConnection(string host, unsigned short port);
void RegisterEndpoint(Endpoint::Ptr endpoint);
void UnregisterEndpoint(Endpoint::Ptr endpoint);
- void SendAnycastRequest(Endpoint::Ptr sender, JsonRpcRequest::Ptr request);
- void SendMulticastRequest(Endpoint::Ptr sender, JsonRpcRequest::Ptr request);
+ void SendAnycastRequest(Endpoint::Ptr sender, const JsonRpcRequest& request, bool fromLocal = true);
+ void SendMulticastRequest(Endpoint::Ptr sender, const JsonRpcRequest& request, bool fromLocal = true);
+
+ void ForeachEndpoint(function<int (Endpoint::Ptr)> callback);
};
}
ConfigCollection::Ptr componentCollection = GetConfigHive()->GetCollection("component");
- function<int (ConfigObjectEventArgs::Ptr)> NewComponentHandler = bind_weak(&IcingaApplication::NewComponentHandler, shared_from_this());
+ function<int (const ConfigObjectEventArgs&)> NewComponentHandler = bind_weak(&IcingaApplication::NewComponentHandler, shared_from_this());
componentCollection->OnObjectCreated += NewComponentHandler;
componentCollection->ForEachObject(NewComponentHandler);
ConfigCollection::Ptr listenerCollection = GetConfigHive()->GetCollection("rpclistener");
- function<int (ConfigObjectEventArgs::Ptr)> NewRpcListenerHandler = bind_weak(&IcingaApplication::NewRpcListenerHandler, shared_from_this());
+ function<int (const ConfigObjectEventArgs&)> NewRpcListenerHandler = bind_weak(&IcingaApplication::NewRpcListenerHandler, shared_from_this());
listenerCollection->OnObjectCreated += NewRpcListenerHandler;
listenerCollection->ForEachObject(NewRpcListenerHandler);
ConfigCollection::Ptr connectionCollection = GetConfigHive()->GetCollection("rpcconnection");
- function<int (ConfigObjectEventArgs::Ptr)> NewRpcConnectionHandler = bind_weak(&IcingaApplication::NewRpcConnectionHandler, shared_from_this());
+ function<int (const ConfigObjectEventArgs&)> NewRpcConnectionHandler = bind_weak(&IcingaApplication::NewRpcConnectionHandler, shared_from_this());
connectionCollection->OnObjectCreated += NewRpcConnectionHandler;
connectionCollection->ForEachObject(NewRpcConnectionHandler);
ConfigCollection::Ptr collection = GetConfigHive()->GetCollection("rpclistener");
+ m_TestEndpoint = make_shared<VirtualEndpoint>();
+ m_EndpointManager->RegisterEndpoint(m_TestEndpoint);
+ m_TestEndpoint->RegisterMethodSink("test");
+ m_TestEndpoint->RegisterMethodSource("test");
+
+ m_TestTimer = make_shared<Timer>();
+ m_TestTimer->SetInterval(5);
+ m_TestTimer->OnTimerExpired += bind_weak(&IcingaApplication::TestTimerHandler, shared_from_this());
+ m_TestTimer->Start();
+
RunEventLoop();
return EXIT_SUCCESS;
}
+int IcingaApplication::TestTimerHandler(const TimerEventArgs& tea)
+{
+ cout << "Problem?" << endl;
+
+ JsonRpcRequest request;
+ request.SetVersion("2.0");
+ request.SetMethod("test");
+ m_EndpointManager->SendMulticastRequest(m_TestEndpoint, request);
+
+ return 0;
+}
+
void IcingaApplication::PrintUsage(const string& programPath)
{
cout << "Syntax: " << programPath << " <config-file>" << endl;
return m_EndpointManager;
}
-int IcingaApplication::NewComponentHandler(ConfigObjectEventArgs::Ptr ea)
+int IcingaApplication::NewComponentHandler(const ConfigObjectEventArgs& ea)
{
string path;
- ConfigObject::Ptr object = static_pointer_cast<ConfigObject>(ea->Source);
+ ConfigObject::Ptr object = static_pointer_cast<ConfigObject>(ea.Source);
if (!object->GetProperty("path", &path)) {
#ifdef _WIN32
return 0;
}
-int IcingaApplication::DeletedComponentHandler(ConfigObjectEventArgs::Ptr ea)
+int IcingaApplication::DeletedComponentHandler(const ConfigObjectEventArgs& ea)
{
- ConfigObject::Ptr object = static_pointer_cast<ConfigObject>(ea->Source);
- UnloadComponent(object->GetName());
+ ConfigObject::Ptr object = static_pointer_cast<ConfigObject>(ea.Source);
+ Component::Ptr component = GetComponent(object->GetName());
+ UnregisterComponent(component);
return 0;
}
-int IcingaApplication::NewRpcListenerHandler(ConfigObjectEventArgs::Ptr ea)
+int IcingaApplication::NewRpcListenerHandler(const ConfigObjectEventArgs& ea)
{
- ConfigObject::Ptr object = static_pointer_cast<ConfigObject>(ea->Source);
+ ConfigObject::Ptr object = static_pointer_cast<ConfigObject>(ea.Source);
int port;
if (!object->GetPropertyInteger("port", &port))
return 0;
}
-int IcingaApplication::DeletedRpcListenerHandler(ConfigObjectEventArgs::Ptr ea)
+int IcingaApplication::DeletedRpcListenerHandler(const ConfigObjectEventArgs& ea)
{
throw Exception("Unsupported operation.");
return 0;
}
-int IcingaApplication::NewRpcConnectionHandler(ConfigObjectEventArgs::Ptr ea)
+int IcingaApplication::NewRpcConnectionHandler(const ConfigObjectEventArgs& ea)
{
- ConfigObject::Ptr object = static_pointer_cast<ConfigObject>(ea->Source);
+ ConfigObject::Ptr object = static_pointer_cast<ConfigObject>(ea.Source);
string hostname;
int port;
return 0;
}
-int IcingaApplication::DeletedRpcConnectionHandler(ConfigObjectEventArgs::Ptr ea)
+int IcingaApplication::DeletedRpcConnectionHandler(const ConfigObjectEventArgs& ea)
{
throw Exception("Unsupported operation.");
{
private:
EndpointManager::Ptr m_EndpointManager;
+ Timer::Ptr m_TestTimer;
+ VirtualEndpoint::Ptr m_TestEndpoint;
- int NewComponentHandler(ConfigObjectEventArgs::Ptr ea);
- int DeletedComponentHandler(ConfigObjectEventArgs::Ptr ea);
+ int NewComponentHandler(const ConfigObjectEventArgs& ea);
+ int DeletedComponentHandler(const ConfigObjectEventArgs& ea);
- int NewRpcListenerHandler(ConfigObjectEventArgs::Ptr ea);
- int DeletedRpcListenerHandler(ConfigObjectEventArgs::Ptr ea);
+ int NewRpcListenerHandler(const ConfigObjectEventArgs& ea);
+ int DeletedRpcListenerHandler(const ConfigObjectEventArgs& ea);
- int NewRpcConnectionHandler(ConfigObjectEventArgs::Ptr ea);
- int DeletedRpcConnectionHandler(ConfigObjectEventArgs::Ptr ea);
+ int NewRpcConnectionHandler(const ConfigObjectEventArgs& ea);
+ int DeletedRpcConnectionHandler(const ConfigObjectEventArgs& ea);
+ int TestTimerHandler(const TimerEventArgs& tea);
public:
typedef shared_ptr<IcingaApplication> Ptr;
typedef weak_ptr<IcingaApplication> WeakPtr;
return m_Client;
}
+void JsonRpcEndpoint::Connect(string host, unsigned short port)
+{
+ JsonRpcClient::Ptr client = make_shared<JsonRpcClient>();
+ client->MakeSocket();
+ client->Connect(host, port);
+ client->Start();
+
+ SetClient(client);
+}
+
+int JsonRpcEndpoint::SyncSubscription(string type, const NewMethodEventArgs& nmea)
+{
+ JsonRpcRequest request;
+ request.SetVersion("2.0");
+ request.SetMethod(type);
+
+ Message params;
+ params.GetDictionary()->SetValueString("method", nmea.Method);
+ request.SetParams(params);
+
+ m_Client->SendMessage(request);
+
+ return 0;
+}
+
+int JsonRpcEndpoint::SyncSubscriptions(Endpoint::Ptr endpoint)
+{
+ if (!endpoint->IsLocal())
+ return 0;
+
+ endpoint->ForeachMethodSink(bind(&JsonRpcEndpoint::SyncSubscription, this, "message::Subscribe", _1));
+ endpoint->ForeachMethodSource(bind(&JsonRpcEndpoint::SyncSubscription, this, "message::Provide", _1));
+
+ return 0;
+}
+
void JsonRpcEndpoint::SetClient(JsonRpcClient::Ptr client)
{
m_Client = client;
+ client->OnNewMessage += bind_weak(&JsonRpcEndpoint::NewMessageHandler, shared_from_this());
+ client->OnClosed += bind_weak(&JsonRpcEndpoint::ClientClosedHandler, shared_from_this());
+ client->OnError += bind_weak(&JsonRpcEndpoint::ClientErrorHandler, shared_from_this());
+
+ NewMethodEventArgs nmea;
+ nmea.Source = shared_from_this();
+
+ nmea.Method = "message::Subscribe";
+ SyncSubscription("message::Subscribe", nmea);
+ SyncSubscription("message::Provide", nmea);
+
+ nmea.Method = "message::Provide";
+ SyncSubscription("message::Subscribe", nmea);
+ SyncSubscription("message::Provide", nmea);
+
+ GetEndpointManager()->ForeachEndpoint(bind(&JsonRpcEndpoint::SyncSubscriptions, this, _1));
+}
+
+bool JsonRpcEndpoint::IsLocal(void) const
+{
+ return false;
}
bool JsonRpcEndpoint::IsConnected(void) const
return (m_Client.get() != NULL);
}
-void JsonRpcEndpoint::SendRequest(Endpoint::Ptr sender, JsonRpcRequest::Ptr message)
+void JsonRpcEndpoint::ProcessRequest(Endpoint::Ptr sender, const JsonRpcRequest& message)
{
- if (IsConnected())
+ if (IsConnected()) {
+ string id;
+ if (message.GetID(&id))
+ // TODO: remove calls after a certain timeout (and notify callers?)
+ m_PendingCalls[id] = sender;
+
m_Client->SendMessage(message);
+ }
}
-void JsonRpcEndpoint::SendResponse(Endpoint::Ptr sender, JsonRpcResponse::Ptr message)
+void JsonRpcEndpoint::ProcessResponse(Endpoint::Ptr sender, const JsonRpcResponse& message)
{
if (IsConnected())
m_Client->SendMessage(message);
}
+
+int JsonRpcEndpoint::NewMessageHandler(const NewMessageEventArgs& nmea)
+{
+ const Message& message = nmea.Message;
+ Endpoint::Ptr sender = static_pointer_cast<Endpoint>(shared_from_this());
+
+ string method;
+ if (message.GetDictionary()->GetValueString("method", &method)) {
+ JsonRpcRequest request = message;
+ Message params;
+ string method;
+
+ if (request.GetMethod(&method) && request.GetParams(¶ms) &&
+ (method == "message::Subscribe" || method == "message::Provide")) {
+ string sub_method;
+ if (params.GetDictionary()->GetValueString("method", &sub_method)) {
+ if (method == "message::Subscribe")
+ RegisterMethodSink(sub_method);
+ else
+ RegisterMethodSource(sub_method);
+ }
+
+ return 0;
+ }
+
+ string id;
+ if (request.GetID(&id))
+ GetEndpointManager()->SendAnycastRequest(sender, request, false);
+ else
+ GetEndpointManager()->SendMulticastRequest(sender, request, false);
+ } else {
+ // TODO: deal with response messages
+ throw NotImplementedException();
+ }
+
+ return 0;
+}
+
+int JsonRpcEndpoint::ClientClosedHandler(const EventArgs& ea)
+{
+ m_PendingCalls.clear();
+
+ // TODO: clear method sources/sinks
+
+ if (m_Client->GetPeerHost() != string()) {
+ Timer::Ptr timer = make_shared<Timer>();
+ timer->SetInterval(30);
+ timer->SetUserArgs(ea);
+ timer->OnTimerExpired += bind_weak(&JsonRpcEndpoint::ClientReconnectHandler, shared_from_this());
+ timer->Start();
+ m_ReconnectTimer = timer;
+ }
+
+ m_Client.reset();
+
+ // TODO: persist events, etc., for now we just disable the endpoint
+
+ return 0;
+}
+
+int JsonRpcEndpoint::ClientErrorHandler(const SocketErrorEventArgs& ea)
+{
+ cerr << "Error occured for JSON-RPC socket: Code=" << ea.Code << "; Message=" << ea.Message << endl;
+
+ return 0;
+}
+
+int JsonRpcEndpoint::ClientReconnectHandler(const TimerEventArgs& ea)
+{
+ JsonRpcClient::Ptr client = static_pointer_cast<JsonRpcClient>(ea.UserArgs.Source);
+ Timer::Ptr timer = static_pointer_cast<Timer>(ea.Source);
+
+ m_Client = client;
+
+ timer->Stop();
+ m_ReconnectTimer.reset();
+
+ return 0;
+}
{
private:
JsonRpcClient::Ptr m_Client;
+ map<string, Endpoint::Ptr> m_PendingCalls;
+ Timer::Ptr m_ReconnectTimer;
bool IsConnected(void) const;
+
+ int NewMessageHandler(const NewMessageEventArgs& nmea);
+ int ClientClosedHandler(const EventArgs& ea);
+ int ClientErrorHandler(const SocketErrorEventArgs& ea);
+ int ClientReconnectHandler(const TimerEventArgs& ea);
+
+ int SyncSubscription(string type, const NewMethodEventArgs& nmea);
+ int SyncSubscriptions(Endpoint::Ptr endpoint);
public:
- JsonRpcEndpoint(void);
+ typedef shared_ptr<JsonRpcEndpoint> Ptr;
+ typedef weak_ptr<JsonRpcEndpoint> WeakPtr;
+
+ void Connect(string host, unsigned short port);
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);
+ virtual bool IsLocal(void) const;
+
+ virtual void ProcessRequest(Endpoint::Ptr sender, const JsonRpcRequest& message);
+ virtual void ProcessResponse(Endpoint::Ptr sender, const JsonRpcResponse& message);
};
}
using namespace icinga;
-void VirtualEndpoint::RegisterMethodHandler(string method, function<int (NewRequestEventArgs::Ptr)> callback)
+bool VirtualEndpoint::IsLocal(void) const
+{
+ return true;
+}
+
+void VirtualEndpoint::RegisterMethodHandler(string method, function<int (const NewRequestEventArgs&)> callback)
{
m_MethodHandlers[method] += callback;
RegisterMethodSink(method);
}
-void VirtualEndpoint::UnregisterMethodHandler(string method, function<int (NewRequestEventArgs::Ptr)> callback)
+void VirtualEndpoint::UnregisterMethodHandler(string method, function<int (const NewRequestEventArgs&)> callback)
{
// TODO: implement
//m_MethodHandlers[method] -= callback;
throw NotImplementedException();
}
-void VirtualEndpoint::SendRequest(Endpoint::Ptr sender, JsonRpcRequest::Ptr request)
+void VirtualEndpoint::ProcessRequest(Endpoint::Ptr sender, const JsonRpcRequest& request)
{
string method;
- if (!request->GetMethod(&method))
+ if (!request.GetMethod(&method))
return;
- map<string, Event<NewRequestEventArgs::Ptr> >::iterator i = m_MethodHandlers.find(method);
+ map<string, Event<NewRequestEventArgs> >::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;
+ NewRequestEventArgs nrea;
+ nrea.Source = shared_from_this();
+ nrea.Sender = sender;
+ nrea.Request = request;
i->second(nrea);
}
-void VirtualEndpoint::SendResponse(Endpoint::Ptr sender, JsonRpcResponse::Ptr response)
+void VirtualEndpoint::ProcessResponse(Endpoint::Ptr sender, const JsonRpcResponse& response)
{
// TODO: figure out which request this response belongs to and notify the caller
throw NotImplementedException();
namespace icinga
{
-struct I2_JSONRPC_API NewRequestEventArgs : public EventArgs
+struct I2_ICINGA_API NewRequestEventArgs : public EventArgs
{
typedef shared_ptr<NewRequestEventArgs> Ptr;
typedef weak_ptr<NewRequestEventArgs> WeakPtr;
Endpoint::Ptr Sender;
- JsonRpcRequest::Ptr Request;
+ JsonRpcRequest Request;
};
class I2_ICINGA_API VirtualEndpoint : public Endpoint
{
private:
- map< string, Event<NewRequestEventArgs::Ptr> > m_MethodHandlers;
+ map< string, Event<NewRequestEventArgs> > m_MethodHandlers;
public:
typedef shared_ptr<VirtualEndpoint> Ptr;
typedef weak_ptr<VirtualEndpoint> WeakPtr;
- void RegisterMethodHandler(string method, function<int (NewRequestEventArgs::Ptr)> callback);
- void UnregisterMethodHandler(string method, function<int (NewRequestEventArgs::Ptr)> callback);
+ void RegisterMethodHandler(string method, function<int (const NewRequestEventArgs&)> callback);
+ void UnregisterMethodHandler(string method, function<int (const NewRequestEventArgs&)> callback);
- virtual void RegisterMethodSource(string method);
- virtual void UnregisterMethodSource(string method);
+ virtual bool IsLocal(void) const;
- virtual void SendRequest(Endpoint::Ptr sender, JsonRpcRequest::Ptr message);
- virtual void SendResponse(Endpoint::Ptr sender, JsonRpcResponse::Ptr message);
+ virtual void ProcessRequest(Endpoint::Ptr sender, const JsonRpcRequest& message);
+ virtual void ProcessResponse(Endpoint::Ptr sender, const JsonRpcResponse& message);
};
}
# define I2_JSONRPC_API I2_IMPORT
#endif /* I2_JSONRPC_BUILD */
+#include "variant.h"
+#include "dictionary.h"
#include "message.h"
#include "netstring.h"
#include "jsonrpcrequest.h"
<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>
OnDataAvailable += bind_weak(&JsonRpcClient::DataAvailableHandler, shared_from_this());
}
-void JsonRpcClient::SendMessage(Message::Ptr message)
+void JsonRpcClient::SendMessage(const Message& message)
{
Netstring::WriteMessageToFIFO(GetSendQueue(), message);
}
-int JsonRpcClient::DataAvailableHandler(EventArgs::Ptr ea)
+int JsonRpcClient::DataAvailableHandler(const EventArgs& ea)
{
- Message::Ptr message;
+ Message message;
+ bool message_read;
while (true) {
try {
- message = Netstring::ReadMessageFromFIFO(GetRecvQueue());
- } catch (const exception&) {
+ message_read = Netstring::ReadMessageFromFIFO(GetRecvQueue(), &message);
+ } catch (const Exception& ex) {
+ cerr << "Exception while reading from JSON-RPC client: " << ex.GetMessage() << endl;
Close();
return 1;
}
- if (message.get() == NULL)
+ if (!message_read)
break;
- NewMessageEventArgs::Ptr nea = make_shared<NewMessageEventArgs>();
- nea->Source = shared_from_this();
- nea->Message = message;
+ NewMessageEventArgs nea;
+ nea.Source = shared_from_this();
+ nea.Message = message;
OnNewMessage(nea);
}
typedef shared_ptr<NewMessageEventArgs> Ptr;
typedef weak_ptr<NewMessageEventArgs> WeakPtr;
- Message::Ptr Message;
+ Message Message;
};
class I2_JSONRPC_API JsonRpcClient : public TCPClient
{
private:
- int DataAvailableHandler(EventArgs::Ptr ea);
+ int DataAvailableHandler(const EventArgs& ea);
public:
typedef shared_ptr<JsonRpcClient> Ptr;
typedef weak_ptr<JsonRpcClient> WeakPtr;
- void SendMessage(Message::Ptr message);
+ void SendMessage(const Message& message);
virtual void Start(void);
- Event<NewMessageEventArgs::Ptr> OnNewMessage;
+ Event<NewMessageEventArgs> OnNewMessage;
};
}
--- /dev/null
+#include "i2-jsonrpc.h"
+#include "jsonrpcrequest.h"
+
+using namespace icinga;
--- /dev/null
+#ifndef JSONRPCREQUEST_H
+#define JSONRPCREQUEST_H
+
+namespace icinga
+{
+
+class I2_JSONRPC_API JsonRpcRequest : public Message
+{
+
+public:
+ JsonRpcRequest(void) : Message() { }
+ JsonRpcRequest(const Message& message) : Message(message) { }
+
+ inline bool GetVersion(string *value) const
+ {
+ return GetDictionary()->GetValueString("jsonrpc", value);
+ }
+
+ inline void SetVersion(const string& value)
+ {
+ GetDictionary()->SetValueString("jsonrpc", value);
+ }
+
+ inline bool GetMethod(string *value) const
+ {
+ return GetDictionary()->GetValueString("method", value);
+ }
+
+ inline void SetMethod(const string& value)
+ {
+ GetDictionary()->SetValueString("method", value);
+ }
+
+ inline bool GetParams(Message *value) const
+ {
+ Dictionary::Ptr dictionary;
+
+ if (!GetDictionary()->GetValueDictionary("params", &dictionary))
+ return false;
+
+ *value = Message(dictionary);
+
+ return true;
+ }
+
+ inline void SetParams(const Message& value)
+ {
+ GetDictionary()->SetValueDictionary("params", value.GetDictionary());
+ }
+
+ inline bool GetID(string *value) const
+ {
+ return GetDictionary()->GetValueString("id", value);
+ }
+
+ inline void SetID(const string& value)
+ {
+ GetDictionary()->SetValueString("id", value);
+ }
+};
+
+}
+
+#endif /* JSONRPCREQUEST_H */
--- /dev/null
+#include "i2-jsonrpc.h"
+#include "jsonrpcresponse.h"
+
+using namespace icinga;
--- /dev/null
+#ifndef JSONRPCRESPONSE_H
+#define JSONRPCRESPONSE_H
+
+namespace icinga
+{
+
+class I2_JSONRPC_API JsonRpcResponse : public Message
+{
+public:
+ JsonRpcResponse(void) : Message() { }
+ JsonRpcResponse(const Message& message) : Message(message) { }
+
+ inline bool GetVersion(string *value) const
+ {
+ return GetDictionary()->GetValueString("jsonrpc", value);
+ }
+
+ inline void SetJsonRpc(const string& value)
+ {
+ GetDictionary()->SetValueString("jsonrpc", value);
+ }
+
+ bool GetResult(string *value) const
+ {
+ return GetDictionary()->GetValueString("result", value);
+ }
+
+ void SetResult(const string& value)
+ {
+ GetDictionary()->SetValueString("result", value);
+ }
+
+ bool GetError(string *value) const
+ {
+ return GetDictionary()->GetValueString("error", value);
+ }
+
+ void SetError(const string& value)
+ {
+ GetDictionary()->SetValueString("error", value);
+ }
+
+ bool GetID(string *value) const
+ {
+ return GetDictionary()->GetValueString("id", value);
+ }
+
+ void SetID(const string& value)
+ {
+ GetDictionary()->SetValueString("id", value);
+ }
+};
+
+}
+
+#endif /* JSONRPCRESPONSE_H */
--- /dev/null
+#include "i2-jsonrpc.h"
+
+using namespace icinga;
+
+Message::Message(void)
+{
+ m_Dictionary = make_shared<Dictionary>();
+}
+
+Message::Message(const Dictionary::Ptr& dictionary)
+{
+ m_Dictionary = dictionary;
+}
+
+Message::Message(const Message& message)
+{
+ m_Dictionary = message.GetDictionary();
+}
+
+Dictionary::Ptr Message::GetDictionary(void) const
+{
+ return m_Dictionary;
+}
--- /dev/null
+#ifndef MESSAGE_H
+#define MESSAGE_H
+
+namespace icinga
+{
+
+class I2_JSONRPC_API Message
+{
+private:
+ Dictionary::Ptr m_Dictionary;
+
+public:
+ Message(void);
+ Message(const Dictionary::Ptr& dictionary);
+ Message(const Message& message);
+
+ Dictionary::Ptr GetDictionary(void) const;
+};
+
+}
+
+#endif /* MESSAGE_H */
using namespace icinga;
+Dictionary::Ptr Netstring::GetDictionaryFromJson(cJSON *json)
+{
+ Dictionary::Ptr dictionary = make_shared<Dictionary>();
+
+ for (cJSON *i = json->child; i != NULL; i = i->next) {
+ switch (i->type) {
+ case cJSON_Number:
+ dictionary->SetValueInteger(i->string, i->valueint);
+ break;
+ case cJSON_String:
+ dictionary->SetValueString(i->string, i->valuestring);
+ break;
+ case cJSON_Object:
+ dictionary->SetValueDictionary(i->string, GetDictionaryFromJson(i));
+ break;
+ default:
+ break;
+ }
+ }
+
+ return dictionary;
+}
+
+cJSON *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.get() != NULL)
+ 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 */
-Message::Ptr Netstring::ReadMessageFromFIFO(FIFO::Ptr fifo)
+bool Netstring::ReadMessageFromFIFO(FIFO::Ptr fifo, Message *message)
{
size_t buffer_length = fifo->GetSize();
char *buffer = (char *)fifo->GetReadBuffer();
/* minimum netstring length is 3 */
if (buffer_length < 3)
- return NULL;
+ return false;
/* no leading zeros allowed */
if (buffer[0] == '0' && isdigit(buffer[1]))
- throw exception(/*"Invalid netstring (leading zero)"*/);
+ throw InvalidArgumentException("Invalid netstring (leading zero)");
size_t len, i;
for (i = 0; i < buffer_length && isdigit(buffer[i]); i++) {
/* length specifier must have at most 9 characters */
if (i >= 9)
- return NULL;
+ return false;
len = len * 10 + (buffer[i] - '0');
}
/* make sure the buffer is large enough */
if (i + len + 1 >= buffer_length)
- return NULL;
+ return false;
/* check for the colon delimiter */
if (buffer[i++] != ':')
- throw exception(/*"Invalid Netstring (missing :)"*/);
+ throw InvalidArgumentException("Invalid Netstring (missing :)");
/* check for the comma delimiter after the string */
if (buffer[i + len] != ',')
- throw exception(/*"Invalid Netstring (missing ,)"*/);
+ throw InvalidArgumentException("Invalid Netstring (missing ,)");
/* nuke the comma delimiter */
buffer[i + len] = '\0';
if (object == NULL) {
/* restore the comma */
buffer[i + len] = ',';
- throw exception(/*"Invalid JSON string"*/);
+ throw InvalidArgumentException("Invalid JSON string");
}
/* remove the data from the fifo */
fifo->Read(NULL, i + len + 1);
- return make_shared<Message>(object);
+ *message = Message(GetDictionaryFromJson(object));
+ cJSON_Delete(object);
+ return true;
}
-void Netstring::WriteMessageToFIFO(FIFO::Ptr fifo, Message::Ptr message)
+void Netstring::WriteMessageToFIFO(FIFO::Ptr fifo, const Message& message)
{
char *json;
- shared_ptr<cJSON> object = message->GetJson();
+ cJSON *object = GetJsonFromDictionary(message.GetDictionary());
size_t len;
#ifdef _DEBUG
- json = cJSON_Print(object.get());
+ json = cJSON_Print(object);
#else /* _DEBUG */
- json = cJSON_PrintUnformatted(object.get());
+ json = cJSON_PrintUnformatted(object);
#endif /* _DEBUG */
+ cJSON_Delete(object);
+
len = strlen(json);
char strLength[50];
- sprintf(strLength, "%lu", (unsigned long)len);
+ sprintf(strLength, "%lu:", (unsigned long)len);
fifo->Write(strLength, strlen(strLength));
fifo->Write(json, len);
size_t m_Length;
void *m_Data;
+ static Dictionary::Ptr Netstring::GetDictionaryFromJson(cJSON *json);
+ static cJSON *GetJsonFromDictionary(const Dictionary::Ptr& dictionary);
+
public:
typedef shared_ptr<Netstring> Ptr;
typedef weak_ptr<Netstring> WeakPtr;
- static Message::Ptr ReadMessageFromFIFO(FIFO::Ptr fifo);
- static void WriteMessageToFIFO(FIFO::Ptr fifo, Message::Ptr message);
+ static bool ReadMessageFromFIFO(FIFO::Ptr fifo, Message *message);
+ static void WriteMessageToFIFO(FIFO::Ptr fifo, const Message& message);
};
}
+++ /dev/null
-#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;
-}
+++ /dev/null
-<?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>
\ No newline at end of file