2 * Copyright (c) 2013, TOYOTA MOTOR CORPORATION.
4 * This program is licensed under the terms and conditions of the
5 * Apache License, version 2.0. The full text of the Apache License is at
6 * http://www.apache.org/licenses/LICENSE-2.0
10 //==========================================================================
12 * @file CicoSCServer.cpp
14 * @brief This file implementation of CicoSCServer class
16 //==========================================================================
21 #include "CicoSCServer.h"
22 #include "CicoSCCommand.h"
23 #include "CicoSCMessage.h"
25 #include "ico_syc_error.h"
26 #include "ico_syc_msg_cmd_def.h"
27 #include "CicoSCWindowController.h"
28 #include "CicoSCInputController.h"
29 #include "CicoSCUserManager.h"
30 #include "CicoSCUser.h"
31 #include "CicoSCResourceManager.h"
32 #include "CicoSCPolicyManager.h"
34 class CicoSCUwsHandler
38 : uwsContext(NULL), id(NULL), fd(-1), serviceFlag(false),
39 ecoreFdHandler(NULL), appid("") {}
40 void dump(void) const {
41 ICO_DBG("uwsContext=0x%08x fd=%d service=%s "
42 "ecoreFdHandler=0x%08x appid=%s",
43 uwsContext, fd, serviceFlag ? "true" : "false",
44 ecoreFdHandler, appid.c_str());
46 struct ico_uws_context *uwsContext;
50 Ecore_Fd_Handler *ecoreFdHandler;
54 //==========================================================================
55 // private static variable
56 //==========================================================================
57 CicoSCServer* CicoSCServer::ms_myInstance = NULL;
59 //--------------------------------------------------------------------------
61 * @brief default constructor
63 //--------------------------------------------------------------------------
64 CicoSCServer::CicoSCServer()
65 : m_uwsContext(NULL), m_windowCtrl(NULL),
66 m_inputCtrl(NULL) , m_userMgr(NULL), m_resourceMgr(NULL),
67 m_policyMgr(NULL), m_dispatchProcessing(false)
71 //--------------------------------------------------------------------------
75 //--------------------------------------------------------------------------
76 CicoSCServer::~CicoSCServer()
81 //--------------------------------------------------------------------------
83 * @brief get CicoSCServer instance
85 * @return CicoSCServer instance
87 //--------------------------------------------------------------------------
89 CicoSCServer::getInstance(void)
91 if (NULL == ms_myInstance) {
92 ms_myInstance = new CicoSCServer();
98 //--------------------------------------------------------------------------
100 * @brief set window controller instance
102 * @param [in] windowCtrl controller instance
104 //--------------------------------------------------------------------------
106 CicoSCServer::setWindowCtrl(CicoSCWindowController *windowCtrl)
108 m_windowCtrl = windowCtrl;
111 //--------------------------------------------------------------------------
113 * @brief set input controller instance
115 * @param [in] inputCtrl controller instance
117 //--------------------------------------------------------------------------
119 CicoSCServer::setInputCtrl(CicoSCInputController *inputCtrl)
121 m_inputCtrl= inputCtrl;
124 //--------------------------------------------------------------------------
126 * @brief set user manager
128 * @param [in] userMgr user manager instance
130 //--------------------------------------------------------------------------
132 CicoSCServer::setUserMgr(CicoSCUserManager *userMgr)
137 //--------------------------------------------------------------------------
139 * @brief set resource manager instance
141 * @param [in] resourceMgr resouce manager instance
143 //--------------------------------------------------------------------------
145 CicoSCServer::setResourceMgr(CicoSCResourceManager *resourceMgr)
147 m_resourceMgr = resourceMgr;
150 //--------------------------------------------------------------------------
152 * @brief set policy manager instance
154 * @param [in] policyMgr policy manager instance
156 //--------------------------------------------------------------------------
158 CicoSCServer::setPolicyMgr(CicoSCPolicyManager *policyMgr)
160 m_policyMgr = policyMgr;
163 //--------------------------------------------------------------------------
165 * @brief startup server
167 * @param [in] port websocket port
168 * @param [in] protocol websocket protocol name
170 * @return ICO_SYC_EOK on success, other on error
171 * @retval ICO_SYC_EOK success
172 * @retval ICO_SYC_ENOSYS error(connection fail)
174 //--------------------------------------------------------------------------
176 CicoSCServer::startup(int port, const char *protocol)
178 /* create uir string ":PORT" */
183 ICO_DBG("called: ico_uws_create_context(port=%s protocol=%s)",
184 uri.str().c_str(), protocol);
185 m_uwsContext = ico_uws_create_context(uri.str().c_str(), protocol);
186 if (NULL == m_uwsContext) {
187 ICO_ERR("ico_uws_create_context() failed.");
188 return ICO_SYC_ENOSYS;
190 ico_uws_service(m_uwsContext);
193 int ret = ico_uws_set_event_cb(m_uwsContext, uwsReceiveEventCB,
195 if (ret != ICO_UWS_ERR_NONE) {
196 ICO_ERR("ico_uws_set_event_cb() failed(%d).", ret);
197 return ICO_SYC_ENOSYS;
199 ico_uws_service(m_uwsContext);
204 //--------------------------------------------------------------------------
206 * @brief add poll websocket file destructor
208 * @param [in] handler websocket handler
210 //--------------------------------------------------------------------------
212 CicoSCServer::addPollFd(CicoSCUwsHandler *handler)
214 ICO_DBG("CicoSCServer::addPollFd Enter(fd=%d)", handler->fd);
215 Ecore_Fd_Handler_Flags flags;
216 flags = (Ecore_Fd_Handler_Flags)(ECORE_FD_READ | ECORE_FD_ERROR);
218 handler->ecoreFdHandler = ecore_main_fd_handler_add(handler->fd, flags,
222 ICO_DBG("Enqueue uwsHandler(0x%08x)", handler);
223 m_uwsHandlerList.push_back(handler);
225 ICO_DBG("CicoSCServer::addPollFd Leave");
228 //--------------------------------------------------------------------------
230 * @brief delete poll websocket file destructor
232 * @param [in] handler websocket handler
234 //--------------------------------------------------------------------------
236 CicoSCServer::delPollFd(CicoSCUwsHandler *handler)
238 ICO_DBG("CicoSCServer::delPollFd Enter");
240 ecore_main_fd_handler_del(handler->ecoreFdHandler);
241 handler->ecoreFdHandler = NULL;
243 list<CicoSCUwsHandler*>::iterator itr;
244 itr = m_uwsHandlerList.begin();
245 for (; itr != m_uwsHandlerList.end(); ++itr) {
246 if (*itr == handler) {
247 ICO_DBG("Dequeue uwsHandler(0x%08x)", *itr);
248 m_uwsHandlerList.erase(itr);
254 ICO_DBG("CicoSCServer::delPollFd Enter");
257 //--------------------------------------------------------------------------
259 * @brief dispatch receive message process and send message process
261 * @param [in] handler websocket handler
263 * @return websocket handler instance on find, NULL on not found
265 //--------------------------------------------------------------------------
267 CicoSCServer::dispatch(const CicoSCUwsHandler *handler)
269 // ICO_DBG("CicoSCServer::dispatch Enter(handler=0x%08x)", handler);
271 if (NULL == handler) {
272 ICO_WRN("handler is null");
273 ICO_DBG("CicoSCServer::dispatch Leave");
277 ico_uws_service(handler->uwsContext);
279 // There is a possibility that after calling ico_uws_service function,
280 // the file is deleted. Check whether handler not the disabled.
281 if (false == isExistUwsHandler(handler)) {
282 ICO_DBG("CicoSCServer::dispatch Leave");
286 if (true == m_dispatchProcessing) {
287 ICO_DBG("CicoSCServer::dispatch Leave(disptch processing)");
291 m_dispatchProcessing = true;
292 list<CicoSCCommand*>::iterator itr;
293 itr = m_recvCmdQueue.begin();
294 while(itr != m_recvCmdQueue.end()) {
295 ICO_DBG("Dequeue command(0x%08x)", (*itr)->cmdid);
296 CicoSCCommand *cmd = *itr;
297 itr = m_recvCmdQueue.erase(itr);
298 switch (cmd->cmdid & MSG_CMD_TYPE_MASK) {
299 case MSG_CMD_TYPE_WINCTRL:
300 //ICO_DBG("command : MSG_CMD_TYPE_WINCTRL");
301 m_windowCtrl->handleCommand(cmd);
303 case MSG_CMD_TYPE_INPUTCTRL:
304 //ICO_DBG("command : MSG_CMD_TYPE_INPUTCTRL");
305 m_inputCtrl->handleCommand(cmd);
307 case MSG_CMD_TYPE_USERMGR:
308 //ICO_DBG("command : MSG_CMD_TYPE_USERMGR");
309 m_userMgr->handleCommand(cmd);
311 case MSG_CMD_TYPE_RESOURCEMGR:
312 //ICO_DBG("command : MSG_CMD_TYPE_RESOURCEMGR");
313 m_resourceMgr->handleCommand(*cmd);
315 case MSG_CMD_TYPE_INPUTDEVSETTING:
316 //ICO_DBG("command : MSG_CMD_TYPE_INPUTDEVSETTING");
317 m_inputCtrl->handleCommand(cmd);
320 ICO_WRN("command: Unknown type");
325 m_dispatchProcessing = false;
327 if (NULL == handler->ecoreFdHandler) {
328 ICO_ERR("ecoreFdHandler is null");
329 ICO_DBG("CicoSCServer::dispatch Leave");
333 Eina_Bool flag = ecore_main_fd_handler_active_get(handler->ecoreFdHandler,
335 if (EINA_TRUE == flag) {
336 // ICO_DBG("start send message");
337 list<CicoSCMessage*>::iterator send_itr;
338 send_itr = m_sendMsgQueue.begin();
339 while (send_itr != m_sendMsgQueue.end()) {
340 // ICO_DBG("m_sendMsgQueue.size=%d", m_sendMsgQueue.size());
341 CicoSCMessage* msg = *send_itr;
342 CicoSCUwsHandler *sendHandler = findUwsHandler(msg->getSendToAppid());
343 if (handler != sendHandler) {
347 send_itr = m_sendMsgQueue.erase(send_itr);
348 ICO_DBG("Dequeue Message(id=%d)", msg->getId());
349 if ((NULL != sendHandler) && (true == sendHandler->serviceFlag)) {
350 ICO_DBG("<<<SEND appid=%s id=0x%08x msg=%s",
351 sendHandler->appid.c_str(), sendHandler->id, msg->getData());
352 // ICO_DBG("called: ico_usw_send called(context=0x%08x id=0x%08x)",
353 // sendHandler->uwsContext, sendHandler->id);
354 ico_uws_send(sendHandler->uwsContext, sendHandler->id,
355 (unsigned char *)msg->getData(),
356 strlen(msg->getData()));
364 Ecore_Fd_Handler_Flags flags;;
365 flags = (Ecore_Fd_Handler_Flags)(ECORE_FD_READ | ECORE_FD_ERROR);
367 ecore_main_fd_handler_active_set(handler->ecoreFdHandler, flags);
370 // ICO_DBG("CicoSCServer::dispatch Leave");
373 //--------------------------------------------------------------------------
375 * @brief send message to application client
377 * @param [in] appid application id of destination
378 * @param [in] msg message
380 * @return ICO_SYC_EOK on success, other on error
382 //--------------------------------------------------------------------------
384 CicoSCServer::sendMessage(const string & appid, CicoSCMessage* msg)
386 ICO_DBG("CicoSCServer::sendMessage Enter(appid=%s, msg=%s)",
387 appid.c_str(), msg->getData());
389 msg->setSendToAppid(appid);
390 ICO_DBG("Enqueue Message(id=%d)", msg->getId());
391 m_sendMsgQueue.push_back(msg);
393 CicoSCUwsHandler *handler = findUwsHandler(appid);
394 if (NULL != handler) {
395 Ecore_Fd_Handler_Flags flags;
396 flags = (Ecore_Fd_Handler_Flags)(ECORE_FD_READ |
400 ecore_main_fd_handler_active_set(handler->ecoreFdHandler, flags);
405 ICO_DBG("CicoSCServer::sendMessage Leave(EOK)");
409 //--------------------------------------------------------------------------
411 * @brief send message to homescreen
413 * @param [in] msg message
415 * @return ICO_SYC_EOK on success, other on error
417 //--------------------------------------------------------------------------
419 CicoSCServer::sendMessageToHomeScreen(CicoSCMessage* msg)
421 const CicoSCUser *loginUser = m_userMgr->getLoginUser();
422 if (NULL == loginUser) {
423 ICO_WRN("homescreen unknown");
424 return ICO_SYC_ENOENT;
426 return sendMessage(loginUser->homescreen, msg);
429 //--------------------------------------------------------------------------
431 * @brief websocket utility callback function
433 * @param [in] context context
434 * @param [in] event event kinds
435 * @param [in] id client id
436 * @param [in] detail event detail
437 * @param [in] data user data
439 //--------------------------------------------------------------------------
441 CicoSCServer::uwsReceiveEventCB(const struct ico_uws_context *context,
442 const ico_uws_evt_e event,
444 const ico_uws_detail *detail,
447 if (NULL == user_data) {
448 ICO_ERR("user_data is NULL");
452 CicoSCServer* server = static_cast<CicoSCServer*>(user_data);
453 server->receiveEventCB(context, event, id, detail, user_data);
456 //--------------------------------------------------------------------------
458 * @brief ecore file destructor callback fucntion
460 * @param [in] data user data
461 * @param [in] handler ecore file destructor handler
463 * @return ECORE_CALLBACK_RENEW on retry , ECORE_CALLBACK_CANCEL on cancel
465 //--------------------------------------------------------------------------
467 CicoSCServer::ecoreFdCallback(void *data, Ecore_Fd_Handler *ecoreFdhandler)
469 // ICO_DBG("CicoSCServer::ecoreFdCallback Enter");
471 CicoSCUwsHandler *handler = NULL;
472 handler = static_cast<CicoSCServer*>(data)->findUwsHandler(ecoreFdhandler);
473 if (NULL != handler) {
474 static_cast<CicoSCServer*>(data)->dispatch(handler);
477 // ICO_DBG("CicoSCServer::ecoreFdCallback Leave");
478 return ECORE_CALLBACK_RENEW;
481 //--------------------------------------------------------------------------
483 * @brief websocket callback function
485 * @param [in] context websocket context
486 * @param [in] event changed event
487 * @param [in] id source applicatin id
488 * @param [in] detail event detail information
489 * @param [in] user_data user data
491 //--------------------------------------------------------------------------
493 CicoSCServer::receiveEventCB(const struct ico_uws_context *context,
494 const ico_uws_evt_e event,
496 const ico_uws_detail *detail,
499 // ICO_DBG("CicoSCServer::receiveEventCB Enter");
502 CicoSCUwsHandler *handler = findUwsHandler(context, id);
503 // If not found handler, create new handler
504 if (NULL == handler) {
505 handler = new CicoSCUwsHandler();
506 handler->uwsContext = (struct ico_uws_context*)context;
507 handler->id = (void*)(id);
508 handler->serviceFlag = false;
512 case ICO_UWS_EVT_OPEN:
513 ICO_DBG(">>>RECV ICO_UWS_EVT_OPEN(id=0x%08x)", (int)id);
515 case ICO_UWS_EVT_CLOSE:
516 ICO_DBG(">>>RECV ICO_UWS_EVT_CLOSE(id=0x%08x)", (int)id);
518 case ICO_UWS_EVT_RECEIVE:
520 ICO_DBG(">>>RECV ICO_UWS_EVT_RECEIVE(id=0x%08x, msg=%s, len=%d)",
521 (int)id, (char *)detail->_ico_uws_message.recv_data,
522 detail->_ico_uws_message.recv_len);
524 // convert message to command
525 CicoSCCommand *cmd = new CicoSCCommand();
526 cmd->parseMessage((const char*)detail->_ico_uws_message.recv_data);
528 // update handler appid
529 if (cmd->cmdid == MSG_CMD_SEND_APPID) {
530 if (0 == cmd->appid.length()) {
531 ICO_WRN("command argument invalid appid null");
534 handler->appid = cmd->appid;
535 handler->serviceFlag = true;
536 ICO_DBG("handler.appid=%s", handler->appid.c_str());
538 Ecore_Fd_Handler_Flags flags;
539 flags = (Ecore_Fd_Handler_Flags)(ECORE_FD_READ |
543 ecore_main_fd_handler_active_set(handler->ecoreFdHandler, flags);
545 notifyConnected(handler->appid);
550 ICO_DBG("Enqueue command(0x%08x)", cmd->cmdid);
551 m_recvCmdQueue.push_back(cmd);
554 case ICO_UWS_EVT_ERROR:
555 ICO_DBG(">>>RECV ICO_UWS_EVT_ERROR(id=0x%08x, err=%d)",
556 (int)id, detail->_ico_uws_error.code);
558 case ICO_UWS_EVT_ADD_FD:
559 ICO_DBG(">>>RECV ICO_UWS_EVT_ADD_FD(id=0x%08x, fd=%d)",
560 (int)id, detail->_ico_uws_fd.fd);
561 handler->fd = detail->_ico_uws_fd.fd;
564 case ICO_UWS_EVT_DEL_FD:
565 ICO_DBG(">>>RECV ICO_UWS_EVT_DEL_FD(id=0x%08x, fd=%d)",
566 (int)id, detail->_ico_uws_fd.fd);
572 // ICO_DBG("CicoSCServer::receiveEventCB Leave");
575 //--------------------------------------------------------------------------
577 * @brief find websocket handler by context and id
579 * @param [in] context websocket context
582 * @return websocket handler instance on find, NULL on not found
584 //--------------------------------------------------------------------------
586 CicoSCServer::findUwsHandler(const struct ico_uws_context *context,
589 list<CicoSCUwsHandler*>::iterator itr;
590 itr = m_uwsHandlerList.begin();
591 for (; itr != m_uwsHandlerList.end(); ++itr) {
592 // ICO_DBG("handler->context=%p handler->id=%p context=%p id=%p",
593 // (*itr)->uwsContext, (*itr)->id, context, id);
594 if (((*itr)->uwsContext == context) &&
595 ((*itr)->id == id)) {
602 //--------------------------------------------------------------------------
604 * @brief find websocket handler by ecore file destructor handler
606 * @param [in] ecoreFdHandler ecore file destructor handler
608 * @return websocket handler instance on find, NULL on not found
610 //--------------------------------------------------------------------------
612 CicoSCServer::findUwsHandler(const Ecore_Fd_Handler *ecoreFdHandler)
614 list<CicoSCUwsHandler*>::iterator itr;
615 itr = m_uwsHandlerList.begin();
616 for (; itr != m_uwsHandlerList.end(); ++itr) {
617 if ((*itr)->ecoreFdHandler == ecoreFdHandler) {
624 //--------------------------------------------------------------------------
626 * @brief find websocket handler by appid
628 * @param [in] addid application id
630 * @return websocket handler instance on find, NULL on not found
632 //--------------------------------------------------------------------------
634 CicoSCServer::findUwsHandler(const string & appid)
636 list<CicoSCUwsHandler*>::iterator itr;
637 itr = m_uwsHandlerList.begin();
638 for (; itr != m_uwsHandlerList.end(); ++itr) {
639 // ICO_DBG("handler->id=%p handler->appid=%s appid=%s",
640 // (*itr)->id, (*itr)->appid.c_str(), appid.c_str());
641 if ((*itr)->appid == appid) {
648 //--------------------------------------------------------------------------
650 * @brief find websocket handler by appid
652 * @param [in] handler websocket handler instance
654 * @return true on exist, false on not exist
656 //--------------------------------------------------------------------------
658 CicoSCServer::isExistUwsHandler(const CicoSCUwsHandler *handler)
660 list<CicoSCUwsHandler*>::iterator itr;
661 itr = m_uwsHandlerList.begin();
662 for (; itr != m_uwsHandlerList.end(); ++itr) {
663 if (*itr == handler) {
670 //--------------------------------------------------------------------------
672 * @brief notify information to homescreen on connected
674 * @param [in] appid application id
676 //--------------------------------------------------------------------------
678 CicoSCServer::notifyConnected(const std::string & appid)
680 const CicoSCUser *loginUser = m_userMgr->getLoginUser();
681 if (NULL == loginUser) {
682 ICO_WRN("homescreen unknown");
686 // if appid equal homescreen
687 if (0 == loginUser->homescreen.compare(appid)) {
688 if (NULL != m_policyMgr) {
689 m_policyMgr->notifyConnected(appid);
693 // vim:set expandtab ts=4 sw=4: