Additional functions of policy and resource management.
[profile/ivi/ico-uxf-homescreen.git] / lib / system-controller / CicoSCServer.cpp
1 /*
2  * Copyright (c) 2013, TOYOTA MOTOR CORPORATION.
3  *
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
7  *
8  */
9
10 //==========================================================================
11 /**
12  *  @file   CicoSCServer.cpp
13  *
14  *  @brief  This file implementation of CicoSCServer class
15  */
16 //==========================================================================
17
18 #include <sstream>
19 using namespace std;
20
21 #include "CicoSCServer.h"
22 #include "CicoSCCommand.h"
23 #include "CicoSCMessage.h"
24 #include "CicoLog.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
33 class CicoSCUwsHandler
34 {
35 public:
36     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());
44     }
45     struct ico_uws_context *uwsContext;
46     void*  id;
47     int    fd;
48     bool   serviceFlag;
49     Ecore_Fd_Handler *ecoreFdHandler;
50     string appid;
51 };
52
53 //==========================================================================    
54 //  private static variable
55 //==========================================================================    
56 CicoSCServer* CicoSCServer::ms_myInstance = NULL;
57
58 //--------------------------------------------------------------------------
59 /**
60  *  @brief  default constructor
61  */
62 //--------------------------------------------------------------------------
63 CicoSCServer::CicoSCServer()
64     : m_uwsContext(NULL), m_windowCtrl(NULL),
65       m_inputCtrl(NULL) , m_userMgr(NULL), m_resourceMgr(NULL)
66 {
67 }
68
69 //--------------------------------------------------------------------------
70 /**
71  *  @brief  destructor
72  */
73 //--------------------------------------------------------------------------
74 CicoSCServer::~CicoSCServer()
75 {
76     // TODO
77 }
78
79 //--------------------------------------------------------------------------
80 /**
81  *  @brief   get CicoSCServer instance
82  *
83  *  @return CicoSCServer instance
84  */
85 //--------------------------------------------------------------------------
86 CicoSCServer*
87 CicoSCServer::getInstance(void)
88 {
89     if (NULL == ms_myInstance) {
90         ms_myInstance = new CicoSCServer();
91     }
92
93     return ms_myInstance;
94 }
95
96 //--------------------------------------------------------------------------
97 /**
98  *  @brief   set window controller instance
99  *
100  *  @param [in] windowCtrl  controller instance
101  */
102 //--------------------------------------------------------------------------
103 void
104 CicoSCServer::setWindowCtrl(CicoSCWindowController *windowCtrl)
105 {
106     m_windowCtrl = windowCtrl;
107 }
108
109 //--------------------------------------------------------------------------
110 /**
111  *  @brief   set input controller instance
112  *
113  *  @param [in] inputCtrl   controller instance
114  */
115 //--------------------------------------------------------------------------
116 void
117 CicoSCServer::setInputCtrl(CicoSCInputController *inputCtrl)
118 {
119     m_inputCtrl= inputCtrl;
120 }
121
122 //--------------------------------------------------------------------------
123 /**
124  *  @brief   set user manager
125  *
126  *  @param [in] userMgr     user manager instance
127  */
128 //--------------------------------------------------------------------------
129 void
130 CicoSCServer::setUserMgr(CicoSCUserManager *userMgr)
131 {
132     m_userMgr = userMgr;
133 }
134
135 //--------------------------------------------------------------------------
136 /**
137  *  @brief   set resource manager instance
138  *
139  *  @param [in] resourceMgr resouce manager instance
140  */
141 //--------------------------------------------------------------------------
142 void
143 CicoSCServer::setResourceMgr(CicoSCResourceManager *resourceMgr)
144 {
145     m_resourceMgr = resourceMgr;
146 }
147
148 //--------------------------------------------------------------------------
149 /**
150  *  @brief   startup server
151  *
152  *  @param [in] port        websocket port
153  *  @param [in] protocol    websocket protocol name
154  *
155  *  @return ICO_SYC_EOK on success, other on error
156  *  @retval ICO_SYC_EOK     success
157  *  @retval ICO_SYC_ENOSYS  error(connection fail)
158  */
159 //--------------------------------------------------------------------------
160 int
161 CicoSCServer::startup(int port, const char *protocol)
162 {
163     /* create uir string ":PORT" */
164     stringstream uri;
165     uri << ":" << port;
166
167     /* create context */
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;
174     }
175     ico_uws_service(m_uwsContext);
176
177     /* set callback */
178     int ret = ico_uws_set_event_cb(m_uwsContext, uwsReceiveEventCB,
179                                    (void *)this);
180     if (ret != ICO_UWS_ERR_NONE) {
181         ICO_ERR("ico_uws_set_event_cb() failed(%d).", ret);
182         return ICO_SYC_ENOSYS;
183     }
184     ico_uws_service(m_uwsContext);
185
186     return ICO_SYC_EOK;
187 }
188
189 //--------------------------------------------------------------------------
190 /**
191  *  @brief   add poll websocket file destructor
192  *
193  *  @param [in] handler  websocket handler
194  */
195 //--------------------------------------------------------------------------
196 void
197 CicoSCServer::addPollFd(CicoSCUwsHandler *handler)
198 {
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);
202
203     handler->ecoreFdHandler = ecore_main_fd_handler_add(handler->fd, flags,
204                                                        ecoreFdCallback,
205                                                        this, NULL, NULL);
206
207     ICO_DBG("Enqueue uwsHandler(0x%08x)", handler);
208     m_uwsHandlerList.push_back(handler);
209
210     ICO_DBG("CicoSCServer::addPollFd Leave");
211 }
212
213 //--------------------------------------------------------------------------
214 /**
215  *  @brief   delete poll websocket file destructor
216  *
217  *  @param [in] handler  websocket handler
218  */
219 //--------------------------------------------------------------------------
220 void
221 CicoSCServer::delPollFd(CicoSCUwsHandler *handler)
222 {
223     ICO_DBG("CicoSCServer::delPollFd Enter");
224
225     ecore_main_fd_handler_del(handler->ecoreFdHandler);
226     handler->ecoreFdHandler = NULL;
227
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);
234             break;
235         }
236     }
237     delete handler;
238
239     ICO_DBG("CicoSCServer::delPollFd Enter");
240 }
241
242 //--------------------------------------------------------------------------
243 /**
244  *  @brief   dispatch receive message process and send message process
245  *
246  *  @param [in] handler  websocket handler
247  *
248  *  @return websocket handler instance on find, NULL on not found
249  */
250 //--------------------------------------------------------------------------
251 void
252 CicoSCServer::dispatch(const CicoSCUwsHandler *handler)
253 {
254     ICO_DBG("CicoSCServer::dispatch Enter(handler=0x%08x)", handler);
255
256     if (NULL == handler) {
257         ICO_WRN("handler is null");
258         ICO_DBG("CicoSCServer::dispatch Leave");
259         return;
260     }
261
262     ico_uws_service(handler->uwsContext);
263
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");
268         return;
269     }
270
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);
281             break;
282         case MSG_CMD_TYPE_INPUTCTRL:
283             //ICO_DBG("command : MSG_CMD_TYPE_INPUTCTRL");
284             m_inputCtrl->handleCommand(cmd);
285             break;
286         case MSG_CMD_TYPE_USERMGR:
287             //ICO_DBG("command : MSG_CMD_TYPE_USERMGR");
288             m_userMgr->handleCommand(cmd);
289             break;
290         case MSG_CMD_TYPE_RESOURCEMGR:
291             //ICO_DBG("command : MSG_CMD_TYPE_RESOURCEMGR");
292             m_resourceMgr->handleCommand(*cmd);
293             break;
294         case MSG_CMD_TYPE_INPUTDEVSETTING:
295             //ICO_DBG("command : MSG_CMD_TYPE_INPUTDEVSETTING");
296             m_inputCtrl->handleCommand(cmd);
297             break;
298         default:
299             ICO_WRN("command: Unknown type");
300             break;
301         }
302         delete cmd;
303     }
304
305     if (NULL == handler->ecoreFdHandler) {
306         ICO_ERR("ecoreFdHandler is null");
307         ICO_DBG("CicoSCServer::dispatch Leave");
308         return;
309     }
310
311     Eina_Bool flag = ecore_main_fd_handler_active_get(handler->ecoreFdHandler,
312                                                       ECORE_FD_WRITE);
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) {
322                 ++send_itr;
323                 continue;
324             }
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()));
335
336                 delete msg;
337
338                 usleep(200);
339             }
340         }
341
342         Ecore_Fd_Handler_Flags flags;;
343         flags = (Ecore_Fd_Handler_Flags)(ECORE_FD_READ | ECORE_FD_ERROR);
344
345         ecore_main_fd_handler_active_set(handler->ecoreFdHandler, flags);
346     }
347
348     ICO_DBG("CicoSCServer::dispatch Leave");
349 }
350
351 //--------------------------------------------------------------------------
352 /**
353  *  @brief   send message to application client
354  *
355  *  @param [in] appid   application id of destination
356  *  @param [in] msg     message
357  *
358  *  @return ICO_SYC_EOK on success, other on error
359  */
360 //--------------------------------------------------------------------------
361 int
362 CicoSCServer::sendMessage(const string & appid, CicoSCMessage* msg)
363 {
364     ICO_DBG("CicoSCServer::sendMessage Enter(appid=%s, msg=%s)",
365             appid.c_str(), msg->getData());
366
367     msg->setSendToAppid(appid);
368     ICO_DBG("Enqueue Message(id=%d)", msg->getId());
369     m_sendMsgQueue.push_back(msg);
370
371     CicoSCUwsHandler *handler = findUwsHandler(appid);
372     if (NULL != handler) {
373         Ecore_Fd_Handler_Flags flags;
374         flags = (Ecore_Fd_Handler_Flags)(ECORE_FD_READ  |
375                                          ECORE_FD_WRITE |
376                                          ECORE_FD_ERROR);
377
378         ecore_main_fd_handler_active_set(handler->ecoreFdHandler, flags);
379
380         dispatch(handler);
381     }
382
383     ICO_DBG("CicoSCServer::sendMessage Leave(EOK)");
384     return ICO_SYC_EOK;
385 }
386
387 //--------------------------------------------------------------------------
388 /**
389  *  @brief   send message to homescreen
390  *
391  *  @param [in] msg     message
392  *
393  *  @return ICO_SYC_EOK on success, other on error
394  */
395 //--------------------------------------------------------------------------
396 int
397 CicoSCServer::sendMessageToHomeScreen(CicoSCMessage* msg)
398 {
399     const CicoSCUser *loginUser = m_userMgr->getLoginUser();
400     if (NULL == loginUser) {
401         ICO_WRN("homescreen unknown");
402         return ICO_SYC_ENOENT;
403     }
404     return sendMessage(loginUser->homescreen, msg);
405 }
406
407 //--------------------------------------------------------------------------
408 /*
409  *  @brief  websocket utility callback function
410  *
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
416  */
417 //--------------------------------------------------------------------------
418 void
419 CicoSCServer::uwsReceiveEventCB(const struct ico_uws_context *context,
420                                 const ico_uws_evt_e event,
421                                 const void *id,
422                                 const ico_uws_detail *detail,
423                                 void *user_data)
424 {
425     if (NULL == user_data) {
426         ICO_ERR("user_data is NULL");
427         return;
428     }
429
430     CicoSCServer* server = static_cast<CicoSCServer*>(user_data);
431     server->receiveEventCB(context, event, id, detail, user_data);
432 }
433
434 //--------------------------------------------------------------------------
435 /**
436  *  @brief   ecore file destructor callback fucntion
437  *
438  *  @param [in] data        user data
439  *  @param [in] handler     ecore file destructor handler
440  *
441  *  @return ECORE_CALLBACK_RENEW on retry , ECORE_CALLBACK_CANCEL on cancel
442  */
443 //--------------------------------------------------------------------------
444 Eina_Bool
445 CicoSCServer::ecoreFdCallback(void *data, Ecore_Fd_Handler *ecoreFdhandler)
446 {
447     ICO_DBG("CicoSCServer::ecoreFdCallback Enter");
448
449     CicoSCUwsHandler *handler = NULL;
450     handler =  static_cast<CicoSCServer*>(data)->findUwsHandler(ecoreFdhandler);
451     if (NULL != handler) {
452         static_cast<CicoSCServer*>(data)->dispatch(handler);
453     }
454
455     ICO_DBG("CicoSCServer::ecoreFdCallback Leave");
456     return ECORE_CALLBACK_RENEW;
457 }
458
459 //--------------------------------------------------------------------------
460 /**
461  *  @brief   websocket callback function
462  *
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
468  */
469 //--------------------------------------------------------------------------
470 void
471 CicoSCServer::receiveEventCB(const struct ico_uws_context *context,
472                              const ico_uws_evt_e          event,
473                              const void                   *id,
474                              const ico_uws_detail         *detail,
475                              void                         *user_data)
476 {
477     ICO_DBG("CicoSCServer::receiveEventCB Enter");
478
479     // find handler
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;
487     }
488
489     switch (event) {
490     case ICO_UWS_EVT_OPEN:
491         ICO_DBG(">>>RECV ICO_UWS_EVT_OPEN(id=0x%08x)", (int)id); 
492         break;
493     case ICO_UWS_EVT_CLOSE:
494         ICO_DBG(">>>RECV ICO_UWS_EVT_CLOSE(id=0x%08x)", (int)id);
495         break;
496     case ICO_UWS_EVT_RECEIVE:
497     {
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);
501
502         // convert message to command
503         CicoSCCommand *cmd = new CicoSCCommand();
504         cmd->parseMessage((const char*)detail->_ico_uws_message.recv_data);
505
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");
510                 break;
511             }
512             handler->appid = cmd->appid;
513             handler->serviceFlag = true;
514             ICO_DBG("handler.appid=%s", handler->appid.c_str());
515
516             Ecore_Fd_Handler_Flags flags;
517             flags = (Ecore_Fd_Handler_Flags)(ECORE_FD_READ  |
518                                              ECORE_FD_WRITE |
519                                              ECORE_FD_ERROR);
520
521             ecore_main_fd_handler_active_set(handler->ecoreFdHandler, flags);
522
523             break;
524         }
525         
526         // Enqueue command
527         ICO_DBG("Enqueue command(0x%08x)", cmd->cmdid);
528         m_recvCmdQueue.push_back(cmd);
529         break;
530     }
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);
534         break;
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;
539         addPollFd(handler);
540         break;
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);
544         delPollFd(handler);
545         break;
546     default:
547         break;
548     }
549     ICO_DBG("CicoSCServer::receiveEventCB Leave");
550 }
551
552 //--------------------------------------------------------------------------
553 /**
554  *  @brief   find websocket handler by context and id
555  *
556  *  @param [in] context     websocket context
557  *  @param [in] id          id
558  *
559  *  @return websocket handler instance on find, NULL on not found
560  */
561 //--------------------------------------------------------------------------
562 CicoSCUwsHandler*
563 CicoSCServer::findUwsHandler(const struct ico_uws_context *context,
564                              const void                   *id)
565 {
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)) {
573             return *itr;
574         }
575     }
576     return NULL;
577 }
578
579 //--------------------------------------------------------------------------
580 /**
581  *  @brief   find websocket handler by ecore file destructor handler
582  *
583  *  @param [in] ecoreFdHandler  ecore file destructor handler
584  *
585  *  @return websocket handler instance on find, NULL on not found
586  */
587 //--------------------------------------------------------------------------
588 CicoSCUwsHandler*
589 CicoSCServer::findUwsHandler(const Ecore_Fd_Handler *ecoreFdHandler)
590 {
591     list<CicoSCUwsHandler*>::iterator itr;
592     itr = m_uwsHandlerList.begin();
593     for (; itr != m_uwsHandlerList.end(); ++itr) {
594         if ((*itr)->ecoreFdHandler == ecoreFdHandler) {
595             return *itr;
596         }
597     }
598     return NULL;
599 }
600
601 //--------------------------------------------------------------------------
602 /**
603  *  @brief   find websocket handler by appid
604  *
605  *  @param [in] addid   application id
606  *
607  *  @return websocket handler instance on find, NULL on not found
608  */
609 //--------------------------------------------------------------------------
610 CicoSCUwsHandler*
611 CicoSCServer::findUwsHandler(const string & appid)
612 {
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) {
619             return *itr;
620         }
621     }
622     return NULL;
623 }
624
625 //--------------------------------------------------------------------------
626 /**
627  *  @brief   find websocket handler by appid
628  *
629  *  @param [in] handler     websocket handler instance
630  *
631  *  @return true on exist, false on not exist
632  */
633 //--------------------------------------------------------------------------
634 bool
635 CicoSCServer::isExistUwsHandler(const CicoSCUwsHandler *handler)
636 {   
637     list<CicoSCUwsHandler*>::iterator itr;
638     itr = m_uwsHandlerList.begin();
639     for (; itr != m_uwsHandlerList.end(); ++itr) {
640         if (*itr == handler) {
641             return true;
642         }
643     }
644     return false;
645 }
646 // vim:set expandtab ts=4 sw=4: