Веб-сайт самохостера Lotigara

summaryrefslogtreecommitdiff
path: root/source/core/StarJsonRpc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/core/StarJsonRpc.cpp')
-rw-r--r--source/core/StarJsonRpc.cpp115
1 files changed, 115 insertions, 0 deletions
diff --git a/source/core/StarJsonRpc.cpp b/source/core/StarJsonRpc.cpp
new file mode 100644
index 0000000..dcdc16e
--- /dev/null
+++ b/source/core/StarJsonRpc.cpp
@@ -0,0 +1,115 @@
+#include "StarJsonRpc.hpp"
+#include "StarDataStreamDevices.hpp"
+#include "StarLogging.hpp"
+
+namespace Star {
+
+JsonRpcInterface::~JsonRpcInterface() {}
+
+JsonRpc::JsonRpc() {
+ m_requestId = 0;
+}
+
+void JsonRpc::registerHandler(String const& handler, JsonRpcRemoteFunction func) {
+ if (m_handlers.contains(handler))
+ throw JsonRpcException(strf("Handler by that name already exists '%s'", handler));
+ m_handlers.add(move(handler), move(func));
+}
+
+void JsonRpc::registerHandlers(JsonRpcHandlers const& handlers) {
+ for (auto const& pair : handlers)
+ registerHandler(pair.first, pair.second);
+}
+
+void JsonRpc::removeHandler(String const& handler) {
+ if (!m_handlers.contains(handler))
+ throw JsonRpcException(strf("No such handler by the name '%s'", handler));
+
+ m_handlers.remove(handler);
+}
+
+void JsonRpc::clearHandlers() {
+ m_handlers.clear();
+}
+
+RpcPromise<Json> JsonRpc::invokeRemote(String const& handler, Json const& arguments) {
+ uint64_t id = m_requestId++;
+ JsonObject request;
+ m_pending.append(JsonObject{
+ {"command", "request"},
+ {"id", id},
+ {"handler", handler},
+ {"arguments", arguments}
+ });
+
+ auto pair = RpcPromise<Json>::createPair();
+ m_pendingResponse.add(id, pair.second);
+
+ return pair.first;
+}
+
+bool JsonRpc::sendPending() const {
+ return !m_pending.empty();
+}
+
+ByteArray JsonRpc::send() {
+ if (m_pending.empty())
+ return {};
+
+ DataStreamBuffer buffer;
+ buffer.writeContainer(m_pending);
+ m_pending.clear();
+
+ return buffer.takeData();
+}
+
+void JsonRpc::receive(ByteArray const& inbuffer) {
+ if (inbuffer.empty())
+ return;
+
+ DataStreamBuffer buffer(inbuffer);
+ List<Json> inbound;
+ buffer.readContainer(inbound);
+
+ for (auto request : inbound) {
+ if (request.get("command") == "request") {
+ try {
+ auto handlerName = request.getString("handler");
+ if (!m_handlers.contains(handlerName))
+ throw JsonRpcException(strf("Unknown handler '%s'", handlerName));
+ m_pending.append(JsonObject{
+ {"command", "response"},
+ {"id", request.get("id")},
+ {"result", m_handlers[handlerName](request.get("arguments"))}
+ });
+ } catch (std::exception& e) {
+ Logger::error("Exception while handling variant rpc request handler call. %s", outputException(e, false));
+ JsonObject response;
+ response["command"] = "fail";
+ response["id"] = request.get("id");
+ m_pending.append(JsonObject{
+ {"command", "fail"},
+ {"id", request.get("id")}
+ });
+ }
+
+ } else if (request.get("command") == "response") {
+ try {
+ auto responseHandler = m_pendingResponse.take(request.getUInt("id"));
+ responseHandler.fulfill(request.get("result"));
+ } catch (std::exception& e) {
+ Logger::error("Exception while handling variant rpc response handler call. %s", outputException(e, true));
+ }
+
+ } else if (request.get("command") == "fail") {
+ try {
+ auto responseHandler = m_pendingResponse.take(request.getUInt("id"));
+ responseHandler.fulfill({});
+ } catch (std::exception& e) {
+ Logger::error("Exception while handling variant rpc failure handler call. %s", outputException(e, true));
+ }
+ }
+ }
+}
+
+}