diff options
Diffstat (limited to 'src/ClientManager.cpp')
-rwxr-xr-x | src/ClientManager.cpp | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/src/ClientManager.cpp b/src/ClientManager.cpp new file mode 100755 index 0000000..74d672d --- /dev/null +++ b/src/ClientManager.cpp @@ -0,0 +1,215 @@ +/*
+ * Copyright (C) 2020 MERA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ClientManager.h"
+#include "hmi-debug.h"
+
+#include <set>
+#include <json-c/json.h>
+
+// static
+void ClientManager::cbRemoveClientCtx(void *data)
+{
+ ClientManager::instance().removeClient((ClientManager::ClientCtx*)data);
+}
+
+
+// static
+ClientManager& ClientManager::instance()
+{
+ static ClientManager instance;
+ return instance;
+}
+
+
+ClientManager::~ClientManager()
+{
+ std::lock_guard<std::mutex> lock(this->m_mutex);
+ for (auto cl : m_clients)
+ delete cl.second;
+}
+
+
+ClientManager::ClientCtx* ClientManager::addClient(afb_req_t req, const std::string& appid)
+{
+ ClientCtx* ctx = (ClientCtx*)afb_req_context_get(req);
+ if (!ctx)
+ {
+ HMI_NOTICE("cloudproxy-service", "create new session for %s", appid.c_str());
+ ctx = new ClientCtx{appid, afb_api_make_event(req->api, appid.c_str())};
+ afb_req_session_set_LOA(req, 1);
+ afb_req_context_set(req, ctx, cbRemoveClientCtx);
+ }
+
+ m_clients[appid] = ctx;
+ return ctx;
+}
+
+
+void ClientManager::removeClient(ClientCtx* ctx)
+{
+ if(!ctx)
+ {
+ HMI_ERROR("cloudproxy-service", "data is nullptr");
+ return;
+ }
+
+ HMI_NOTICE("cloudproxy-service", "remove app %s", ctx->appid.c_str());
+ std::lock_guard<std::mutex> lock(this->m_mutex);
+
+ auto it = m_clients.find(ctx->appid);
+ if (it != m_clients.end())
+ {
+ delete it->second;
+ m_clients.erase(it);
+ }
+}
+
+
+bool ClientManager::handleRequest(afb_req_t request, const std::string& verb, const std::string& appid)
+{
+ HMI_NOTICE("cloudproxy-service", "handleRequest: verb='%s', appid='%s'", verb.c_str(), appid.c_str());
+ std::lock_guard<std::mutex> lock(this->m_mutex);
+
+ if (appid.empty())
+ {
+ HMI_ERROR("cloudproxy-service", "appid is empty");
+ return false;
+ }
+
+ auto client_it = m_clients.find(appid);
+ if (verb != "subscribe" && client_it == m_clients.end())
+ {
+ HMI_NOTICE("cloudproxy-service", "client with appid '%s' is not registered", appid.c_str());
+ return false;
+ }
+
+ if (verb == "subscribe")
+ {
+ const char *value = afb_req_value(request, "event");
+ if(!value)
+ {
+ HMI_ERROR("cloudproxy-service", "Can't subscribe: event name is not defined");
+ return false;
+ }
+ std::string req_event{value};
+ HMI_NOTICE("cloudproxy-service", "subscribe req: appid '%s', event '%s'", appid.c_str(), req_event.c_str());
+
+ if (!isSupportedEvent(req_event))
+ {
+ HMI_ERROR("cloudproxy-service", "event '%s' is not supported", req_event.c_str());
+ return false;
+ }
+
+ ClientCtx* ctx = addClient(request, appid);
+ ctx->subs_events.insert(req_event);
+ if(!ctx->subscription)
+ {
+ if(afb_req_subscribe(request, ctx->event) == 0)
+ {
+ ctx->subscription = true;
+ }
+ else
+ {
+ HMI_ERROR("cloudproxy-service", "API error in afb_req_subscribe");
+ return false;
+ }
+ }
+
+ return true;
+ }
+ else if (verb == "unsubscribe")
+ {
+ const char *value = afb_req_value(request, "event");
+ if(!value)
+ {
+ HMI_ERROR("cloudproxy-service", "Can't unsubscribe: event name is not defined");
+ return false;
+ }
+ std::string req_event{value};
+ HMI_NOTICE("cloudproxy-service", "unsubscribe req: appid '%s', event '%s'", appid.c_str(), req_event.c_str());
+
+ ClientCtx* ctx{client_it->second};
+ ctx->subs_events.erase(req_event);
+
+ if(ctx->subs_events.empty())
+ {
+ if (afb_req_unsubscribe(request, ctx->event) != 0)
+ HMI_ERROR("cloudproxy-service", "API error in afb_req_unsubscribe");
+
+ ctx->subscription = false;
+ }
+
+ return true;
+ }
+
+ HMI_NOTICE("cloudproxy-service", "Unsupported verb '%s'", verb.c_str());
+ return false;
+}
+
+
+bool ClientManager::isSupportedEvent(const std::string& event)
+{
+ const std::set<std::string> event_list{
+ "sendMessageConfirmation",
+ "receivedMessage"
+ };
+
+ return (event_list.end() != event_list.find(event));
+}
+
+
+bool ClientManager::emitReceivedMessage(const std::string& appid, const std::string& data)
+{
+ std::lock_guard<std::mutex> lock(this->m_mutex);
+
+ auto it = m_clients.find(appid);
+ if (it == m_clients.end())
+ {
+ HMI_WARNING("cloudproxy-service", "Client with appid '%s' is not present in list", appid.c_str());
+ // print app list
+ for (const auto& i : m_clients)
+ HMI_DEBUG("cloudproxy-service", "Client list: appid '%s' - '%s'", i.first.c_str(), i.second->appid.c_str());
+
+ return false;
+ }
+
+ json_object* push_obj = json_object_new_object();
+ json_object_object_add(push_obj, "type", json_object_new_string("receivedMessage"));
+ json_object_object_add(push_obj, "data", json_object_new_string(data.c_str()));
+ return (0 == afb_event_push(it->second->event, push_obj));
+}
+
+bool ClientManager::emitSendMessageConfirmation(const std::string& appid, bool result)
+{
+ std::lock_guard<std::mutex> lock(this->m_mutex);
+
+ auto it = m_clients.find(appid);
+ if (it == m_clients.end())
+ {
+ HMI_WARNING("cloudproxy-service", "Client with appid '%s' is not present in list", appid.c_str());
+ // print app list
+ for (const auto& i : m_clients)
+ HMI_DEBUG("cloudproxy-service", "Client list: appid '%s' - '%s'", i.first.c_str(), i.second->appid.c_str());
+
+ return false;
+ }
+
+ json_object* push_obj = json_object_new_object();
+ json_object_object_add(push_obj, "type", json_object_new_string("sendMessageConfirmation"));
+ json_object_object_add(push_obj, "result", json_object_new_boolean(result));
+ return (0 == afb_event_push(it->second->event, push_obj));
+}
|