Refactoring homescreen.
[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  * @brief   library to communicate with outer process
11  *
12  * @date    Feb-15-2013
13  */
14
15 #include <sstream>
16 using namespace std;
17
18 #include "CicoSCServer.h"
19 #include "CicoSCCommandParser.h"
20 #include "CicoSCMessage.h"
21 #include "CicoLog.h"
22 #include "ico_syc_error.h"
23 #include "ico_syc_msg_cmd_def.h"
24 #include "CicoSCWindowController.h"
25 #include "CicoSCInputController.h"
26 #include "CicoSCUserManager.h"
27 #include "CicoSCUser.h"
28 #include "CicoSCResourceManager.h"
29
30 class CicoSCUwsHandle
31 {
32 public:
33     CicoSCUwsHandle()
34         : uwsContext(NULL), id(NULL), fd(-1), serviceFlag(false),
35           ecoreFdHandler(NULL), appid("") {}
36     void dump(void) const {
37         ICO_DBG("uwsContext=%08X fd=%d service=%s ecoreFdHandler=%08X appid=%s",
38                 uwsContext, fd, serviceFlag ? "true" : "false",
39                 ecoreFdHandler, appid.c_str());
40     }
41     struct ico_uws_context *uwsContext;
42     void* id;
43     int fd;
44     bool serviceFlag;
45     Ecore_Fd_Handler *ecoreFdHandler;
46     string appid;
47 };
48
49 CicoSCServer* CicoSCServer::ms_myInstance = NULL;
50
51 CicoSCServer::CicoSCServer()
52     : m_uwsContext(NULL), m_windowCtrl(NULL),
53       m_inputCtrl(NULL) , m_userMgr(NULL)
54 {
55 }
56
57 CicoSCServer::~CicoSCServer()
58 {
59 }
60
61 CicoSCServer*
62 CicoSCServer::getInstance(void)
63 {
64         if (NULL == ms_myInstance) {
65                 ms_myInstance = new CicoSCServer();
66         }
67
68         return ms_myInstance;
69 }
70
71 void
72 CicoSCServer::setWindowCtrl(CicoSCWindowController *windowCtrl)
73 {
74     m_windowCtrl = windowCtrl;
75 }
76
77 void
78 CicoSCServer::setInputCtrl(CicoSCInputController *inputCtrl)
79 {
80     m_inputCtrl= inputCtrl;
81 }
82
83 void
84 CicoSCServer::setUserMgr(CicoSCUserManager *userMgr)
85 {
86     m_userMgr = userMgr;
87 }
88
89 //--------------------------------------------------------------------------
90 /**
91  *  @brief   startup server
92  *
93  *  @param [IN] port        websocket port
94  *  @param [IN] protocol    websocket protocol name
95  *  @return result
96  *  @retval ICO_SYC_EOK     success
97  *  @retval ICO_SYC_ENOSYS  error(connection faile)
98  */
99 //--------------------------------------------------------------------------
100 void
101 CicoSCServer::setResourceMgr(CicoSCResourceManager *resourceMgr)
102 {
103     m_resourceMgr = resourceMgr;
104 }
105
106 //--------------------------------------------------------------------------
107 /**
108  *  @brief   startup server
109  *
110  *  @param [IN] port        websocket port
111  *  @param [IN] protocol    websocket protocol name
112  *  @return result
113  *  @retval ICO_SYC_EOK     success
114  *  @retval ICO_SYC_ENOSYS  error(connection faile)
115  */
116 //--------------------------------------------------------------------------
117 int
118 CicoSCServer::startup(int port, const char *protocol)
119 {
120     /* create uir string ":PORT" */
121     stringstream uri;
122     uri << ":" << port;
123
124     /* create context */
125     ICO_DBG("ico_uws_create_context(%s,%s) called.",
126             uri.str().c_str(), protocol);
127     m_uwsContext = ico_uws_create_context(uri.str().c_str(), protocol);
128     if (NULL == m_uwsContext) {
129         ICO_ERR("ico_uws_create_context() failed.");
130         return ICO_SYC_ENOSYS;
131     }
132     ico_uws_service(m_uwsContext);
133
134     /* set callback */
135     int ret = ico_uws_set_event_cb(m_uwsContext, uwsCallback, (void *)this);
136     if (ret != ICO_UWS_ERR_NONE) {
137         ICO_ERR("ico_uws_set_event_cb() failed(%d).", ret);
138         return ICO_SYC_ENOSYS;
139     }
140     ico_uws_service(m_uwsContext);
141
142     return ICO_SYC_EOK;
143 }
144
145 CicoSCUwsHandle*
146 CicoSCServer::findUwsHandler(const struct ico_uws_context *context,
147                              const void *id)
148 {
149         list<CicoSCUwsHandle*>::iterator itr;
150         itr = m_uwsHandlerList.begin();
151         for (; itr != m_uwsHandlerList.end(); ++itr) {
152         ICO_DBG("handle->context=%p handle->id=%p context=%p id=%p",
153                 (*itr)->uwsContext, (*itr)->id, context, id);
154         if (((*itr)->uwsContext == context) &&
155             ((*itr)->id == id)) {
156             return *itr;
157                 }
158     }
159     return NULL;
160 }
161
162 CicoSCUwsHandle*
163 CicoSCServer::findUwsHandler(const Ecore_Fd_Handler *ecoreFdHandler)
164 {
165         list<CicoSCUwsHandle*>::iterator itr;
166         itr = m_uwsHandlerList.begin();
167         for (; itr != m_uwsHandlerList.end(); ++itr) {
168         if ((*itr)->ecoreFdHandler == ecoreFdHandler) {
169             return *itr;
170                 }
171     }
172     return NULL;
173 }
174
175 CicoSCUwsHandle*
176 CicoSCServer::findUwsHandler(const string & appid)
177 {
178         list<CicoSCUwsHandle*>::iterator itr;
179         itr = m_uwsHandlerList.begin();
180         for (; itr != m_uwsHandlerList.end(); ++itr) {
181         ICO_DBG("handle->id=%p handle->appid=%s appid=%s",
182                 (*itr)->id, (*itr)->appid.c_str(), appid.c_str());
183         if ((*itr)->appid == appid) {
184             return *itr;
185                 }
186     }
187     return NULL;
188 }
189
190 void
191 CicoSCServer::addPollFd(CicoSCUwsHandle *handle)
192 {
193     ICO_DBG("CicoSCServer::addPollFd Enter(fd=%d)", handle->fd);
194     Ecore_Fd_Handler_Flags flags = (Ecore_Fd_Handler_Flags)(ECORE_FD_READ | ECORE_FD_ERROR);
195
196     handle->ecoreFdHandler = ecore_main_fd_handler_add(handle->fd, flags,
197                                                        ecoreFdCallback,
198                                                        this, NULL, NULL);
199     ICO_DBG("CicoSCServer::addPollFd Leave");
200 }
201
202 void
203 CicoSCServer::delPollFd(CicoSCUwsHandle *handle)
204 {
205     ICO_DBG("CicoSCServer::delPollFd Enter");
206     ecore_main_fd_handler_del(handle->ecoreFdHandler);
207     handle->ecoreFdHandler = NULL;
208     ICO_DBG("CicoSCServer::delPollFd Enter");
209 }
210
211 Eina_Bool
212 CicoSCServer::ecoreFdCallback(void *data, Ecore_Fd_Handler *handler)
213 {
214     ICO_DBG("CicoSCServer::ecoreFdCallback Enter");
215
216     int fdFlags = 0;
217 #if 0
218     Eina_Bool flag = ecore_main_fd_handler_active_get(handler, ECORE_FD_READ);
219     if (Eina_True == flag) {
220         fdFlags |= ECORE_FD_READ;
221     }
222
223     Eina_Bool flag = ecore_main_fd_handler_active_get(handler, ECORE_FD_ERROR);
224     if (Eina_True == flag) {
225         fdFlags |= ECORE_FD_ERROR;
226     }
227
228     Eina_Bool flag = ecore_main_fd_handler_active_get(handler, ECORE_FD_WRITE);
229     if (Eina_True == flag) {
230         fdFlags |= ECORE_FD_WRITE;
231     }
232 #endif
233
234     CicoSCUwsHandle *handle = NULL;
235     handle =  static_cast<CicoSCServer*>(data)->findUwsHandler(handler);
236     if (NULL != handle) {
237         static_cast<CicoSCServer*>(data)->dispatch(handle, fdFlags);
238     }
239
240     ICO_DBG("CicoSCServer::ecoreFdCallback Leave");
241     return ECORE_CALLBACK_RENEW;
242 }
243
244 void
245 CicoSCServer::dispatch(const CicoSCUwsHandle *handle, int flags)
246 {
247     ICO_DBG("CicoSCServer::dispatch Enter");
248
249     if (NULL == handle) {
250         ICO_WRN("handle is null");
251         ICO_DBG("CicoSCServer::dispatch Leave");
252         return;
253     }
254     handle->dump(); //TODO
255
256     ico_uws_service(handle->uwsContext);
257
258     list<CicoSCCommand*>::iterator itr;
259     itr = m_recvCmdQueue.begin();
260     while(itr != m_recvCmdQueue.end()) {
261         ICO_DBG("Deque command(0x%08X)", (*itr)->cmdid);
262         CicoSCCommand *cmd = *itr;
263         itr = m_recvCmdQueue.erase(itr);
264         switch (cmd->cmdid & MSG_CMD_TYPE_MASK) {
265         case MSG_CMD_TYPE_WINCTRL:
266             ICO_DBG("command : MSG_CMD_TYPE_WINCTRL");
267             m_windowCtrl->handleCommand(cmd);
268             break;
269         case MSG_CMD_TYPE_INPUTCTRL:
270             ICO_DBG("command : MSG_CMD_TYPE_INPUTCTRL");
271             m_inputCtrl->handleCommand(cmd);
272             break;
273         case MSG_CMD_TYPE_USERMGR:
274             ICO_DBG("command : MSG_CMD_TYPE_USERMGR");
275             m_userMgr->handleCommand(cmd);
276             break;
277         case MSG_CMD_TYPE_RESOURCEMGR:
278             ICO_DBG("command : MSG_CMD_TYPE_RESOURCEMGR");
279             m_resourceMgr->handleCommand(*cmd);
280             break;
281         default:
282             ICO_DBG("command : unknown");
283             break;
284         }
285         delete cmd;
286     }
287
288     if (NULL == handle->ecoreFdHandler) {
289         ICO_ERR("ecoreFdHandler is null");
290         ICO_DBG("CicoSCServer::dispatch Leave");
291         return;
292     }
293
294     Eina_Bool flag = ecore_main_fd_handler_active_get(handle->ecoreFdHandler,
295                                                                                                       ECORE_FD_WRITE);
296     if (EINA_TRUE == flag) {
297         ICO_DBG("start send message");
298         list<CicoSCMessage*>::iterator send_itr;
299         send_itr = m_sendMsgQueue.begin();
300         while (send_itr != m_sendMsgQueue.end()) {
301             ICO_DBG("m_sendMsgQueue.size=%d", m_sendMsgQueue.size());
302             CicoSCMessage* msg = *send_itr;
303             CicoSCUwsHandle *sendHandle = findUwsHandler(msg->getSendToAppid());
304             if (handle != sendHandle) {
305                 ++send_itr;
306                 continue;
307             }
308             send_itr = m_sendMsgQueue.erase(send_itr);
309             ICO_DBG("Deque Message(id=%d)", msg->getId());
310             if ((NULL != sendHandle) && (true == sendHandle->serviceFlag)) {
311                 sendHandle->dump();
312                 ICO_DBG("<<<SEND id=%08X msg=%s",
313                         sendHandle->id, msg->getData());
314                 ICO_DBG("ico_usw_send called.");
315                 ico_uws_send(sendHandle->uwsContext, sendHandle->id,
316                              (unsigned char *)msg->getData(),
317                              strlen(msg->getData()));
318
319                 delete msg;
320
321                 usleep(200);
322             }
323         }
324         ecore_main_fd_handler_active_set(handle->ecoreFdHandler,
325             (Ecore_Fd_Handler_Flags)(ECORE_FD_READ | ECORE_FD_ERROR));
326     }
327
328     ICO_DBG("CicoSCServer::dispatch Leave");
329 }
330
331 int
332 CicoSCServer::sendMessage(const string & appid, CicoSCMessage* msg)
333 {
334     ICO_DBG("CicoSCServer::sendMessage Enter(appid=%s, msg=%s)",
335             appid.c_str(), msg->getData());
336
337     msg->setSendToAppid(appid);
338     ICO_DBG("Enque Message(id=%d)", msg->getId());
339     m_sendMsgQueue.push_back(msg);
340
341     CicoSCUwsHandle *handle = findUwsHandler(appid);
342     if (NULL != handle) {
343                 ecore_main_fd_handler_active_set(handle->ecoreFdHandler,
344                         (Ecore_Fd_Handler_Flags)(ECORE_FD_READ |
345                                                                      ECORE_FD_WRITE |
346                                                                          ECORE_FD_ERROR));
347                 dispatch(handle, 0);
348     }
349
350     ICO_DBG("CicoSCServer::sendMessage Leave(EOK)");
351     return ICO_SYC_EOK;
352 }
353
354 int
355 CicoSCServer::sendMessageToHomeScreen(CicoSCMessage* msg)
356 {
357     const CicoSCUser *loginUser = m_userMgr->getLoginUser();
358     if (NULL == loginUser) {
359         ICO_WRN("homescree unknow");
360         return ICO_SYC_ENOENT;
361     }
362     return sendMessage(loginUser->homescreen, msg);
363 }
364
365 void
366 CicoSCServer::uwsCallbackImpl(const struct ico_uws_context *context,
367                               const ico_uws_evt_e event,
368                               const void *id,
369                               const ico_uws_detail *detail,
370                               void *user_data)
371 {
372     ICO_DBG("CicoSCServer::uwsCallbackImpl Enter");
373
374     // find hanle
375     CicoSCUwsHandle *handle = findUwsHandler(context, id);
376     // If not found handle, create new handle
377     if (NULL == handle) {
378         handle = new CicoSCUwsHandle();
379         m_uwsHandlerList.push_back(handle);
380         handle->uwsContext = (struct ico_uws_context*)context;
381         handle->id = (void*)(id);
382         handle->serviceFlag = false;
383     }
384
385     switch (event) {
386     case ICO_UWS_EVT_OPEN:
387     {
388         ICO_DBG(">>>RECV ICO_UWS_EVT_OPEN(id=%08x)", (int)id); 
389         break;
390     }
391     case ICO_UWS_EVT_CLOSE:
392         ICO_DBG(">>>RECV ICO_UWS_EVT_CLOSE(id=%08x)", (int)id);
393         m_uwsContext = NULL;
394         break;
395     case ICO_UWS_EVT_RECEIVE:
396         {
397         ICO_DBG(">>>RECV ICO_UWS_EVT_RECEIVE(id=%08x, msg=%s, len=%d)", 
398                 (int)id, (char *)detail->_ico_uws_message.recv_data,
399                 detail->_ico_uws_message.recv_len);
400
401         // convert message to command
402         CicoSCCommand *cmd = new CicoSCCommand();
403         CicoSCCommandParser cmdParser;
404         cmdParser.parse((const char*)detail->_ico_uws_message.recv_data, *cmd);
405
406         // update handle appid
407         if (cmd->cmdid == MSG_CMD_SEND_APPID) {
408             if (0 == cmd->appid.length()) {
409                 ICO_WRN("command argument invalid appid null");
410                 break;
411             }
412             handle->appid = cmd->appid;
413             handle->serviceFlag = true;
414             ICO_DBG("handle.appid=%s", handle->appid.c_str());
415     ecore_main_fd_handler_active_set(handle->ecoreFdHandler,
416                                      (Ecore_Fd_Handler_Flags)(ECORE_FD_READ |
417                                      ECORE_FD_WRITE |
418                                      ECORE_FD_ERROR));
419  
420
421             break;
422         }
423         
424         // Enqueue command
425         ICO_DBG("Enque command(0x%08X)", cmd->cmdid);
426         m_recvCmdQueue.push_back(cmd);
427         break;
428         }
429     case ICO_UWS_EVT_ERROR:
430         ICO_DBG(">>>RECV ICO_UWS_EVT_ERROR(id=%08x, err=%d)", 
431                 (int)id, detail->_ico_uws_error.code);
432         break;
433     case ICO_UWS_EVT_ADD_FD:
434         ICO_DBG(">>>RECV ICO_UWS_EVT_ADD_FD(id=%08x, fd=%d)",
435                     (int)id, detail->_ico_uws_fd.fd);
436         handle->fd = detail->_ico_uws_fd.fd;
437         addPollFd(handle);
438
439         break;
440     case ICO_UWS_EVT_DEL_FD:
441         ICO_DBG(">>>RECV ICO_UWS_EVT_DEL_FD(id=%d, fd=%d)",
442                     (int)id, detail->_ico_uws_fd.fd);
443         delPollFd(handle);
444                 delete handle;
445         break;
446     default:
447         break;
448     }
449     ICO_DBG("CicoSCServer::uwsCallbackImpl Leave");
450 }
451
452 /*--------------------------------------------------------------------------*/
453 /*
454  * @brief   callback_uws
455  *          callback function from UWS
456  *
457  * @param[in]   context             context * @param[in]   event               event kinds
458  * @param[in]   id                  client id
459  * @param[in]   detail              event detail
460  * @param[in]   data                user data
461  * @return      none
462  */
463 /*--------------------------------------------------------------------------*/
464 void
465 CicoSCServer::uwsCallback(const struct ico_uws_context *context,
466                            const ico_uws_evt_e event,
467                            const void *id,
468                            const ico_uws_detail *detail,
469                            void *user_data)
470 {
471     ICO_DBG("callback_uws: context=%08x id=%08x", (int)context, (int)id);
472
473         CicoSCServer* server = static_cast<CicoSCServer*>(user_data);
474     server->uwsCallbackImpl(context, event, id, detail, user_data);
475 }
476 // vim:set expandtab ts=4 sw=4: