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)
70 //--------------------------------------------------------------------------
74 //--------------------------------------------------------------------------
75 CicoSCServer::~CicoSCServer()
80 //--------------------------------------------------------------------------
82 * @brief get CicoSCServer instance
84 * @return CicoSCServer instance
86 //--------------------------------------------------------------------------
88 CicoSCServer::getInstance(void)
90 if (NULL == ms_myInstance) {
91 ms_myInstance = new CicoSCServer();
97 //--------------------------------------------------------------------------
99 * @brief set window controller instance
101 * @param [in] windowCtrl controller instance
103 //--------------------------------------------------------------------------
105 CicoSCServer::setWindowCtrl(CicoSCWindowController *windowCtrl)
107 m_windowCtrl = windowCtrl;
110 //--------------------------------------------------------------------------
112 * @brief set input controller instance
114 * @param [in] inputCtrl controller instance
116 //--------------------------------------------------------------------------
118 CicoSCServer::setInputCtrl(CicoSCInputController *inputCtrl)
120 m_inputCtrl= inputCtrl;
123 //--------------------------------------------------------------------------
125 * @brief set user manager
127 * @param [in] userMgr user manager instance
129 //--------------------------------------------------------------------------
131 CicoSCServer::setUserMgr(CicoSCUserManager *userMgr)
136 //--------------------------------------------------------------------------
138 * @brief set resource manager instance
140 * @param [in] resourceMgr resouce manager instance
142 //--------------------------------------------------------------------------
144 CicoSCServer::setResourceMgr(CicoSCResourceManager *resourceMgr)
146 m_resourceMgr = resourceMgr;
149 //--------------------------------------------------------------------------
151 * @brief set policy manager instance
153 * @param [in] policyMgr policy manager instance
155 //--------------------------------------------------------------------------
157 CicoSCServer::setPolicyMgr(CicoSCPolicyManager *policyMgr)
159 m_policyMgr = policyMgr;
162 //--------------------------------------------------------------------------
164 * @brief startup server
166 * @param [in] port websocket port
167 * @param [in] protocol websocket protocol name
169 * @return ICO_SYC_EOK on success, other on error
170 * @retval ICO_SYC_EOK success
171 * @retval ICO_SYC_ENOSYS error(connection fail)
173 //--------------------------------------------------------------------------
175 CicoSCServer::startup(int port, const char *protocol)
177 /* create uir string ":PORT" */
182 ICO_DBG("called: ico_uws_create_context(port=%s protocol=%s)",
183 uri.str().c_str(), protocol);
184 m_uwsContext = ico_uws_create_context(uri.str().c_str(), protocol);
185 if (NULL == m_uwsContext) {
186 ICO_ERR("ico_uws_create_context() failed.");
187 return ICO_SYC_ENOSYS;
189 ico_uws_service(m_uwsContext);
192 int ret = ico_uws_set_event_cb(m_uwsContext, uwsReceiveEventCB,
194 if (ret != ICO_UWS_ERR_NONE) {
195 ICO_ERR("ico_uws_set_event_cb() failed(%d).", ret);
196 return ICO_SYC_ENOSYS;
198 ico_uws_service(m_uwsContext);
203 //--------------------------------------------------------------------------
205 * @brief add poll websocket file destructor
207 * @param [in] handler websocket handler
209 //--------------------------------------------------------------------------
211 CicoSCServer::addPollFd(CicoSCUwsHandler *handler)
213 ICO_DBG("CicoSCServer::addPollFd Enter(fd=%d)", handler->fd);
214 Ecore_Fd_Handler_Flags flags;
215 flags = (Ecore_Fd_Handler_Flags)(ECORE_FD_READ | ECORE_FD_ERROR);
217 handler->ecoreFdHandler = ecore_main_fd_handler_add(handler->fd, flags,
221 ICO_DBG("Enqueue uwsHandler(0x%08x)", handler);
222 m_uwsHandlerList.push_back(handler);
224 ICO_DBG("CicoSCServer::addPollFd Leave");
227 //--------------------------------------------------------------------------
229 * @brief delete poll websocket file destructor
231 * @param [in] handler websocket handler
233 //--------------------------------------------------------------------------
235 CicoSCServer::delPollFd(CicoSCUwsHandler *handler)
237 ICO_DBG("CicoSCServer::delPollFd Enter");
239 ecore_main_fd_handler_del(handler->ecoreFdHandler);
240 handler->ecoreFdHandler = NULL;
242 list<CicoSCUwsHandler*>::iterator itr;
243 itr = m_uwsHandlerList.begin();
244 for (; itr != m_uwsHandlerList.end(); ++itr) {
245 if (*itr == handler) {
246 ICO_DBG("Dequeue uwsHandler(0x%08x)", *itr);
247 m_uwsHandlerList.erase(itr);
253 ICO_DBG("CicoSCServer::delPollFd Enter");
256 //--------------------------------------------------------------------------
258 * @brief dispatch receive message process and send message process
260 * @param [in] handler websocket handler
262 * @return websocket handler instance on find, NULL on not found
264 //--------------------------------------------------------------------------
266 CicoSCServer::dispatch(const CicoSCUwsHandler *handler)
268 // ICO_DBG("CicoSCServer::dispatch Enter(handler=0x%08x)", handler);
270 if (NULL == handler) {
271 ICO_WRN("handler is null");
272 ICO_DBG("CicoSCServer::dispatch Leave");
276 ico_uws_service(handler->uwsContext);
278 // There is a possibility that after calling ico_uws_service function,
279 // the file is deleted. Check whether handler not the disabled.
280 if (false == isExistUwsHandler(handler)) {
281 ICO_DBG("CicoSCServer::dispatch Leave");
285 list<CicoSCCommand*>::iterator itr;
286 itr = m_recvCmdQueue.begin();
287 while(itr != m_recvCmdQueue.end()) {
288 ICO_DBG("Dequeue command(0x%08x)", (*itr)->cmdid);
289 CicoSCCommand *cmd = *itr;
290 itr = m_recvCmdQueue.erase(itr);
291 switch (cmd->cmdid & MSG_CMD_TYPE_MASK) {
292 case MSG_CMD_TYPE_WINCTRL:
293 //ICO_DBG("command : MSG_CMD_TYPE_WINCTRL");
294 m_windowCtrl->handleCommand(cmd);
296 case MSG_CMD_TYPE_INPUTCTRL:
297 //ICO_DBG("command : MSG_CMD_TYPE_INPUTCTRL");
298 m_inputCtrl->handleCommand(cmd);
300 case MSG_CMD_TYPE_USERMGR:
301 //ICO_DBG("command : MSG_CMD_TYPE_USERMGR");
302 m_userMgr->handleCommand(cmd);
304 case MSG_CMD_TYPE_RESOURCEMGR:
305 //ICO_DBG("command : MSG_CMD_TYPE_RESOURCEMGR");
306 m_resourceMgr->handleCommand(*cmd);
308 case MSG_CMD_TYPE_INPUTDEVSETTING:
309 //ICO_DBG("command : MSG_CMD_TYPE_INPUTDEVSETTING");
310 m_inputCtrl->handleCommand(cmd);
313 ICO_WRN("command: Unknown type");
319 if (NULL == handler->ecoreFdHandler) {
320 ICO_ERR("ecoreFdHandler is null");
321 ICO_DBG("CicoSCServer::dispatch Leave");
325 Eina_Bool flag = ecore_main_fd_handler_active_get(handler->ecoreFdHandler,
327 if (EINA_TRUE == flag) {
328 // ICO_DBG("start send message");
329 list<CicoSCMessage*>::iterator send_itr;
330 send_itr = m_sendMsgQueue.begin();
331 while (send_itr != m_sendMsgQueue.end()) {
332 // ICO_DBG("m_sendMsgQueue.size=%d", m_sendMsgQueue.size());
333 CicoSCMessage* msg = *send_itr;
334 CicoSCUwsHandler *sendHandler = findUwsHandler(msg->getSendToAppid());
335 if (handler != sendHandler) {
339 send_itr = m_sendMsgQueue.erase(send_itr);
340 ICO_DBG("Dequeue Message(id=%d)", msg->getId());
341 if ((NULL != sendHandler) && (true == sendHandler->serviceFlag)) {
342 ICO_DBG("<<<SEND appid=%s id=0x%08x msg=%s",
343 sendHandler->appid.c_str(), sendHandler->id, msg->getData());
344 // ICO_DBG("called: ico_usw_send called(context=0x%08x id=0x%08x)",
345 // sendHandler->uwsContext, sendHandler->id);
346 ico_uws_send(sendHandler->uwsContext, sendHandler->id,
347 (unsigned char *)msg->getData(),
348 strlen(msg->getData()));
356 Ecore_Fd_Handler_Flags flags;;
357 flags = (Ecore_Fd_Handler_Flags)(ECORE_FD_READ | ECORE_FD_ERROR);
359 ecore_main_fd_handler_active_set(handler->ecoreFdHandler, flags);
362 // ICO_DBG("CicoSCServer::dispatch Leave");
365 //--------------------------------------------------------------------------
367 * @brief send message to application client
369 * @param [in] appid application id of destination
370 * @param [in] msg message
372 * @return ICO_SYC_EOK on success, other on error
374 //--------------------------------------------------------------------------
376 CicoSCServer::sendMessage(const string & appid, CicoSCMessage* msg)
378 ICO_DBG("CicoSCServer::sendMessage Enter(appid=%s, msg=%s)",
379 appid.c_str(), msg->getData());
381 msg->setSendToAppid(appid);
382 ICO_DBG("Enqueue Message(id=%d)", msg->getId());
383 m_sendMsgQueue.push_back(msg);
385 CicoSCUwsHandler *handler = findUwsHandler(appid);
386 if (NULL != handler) {
387 Ecore_Fd_Handler_Flags flags;
388 flags = (Ecore_Fd_Handler_Flags)(ECORE_FD_READ |
392 ecore_main_fd_handler_active_set(handler->ecoreFdHandler, flags);
397 ICO_DBG("CicoSCServer::sendMessage Leave(EOK)");
401 //--------------------------------------------------------------------------
403 * @brief send message to homescreen
405 * @param [in] msg message
407 * @return ICO_SYC_EOK on success, other on error
409 //--------------------------------------------------------------------------
411 CicoSCServer::sendMessageToHomeScreen(CicoSCMessage* msg)
413 const CicoSCUser *loginUser = m_userMgr->getLoginUser();
414 if (NULL == loginUser) {
415 ICO_WRN("homescreen unknown");
416 return ICO_SYC_ENOENT;
418 return sendMessage(loginUser->homescreen, msg);
421 //--------------------------------------------------------------------------
423 * @brief websocket utility callback function
425 * @param [in] context context
426 * @param [in] event event kinds
427 * @param [in] id client id
428 * @param [in] detail event detail
429 * @param [in] data user data
431 //--------------------------------------------------------------------------
433 CicoSCServer::uwsReceiveEventCB(const struct ico_uws_context *context,
434 const ico_uws_evt_e event,
436 const ico_uws_detail *detail,
439 if (NULL == user_data) {
440 ICO_ERR("user_data is NULL");
444 CicoSCServer* server = static_cast<CicoSCServer*>(user_data);
445 server->receiveEventCB(context, event, id, detail, user_data);
448 //--------------------------------------------------------------------------
450 * @brief ecore file destructor callback fucntion
452 * @param [in] data user data
453 * @param [in] handler ecore file destructor handler
455 * @return ECORE_CALLBACK_RENEW on retry , ECORE_CALLBACK_CANCEL on cancel
457 //--------------------------------------------------------------------------
459 CicoSCServer::ecoreFdCallback(void *data, Ecore_Fd_Handler *ecoreFdhandler)
461 // ICO_DBG("CicoSCServer::ecoreFdCallback Enter");
463 CicoSCUwsHandler *handler = NULL;
464 handler = static_cast<CicoSCServer*>(data)->findUwsHandler(ecoreFdhandler);
465 if (NULL != handler) {
466 static_cast<CicoSCServer*>(data)->dispatch(handler);
469 // ICO_DBG("CicoSCServer::ecoreFdCallback Leave");
470 return ECORE_CALLBACK_RENEW;
473 //--------------------------------------------------------------------------
475 * @brief websocket callback function
477 * @param [in] context websocket context
478 * @param [in] event changed event
479 * @param [in] id source applicatin id
480 * @param [in] detail event detail information
481 * @param [in] user_data user data
483 //--------------------------------------------------------------------------
485 CicoSCServer::receiveEventCB(const struct ico_uws_context *context,
486 const ico_uws_evt_e event,
488 const ico_uws_detail *detail,
491 // ICO_DBG("CicoSCServer::receiveEventCB Enter");
494 CicoSCUwsHandler *handler = findUwsHandler(context, id);
495 // If not found handler, create new handler
496 if (NULL == handler) {
497 handler = new CicoSCUwsHandler();
498 handler->uwsContext = (struct ico_uws_context*)context;
499 handler->id = (void*)(id);
500 handler->serviceFlag = false;
504 case ICO_UWS_EVT_OPEN:
505 ICO_DBG(">>>RECV ICO_UWS_EVT_OPEN(id=0x%08x)", (int)id);
507 case ICO_UWS_EVT_CLOSE:
508 ICO_DBG(">>>RECV ICO_UWS_EVT_CLOSE(id=0x%08x)", (int)id);
510 case ICO_UWS_EVT_RECEIVE:
512 ICO_DBG(">>>RECV ICO_UWS_EVT_RECEIVE(id=0x%08x, msg=%s, len=%d)",
513 (int)id, (char *)detail->_ico_uws_message.recv_data,
514 detail->_ico_uws_message.recv_len);
516 // convert message to command
517 CicoSCCommand *cmd = new CicoSCCommand();
518 cmd->parseMessage((const char*)detail->_ico_uws_message.recv_data);
520 // update handler appid
521 if (cmd->cmdid == MSG_CMD_SEND_APPID) {
522 if (0 == cmd->appid.length()) {
523 ICO_WRN("command argument invalid appid null");
526 handler->appid = cmd->appid;
527 handler->serviceFlag = true;
528 ICO_DBG("handler.appid=%s", handler->appid.c_str());
530 Ecore_Fd_Handler_Flags flags;
531 flags = (Ecore_Fd_Handler_Flags)(ECORE_FD_READ |
535 ecore_main_fd_handler_active_set(handler->ecoreFdHandler, flags);
537 notifyConnected(handler->appid);
542 ICO_DBG("Enqueue command(0x%08x)", cmd->cmdid);
543 m_recvCmdQueue.push_back(cmd);
546 case ICO_UWS_EVT_ERROR:
547 ICO_DBG(">>>RECV ICO_UWS_EVT_ERROR(id=0x%08x, err=%d)",
548 (int)id, detail->_ico_uws_error.code);
550 case ICO_UWS_EVT_ADD_FD:
551 ICO_DBG(">>>RECV ICO_UWS_EVT_ADD_FD(id=0x%08x, fd=%d)",
552 (int)id, detail->_ico_uws_fd.fd);
553 handler->fd = detail->_ico_uws_fd.fd;
556 case ICO_UWS_EVT_DEL_FD:
557 ICO_DBG(">>>RECV ICO_UWS_EVT_DEL_FD(id=0x%08x, fd=%d)",
558 (int)id, detail->_ico_uws_fd.fd);
564 // ICO_DBG("CicoSCServer::receiveEventCB Leave");
567 //--------------------------------------------------------------------------
569 * @brief find websocket handler by context and id
571 * @param [in] context websocket context
574 * @return websocket handler instance on find, NULL on not found
576 //--------------------------------------------------------------------------
578 CicoSCServer::findUwsHandler(const struct ico_uws_context *context,
581 list<CicoSCUwsHandler*>::iterator itr;
582 itr = m_uwsHandlerList.begin();
583 for (; itr != m_uwsHandlerList.end(); ++itr) {
584 // ICO_DBG("handler->context=%p handler->id=%p context=%p id=%p",
585 // (*itr)->uwsContext, (*itr)->id, context, id);
586 if (((*itr)->uwsContext == context) &&
587 ((*itr)->id == id)) {
594 //--------------------------------------------------------------------------
596 * @brief find websocket handler by ecore file destructor handler
598 * @param [in] ecoreFdHandler ecore file destructor handler
600 * @return websocket handler instance on find, NULL on not found
602 //--------------------------------------------------------------------------
604 CicoSCServer::findUwsHandler(const Ecore_Fd_Handler *ecoreFdHandler)
606 list<CicoSCUwsHandler*>::iterator itr;
607 itr = m_uwsHandlerList.begin();
608 for (; itr != m_uwsHandlerList.end(); ++itr) {
609 if ((*itr)->ecoreFdHandler == ecoreFdHandler) {
616 //--------------------------------------------------------------------------
618 * @brief find websocket handler by appid
620 * @param [in] addid application id
622 * @return websocket handler instance on find, NULL on not found
624 //--------------------------------------------------------------------------
626 CicoSCServer::findUwsHandler(const string & appid)
628 list<CicoSCUwsHandler*>::iterator itr;
629 itr = m_uwsHandlerList.begin();
630 for (; itr != m_uwsHandlerList.end(); ++itr) {
631 // ICO_DBG("handler->id=%p handler->appid=%s appid=%s",
632 // (*itr)->id, (*itr)->appid.c_str(), appid.c_str());
633 if ((*itr)->appid == appid) {
640 //--------------------------------------------------------------------------
642 * @brief find websocket handler by appid
644 * @param [in] handler websocket handler instance
646 * @return true on exist, false on not exist
648 //--------------------------------------------------------------------------
650 CicoSCServer::isExistUwsHandler(const CicoSCUwsHandler *handler)
652 list<CicoSCUwsHandler*>::iterator itr;
653 itr = m_uwsHandlerList.begin();
654 for (; itr != m_uwsHandlerList.end(); ++itr) {
655 if (*itr == handler) {
662 //--------------------------------------------------------------------------
664 * @brief notify information to homescreen on connected
666 * @param [in] appid application id
668 //--------------------------------------------------------------------------
670 CicoSCServer::notifyConnected(const std::string & appid)
672 const CicoSCUser *loginUser = m_userMgr->getLoginUser();
673 if (NULL == loginUser) {
674 ICO_WRN("homescreen unknown");
678 // if appid equal homescreen
679 if (0 == loginUser->homescreen.compare(appid)) {
680 if (NULL != m_policyMgr) {
681 m_policyMgr->notifyConnected(appid);
685 // vim:set expandtab ts=4 sw=4: