From 1ebda64e753366430802cb0d4d8b714297305813 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Thu, 29 Mar 2012 20:03:29 +0200 Subject: [PATCH] Implemented support for binding methods to the ConnectionManager class --- base/application.cpp | 12 +++---- base/fifo.cpp | 8 +++-- base/fifo.h | 2 +- base/tcpclient.cpp | 33 +++++++----------- base/unix.h | 1 + jsonrpc/connectionmanager.cpp | 38 +++++++++++++++++++- jsonrpc/connectionmanager.h | 6 +++- jsonrpc/i2-jsonrpc.h | 1 + jsonrpc/jsonrpcmessage.cpp | 66 ++++++++++++++++++++++++++--------- jsonrpc/jsonrpcmessage.h | 14 +++++--- miniapp/miniapp.cpp | 41 +++------------------- 11 files changed, 132 insertions(+), 90 deletions(-) diff --git a/base/application.cpp b/base/application.cpp index 038fb909e..31a0b5e68 100644 --- a/base/application.cpp +++ b/base/application.cpp @@ -42,12 +42,12 @@ void Application::RunEventLoop(void) int fd = socket->GetFD(); - if (socket->WantsToRead()) - FD_SET(fd, &readfds); - if (socket->WantsToWrite()) FD_SET(fd, &writefds); + if (socket->WantsToRead()) + FD_SET(fd, &readfds); + FD_SET(fd, &exceptfds); if (fd > nfds) @@ -96,12 +96,12 @@ void Application::RunEventLoop(void) int fd = socket->GetFD(); - if (FD_ISSET(fd, &readfds)) - socket->OnReadable(ea); - if (FD_ISSET(fd, &writefds)) socket->OnWritable(ea); + if (FD_ISSET(fd, &readfds)) + socket->OnReadable(ea); + if (FD_ISSET(fd, &exceptfds)) socket->OnException(ea); } diff --git a/base/fifo.cpp b/base/fifo.cpp index 6330256b8..5abbdd06b 100644 --- a/base/fifo.cpp +++ b/base/fifo.cpp @@ -75,9 +75,10 @@ size_t FIFO::Read(void *buffer, size_t count) return count; } -void *FIFO::GetWriteBuffer(size_t count) +void *FIFO::GetWriteBuffer(size_t *count) { - ResizeBuffer(m_Offset + m_DataSize + count); + ResizeBuffer(m_Offset + m_DataSize + *count); + *count = m_AllocSize - m_Offset - m_DataSize; return m_Buffer + m_Offset + m_DataSize; } @@ -85,7 +86,8 @@ void *FIFO::GetWriteBuffer(size_t count) size_t FIFO::Write(const void *buffer, size_t count) { if (buffer != NULL) { - void *target_buffer = GetWriteBuffer(count); + size_t bufferSize = count; + void *target_buffer = GetWriteBuffer(&bufferSize); memcpy(target_buffer, buffer, count); } diff --git a/base/fifo.h b/base/fifo.h index 71654e2f2..4d7f159cb 100644 --- a/base/fifo.h +++ b/base/fifo.h @@ -27,7 +27,7 @@ public: size_t GetSize(void) const; const void *GetReadBuffer(void) const; - void *GetWriteBuffer(size_t count); + void *GetWriteBuffer(size_t *count); size_t Read(void *buffer, size_t count); size_t Write(const void *buffer, size_t count); diff --git a/base/tcpclient.cpp b/base/tcpclient.cpp index ee0f00de8..8969b2a7b 100644 --- a/base/tcpclient.cpp +++ b/base/tcpclient.cpp @@ -31,35 +31,26 @@ FIFO::RefType TCPClient::GetRecvQueue(void) int TCPClient::ReadableEventHandler(EventArgs::RefType ea) { - int read_total, rc; - - read_total = 0; + int rc; - while (true) { - static const size_t BufferSize = FIFO::BlockSize / 2; - char *buffer = (char *)m_RecvQueue->GetWriteBuffer(BufferSize); - rc = recv(GetFD(), buffer, BufferSize, 0); + size_t bufferSize = FIFO::BlockSize / 2; + char *buffer = (char *)m_RecvQueue->GetWriteBuffer(&bufferSize); + rc = recv(GetFD(), buffer, bufferSize, 0); #ifdef _WIN32 - if (rc < 0 && WSAGetLastError() == WSAEWOULDBLOCK) + if (rc < 0 && WSAGetLastError() == WSAEWOULDBLOCK) #else /* _WIN32 */ - if (rc < 0 && errno == EAGAIN) + if (rc < 0 && errno == EAGAIN) #endif /* _WIN32 */ - break; - - if (rc <= 0) { - Close(); - return 0; - } - - m_RecvQueue->Write(NULL, rc); - read_total += rc; + return 0; - /* make sure we don't starve other sockets */ - if (read_total > 128 * 1024) - break; + if (rc <= 0) { + Close(); + return 0; } + m_RecvQueue->Write(NULL, rc); + EventArgs::RefType dea = new_object(); dea->Source = shared_from_this(); OnDataAvailable(dea); diff --git a/base/unix.h b/base/unix.h index 20f795289..507e18a99 100644 --- a/base/unix.h +++ b/base/unix.h @@ -5,6 +5,7 @@ #include #include #include +#include #include #include diff --git a/jsonrpc/connectionmanager.cpp b/jsonrpc/connectionmanager.cpp index 91041b7bd..98787f35d 100644 --- a/jsonrpc/connectionmanager.cpp +++ b/jsonrpc/connectionmanager.cpp @@ -1,6 +1,8 @@ #include "i2-jsonrpc.h" using namespace icinga; +using std::map; +using std::function; void ConnectionManager::BindServer(JsonRpcServer::RefType server) { @@ -43,7 +45,41 @@ int ConnectionManager::CloseClientHandler(EventArgs::RefType ea) int ConnectionManager::NewMessageHandler(NewMessageEventArgs::RefType nmea) { - OnNewMessage(nmea); + JsonRpcMessage::RefType request = nmea->Message; + JsonRpcClient::RefType client = static_pointer_cast(nmea->Source); + + map >::iterator i; + i = m_Methods.find(request->GetMethod()); + + if (i == m_Methods.end()) { + JsonRpcMessage::RefType response = new_object(); + response->SetVersion("2.0"); + response->SetError("Unknown method."); + response->SetID(request->GetID()); + Netstring::WriteJSONToFIFO(client->GetSendQueue(), response->GetJSON()); + + return 0; + } + + i->second(nmea); return 0; } + +void ConnectionManager::RegisterMethod(string method, function callback) +{ + map >::iterator i; + i = m_Methods.find(method); + + if (i == m_Methods.end()) { + m_Methods[method] = event(); + i = m_Methods.find(method); + } + + i->second.bind(callback); +} + +void ConnectionManager::UnregisterMethod(string method, function function) +{ + // TODO: implement +} diff --git a/jsonrpc/connectionmanager.h b/jsonrpc/connectionmanager.h index 07aee6bdc..13e8ca03f 100644 --- a/jsonrpc/connectionmanager.h +++ b/jsonrpc/connectionmanager.h @@ -4,10 +4,13 @@ namespace icinga { +using std::map; + class ConnectionManager : public Object { list m_Servers; list m_Clients; + map< string, event > m_Methods; int NewClientHandler(NewClientEventArgs::RefType ncea); int CloseClientHandler(EventArgs::RefType ea); @@ -23,7 +26,8 @@ public: void BindClient(JsonRpcClient::RefType client); void UnbindClient(JsonRpcClient::RefType client); - event OnNewMessage; + void RegisterMethod(string method, function function); + void UnregisterMethod(string method, function function); }; } diff --git a/jsonrpc/i2-jsonrpc.h b/jsonrpc/i2-jsonrpc.h index 66baa0823..127cffd8d 100644 --- a/jsonrpc/i2-jsonrpc.h +++ b/jsonrpc/i2-jsonrpc.h @@ -1,6 +1,7 @@ #ifndef I2_JSONRPC_H #define I2_JSONRPC_H +#include #include #include "cJSON.h" diff --git a/jsonrpc/jsonrpcmessage.cpp b/jsonrpc/jsonrpcmessage.cpp index 84839b28b..81a7d8945 100644 --- a/jsonrpc/jsonrpcmessage.cpp +++ b/jsonrpc/jsonrpcmessage.cpp @@ -23,27 +23,47 @@ cJSON *JsonRpcMessage::GetJSON(void) return m_JSON; } -void JsonRpcMessage::SetFieldString(const char *field, const string& value) +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 *object = cJSON_CreateString(value.c_str()); cJSON_DeleteItemFromObject(m_JSON, field); - cJSON_AddItemToObject(m_JSON, field, object); + + if (object != NULL) + cJSON_AddItemToObject(m_JSON, field, object); } -string JsonRpcMessage::GetFieldString(const char *field) +cJSON *JsonRpcMessage::GetFieldObject(const char *field) { if (m_JSON == NULL) - m_JSON = cJSON_CreateObject(); + return NULL; + + return cJSON_GetObjectItem(m_JSON, field); +} - cJSON *idObject = cJSON_GetObjectItem(m_JSON, field); +void JsonRpcMessage::SetFieldString(const char *field, const string& value) +{ + cJSON *object = cJSON_CreateString(value.c_str()); + SetFieldObject(field, object); +} - if (idObject == NULL || idObject->type != cJSON_String) +string JsonRpcMessage::GetFieldString(const char *field) +{ + cJSON *object = GetFieldObject(field); + + if (object == NULL || object->type != cJSON_String) return string(); - return string(idObject->valuestring); + return string(object->valuestring); } void JsonRpcMessage::SetVersion(const string& version) @@ -76,24 +96,38 @@ string JsonRpcMessage::GetMethod(void) return GetFieldString("method"); } -void JsonRpcMessage::SetParams(const string& params) +void JsonRpcMessage::ClearParams(void) { - SetFieldString("params", params); + SetFieldObject("params", NULL); } -string JsonRpcMessage::GetParams(void) +cJSON *JsonRpcMessage::GetParams(void) { - return GetFieldString("params"); + cJSON *object = GetFieldObject("params"); + + if (object == NULL) { + object = cJSON_CreateObject(); + cJSON_AddItemToObject(m_JSON, "params", object); + } + + return object; } -void JsonRpcMessage::SetResult(const string& result) +void JsonRpcMessage::ClearResult(void) { - SetFieldString("result", result); + SetFieldObject("result", NULL); } -string JsonRpcMessage::GetResult(void) +cJSON *JsonRpcMessage::GetResult(void) { - return GetFieldString("result"); + cJSON *object = GetFieldObject("result"); + + if (object == NULL) { + object = cJSON_CreateObject(); + cJSON_AddItemToObject(m_JSON, "result", object); + } + + return object; } void JsonRpcMessage::SetError(const string& error) diff --git a/jsonrpc/jsonrpcmessage.h b/jsonrpc/jsonrpcmessage.h index 36296e8d6..ca5f6d7c0 100644 --- a/jsonrpc/jsonrpcmessage.h +++ b/jsonrpc/jsonrpcmessage.h @@ -9,9 +9,15 @@ class 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 RefType; typedef weak_ptr WeakRefType; @@ -31,11 +37,11 @@ public: void SetMethod(const string& method); string GetMethod(void); - void SetParams(const string& params); - string GetParams(void); + void ClearParams(void); + cJSON *GetParams(void); - void SetResult(const string& result); - string GetResult(void); + void ClearResult(); + cJSON *GetResult(void); void SetError(const string& error); string GetError(void); diff --git a/miniapp/miniapp.cpp b/miniapp/miniapp.cpp index 0a4524ef3..65a8faefc 100644 --- a/miniapp/miniapp.cpp +++ b/miniapp/miniapp.cpp @@ -10,37 +10,19 @@ using std::endl; class MyApplication : public Application { -private: - int m_Foo; - public: typedef shared_ptr RefType; typedef weak_ptr WeakRefType; - MyApplication(void) - { - m_Foo = 0; - } - int Main(const vector& args) { - /*FIFO::RefType f = new_object(); - f->Write("12:Hello World!,", 16); - Netstring::RefType ns = new_object(); - ns->ReadFromFIFO(f); - - Timer::RefType t = new_object(); - t->SetInterval(2); - t->OnTimerExpired.bind(bind_weak(&MyApplication::TimerCallback, shared_from_this())); - t->Start();*/ - JsonRpcServer::RefType ts = new_object(); ts->MakeSocket(); ts->Bind(7777); ts->Listen(); ConnectionManager::RefType cm = new_object(); - cm->OnNewMessage.bind(bind_weak(&MyApplication::MessageHandler, shared_from_this())); + cm->RegisterMethod("HelloWorld", bind_weak(&MyApplication::HelloWorld, shared_from_this())); cm->BindServer(ts); RunEventLoop(); @@ -48,7 +30,7 @@ public: return 0; } - int MessageHandler(NewMessageEventArgs::RefType nea) + int HelloWorld(NewMessageEventArgs::RefType nea) { JsonRpcClient::RefType client = static_pointer_cast(nea->Source); JsonRpcMessage::RefType msg = nea->Message; @@ -56,27 +38,12 @@ public: JsonRpcMessage::RefType response = new_object(); response->SetVersion("2.0"); response->SetID(msg->GetID()); - response->SetResult("moo"); + cJSON *result = response->GetResult(); + cJSON_AddStringToObject(result, "greeting", "Hello World!"); client->SendMessage(response); return 0; } - - int TimerCallback(TimerEventArgs::RefType tda) - { - Timer::RefType t = static_pointer_cast(tda->Source); - - m_Foo++; - - printf("Hello World!\n"); - - if (m_Foo >= 5) { - t->Stop(); - Shutdown(); - } - - return 0; - } }; SET_START_CLASS(MyApplication); -- 2.40.0