2 * Copyright (c) 2018 TOYOTA MOTOR CORPORATION
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include "hs-clientmanager.h"
20 #include "hs-apprecover.h"
22 static const char _homescreen[] = "homescreen";
23 const std::string _listen_all("all");
25 HS_ClientManager* HS_ClientManager::me = nullptr;
27 static void cbRemoveClientCtxt(void *data)
29 HS_ClientManager::instance()->removeClientCtxt(data);
33 * HS_ClientManager construction function
42 HS_ClientManager::HS_ClientManager()
53 * HS_ClientManager instance pointer
56 HS_ClientManager* HS_ClientManager::instance(void)
59 me = new HS_ClientManager();
65 * HS_ClientManager init function
74 int HS_ClientManager::init(void)
76 listener_list.clear();
77 std::list<listener_interface*> interface_list;
78 listener_list[_listen_all] = std::move(interface_list);
82 * create client's afb_req_context
88 * HS_ClientCtxt pointer
91 HS_ClientCtxt* HS_ClientManager::createClientCtxt(afb_req_t req, std::string appid)
93 HS_ClientCtxt *ctxt = (HS_ClientCtxt *)afb_req_context_get(req);
96 AFB_INFO( "create new session for %s", appid.c_str());
97 HS_ClientCtxt *ctxt = new HS_ClientCtxt(appid.c_str());
98 afb_req_session_set_LOA(req, 1);
99 afb_req_context_set(req, ctxt, cbRemoveClientCtxt);
114 HS_Client* HS_ClientManager::addClient(afb_req_t req, std::string appid)
116 return (client_list[appid] = new HS_Client(req, appid));
129 void HS_ClientManager::removeClient(std::string appid)
131 delete client_list[appid];
132 client_list.erase(appid);
136 * remove Client from list
139 * - data: HS_ClientCtxt pointer
145 void HS_ClientManager::removeClientCtxt(void *data)
147 HS_ClientCtxt *ctxt = (HS_ClientCtxt *)data;
150 AFB_WARNING( "data is nullptr");
154 AFB_INFO( "remove app %s", ctxt->id.c_str());
155 std::lock_guard<std::mutex> lock(this->mtx);
156 removeClient(ctxt->id);
157 delete appid2ctxt[ctxt->id];
158 appid2ctxt.erase(ctxt->id);
162 * handle homescreen request
165 * - request : the request
166 * - verb : the verb name
167 * - appid : to which application
174 int HS_ClientManager::handleRequest(afb_req_t request, const char *verb, const char *appid)
176 AFB_INFO("verb=[%s],appid=[%s].", verb, appid);
178 bool isRegisterApp = false;
179 if(appid == nullptr) {
180 std::lock_guard<std::mutex> lock(this->mtx);
181 for(auto m : client_list) {
182 m.second->handleRequest(request, verb);
186 std::lock_guard<std::mutex> lock(this->mtx);
187 auto ip = client_list.find(std::string(appid));
188 if(ip != client_list.end()) {
189 ret = ip->second->handleRequest(request, verb);
192 if(!strcasecmp(verb, "subscribe")) {
193 appid2ctxt[appid] = createClientCtxt(request, appid);
194 HS_Client* client = addClient(request, appid);
195 ret = client->handleRequest(request, "subscribe");
196 isRegisterApp = true;
199 AFB_NOTICE("not exist session");
200 ret = AFB_REQ_NOT_STARTED_APPLICATION;
205 notifyListener(request->api, std::string(appid));
214 * - event : the event want to push
215 * - param : the parameter contents of event
216 * - appid : the destination application's id
223 int HS_ClientManager::pushEvent(const char *event, struct json_object *param, std::string appid)
225 AFB_INFO("event=[%s], appid=[%s].", event, appid.c_str());
226 if(event == nullptr) {
227 AFB_WARNING("event name is null.");
231 std::lock_guard<std::mutex> lock(this->mtx);
232 if(appid.empty()) { // broadcast event to clients who subscribed this event
233 for(auto m : client_list) {
234 m.second->pushEvent(event, param);
237 else { // push event to specific client
238 auto ip = client_list.find(appid);
239 if(ip != client_list.end()) {
240 ip->second->pushEvent(event, param);
248 * check register application
252 * - appid : register application's id
256 * false : not checked
259 bool HS_ClientManager::checkRegisterApp(afb_api_t api, const std::string &appid)
262 auto &ip = listener_list[_listen_all];
265 it->notify(api, appid);
268 else if(startup_appid == appid) {
269 startup_appid.clear();
270 pushEvent("showWindow", nullptr, appid);
279 * check whether application was started
282 * - appid : application's id
289 bool HS_ClientManager::isAppStarted(const std::string &appid)
291 auto it = client_list.find(appid);
292 return it != client_list.end() ? true : false;
296 * add app register listener
299 * - listener_interface : listener interface
305 void HS_ClientManager::addListener(listener_interface* listener)
307 for (auto &it : listener->listenAppSet()) {
308 auto ip = listener_list.find(it);
309 if(ip != listener_list.end()) {
310 ip->second.push_back(listener);
313 std::list<listener_interface*> lst;
314 lst.push_back(listener);
315 listener_list[it] = std::move(lst);
321 * remove app register listener
324 * - listener_interface : listener interface
330 void HS_ClientManager::removeListener(listener_interface* listener)
332 for (auto &iter : listener->listenAppSet()) {
333 auto it = listener_list.find(iter);
334 if(it != listener_list.end()) {
335 auto ip = it->second.begin();
336 for(; ip != it->second.end(); ++ip) {
337 if(listener->myUid() == (*ip)->myUid()) {
341 it->second.erase(ip);
342 if(it->second.empty()) {
343 listener_list.erase(it->first);
354 * - appid : register application's id
360 void HS_ClientManager::notifyListener(afb_api_t api, const std::string &appid)
362 if (checkRegisterApp(api, appid)) {
366 AFB_INFO("listen %s, notified", appid.c_str());
367 std::list<listener_interface*> interface_list;
368 auto ip = listener_list.find(appid);
369 if(ip != listener_list.end()) {
370 if(!ip->second.empty()) {
371 interface_list = ip->second;
374 AFB_WARNING("listener is null.");
379 for(auto &it : interface_list) {
380 it->notify(api, appid);