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)
69 CicoSCServer::ms_myInstance = this;
72 //--------------------------------------------------------------------------
76 //--------------------------------------------------------------------------
77 CicoSCServer::~CicoSCServer()
79 CicoSCServer::ms_myInstance = NULL;
80 if (NULL != m_uwsContext) {
81 ico_uws_close(m_uwsContext);
85 //--------------------------------------------------------------------------
87 * @brief get CicoSCServer instance
89 * @return CicoSCServer instance
91 //--------------------------------------------------------------------------
93 CicoSCServer::getInstance(void)
95 if (NULL == ms_myInstance) {
96 ms_myInstance = new CicoSCServer();
102 //--------------------------------------------------------------------------
104 * @brief set window controller instance
106 * @param [in] windowCtrl controller instance
108 //--------------------------------------------------------------------------
110 CicoSCServer::setWindowCtrl(CicoSCWindowController *windowCtrl)
112 m_windowCtrl = windowCtrl;
115 //--------------------------------------------------------------------------
117 * @brief set input controller instance
119 * @param [in] inputCtrl controller instance
121 //--------------------------------------------------------------------------
123 CicoSCServer::setInputCtrl(CicoSCInputController *inputCtrl)
125 m_inputCtrl= inputCtrl;
128 //--------------------------------------------------------------------------
130 * @brief set user manager
132 * @param [in] userMgr user manager instance
134 //--------------------------------------------------------------------------
136 CicoSCServer::setUserMgr(CicoSCUserManager *userMgr)
141 //--------------------------------------------------------------------------
143 * @brief set resource manager instance
145 * @param [in] resourceMgr resouce manager instance
147 //--------------------------------------------------------------------------
149 CicoSCServer::setResourceMgr(CicoSCResourceManager *resourceMgr)
151 m_resourceMgr = resourceMgr;
154 //--------------------------------------------------------------------------
156 * @brief set policy manager instance
158 * @param [in] policyMgr policy manager instance
160 //--------------------------------------------------------------------------
162 CicoSCServer::setPolicyMgr(CicoSCPolicyManager *policyMgr)
164 m_policyMgr = policyMgr;
167 //--------------------------------------------------------------------------
169 * @brief startup server
171 * @param [in] port websocket port
172 * @param [in] protocol websocket protocol name
174 * @return ICO_SYC_EOK on success, other on error
175 * @retval ICO_SYC_EOK success
176 * @retval ICO_SYC_ENOSYS error(connection fail)
178 //--------------------------------------------------------------------------
180 CicoSCServer::startup(int port, const char *protocol)
182 /* create uir string ":PORT" */
187 ICO_DBG("called: ico_uws_create_context(port=%s protocol=%s)",
188 uri.str().c_str(), protocol);
189 m_uwsContext = ico_uws_create_context(uri.str().c_str(), protocol);
190 if (NULL == m_uwsContext) {
191 ICO_ERR("ico_uws_create_context() failed.");
192 return ICO_SYC_ENOSYS;
194 ico_uws_service(m_uwsContext);
197 int ret = ico_uws_set_event_cb(m_uwsContext, uwsReceiveEventCB,
199 if (ret != ICO_UWS_ERR_NONE) {
200 ICO_ERR("ico_uws_set_event_cb() failed(%d).", ret);
201 return ICO_SYC_ENOSYS;
203 ico_uws_service(m_uwsContext);
208 //--------------------------------------------------------------------------
210 * @brief teardown server
212 //--------------------------------------------------------------------------
214 CicoSCServer::teardown(void)
216 ICO_TRA("CicoSCServer::teardown Enter");
218 std::list<CicoSCUwsHandler*>::iterator itr;
219 itr = m_uwsHandlerList.begin();
220 for (; itr != m_uwsHandlerList.end(); ++itr) {
221 if (NULL != (*itr)->ecoreFdHandler) {
222 ecore_main_fd_handler_del((*itr)->ecoreFdHandler);
223 (*itr)->ecoreFdHandler = NULL;
227 m_uwsHandlerList.clear();
231 std::list<CicoSCMessage*>::iterator itr;
232 itr = m_sendMsgQueue.begin();
233 for (; itr != m_sendMsgQueue.end(); ++itr) {
236 m_sendMsgQueue.clear();
240 std::list<CicoSCCommand*>::iterator itr;
241 itr = m_recvCmdQueue.begin();
242 for (; itr != m_recvCmdQueue.end(); ++itr) {
247 if (NULL != m_uwsContext) {
248 ico_uws_close(m_uwsContext);
251 ICO_TRA("CicoSCServer::teardown Leave");
254 //--------------------------------------------------------------------------
256 * @brief add poll websocket file destructor
258 * @param [in] handler websocket handler
260 //--------------------------------------------------------------------------
262 CicoSCServer::addPollFd(CicoSCUwsHandler *handler)
264 ICO_TRA("CicoSCServer::addPollFd Enter(fd=%d)", handler->fd);
265 Ecore_Fd_Handler_Flags flags;
266 flags = (Ecore_Fd_Handler_Flags)(ECORE_FD_READ | ECORE_FD_ERROR);
268 handler->ecoreFdHandler = ecore_main_fd_handler_add(handler->fd, flags,
272 ICO_DBG("Enqueue uwsHandler(0x%08x)", handler);
273 m_uwsHandlerList.push_back(handler);
275 ICO_TRA("CicoSCServer::addPollFd Leave");
278 //--------------------------------------------------------------------------
280 * @brief delete poll websocket file destructor
282 * @param [in] handler websocket handler
284 //--------------------------------------------------------------------------
286 CicoSCServer::delPollFd(CicoSCUwsHandler *handler)
288 ICO_TRA("CicoSCServer::delPollFd Enter");
290 if (NULL == handler) {
291 ICO_WRN("handler is null");
292 ICO_TRA("CicoSCServer::delPollFd Leave");
296 if (NULL != handler->ecoreFdHandler) {
297 ecore_main_fd_handler_del(handler->ecoreFdHandler);
298 handler->ecoreFdHandler = NULL;
301 list<CicoSCUwsHandler*>::iterator itr;
302 itr = m_uwsHandlerList.begin();
303 for (; itr != m_uwsHandlerList.end(); ++itr) {
304 if (*itr == handler) {
305 ICO_DBG("Dequeue uwsHandler(0x%08x)", *itr);
306 m_uwsHandlerList.erase(itr);
312 ICO_TRA("CicoSCServer::delPollFd Leave");
315 //--------------------------------------------------------------------------
317 * @brief dispatch receive message process and send message process
319 * @param [in] handler websocket handler
321 * @return websocket handler instance on find, NULL on not found
323 //--------------------------------------------------------------------------
325 CicoSCServer::dispatch(const CicoSCUwsHandler *handler)
327 // ICO_TRA("CicoSCServer::dispatch Enter(handler=0x%08x)", handler);
329 if (NULL == handler) {
330 ICO_WRN("handler is null");
331 ICO_TRA("CicoSCServer::dispatch Leave");
335 ico_uws_service(handler->uwsContext);
337 // There is a possibility that after calling ico_uws_service function,
338 // the file is deleted. Check whether handler not the disabled.
339 if (false == isExistUwsHandler(handler)) {
340 ICO_TRA("CicoSCServer::dispatch Leave");
344 if (true == m_dispatchProcessing) {
345 ICO_TRA("CicoSCServer::dispatch Leave(disptch processing)");
349 m_dispatchProcessing = true;
350 list<CicoSCCommand*>::iterator itr;
351 itr = m_recvCmdQueue.begin();
352 while(itr != m_recvCmdQueue.end()) {
353 ICO_DBG("Dequeue command(0x%08x)", (*itr)->cmdid);
354 CicoSCCommand *cmd = *itr;
355 itr = m_recvCmdQueue.erase(itr);
356 switch (cmd->cmdid & MSG_CMD_TYPE_MASK) {
357 case MSG_CMD_TYPE_WINCTRL:
358 //ICO_DBG("command : MSG_CMD_TYPE_WINCTRL");
359 m_windowCtrl->handleCommand(cmd);
361 case MSG_CMD_TYPE_INPUTCTRL:
362 //ICO_DBG("command : MSG_CMD_TYPE_INPUTCTRL");
363 m_inputCtrl->handleCommand(cmd);
365 case MSG_CMD_TYPE_USERMGR:
366 //ICO_DBG("command : MSG_CMD_TYPE_USERMGR");
367 m_userMgr->handleCommand(cmd);
369 case MSG_CMD_TYPE_RESOURCEMGR:
370 //ICO_DBG("command : MSG_CMD_TYPE_RESOURCEMGR");
371 m_resourceMgr->handleCommand(*cmd);
373 case MSG_CMD_TYPE_INPUTDEVSETTING:
374 //ICO_DBG("command : MSG_CMD_TYPE_INPUTDEVSETTING");
375 m_inputCtrl->handleCommand(cmd);
378 ICO_WRN("command: Unknown type");
383 m_dispatchProcessing = false;
385 if (NULL == handler->ecoreFdHandler) {
386 ICO_ERR("ecoreFdHandler is null");
387 ICO_TRA("CicoSCServer::dispatch Leave");
391 Eina_Bool flag = ecore_main_fd_handler_active_get(handler->ecoreFdHandler,
393 if (EINA_TRUE == flag) {
394 // ICO_DBG("start send message");
395 list<CicoSCMessage*>::iterator send_itr;
396 send_itr = m_sendMsgQueue.begin();
397 while (send_itr != m_sendMsgQueue.end()) {
398 // ICO_DBG("m_sendMsgQueue.size=%d", m_sendMsgQueue.size());
399 CicoSCMessage* msg = *send_itr;
400 CicoSCUwsHandler *sendHandler = findUwsHandler(msg->getSendToAppid());
401 if (handler != sendHandler) {
405 send_itr = m_sendMsgQueue.erase(send_itr);
406 ICO_DBG("Dequeue Message(id=%d)", msg->getId());
407 if ((NULL != sendHandler) && (true == sendHandler->serviceFlag)) {
408 const char *data = msg->getData();
409 ICO_DBG("<<<SEND appid=%s id=0x%08x msg=%s",
410 sendHandler->appid.c_str(), sendHandler->id, data);
411 // ICO_DBG("called: ico_usw_send called(context=0x%08x id=0x%08x)",
412 // sendHandler->uwsContext, sendHandler->id);
413 ico_uws_send(sendHandler->uwsContext, sendHandler->id,
414 (unsigned char *)data, strlen(data));
422 Ecore_Fd_Handler_Flags flags;;
423 flags = (Ecore_Fd_Handler_Flags)(ECORE_FD_READ | ECORE_FD_ERROR);
425 ecore_main_fd_handler_active_set(handler->ecoreFdHandler, flags);
428 // ICO_TRA("CicoSCServer::dispatch Leave");
431 //--------------------------------------------------------------------------
433 * @brief send message to application client
435 * @param [in] appid application id of destination
436 * @param [in] msg message
438 * @return ICO_SYC_EOK on success, other on error
440 //--------------------------------------------------------------------------
442 CicoSCServer::sendMessage(const string & appid, CicoSCMessage* msg)
444 ICO_TRA("CicoSCServer::sendMessage Enter(appid=%s, msg=%s)",
445 appid.c_str(), msg->getData());
447 msg->setSendToAppid(appid);
448 ICO_DBG("Enqueue Message(id=%d)", msg->getId());
449 m_sendMsgQueue.push_back(msg);
451 CicoSCUwsHandler *handler = findUwsHandler(appid);
452 if (NULL != handler) {
453 Ecore_Fd_Handler_Flags flags;
454 flags = (Ecore_Fd_Handler_Flags)(ECORE_FD_READ |
458 ecore_main_fd_handler_active_set(handler->ecoreFdHandler, flags);
463 ICO_TRA("CicoSCServer::sendMessage Leave(EOK)");
467 //--------------------------------------------------------------------------
469 * @brief send message to homescreen
471 * @param [in] msg message
473 * @return ICO_SYC_EOK on success, other on error
475 //--------------------------------------------------------------------------
477 CicoSCServer::sendMessageToHomeScreen(CicoSCMessage* msg)
479 // if user change processing(homescree is not running)
480 if (true == m_userMgr->isStoppingNow()) {
481 ICO_DBG("homescreen not running");
483 return ICO_SYC_ENOENT;
486 const CicoSCUser *loginUser = m_userMgr->getLoginUser();
487 if (NULL == loginUser) {
488 ICO_WRN("homescreen unknown");
490 return ICO_SYC_ENOENT;
492 return sendMessage(loginUser->homescreen, msg);
495 //--------------------------------------------------------------------------
497 * @brief websocket utility callback function
499 * @param [in] context context
500 * @param [in] event event kinds
501 * @param [in] id client id
502 * @param [in] detail event detail
503 * @param [in] data user data
505 //--------------------------------------------------------------------------
507 CicoSCServer::uwsReceiveEventCB(const struct ico_uws_context *context,
508 const ico_uws_evt_e event,
510 const ico_uws_detail *detail,
513 if (NULL == user_data) {
514 ICO_ERR("user_data is NULL");
518 CicoSCServer* server = static_cast<CicoSCServer*>(user_data);
519 server->receiveEventCB(context, event, id, detail, user_data);
522 //--------------------------------------------------------------------------
524 * @brief ecore file destructor callback fucntion
526 * @param [in] data user data
527 * @param [in] handler ecore file destructor handler
529 * @return ECORE_CALLBACK_RENEW on retry , ECORE_CALLBACK_CANCEL on cancel
531 //--------------------------------------------------------------------------
533 CicoSCServer::ecoreFdCallback(void *data, Ecore_Fd_Handler *ecoreFdhandler)
535 // ICO_TRA("CicoSCServer::ecoreFdCallback Enter");
537 CicoSCUwsHandler *handler = NULL;
538 handler = static_cast<CicoSCServer*>(data)->findUwsHandler(ecoreFdhandler);
539 if (NULL != handler) {
540 static_cast<CicoSCServer*>(data)->dispatch(handler);
543 // ICO_TRA("CicoSCServer::ecoreFdCallback Leave");
544 return ECORE_CALLBACK_RENEW;
547 //--------------------------------------------------------------------------
549 * @brief websocket callback function
551 * @param [in] context websocket context
552 * @param [in] event changed event
553 * @param [in] id source applicatin id
554 * @param [in] detail event detail information
555 * @param [in] user_data user data
557 //--------------------------------------------------------------------------
559 CicoSCServer::receiveEventCB(const struct ico_uws_context *context,
560 const ico_uws_evt_e event,
562 const ico_uws_detail *detail,
565 // ICO_TRA("CicoSCServer::receiveEventCB Enter");
568 case ICO_UWS_EVT_CLOSE:
569 ICO_DBG(">>>RECV ICO_UWS_EVT_CLOSE(id=0x%08x)", (int)id);
570 // ICO_TRA("CicoSCServer::receiveEventCB Leave");
572 case ICO_UWS_EVT_ERROR:
573 ICO_DBG(">>>RECV ICO_UWS_EVT_ERROR(id=0x%08x, err=%d)",
574 (int)id, detail->_ico_uws_error.code);
575 // ICO_TRA("CicoSCServer::receiveEventCB Leave");
582 CicoSCUwsHandler *handler = findUwsHandler(context, id);
583 // If not found handler, create new handler
584 if (NULL == handler) {
585 handler = new CicoSCUwsHandler();
586 handler->uwsContext = (struct ico_uws_context*)context;
587 handler->id = (void*)(id);
588 handler->serviceFlag = false;
592 case ICO_UWS_EVT_OPEN:
593 ICO_DBG(">>>RECV ICO_UWS_EVT_OPEN(id=0x%08x)", (int)id);
594 break; // break of switch event
595 case ICO_UWS_EVT_CLOSE:
596 ICO_DBG(">>>RECV ICO_UWS_EVT_CLOSE(id=0x%08x)", (int)id);
598 break; // break of switch event
599 case ICO_UWS_EVT_RECEIVE:
601 ICO_DBG(">>>RECV ICO_UWS_EVT_RECEIVE(id=0x%08x, msg=%s, len=%d)",
602 (int)id, (char *)detail->_ico_uws_message.recv_data,
603 detail->_ico_uws_message.recv_len);
605 // convert message to command
606 CicoSCCommand *cmd = new CicoSCCommand();
607 cmd->parseMessage((const char*)detail->_ico_uws_message.recv_data);
609 // update handler appid
610 if (cmd->cmdid == MSG_CMD_SEND_APPID) {
611 if (0 == cmd->appid.length()) {
612 ICO_WRN("command argument invalid appid null");
614 break; // break of switch event
616 handler->appid = cmd->appid;
617 handler->serviceFlag = true;
618 ICO_DBG("handler.appid=%s", handler->appid.c_str());
620 Ecore_Fd_Handler_Flags flags;
621 flags = (Ecore_Fd_Handler_Flags)(ECORE_FD_READ |
625 ecore_main_fd_handler_active_set(handler->ecoreFdHandler, flags);
627 notifyConnected(handler->appid);
629 break; // break of switch event
633 ICO_DBG("Enqueue command(0x%08x)", cmd->cmdid);
634 m_recvCmdQueue.push_back(cmd);
635 break; // break of switch event
637 case ICO_UWS_EVT_ADD_FD:
638 ICO_DBG(">>>RECV ICO_UWS_EVT_ADD_FD(id=0x%08x, fd=%d)",
639 (int)id, detail->_ico_uws_fd.fd);
640 handler->fd = detail->_ico_uws_fd.fd;
642 break; // break of switch event
643 case ICO_UWS_EVT_DEL_FD:
644 ICO_DBG(">>>RECV ICO_UWS_EVT_DEL_FD(id=0x%08x, fd=%d, appid=%s)",
645 (int)id, detail->_ico_uws_fd.fd, handler->appid.c_str());
646 clearRecvCmdQueue(handler->appid);
647 clearSendMsgQueue(handler->appid);
649 break; // break of switch event
651 break; // break of switch event
653 // ICO_TRA("CicoSCServer::receiveEventCB Leave");
656 //--------------------------------------------------------------------------
658 * @brief clear receive command queue
660 * @param [in] appid clear command application id
662 //--------------------------------------------------------------------------
664 CicoSCServer::clearRecvCmdQueue(const std::string & appid)
666 ICO_TRA("CicoSCServer::clearCmdQueue Enter(appid=%s)", appid.c_str());
668 std::list<CicoSCCommand*>::iterator itr;
669 itr = m_recvCmdQueue.begin();
670 for (; itr != m_recvCmdQueue.end(); ) {
671 if (0 == appid.compare((*itr)->appid)) {
672 ICO_DBG("Dequeue command(0x%08x)", (*itr)->cmdid);
674 itr = m_recvCmdQueue.erase(itr);
681 ICO_TRA("CicoSCServer::clearCmdQueue Leave")
684 //--------------------------------------------------------------------------
686 * @brief clear send message queue
688 * @param [in] appid clear message application id
690 //--------------------------------------------------------------------------
692 CicoSCServer::clearSendMsgQueue(const std::string & appid)
694 ICO_TRA("CicoSCServer::clearMsgQueue Enter(appid=%s)", appid.c_str())
696 std::list<CicoSCMessage*>::iterator itr;
697 itr = m_sendMsgQueue.begin();
698 while(itr != m_sendMsgQueue.end()) {
699 if (0 == appid.compare((*itr)->getSendToAppid())) {
700 ICO_DBG("Dequeue Message(id=%d)", (*itr)->getId());
702 itr = m_sendMsgQueue.erase(itr);
709 ICO_TRA("CicoSCServer::clearMsgQueue Leave")
712 //--------------------------------------------------------------------------
714 * @brief find websocket handler by context and id
716 * @param [in] context websocket context
719 * @return websocket handler instance on find, NULL on not found
721 //--------------------------------------------------------------------------
723 CicoSCServer::findUwsHandler(const struct ico_uws_context *context,
726 list<CicoSCUwsHandler*>::iterator itr;
727 itr = m_uwsHandlerList.begin();
728 for (; itr != m_uwsHandlerList.end(); ++itr) {
729 // ICO_DBG("handler->context=%p handler->id=%p context=%p id=%p",
730 // (*itr)->uwsContext, (*itr)->id, context, id);
731 if (((*itr)->uwsContext == context) &&
732 ((*itr)->id == id)) {
739 //--------------------------------------------------------------------------
741 * @brief find websocket handler by ecore file destructor handler
743 * @param [in] ecoreFdHandler ecore file destructor handler
745 * @return websocket handler instance on find, NULL on not found
747 //--------------------------------------------------------------------------
749 CicoSCServer::findUwsHandler(const Ecore_Fd_Handler *ecoreFdHandler)
751 list<CicoSCUwsHandler*>::iterator itr;
752 itr = m_uwsHandlerList.begin();
753 for (; itr != m_uwsHandlerList.end(); ++itr) {
754 if ((*itr)->ecoreFdHandler == ecoreFdHandler) {
761 //--------------------------------------------------------------------------
763 * @brief find websocket handler by appid
765 * @param [in] addid application id
767 * @return websocket handler instance on find, NULL on not found
769 //--------------------------------------------------------------------------
771 CicoSCServer::findUwsHandler(const string & appid)
773 list<CicoSCUwsHandler*>::iterator itr;
774 itr = m_uwsHandlerList.begin();
775 for (; itr != m_uwsHandlerList.end(); ++itr) {
776 // ICO_DBG("handler->id=%p handler->appid=%s appid=%s",
777 // (*itr)->id, (*itr)->appid.c_str(), appid.c_str());
778 if ((*itr)->appid == appid) {
785 //--------------------------------------------------------------------------
787 * @brief find websocket handler by appid
789 * @param [in] handler websocket handler instance
791 * @return true on exist, false on not exist
793 //--------------------------------------------------------------------------
795 CicoSCServer::isExistUwsHandler(const CicoSCUwsHandler *handler)
797 list<CicoSCUwsHandler*>::iterator itr;
798 itr = m_uwsHandlerList.begin();
799 for (; itr != m_uwsHandlerList.end(); ++itr) {
800 if (*itr == handler) {
807 //--------------------------------------------------------------------------
809 * @brief notify information to homescreen on connected
811 * @param [in] appid application id
813 //--------------------------------------------------------------------------
815 CicoSCServer::notifyConnected(const std::string & appid)
817 const CicoSCUser *loginUser = m_userMgr->getLoginUser();
818 if (NULL == loginUser) {
819 ICO_WRN("homescreen unknown");
823 // if appid equal homescreen
824 if (0 == loginUser->homescreen.compare(appid)) {
825 if (NULL != m_policyMgr) {
826 m_policyMgr->notifyConnected(appid);
830 // vim:set expandtab ts=4 sw=4: