summaryrefslogtreecommitdiffstats
path: root/lib/remote/jsonrpc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/remote/jsonrpc.cpp')
-rw-r--r--lib/remote/jsonrpc.cpp157
1 files changed, 157 insertions, 0 deletions
diff --git a/lib/remote/jsonrpc.cpp b/lib/remote/jsonrpc.cpp
new file mode 100644
index 0000000..d4d3d3c
--- /dev/null
+++ b/lib/remote/jsonrpc.cpp
@@ -0,0 +1,157 @@
+/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
+
+#include "remote/jsonrpc.hpp"
+#include "base/netstring.hpp"
+#include "base/json.hpp"
+#include "base/console.hpp"
+#include "base/scriptglobal.hpp"
+#include "base/convert.hpp"
+#include "base/tlsstream.hpp"
+#include <iostream>
+#include <memory>
+#include <utility>
+#include <boost/asio/spawn.hpp>
+
+using namespace icinga;
+
+#ifdef I2_DEBUG
+/**
+ * Determine whether the developer wants to see raw JSON messages.
+ *
+ * @return Internal.DebugJsonRpc boolean
+ */
+static bool GetDebugJsonRpcCached()
+{
+ static int debugJsonRpc = -1;
+
+ if (debugJsonRpc != -1)
+ return debugJsonRpc;
+
+ debugJsonRpc = false;
+
+ Namespace::Ptr internal = ScriptGlobal::Get("Internal", &Empty);
+
+ if (!internal)
+ return false;
+
+ Value vdebug;
+
+ if (!internal->Get("DebugJsonRpc", &vdebug))
+ return false;
+
+ debugJsonRpc = Convert::ToLong(vdebug);
+
+ return debugJsonRpc;
+}
+#endif /* I2_DEBUG */
+
+/**
+ * Sends a message to the connected peer and returns the bytes sent.
+ *
+ * @param message The message.
+ *
+ * @return The amount of bytes sent.
+ */
+size_t JsonRpc::SendMessage(const Shared<AsioTlsStream>::Ptr& stream, const Dictionary::Ptr& message)
+{
+ String json = JsonEncode(message);
+
+#ifdef I2_DEBUG
+ if (GetDebugJsonRpcCached())
+ std::cerr << ConsoleColorTag(Console_ForegroundBlue) << ">> " << json << ConsoleColorTag(Console_Normal) << "\n";
+#endif /* I2_DEBUG */
+
+ return NetString::WriteStringToStream(stream, json);
+}
+
+/**
+ * Sends a message to the connected peer and returns the bytes sent.
+ *
+ * @param message The message.
+ *
+ * @return The amount of bytes sent.
+ */
+size_t JsonRpc::SendMessage(const Shared<AsioTlsStream>::Ptr& stream, const Dictionary::Ptr& message, boost::asio::yield_context yc)
+{
+ return JsonRpc::SendRawMessage(stream, JsonEncode(message), yc);
+}
+
+ /**
+ * Sends a raw message to the connected peer.
+ *
+ * @param stream ASIO TLS Stream
+ * @param json message
+ * @param yc Yield context required for ASIO
+ *
+ * @return bytes sent
+ */
+size_t JsonRpc::SendRawMessage(const Shared<AsioTlsStream>::Ptr& stream, const String& json, boost::asio::yield_context yc)
+{
+#ifdef I2_DEBUG
+ if (GetDebugJsonRpcCached())
+ std::cerr << ConsoleColorTag(Console_ForegroundBlue) << ">> " << json << ConsoleColorTag(Console_Normal) << "\n";
+#endif /* I2_DEBUG */
+
+ return NetString::WriteStringToStream(stream, json, yc);
+}
+
+/**
+ * Reads a message from the connected peer.
+ *
+ * @param stream ASIO TLS Stream
+ * @param maxMessageLength maximum size of bytes read.
+ *
+ * @return A JSON string
+ */
+
+String JsonRpc::ReadMessage(const Shared<AsioTlsStream>::Ptr& stream, ssize_t maxMessageLength)
+{
+ String jsonString = NetString::ReadStringFromStream(stream, maxMessageLength);
+
+#ifdef I2_DEBUG
+ if (GetDebugJsonRpcCached())
+ std::cerr << ConsoleColorTag(Console_ForegroundBlue) << "<< " << jsonString << ConsoleColorTag(Console_Normal) << "\n";
+#endif /* I2_DEBUG */
+
+ return jsonString;
+}
+
+/**
+ * Reads a message from the connected peer.
+ *
+ * @param stream ASIO TLS Stream
+ * @param yc Yield Context for ASIO
+ * @param maxMessageLength maximum size of bytes read.
+ *
+ * @return A JSON string
+ */
+String JsonRpc::ReadMessage(const Shared<AsioTlsStream>::Ptr& stream, boost::asio::yield_context yc, ssize_t maxMessageLength)
+{
+ String jsonString = NetString::ReadStringFromStream(stream, yc, maxMessageLength);
+
+#ifdef I2_DEBUG
+ if (GetDebugJsonRpcCached())
+ std::cerr << ConsoleColorTag(Console_ForegroundBlue) << "<< " << jsonString << ConsoleColorTag(Console_Normal) << "\n";
+#endif /* I2_DEBUG */
+
+ return jsonString;
+}
+
+/**
+ * Decode message, enforce a Dictionary
+ *
+ * @param message JSON string
+ *
+ * @return Dictionary ptr
+ */
+Dictionary::Ptr JsonRpc::DecodeMessage(const String& message)
+{
+ Value value = JsonDecode(message);
+
+ if (!value.IsObjectType<Dictionary>()) {
+ BOOST_THROW_EXCEPTION(std::invalid_argument("JSON-RPC"
+ " message must be a dictionary."));
+ }
+
+ return value;
+}