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"
33 class CicoSCUwsHandler
37 : uwsContext(NULL), id(NULL), fd(-1), serviceFlag(false),
38 ecoreFdHandler(NULL), appid("") {}
39 void dump(void) const {
40 ICO_DBG("uwsContext=0x%08x fd=%d service=%s "
41 "ecoreFdHandler=0x%08x appid=%s",
42 uwsContext, fd, serviceFlag ? "true" : "false",
43 ecoreFdHandler, appid.c_str());
45 struct ico_uws_context *uwsContext;
49 Ecore_Fd_Handler *ecoreFdHandler;
53 //==========================================================================
54 // private static variable
55 //==========================================================================
56 CicoSCServer* CicoSCServer::ms_myInstance = NULL;
58 //--------------------------------------------------------------------------
60 * @brief default constructor
62 //--------------------------------------------------------------------------
63 CicoSCServer::CicoSCServer()
64 : m_uwsContext(NULL), m_windowCtrl(NULL),
65 m_inputCtrl(NULL) , m_userMgr(NULL), m_resourceMgr(NULL)
69 //--------------------------------------------------------------------------
73 //--------------------------------------------------------------------------
74 CicoSCServer::~CicoSCServer()
79 //--------------------------------------------------------------------------
81 * @brief get CicoSCServer instance
83 * @return CicoSCServer instance
85 //--------------------------------------------------------------------------
87 CicoSCServer::getInstance(void)
89 if (NULL == ms_myInstance) {
90 ms_myInstance = new CicoSCServer();
96 //--------------------------------------------------------------------------
98 * @brief set window controller instance
100 * @param [in] windowCtrl controller instance
102 //--------------------------------------------------------------------------
104 CicoSCServer::setWindowCtrl(CicoSCWindowController *windowCtrl)
106 m_windowCtrl = windowCtrl;
109 //--------------------------------------------------------------------------
111 * @brief set input controller instance
113 * @param [in] inputCtrl controller instance
115 //--------------------------------------------------------------------------
117 CicoSCServer::setInputCtrl(CicoSCInputController *inputCtrl)
119 m_inputCtrl= inputCtrl;
122 //--------------------------------------------------------------------------
124 * @brief set user manager
126 * @param [in] userMgr user manager instance
128 //--------------------------------------------------------------------------
130 CicoSCServer::setUserMgr(CicoSCUserManager *userMgr)
135 //--------------------------------------------------------------------------
137 * @brief set resource manager instance
139 * @param [in] resourceMgr resouce manager instance
141 //--------------------------------------------------------------------------
143 CicoSCServer::setResourceMgr(CicoSCResourceManager *resourceMgr)
145 m_resourceMgr = resourceMgr;
148 //--------------------------------------------------------------------------
150 * @brief startup server
152 * @param [in] port websocket port
153 * @param [in] protocol websocket protocol name
155 * @return ICO_SYC_EOK on success, other on error
156 * @retval ICO_SYC_EOK success
157 * @retval ICO_SYC_ENOSYS error(connection fail)
159 //--------------------------------------------------------------------------
161 CicoSCServer::startup(int port, const char *protocol)
163 /* create uir string ":PORT" */
168 ICO_DBG("called: ico_uws_create_context(port=%s protocol=%s)",
169 uri.str().c_str(), protocol);
170 m_uwsContext = ico_uws_create_context(uri.str().c_str(), protocol);
171 if (NULL == m_uwsContext) {
172 ICO_ERR("ico_uws_create_context() failed.");
173 return ICO_SYC_ENOSYS;
175 ico_uws_service(m_uwsContext);
178 int ret = ico_uws_set_event_cb(m_uwsContext, uwsReceiveEventCB,
180 if (ret != ICO_UWS_ERR_NONE) {
181 ICO_ERR("ico_uws_set_event_cb() failed(%d).", ret);
182 return ICO_SYC_ENOSYS;
184 ico_uws_service(m_uwsContext);
189 //--------------------------------------------------------------------------
191 * @brief add poll websocket file destructor
193 * @param [in] handler websocket handler
195 //--------------------------------------------------------------------------
197 CicoSCServer::addPollFd(CicoSCUwsHandler *handler)
199 ICO_DBG("CicoSCServer::addPollFd Enter(fd=%d)", handler->fd);
200 Ecore_Fd_Handler_Flags flags;
201 flags = (Ecore_Fd_Handler_Flags)(ECORE_FD_READ | ECORE_FD_ERROR);
203 handler->ecoreFdHandler = ecore_main_fd_handler_add(handler->fd, flags,
207 ICO_DBG("Enqueue uwsHandler(0x%08x)", handler);
208 m_uwsHandlerList.push_back(handler);
210 ICO_DBG("CicoSCServer::addPollFd Leave");
213 //--------------------------------------------------------------------------
215 * @brief delete poll websocket file destructor
217 * @param [in] handler websocket handler
219 //--------------------------------------------------------------------------
221 CicoSCServer::delPollFd(CicoSCUwsHandler *handler)
223 ICO_DBG("CicoSCServer::delPollFd Enter");
225 ecore_main_fd_handler_del(handler->ecoreFdHandler);
226 handler->ecoreFdHandler = NULL;
228 list<CicoSCUwsHandler*>::iterator itr;
229 itr = m_uwsHandlerList.begin();
230 for (; itr != m_uwsHandlerList.end(); ++itr) {
231 if (*itr == handler) {
232 ICO_DBG("Dequeue uwsHandler(0x%08x)", *itr);
233 m_uwsHandlerList.erase(itr);
239 ICO_DBG("CicoSCServer::delPollFd Enter");
242 //--------------------------------------------------------------------------
244 * @brief dispatch receive message process and send message process
246 * @param [in] handler websocket handler
248 * @return websocket handler instance on find, NULL on not found
250 //--------------------------------------------------------------------------
252 CicoSCServer::dispatch(const CicoSCUwsHandler *handler)
254 ICO_DBG("CicoSCServer::dispatch Enter(handler=0x%08x)", handler);
256 if (NULL == handler) {
257 ICO_WRN("handler is null");
258 ICO_DBG("CicoSCServer::dispatch Leave");
262 ico_uws_service(handler->uwsContext);
264 // There is a possibility that after calling ico_uws_service function,
265 // the file is deleted. Check whether handler not the disabled.
266 if (false == isExistUwsHandler(handler)) {
267 ICO_DBG("CicoSCServer::dispatch Leave");
271 list<CicoSCCommand*>::iterator itr;
272 itr = m_recvCmdQueue.begin();
273 while(itr != m_recvCmdQueue.end()) {
274 ICO_DBG("Dequeue command(0x%08x)", (*itr)->cmdid);
275 CicoSCCommand *cmd = *itr;
276 itr = m_recvCmdQueue.erase(itr);
277 switch (cmd->cmdid & MSG_CMD_TYPE_MASK) {
278 case MSG_CMD_TYPE_WINCTRL:
279 //ICO_DBG("command : MSG_CMD_TYPE_WINCTRL");
280 m_windowCtrl->handleCommand(cmd);
282 case MSG_CMD_TYPE_INPUTCTRL:
283 //ICO_DBG("command : MSG_CMD_TYPE_INPUTCTRL");
284 m_inputCtrl->handleCommand(cmd);
286 case MSG_CMD_TYPE_USERMGR:
287 //ICO_DBG("command : MSG_CMD_TYPE_USERMGR");
288 m_userMgr->handleCommand(cmd);
290 case MSG_CMD_TYPE_RESOURCEMGR:
291 //ICO_DBG("command : MSG_CMD_TYPE_RESOURCEMGR");
292 m_resourceMgr->handleCommand(*cmd);
294 case MSG_CMD_TYPE_INPUTDEVSETTING:
295 //ICO_DBG("command : MSG_CMD_TYPE_INPUTDEVSETTING");
296 m_inputCtrl->handleCommand(cmd);
299 ICO_WRN("command: Unknown type");
305 if (NULL == handler->ecoreFdHandler) {
306 ICO_ERR("ecoreFdHandler is null");
307 ICO_DBG("CicoSCServer::dispatch Leave");
311 Eina_Bool flag = ecore_main_fd_handler_active_get(handler->ecoreFdHandler,
313 if (EINA_TRUE == flag) {
314 ICO_DBG("start send message");
315 list<CicoSCMessage*>::iterator send_itr;
316 send_itr = m_sendMsgQueue.begin();
317 while (send_itr != m_sendMsgQueue.end()) {
318 ICO_DBG("m_sendMsgQueue.size=%d", m_sendMsgQueue.size());
319 CicoSCMessage* msg = *send_itr;
320 CicoSCUwsHandler *sendHandler = findUwsHandler(msg->getSendToAppid());
321 if (handler != sendHandler) {
325 send_itr = m_sendMsgQueue.erase(send_itr);
326 ICO_DBG("Dequeue Message(id=%d)", msg->getId());
327 if ((NULL != sendHandler) && (true == sendHandler->serviceFlag)) {
328 ICO_DBG("<<<SEND appid=%s id=0x%08x msg=%s",
329 sendHandler->appid.c_str(), sendHandler->id, msg->getData());
330 ICO_DBG("called: ico_usw_send called(context=0x%08x id=0x%08x)",
331 sendHandler->uwsContext, sendHandler->id);
332 ico_uws_send(sendHandler->uwsContext, sendHandler->id,
333 (unsigned char *)msg->getData(),
334 strlen(msg->getData()));
342 Ecore_Fd_Handler_Flags flags;;
343 flags = (Ecore_Fd_Handler_Flags)(ECORE_FD_READ | ECORE_FD_ERROR);
345 ecore_main_fd_handler_active_set(handler->ecoreFdHandler, flags);
348 ICO_DBG("CicoSCServer::dispatch Leave");
351 //--------------------------------------------------------------------------
353 * @brief send message to application client
355 * @param [in] appid application id of destination
356 * @param [in] msg message
358 * @return ICO_SYC_EOK on success, other on error
360 //--------------------------------------------------------------------------
362 CicoSCServer::sendMessage(const string & appid, CicoSCMessage* msg)
364 ICO_DBG("CicoSCServer::sendMessage Enter(appid=%s, msg=%s)",
365 appid.c_str(), msg->getData());
367 msg->setSendToAppid(appid);
368 ICO_DBG("Enqueue Message(id=%d)", msg->getId());
369 m_sendMsgQueue.push_back(msg);
371 CicoSCUwsHandler *handler = findUwsHandler(appid);
372 if (NULL != handler) {
373 Ecore_Fd_Handler_Flags flags;
374 flags = (Ecore_Fd_Handler_Flags)(ECORE_FD_READ |
378 ecore_main_fd_handler_active_set(handler->ecoreFdHandler, flags);
383 ICO_DBG("CicoSCServer::sendMessage Leave(EOK)");
387 //--------------------------------------------------------------------------
389 * @brief send message to homescreen
391 * @param [in] msg message
393 * @return ICO_SYC_EOK on success, other on error
395 //--------------------------------------------------------------------------
397 CicoSCServer::sendMessageToHomeScreen(CicoSCMessage* msg)
399 const CicoSCUser *loginUser = m_userMgr->getLoginUser();
400 if (NULL == loginUser) {
401 ICO_WRN("homescreen unknown");
402 return ICO_SYC_ENOENT;
404 return sendMessage(loginUser->homescreen, msg);
407 //--------------------------------------------------------------------------
409 * @brief websocket utility callback function
411 * @param [in] context context
412 * @param [in] event event kinds
413 * @param [in] id client id
414 * @param [in] detail event detail
415 * @param [in] data user data
417 //--------------------------------------------------------------------------
419 CicoSCServer::uwsReceiveEventCB(const struct ico_uws_context *context,
420 const ico_uws_evt_e event,
422 const ico_uws_detail *detail,
425 if (NULL == user_data) {
426 ICO_ERR("user_data is NULL");
430 CicoSCServer* server = static_cast<CicoSCServer*>(user_data);
431 server->receiveEventCB(context, event, id, detail, user_data);
434 //--------------------------------------------------------------------------
436 * @brief ecore file destructor callback fucntion
438 * @param [in] data user data
439 * @param [in] handler ecore file destructor handler
441 * @return ECORE_CALLBACK_RENEW on retry , ECORE_CALLBACK_CANCEL on cancel
443 //--------------------------------------------------------------------------
445 CicoSCServer::ecoreFdCallback(void *data, Ecore_Fd_Handler *ecoreFdhandler)
447 ICO_DBG("CicoSCServer::ecoreFdCallback Enter");
449 CicoSCUwsHandler *handler = NULL;
450 handler = static_cast<CicoSCServer*>(data)->findUwsHandler(ecoreFdhandler);
451 if (NULL != handler) {
452 static_cast<CicoSCServer*>(data)->dispatch(handler);
455 ICO_DBG("CicoSCServer::ecoreFdCallback Leave");
456 return ECORE_CALLBACK_RENEW;
459 //--------------------------------------------------------------------------
461 * @brief websocket callback function
463 * @param [in] context websocket context
464 * @param [in] event changed event
465 * @param [in] id source applicatin id
466 * @param [in] detail event detail information
467 * @param [in] user_data user data
469 //--------------------------------------------------------------------------
471 CicoSCServer::receiveEventCB(const struct ico_uws_context *context,
472 const ico_uws_evt_e event,
474 const ico_uws_detail *detail,
477 ICO_DBG("CicoSCServer::receiveEventCB Enter");
480 CicoSCUwsHandler *handler = findUwsHandler(context, id);
481 // If not found handler, create new handler
482 if (NULL == handler) {
483 handler = new CicoSCUwsHandler();
484 handler->uwsContext = (struct ico_uws_context*)context;
485 handler->id = (void*)(id);
486 handler->serviceFlag = false;
490 case ICO_UWS_EVT_OPEN:
491 ICO_DBG(">>>RECV ICO_UWS_EVT_OPEN(id=0x%08x)", (int)id);
493 case ICO_UWS_EVT_CLOSE:
494 ICO_DBG(">>>RECV ICO_UWS_EVT_CLOSE(id=0x%08x)", (int)id);
496 case ICO_UWS_EVT_RECEIVE:
498 ICO_DBG(">>>RECV ICO_UWS_EVT_RECEIVE(id=0x%08x, msg=%s, len=%d)",
499 (int)id, (char *)detail->_ico_uws_message.recv_data,
500 detail->_ico_uws_message.recv_len);
502 // convert message to command
503 CicoSCCommand *cmd = new CicoSCCommand();
504 cmd->parseMessage((const char*)detail->_ico_uws_message.recv_data);
506 // update handler appid
507 if (cmd->cmdid == MSG_CMD_SEND_APPID) {
508 if (0 == cmd->appid.length()) {
509 ICO_WRN("command argument invalid appid null");
512 handler->appid = cmd->appid;
513 handler->serviceFlag = true;
514 ICO_DBG("handler.appid=%s", handler->appid.c_str());
516 Ecore_Fd_Handler_Flags flags;
517 flags = (Ecore_Fd_Handler_Flags)(ECORE_FD_READ |
521 ecore_main_fd_handler_active_set(handler->ecoreFdHandler, flags);
527 ICO_DBG("Enqueue command(0x%08x)", cmd->cmdid);
528 m_recvCmdQueue.push_back(cmd);
531 case ICO_UWS_EVT_ERROR:
532 ICO_DBG(">>>RECV ICO_UWS_EVT_ERROR(id=0x%08x, err=%d)",
533 (int)id, detail->_ico_uws_error.code);
535 case ICO_UWS_EVT_ADD_FD:
536 ICO_DBG(">>>RECV ICO_UWS_EVT_ADD_FD(id=0x%08x, fd=%d)",
537 (int)id, detail->_ico_uws_fd.fd);
538 handler->fd = detail->_ico_uws_fd.fd;
541 case ICO_UWS_EVT_DEL_FD:
542 ICO_DBG(">>>RECV ICO_UWS_EVT_DEL_FD(id=0x%08x, fd=%d)",
543 (int)id, detail->_ico_uws_fd.fd);
549 ICO_DBG("CicoSCServer::receiveEventCB Leave");
552 //--------------------------------------------------------------------------
554 * @brief find websocket handler by context and id
556 * @param [in] context websocket context
559 * @return websocket handler instance on find, NULL on not found
561 //--------------------------------------------------------------------------
563 CicoSCServer::findUwsHandler(const struct ico_uws_context *context,
566 list<CicoSCUwsHandler*>::iterator itr;
567 itr = m_uwsHandlerList.begin();
568 for (; itr != m_uwsHandlerList.end(); ++itr) {
569 ICO_DBG("handler->context=%p handler->id=%p context=%p id=%p",
570 (*itr)->uwsContext, (*itr)->id, context, id);
571 if (((*itr)->uwsContext == context) &&
572 ((*itr)->id == id)) {
579 //--------------------------------------------------------------------------
581 * @brief find websocket handler by ecore file destructor handler
583 * @param [in] ecoreFdHandler ecore file destructor handler
585 * @return websocket handler instance on find, NULL on not found
587 //--------------------------------------------------------------------------
589 CicoSCServer::findUwsHandler(const Ecore_Fd_Handler *ecoreFdHandler)
591 list<CicoSCUwsHandler*>::iterator itr;
592 itr = m_uwsHandlerList.begin();
593 for (; itr != m_uwsHandlerList.end(); ++itr) {
594 if ((*itr)->ecoreFdHandler == ecoreFdHandler) {
601 //--------------------------------------------------------------------------
603 * @brief find websocket handler by appid
605 * @param [in] addid application id
607 * @return websocket handler instance on find, NULL on not found
609 //--------------------------------------------------------------------------
611 CicoSCServer::findUwsHandler(const string & appid)
613 list<CicoSCUwsHandler*>::iterator itr;
614 itr = m_uwsHandlerList.begin();
615 for (; itr != m_uwsHandlerList.end(); ++itr) {
616 ICO_DBG("handler->id=%p handler->appid=%s appid=%s",
617 (*itr)->id, (*itr)->appid.c_str(), appid.c_str());
618 if ((*itr)->appid == appid) {
625 //--------------------------------------------------------------------------
627 * @brief find websocket handler by appid
629 * @param [in] handler websocket handler instance
631 * @return true on exist, false on not exist
633 //--------------------------------------------------------------------------
635 CicoSCServer::isExistUwsHandler(const CicoSCUwsHandler *handler)
637 list<CicoSCUwsHandler*>::iterator itr;
638 itr = m_uwsHandlerList.begin();
639 for (; itr != m_uwsHandlerList.end(); ++itr) {
640 if (*itr == handler) {
646 // vim:set expandtab ts=4 sw=4: