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()
78 if (NULL != m_uwsContext) {
79 ico_uws_close(m_uwsContext);
83 //--------------------------------------------------------------------------
85 * @brief get CicoSCServer instance
87 * @return CicoSCServer instance
89 //--------------------------------------------------------------------------
91 CicoSCServer::getInstance(void)
93 if (NULL == ms_myInstance) {
94 ms_myInstance = new CicoSCServer();
100 //--------------------------------------------------------------------------
102 * @brief set window controller instance
104 * @param [in] windowCtrl controller instance
106 //--------------------------------------------------------------------------
108 CicoSCServer::setWindowCtrl(CicoSCWindowController *windowCtrl)
110 m_windowCtrl = windowCtrl;
113 //--------------------------------------------------------------------------
115 * @brief set input controller instance
117 * @param [in] inputCtrl controller instance
119 //--------------------------------------------------------------------------
121 CicoSCServer::setInputCtrl(CicoSCInputController *inputCtrl)
123 m_inputCtrl= inputCtrl;
126 //--------------------------------------------------------------------------
128 * @brief set user manager
130 * @param [in] userMgr user manager instance
132 //--------------------------------------------------------------------------
134 CicoSCServer::setUserMgr(CicoSCUserManager *userMgr)
139 //--------------------------------------------------------------------------
141 * @brief set resource manager instance
143 * @param [in] resourceMgr resouce manager instance
145 //--------------------------------------------------------------------------
147 CicoSCServer::setResourceMgr(CicoSCResourceManager *resourceMgr)
149 m_resourceMgr = resourceMgr;
152 //--------------------------------------------------------------------------
154 * @brief set policy manager instance
156 * @param [in] policyMgr policy manager instance
158 //--------------------------------------------------------------------------
160 CicoSCServer::setPolicyMgr(CicoSCPolicyManager *policyMgr)
162 m_policyMgr = policyMgr;
165 //--------------------------------------------------------------------------
167 * @brief startup server
169 * @param [in] port websocket port
170 * @param [in] protocol websocket protocol name
172 * @return ICO_SYC_EOK on success, other on error
173 * @retval ICO_SYC_EOK success
174 * @retval ICO_SYC_ENOSYS error(connection fail)
176 //--------------------------------------------------------------------------
178 CicoSCServer::startup(int port, const char *protocol)
180 /* create uir string ":PORT" */
185 ICO_DBG("called: ico_uws_create_context(port=%s protocol=%s)",
186 uri.str().c_str(), protocol);
187 m_uwsContext = ico_uws_create_context(uri.str().c_str(), protocol);
188 if (NULL == m_uwsContext) {
189 ICO_ERR("ico_uws_create_context() failed.");
190 return ICO_SYC_ENOSYS;
192 ico_uws_service(m_uwsContext);
195 int ret = ico_uws_set_event_cb(m_uwsContext, uwsReceiveEventCB,
197 if (ret != ICO_UWS_ERR_NONE) {
198 ICO_ERR("ico_uws_set_event_cb() failed(%d).", ret);
199 return ICO_SYC_ENOSYS;
201 ico_uws_service(m_uwsContext);
206 //--------------------------------------------------------------------------
208 * @brief teardown server
210 //--------------------------------------------------------------------------
212 CicoSCServer::teardown(void)
214 ICO_TRA("CicoSCServer::teardown Enter");
216 std::list<CicoSCUwsHandler*>::iterator itr;
217 itr = m_uwsHandlerList.begin();
218 for (; itr != m_uwsHandlerList.end(); ++itr) {
219 if (NULL != (*itr)->ecoreFdHandler) {
220 ecore_main_fd_handler_del((*itr)->ecoreFdHandler);
221 (*itr)->ecoreFdHandler = NULL;
225 m_uwsHandlerList.clear();
229 std::list<CicoSCMessage*>::iterator itr;
230 itr = m_sendMsgQueue.begin();
231 for (; itr != m_sendMsgQueue.end(); ++itr) {
234 m_sendMsgQueue.clear();
238 std::list<CicoSCCommand*>::iterator itr;
239 itr = m_recvCmdQueue.begin();
240 for (; itr != m_recvCmdQueue.end(); ++itr) {
245 if (NULL != m_uwsContext) {
246 ico_uws_close(m_uwsContext);
249 ICO_TRA("CicoSCServer::teardown Leave");
252 //--------------------------------------------------------------------------
254 * @brief add poll websocket file destructor
256 * @param [in] handler websocket handler
258 //--------------------------------------------------------------------------
260 CicoSCServer::addPollFd(CicoSCUwsHandler *handler)
262 ICO_TRA("CicoSCServer::addPollFd Enter(fd=%d)", handler->fd);
263 Ecore_Fd_Handler_Flags flags;
264 flags = (Ecore_Fd_Handler_Flags)(ECORE_FD_READ | ECORE_FD_ERROR);
266 handler->ecoreFdHandler = ecore_main_fd_handler_add(handler->fd, flags,
270 ICO_DBG("Enqueue uwsHandler(0x%08x)", handler);
271 m_uwsHandlerList.push_back(handler);
273 ICO_TRA("CicoSCServer::addPollFd Leave");
276 //--------------------------------------------------------------------------
278 * @brief delete poll websocket file destructor
280 * @param [in] handler websocket handler
282 //--------------------------------------------------------------------------
284 CicoSCServer::delPollFd(CicoSCUwsHandler *handler)
286 ICO_TRA("CicoSCServer::delPollFd Enter");
288 if (NULL == handler) {
289 ICO_WRN("handler is null");
290 ICO_TRA("CicoSCServer::delPollFd Leave");
294 if (NULL != handler->ecoreFdHandler) {
295 ecore_main_fd_handler_del(handler->ecoreFdHandler);
296 handler->ecoreFdHandler = NULL;
299 list<CicoSCUwsHandler*>::iterator itr;
300 itr = m_uwsHandlerList.begin();
301 for (; itr != m_uwsHandlerList.end(); ++itr) {
302 if (*itr == handler) {
303 ICO_DBG("Dequeue uwsHandler(0x%08x)", *itr);
304 m_uwsHandlerList.erase(itr);
310 ICO_TRA("CicoSCServer::delPollFd Leave");
313 //--------------------------------------------------------------------------
315 * @brief dispatch receive message process and send message process
317 * @param [in] handler websocket handler
319 * @return websocket handler instance on find, NULL on not found
321 //--------------------------------------------------------------------------
323 CicoSCServer::dispatch(const CicoSCUwsHandler *handler)
325 // ICO_TRA("CicoSCServer::dispatch Enter(handler=0x%08x)", handler);
327 if (NULL == handler) {
328 ICO_WRN("handler is null");
329 ICO_TRA("CicoSCServer::dispatch Leave");
333 ico_uws_service(handler->uwsContext);
335 // There is a possibility that after calling ico_uws_service function,
336 // the file is deleted. Check whether handler not the disabled.
337 if (false == isExistUwsHandler(handler)) {
338 ICO_TRA("CicoSCServer::dispatch Leave");
342 if (true == m_dispatchProcessing) {
343 ICO_TRA("CicoSCServer::dispatch Leave(disptch processing)");
347 m_dispatchProcessing = true;
348 list<CicoSCCommand*>::iterator itr;
349 itr = m_recvCmdQueue.begin();
350 while(itr != m_recvCmdQueue.end()) {
351 ICO_DBG("Dequeue command(0x%08x)", (*itr)->cmdid);
352 CicoSCCommand *cmd = *itr;
353 itr = m_recvCmdQueue.erase(itr);
354 switch (cmd->cmdid & MSG_CMD_TYPE_MASK) {
355 case MSG_CMD_TYPE_WINCTRL:
356 //ICO_DBG("command : MSG_CMD_TYPE_WINCTRL");
357 m_windowCtrl->handleCommand(cmd);
359 case MSG_CMD_TYPE_INPUTCTRL:
360 //ICO_DBG("command : MSG_CMD_TYPE_INPUTCTRL");
361 m_inputCtrl->handleCommand(cmd);
363 case MSG_CMD_TYPE_USERMGR:
364 //ICO_DBG("command : MSG_CMD_TYPE_USERMGR");
365 m_userMgr->handleCommand(cmd);
367 case MSG_CMD_TYPE_RESOURCEMGR:
368 //ICO_DBG("command : MSG_CMD_TYPE_RESOURCEMGR");
369 m_resourceMgr->handleCommand(*cmd);
371 case MSG_CMD_TYPE_INPUTDEVSETTING:
372 //ICO_DBG("command : MSG_CMD_TYPE_INPUTDEVSETTING");
373 m_inputCtrl->handleCommand(cmd);
376 ICO_WRN("command: Unknown type");
381 m_dispatchProcessing = false;
383 if (NULL == handler->ecoreFdHandler) {
384 ICO_ERR("ecoreFdHandler is null");
385 ICO_TRA("CicoSCServer::dispatch Leave");
389 Eina_Bool flag = ecore_main_fd_handler_active_get(handler->ecoreFdHandler,
391 if (EINA_TRUE == flag) {
392 // ICO_DBG("start send message");
393 list<CicoSCMessage*>::iterator send_itr;
394 send_itr = m_sendMsgQueue.begin();
395 while (send_itr != m_sendMsgQueue.end()) {
396 // ICO_DBG("m_sendMsgQueue.size=%d", m_sendMsgQueue.size());
397 CicoSCMessage* msg = *send_itr;
398 CicoSCUwsHandler *sendHandler = findUwsHandler(msg->getSendToAppid());
399 if (handler != sendHandler) {
403 send_itr = m_sendMsgQueue.erase(send_itr);
404 ICO_DBG("Dequeue Message(id=%d)", msg->getId());
405 if ((NULL != sendHandler) && (true == sendHandler->serviceFlag)) {
406 const char *data = msg->getData();
407 ICO_DBG("<<<SEND appid=%s id=0x%08x msg=%s",
408 sendHandler->appid.c_str(), sendHandler->id, data);
409 // ICO_DBG("called: ico_usw_send called(context=0x%08x id=0x%08x)",
410 // sendHandler->uwsContext, sendHandler->id);
411 ico_uws_send(sendHandler->uwsContext, sendHandler->id,
412 (unsigned char *)data, strlen(data));
420 Ecore_Fd_Handler_Flags flags;;
421 flags = (Ecore_Fd_Handler_Flags)(ECORE_FD_READ | ECORE_FD_ERROR);
423 ecore_main_fd_handler_active_set(handler->ecoreFdHandler, flags);
426 // ICO_TRA("CicoSCServer::dispatch Leave");
429 //--------------------------------------------------------------------------
431 * @brief send message to application client
433 * @param [in] appid application id of destination
434 * @param [in] msg message
436 * @return ICO_SYC_EOK on success, other on error
438 //--------------------------------------------------------------------------
440 CicoSCServer::sendMessage(const string & appid, CicoSCMessage* msg)
442 ICO_TRA("CicoSCServer::sendMessage Enter(appid=%s, msg=%s)",
443 appid.c_str(), msg->getData());
445 msg->setSendToAppid(appid);
446 ICO_DBG("Enqueue Message(id=%d)", msg->getId());
447 m_sendMsgQueue.push_back(msg);
449 CicoSCUwsHandler *handler = findUwsHandler(appid);
450 if (NULL != handler) {
451 Ecore_Fd_Handler_Flags flags;
452 flags = (Ecore_Fd_Handler_Flags)(ECORE_FD_READ |
456 ecore_main_fd_handler_active_set(handler->ecoreFdHandler, flags);
461 ICO_TRA("CicoSCServer::sendMessage Leave(EOK)");
465 //--------------------------------------------------------------------------
467 * @brief send message to homescreen
469 * @param [in] msg message
471 * @return ICO_SYC_EOK on success, other on error
473 //--------------------------------------------------------------------------
475 CicoSCServer::sendMessageToHomeScreen(CicoSCMessage* msg)
477 // if user change processing(homescree is not running)
478 if (true == m_userMgr->isStoppingNow()) {
479 ICO_DBG("homescreen not running");
480 return ICO_SYC_ENOENT;
483 const CicoSCUser *loginUser = m_userMgr->getLoginUser();
484 if (NULL == loginUser) {
485 ICO_WRN("homescreen unknown");
486 return ICO_SYC_ENOENT;
488 return sendMessage(loginUser->homescreen, msg);
491 //--------------------------------------------------------------------------
493 * @brief websocket utility callback function
495 * @param [in] context context
496 * @param [in] event event kinds
497 * @param [in] id client id
498 * @param [in] detail event detail
499 * @param [in] data user data
501 //--------------------------------------------------------------------------
503 CicoSCServer::uwsReceiveEventCB(const struct ico_uws_context *context,
504 const ico_uws_evt_e event,
506 const ico_uws_detail *detail,
509 if (NULL == user_data) {
510 ICO_ERR("user_data is NULL");
514 CicoSCServer* server = static_cast<CicoSCServer*>(user_data);
515 server->receiveEventCB(context, event, id, detail, user_data);
518 //--------------------------------------------------------------------------
520 * @brief ecore file destructor callback fucntion
522 * @param [in] data user data
523 * @param [in] handler ecore file destructor handler
525 * @return ECORE_CALLBACK_RENEW on retry , ECORE_CALLBACK_CANCEL on cancel
527 //--------------------------------------------------------------------------
529 CicoSCServer::ecoreFdCallback(void *data, Ecore_Fd_Handler *ecoreFdhandler)
531 // ICO_TRA("CicoSCServer::ecoreFdCallback Enter");
533 CicoSCUwsHandler *handler = NULL;
534 handler = static_cast<CicoSCServer*>(data)->findUwsHandler(ecoreFdhandler);
535 if (NULL != handler) {
536 static_cast<CicoSCServer*>(data)->dispatch(handler);
539 // ICO_TRA("CicoSCServer::ecoreFdCallback Leave");
540 return ECORE_CALLBACK_RENEW;
543 //--------------------------------------------------------------------------
545 * @brief websocket callback function
547 * @param [in] context websocket context
548 * @param [in] event changed event
549 * @param [in] id source applicatin id
550 * @param [in] detail event detail information
551 * @param [in] user_data user data
553 //--------------------------------------------------------------------------
555 CicoSCServer::receiveEventCB(const struct ico_uws_context *context,
556 const ico_uws_evt_e event,
558 const ico_uws_detail *detail,
561 // ICO_TRA("CicoSCServer::receiveEventCB Enter");
564 case ICO_UWS_EVT_CLOSE:
565 ICO_DBG(">>>RECV ICO_UWS_EVT_CLOSE(id=0x%08x)", (int)id);
566 // ICO_TRA("CicoSCServer::receiveEventCB Leave");
568 case ICO_UWS_EVT_ERROR:
569 ICO_DBG(">>>RECV ICO_UWS_EVT_ERROR(id=0x%08x, err=%d)",
570 (int)id, detail->_ico_uws_error.code);
571 // ICO_TRA("CicoSCServer::receiveEventCB Leave");
578 CicoSCUwsHandler *handler = findUwsHandler(context, id);
579 // If not found handler, create new handler
580 if (NULL == handler) {
581 handler = new CicoSCUwsHandler();
582 handler->uwsContext = (struct ico_uws_context*)context;
583 handler->id = (void*)(id);
584 handler->serviceFlag = false;
588 case ICO_UWS_EVT_OPEN:
589 ICO_DBG(">>>RECV ICO_UWS_EVT_OPEN(id=0x%08x)", (int)id);
591 case ICO_UWS_EVT_CLOSE:
592 ICO_DBG(">>>RECV ICO_UWS_EVT_CLOSE(id=0x%08x)", (int)id);
595 case ICO_UWS_EVT_RECEIVE:
597 ICO_DBG(">>>RECV ICO_UWS_EVT_RECEIVE(id=0x%08x, msg=%s, len=%d)",
598 (int)id, (char *)detail->_ico_uws_message.recv_data,
599 detail->_ico_uws_message.recv_len);
601 // convert message to command
602 CicoSCCommand *cmd = new CicoSCCommand();
603 cmd->parseMessage((const char*)detail->_ico_uws_message.recv_data);
605 // update handler appid
606 if (cmd->cmdid == MSG_CMD_SEND_APPID) {
607 if (0 == cmd->appid.length()) {
608 ICO_WRN("command argument invalid appid null");
612 handler->appid = cmd->appid;
613 handler->serviceFlag = true;
614 ICO_DBG("handler.appid=%s", handler->appid.c_str());
616 Ecore_Fd_Handler_Flags flags;
617 flags = (Ecore_Fd_Handler_Flags)(ECORE_FD_READ |
621 ecore_main_fd_handler_active_set(handler->ecoreFdHandler, flags);
623 notifyConnected(handler->appid);
629 ICO_DBG("Enqueue command(0x%08x)", cmd->cmdid);
630 m_recvCmdQueue.push_back(cmd);
633 case ICO_UWS_EVT_ADD_FD:
634 ICO_DBG(">>>RECV ICO_UWS_EVT_ADD_FD(id=0x%08x, fd=%d)",
635 (int)id, detail->_ico_uws_fd.fd);
636 handler->fd = detail->_ico_uws_fd.fd;
639 case ICO_UWS_EVT_DEL_FD:
640 ICO_DBG(">>>RECV ICO_UWS_EVT_DEL_FD(id=0x%08x, fd=%d, appid=%s)",
641 (int)id, detail->_ico_uws_fd.fd, handler->appid.c_str());
642 clearRecvCmdQueue(handler->appid);
643 clearSendMsgQueue(handler->appid);
649 // ICO_TRA("CicoSCServer::receiveEventCB Leave");
652 //--------------------------------------------------------------------------
654 * @brief clear receive command queue
656 * @param [in] appid clear command application id
658 //--------------------------------------------------------------------------
660 CicoSCServer::clearRecvCmdQueue(const std::string & appid)
662 ICO_TRA("CicoSCServer::clearCmdQueue Enter(appid=%s)", appid.c_str());
664 std::list<CicoSCCommand*>::iterator itr;
665 itr = m_recvCmdQueue.begin();
666 for (; itr != m_recvCmdQueue.end(); ) {
667 if (0 == appid.compare((*itr)->appid)) {
668 ICO_DBG("Dequeue command(0x%08x)", (*itr)->cmdid);
670 itr = m_recvCmdQueue.erase(itr);
676 m_recvCmdQueue.clear();
678 ICO_TRA("CicoSCServer::clearCmdQueue Leave")
681 //--------------------------------------------------------------------------
683 * @brief clear send message queue
685 * @param [in] appid clear message application id
687 //--------------------------------------------------------------------------
689 CicoSCServer::clearSendMsgQueue(const std::string & appid)
691 ICO_TRA("CicoSCServer::clearMsgQueue Enter(appid=%s)", appid.c_str())
693 std::list<CicoSCMessage*>::iterator itr;
694 itr = m_sendMsgQueue.begin();
695 while(itr != m_sendMsgQueue.end()) {
696 if (0 == appid.compare((*itr)->getSendToAppid())) {
697 ICO_DBG("Dequeue Message(id=%d)", (*itr)->getId());
699 itr = m_sendMsgQueue.erase(itr);
705 m_sendMsgQueue.clear();
707 ICO_TRA("CicoSCServer::clearMsgQueue Leave")
710 //--------------------------------------------------------------------------
712 * @brief find websocket handler by context and id
714 * @param [in] context websocket context
717 * @return websocket handler instance on find, NULL on not found
719 //--------------------------------------------------------------------------
721 CicoSCServer::findUwsHandler(const struct ico_uws_context *context,
724 list<CicoSCUwsHandler*>::iterator itr;
725 itr = m_uwsHandlerList.begin();
726 for (; itr != m_uwsHandlerList.end(); ++itr) {
727 // ICO_DBG("handler->context=%p handler->id=%p context=%p id=%p",
728 // (*itr)->uwsContext, (*itr)->id, context, id);
729 if (((*itr)->uwsContext == context) &&
730 ((*itr)->id == id)) {
737 //--------------------------------------------------------------------------
739 * @brief find websocket handler by ecore file destructor handler
741 * @param [in] ecoreFdHandler ecore file destructor handler
743 * @return websocket handler instance on find, NULL on not found
745 //--------------------------------------------------------------------------
747 CicoSCServer::findUwsHandler(const Ecore_Fd_Handler *ecoreFdHandler)
749 list<CicoSCUwsHandler*>::iterator itr;
750 itr = m_uwsHandlerList.begin();
751 for (; itr != m_uwsHandlerList.end(); ++itr) {
752 if ((*itr)->ecoreFdHandler == ecoreFdHandler) {
759 //--------------------------------------------------------------------------
761 * @brief find websocket handler by appid
763 * @param [in] addid application id
765 * @return websocket handler instance on find, NULL on not found
767 //--------------------------------------------------------------------------
769 CicoSCServer::findUwsHandler(const string & appid)
771 list<CicoSCUwsHandler*>::iterator itr;
772 itr = m_uwsHandlerList.begin();
773 for (; itr != m_uwsHandlerList.end(); ++itr) {
774 // ICO_DBG("handler->id=%p handler->appid=%s appid=%s",
775 // (*itr)->id, (*itr)->appid.c_str(), appid.c_str());
776 if ((*itr)->appid == appid) {
783 //--------------------------------------------------------------------------
785 * @brief find websocket handler by appid
787 * @param [in] handler websocket handler instance
789 * @return true on exist, false on not exist
791 //--------------------------------------------------------------------------
793 CicoSCServer::isExistUwsHandler(const CicoSCUwsHandler *handler)
795 list<CicoSCUwsHandler*>::iterator itr;
796 itr = m_uwsHandlerList.begin();
797 for (; itr != m_uwsHandlerList.end(); ++itr) {
798 if (*itr == handler) {
805 //--------------------------------------------------------------------------
807 * @brief notify information to homescreen on connected
809 * @param [in] appid application id
811 //--------------------------------------------------------------------------
813 CicoSCServer::notifyConnected(const std::string & appid)
815 const CicoSCUser *loginUser = m_userMgr->getLoginUser();
816 if (NULL == loginUser) {
817 ICO_WRN("homescreen unknown");
821 // if appid equal homescreen
822 if (0 == loginUser->homescreen.compare(appid)) {
823 if (NULL != m_policyMgr) {
824 m_policyMgr->notifyConnected(appid);
828 // vim:set expandtab ts=4 sw=4: