Fixed some RPMlint errors - group name, duplicate files, etc.
[profile/ivi/ico-uxf-homescreen.git] / ico-app-framework / ico_apf_communication.c
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   client library for communicate to AppsController in HomeScreen
11  *
12  * @date    Feb-28-2013
13  */
14
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <unistd.h>
18 #include <getopt.h>
19 #include <string.h>
20 #include <poll.h>
21 #include <sys/time.h>
22 #include <sys/socket.h>
23 #include <netinet/in.h>
24
25 #include <ico_uws.h>
26 #include "ico_apf_private.h"
27 #include "ico_uxf_conf.h"
28
29 /*==============================================================================*/
30 /* define static function prototype                                             */
31 /*==============================================================================*/
32 static ico_apf_com_handle_t *ico_apf_alloc_handle(void);
33 static int ico_apf_com_connect(ico_apf_com_handle_t *handle);
34 static int ico_apf_com_realsend(ico_apf_com_handle_t *handle,
35                                 ico_apf_com_buffer_t *msg);
36 static void ico_apf_callback_uws(const struct ico_uws_context *context,
37                                  const ico_uws_evt_e reason, const void *id,
38                                  const ico_uws_detail *detail, void *user_data);
39 static void ico_apf_put_recvmsg(const int cmd, const int res, const int pid,
40                                 const char *appid, char *msg, const int len,
41                                 ico_apf_com_handle_t *handle);
42 static int ico_apf_poll_fd_add(const int fd, const int flag);
43 static void ico_apf_poll_fd_del(const int fd);
44 static void ico_apf_poll_write_event(ico_apf_com_handle_t *handle, const int write);
45
46 /*==============================================================================*/
47 /* variable & table                                                             */
48 /*==============================================================================*/
49 /* variable that control program name in Linux  */
50 extern const char *program_invocation_name;
51
52 /* application framework control handle */
53 static struct ico_uws_context  *global_uwscontext = NULL;
54 static ico_apf_com_handle_t *handles = NULL;
55 static ico_apf_com_handle_t *freehandles = NULL;
56
57 /* file descriptor controll table       */
58 static ico_apf_com_poll_t       *com_polls = NULL;
59 static ico_apf_com_poll_t       *freecom_polls = NULL;
60 static ico_apf_com_pollfd_cb   ico_apf_pollfd_func = NULL;
61
62 /* global user listener                 */
63 static ico_apf_com_eventlistener    global_listener = NULL;
64 static void                         *global_user_data = NULL;
65
66 /* flag for callback from comminucation */
67 static int      uws_callbacked = 0;
68
69 /* command/event string                 */
70 const char  *ico_apf_cmd_table[] = {
71     ICO_APF_SRESOURCE_STATE_ACQUIRED,       /* acquired         */
72     ICO_APF_SRESOURCE_STATE_DEPRIVED,       /* deprived         */
73     ICO_APF_SRESOURCE_STATE_WAITTING,       /* waitting         */
74     ICO_APF_SRESOURCE_STATE_RELEASED,       /* released         */
75
76     ICO_APF_SRESOURCE_COMMAND_GET,          /* get command      */
77     ICO_APF_SRESOURCE_COMMAND_RELEASE,      /* release command  */
78     ICO_APF_SRESOURCE_COMMAND_ADD,          /* add command      */
79     ICO_APF_SRESOURCE_COMMAND_CHANGE,       /* change command   */
80     ICO_APF_SRESOURCE_COMMAND_DELETE,       /* delete command   */
81
82     ICO_APF_SRESOURCE_REPLY_OK,             /* OK reply         */
83     ICO_APF_SRESOURCE_REPLY_NG,             /* NG reply         */
84     ICO_APF_SRESOURCE_STATE_CONNECTED,      /* connected        */
85     ICO_APF_SRESOURCE_STATE_DISCONNECTED    /* disconnected     */
86 };
87 const char  *ico_apf_res_table[] = {
88     ICO_APF_SRESID_BASIC_SCREEN,            /* basic screen     */
89     ICO_APF_SRESID_INT_SCREEN,              /* interrupt screen */
90     ICO_APF_SRESID_ON_SCREEN,               /* onscreeen        */
91     ICO_APF_SRESID_BASIC_SOUND,             /* basic sound      */
92     ICO_APF_SRESID_INT_SOUND,               /* interrupt sound  */
93     ICO_APF_SRESID_INPUT_DEV                /* input device     */
94 };
95 const char  *ico_apf_sound_table[] = {
96     ICO_APF_SSOUND_COMMAND_MUTEON,          /* mute on          */
97     ICO_APF_SSOUND_COMMAND_MUTEOFF,         /* mute off         */
98     ICO_APF_SSOUND_COMMAND_CANCEL,          /* cancel           */
99     ICO_APF_SSOUND_COMMAND_GETLIST,         /* get stream list  */
100     ICO_APF_SSOUND_COMMAND_FRESH,           /* fresh            */
101     ICO_APF_SSOUND_COMMAND_ALLMUTEON,       /* mute set all stream*/
102     ICO_APF_SSOUND_COMMAND_ALLMUTEOFF,      /* mute reset all stream*/
103     ICO_APF_SSOUND_EVENT_NEW,               /* created new stream*/
104     ICO_APF_SSOUND_EVENT_FREE,              /* destoryed stream */
105     ICO_APF_SSOUND_REPLY_LIST               /* reply of stream list*/
106 };
107
108 /*--------------------------------------------------------------------------*/
109 /**
110  * @brief   ico_apf_com_init_client
111  *          This function connects to AppsController in HomeScreen.
112  *          If you use AppsController's function, you must call this function.
113  *
114  * @param[in]   uri                 connection URI, NULL is host myself
115  * @param[in]   type                connection type
116  * @return      handle address
117  * @retval      handle address      success
118  * @retval      NULL                error(failed connect AppsController)
119  */
120 /*--------------------------------------------------------------------------*/
121 ico_apf_com_handle_t *
122 ico_apf_com_init_client(const char *uri, const int type)
123 {
124     int i;
125     int ret;
126     int port;
127     char* address;
128     ico_apf_com_poll_t *p;
129     ico_apf_com_handle_t *handle;
130     Ico_Uxf_Sys_Config *sysconf;
131     Ico_Uxf_Sys_Config *ifsysconf = (Ico_Uxf_Sys_Config *)0xffffffff;
132     char *port_env;
133     char *host_env;
134
135     apfw_trace("ico_apf_com_init_client: Enter(%s,%d)",
136                 uri ? uri : "(NULL)", type);
137
138     ifsysconf = (Ico_Uxf_Sys_Config *)ico_uxf_ifGetSysConfig();
139
140     if (ifsysconf)  {
141         /* Another module already reads config file                             */
142         /* In this case, you don't release sysconf at finished this function.   */
143         sysconf = (Ico_Uxf_Sys_Config *)ifsysconf;
144     }
145     else    {
146         /* never read a system config                   */
147         sysconf = (Ico_Uxf_Sys_Config *)ico_uxf_getSysConfig();
148     }
149     if (!sysconf)   {
150         apfw_error("ico_apf_com_init_client: Leave(can not read configuration files)");
151         return NULL;
152     }
153
154     /* If URI is host name, find address from config.   */
155     /* If node is a null character string, it regards NULL. */
156     Ico_Uxf_conf_host *phost =
157         (Ico_Uxf_conf_host *) ico_uxf_getSysHostById(ico_uxf_getSysHostByName(uri));
158     if (phost)  {
159         address = phost->address;
160     }
161     else    {
162         /* If don't find host name from config, regards ipaddress is set as node.*/
163         address = (char *)uri;
164     }
165
166     /* environment variable for port & host */
167     if (type == ICO_APF_COM_TYPE_APPSCTL)   {
168         port = sysconf->misc.appscontrollerport;
169         port_env = getenv("ICO_APF_APPSCTL_PORT");
170         host_env = getenv("ICO_APF_APPSCTL_HOST");
171     }
172     else    {
173         port = sysconf->misc.soundpluginport;
174         port_env = getenv("ICO_APF_SOUNDMGR_PORT");
175         host_env = getenv("ICO_APF_SOUNDMGR_HOST");
176     }
177     if (port_env) {
178         i = atoi(port_env);
179         if (i > 0)  port = i;
180     }
181     if (host_env)   {
182         address = host_env;
183     }
184
185     /* get a port number from system configuration(system/system.conf)  */
186     apfw_trace("ico_apf_com_init_client: connect Host=%s Port=%d", address, port);
187
188     handle = handles;
189     while (handle)  {
190         if ((strcmp(handle->ip, address) == 0) &&
191             (handle->port == port) && (handle->type == type))   {
192             break;
193         }
194         handle = handle->next;
195     }
196
197     if (handle) {
198         apfw_trace("ico_apf_com_init_client: Leave(Connected)");
199         return handle;
200     }
201
202     handle = ico_apf_alloc_handle();
203     if (! handle)   {
204         apfw_trace("ico_apf_com_init_client: Leave(No Memory)");
205         return NULL;
206     }
207
208     handle->type = type;
209     handle->port = port;
210     strncpy(handle->ip, address, ICO_APF_RESOURCE_IP_LEN-1);
211     handle->ip[ICO_APF_RESOURCE_IP_LEN-1] = 0;
212
213     /* connect to AppsController            */
214     ret = ico_apf_com_connect(handle);
215
216     if (! ifsysconf)    {
217         ico_uxf_closeSysConfig();
218     }
219
220     if (ret != ICO_APF_RESOURCE_E_NONE) {
221         apfw_error("ico_apf_com_init_client: Leave(RESOURCE_E_INIT_COM_FAILD)");
222         (void) ico_apf_com_term_client(handle);
223         return NULL;
224     }
225
226     /* Try to connection        */
227     ico_apf_com_dispatch(handle);
228
229     /* add poll callback if fd is exist */
230     if (handle->fd > 0) {
231         handle->service_on = 1;
232         (void)ico_apf_poll_fd_add(handle->fd, POLLIN);
233     }
234
235     p = com_polls;
236     while (p)   {
237         if (p->fd == handle->fd)    {
238             p->apf_fd_control = (void *)handle;
239             handle->poll = p;
240         }
241         p = p->next;
242     }
243     apfw_trace("ico_apf_com_init_client: Leave(OK,fd=%d)", handle->fd);
244     return handle;
245 }
246
247 /*--------------------------------------------------------------------------*/
248 /**
249  * @brief   ico_apf_com_init_server
250  *          This function connects to aplicationto in AppsController.
251  *
252  * @param[in]   uri                 my URI, NULL is host myself
253  * @param[in]   type                connection type
254  * @return      handle address
255  * @retval      handle address      success
256  * @retval      NULL                error(failed connect AppsController)
257  */
258 /*--------------------------------------------------------------------------*/
259 ico_apf_com_handle_t *
260 ico_apf_com_init_server(const char *uri, const int type)
261 {
262     int i;
263     int ret;
264     int port;
265     int svrtype;
266     char* address;
267     ico_apf_com_handle_t *handle;
268     Ico_Uxf_Sys_Config *sysconf;
269     Ico_Uxf_Sys_Config *ifsysconf = (Ico_Uxf_Sys_Config *)0xffffffff;
270     char *port_env;
271     char uri_name[32];
272
273     apfw_trace("ico_apf_com_init_server: Enter(%s,%d)",
274                uri ? uri : "(NULL)", type);
275
276     ifsysconf = (Ico_Uxf_Sys_Config *)ico_uxf_ifGetSysConfig();
277
278     if (ifsysconf)  {
279         /* Another module already reads config file                             */
280         /* In this case, you don't release sysconf at finished this function.   */
281         sysconf = (Ico_Uxf_Sys_Config *)ifsysconf;
282     }
283     else    {
284         /* never read a system config                   */
285         sysconf = (Ico_Uxf_Sys_Config *)ico_uxf_getSysConfig();
286     }
287     if (!sysconf)   {
288         apfw_error("ico_apf_com_init_server: Leave(can not read configuration files)");
289         return NULL;
290     }
291
292     /* currently server support only Application Controler  */
293     svrtype = ICO_APF_COM_TYPE_SVR_APPSCTL;
294
295     /* If URI is host name, find address from config.   */
296     /* If node is a null character string, it regards NULL. */
297     Ico_Uxf_conf_host *phost =
298         (Ico_Uxf_conf_host *) ico_uxf_getSysHostById(ico_uxf_getSysHostByName(uri));
299     if (phost)  {
300         address = phost->address;
301     }
302     else    {
303         /* If don't find host name from config, regards ipaddress is set as node.*/
304         address = (char *)uri;
305     }
306
307     /* get a port number from system configuration(system/system.conf)  */
308     port = sysconf->misc.appscontrollerport;
309     apfw_trace("ico_apf_com_init_server: Config, Host=%s Port=%d", address, port);
310
311     /* environment variable for port        */
312     port = sysconf->misc.appscontrollerport;
313     port_env = getenv("ICO_APF_APPSCTL_PORT");
314     if (port_env) {
315         i = atoi(port_env);
316         if (i > 0)  port = i;
317     }
318
319     handle = handles;
320     while (handle)  {
321         if ((strcmp(address, handle->ip) == 0) &&
322             (handle->port == port) && (handle->type == svrtype))    break;
323         handle = handle->next;
324     }
325
326     if (handle) {
327         apfw_trace("ico_apf_com_init_server: Leave(Created)");
328         return handle;
329     }
330
331     handle = ico_apf_alloc_handle();
332     if (! handle)   {
333         apfw_error("ico_apf_com_init_server: Leave(No Memory)");
334         return NULL;
335     }
336
337     handle->type = svrtype;
338     handle->port = port;
339     strncpy(handle->ip, address, ICO_APF_RESOURCE_IP_LEN-1);
340     handle->ip[ICO_APF_RESOURCE_IP_LEN-1] = 0;
341
342     /* connect to AppsController            */
343     snprintf(uri_name, sizeof(uri_name), ":%d", port);
344     handle->uws_context = ico_uws_create_context(uri_name, ICO_PROTOCOL_APPSCONTROLLER);
345
346     if (! handle->uws_context)  {
347         apfw_error("ico_apf_com_init_server: Leave(ico_uws_create_context create Error)");
348         (void) ico_apf_com_term_server(handle);
349         return NULL;
350     }
351     apfw_trace("ico_apf_com_init_server: create server context 0x%08x",
352                (int)handle->uws_context);
353
354     ret = ico_uws_set_event_cb(handle->uws_context, ico_apf_callback_uws, (void *)handle);
355     if (ret != ICO_UWS_ERR_NONE)    {
356         apfw_error("co_apf_com_init_server: ico_uws_set_event_cb Error(%d)", ret);
357         apfw_trace("ico_apf_com_init_server: Leave(ERR)");
358         return NULL;
359     }
360
361     global_uwscontext = handle->uws_context;
362
363     ico_apf_com_dispatch(handle);
364
365     apfw_trace("ico_apf_com_init_server: Leave(OK)");
366     return handle;
367 }
368
369 /*--------------------------------------------------------------------------*/
370 /**
371  * @brief   ico_apf_alloc_handle
372  *          Allocate ccommunication handle.
373  *
374  * @param       none
375  * @return      handle address
376  * @retval      addres      success, return handle address
377  * @retval      NULL        error(no memory)
378  */
379 /*--------------------------------------------------------------------------*/
380 static ico_apf_com_handle_t *
381 ico_apf_alloc_handle(void)
382 {
383     ico_apf_com_handle_t *handle;
384     int     i;
385
386     if (! freehandles)  {
387
388         handle = malloc(sizeof(ico_apf_com_handle_t));
389         if (! handle)   {
390             return NULL;
391         }
392         memset(handle, 0, sizeof(ico_apf_com_handle_t));
393
394         /* Queue buffers initialize.                */
395         for (i = 0; i < ICO_APF_RESOURCE_WSOCK_BUFR; i++)   {
396             handle->rbuf[i] = calloc(sizeof(ico_apf_com_buffer_t), 1);
397             if (! handle->rbuf[i])  {
398                 return NULL;
399             }
400         }
401         for (i = 0; i < ICO_APF_RESOURCE_WSOCK_BUFS; i++)   {
402             handle->sbuf[i] = calloc(sizeof(ico_apf_com_buffer_t), 1);
403             if (! handle->sbuf[i])  {
404                 return NULL;
405             }
406         }
407     }
408     else    {
409         handle = freehandles;
410         freehandles = freehandles->next;
411         handle->next = NULL;
412         handle->fd = 0;
413         handle->pid = 0;
414         handle->uws_context = NULL;
415         handle->uws_id = NULL;
416         handle->service_on = 0;
417         handle->retry = 0;
418         handle->shead = 0;
419         handle->stail = 0;
420         handle->rhead = 0;
421         handle->rtail = 0;
422         handle->listener = NULL;
423         handle->user_data = NULL;
424         handle->type = 0;
425     }
426
427     if (handles)    {
428         handle->next = handles;
429     }
430     handles = handle;
431
432     return handle;
433 }
434
435 /*--------------------------------------------------------------------------*/
436 /**
437  * @brief   ico_apf_com_connect
438  *          This function connects to AppsController.
439  *
440  * @param[in]   handle          Communication handle
441  * @return      result status
442  * @retval      ICO_APF_RESOURCE_E_NONE             success
443  * @retval      ICO_APF_RESOURCE_E_INIT_COM_FAILD   error(connect failed)
444  */
445 /*--------------------------------------------------------------------------*/
446 static int
447 ico_apf_com_connect(ico_apf_com_handle_t *handle)
448 {
449     int     ret;
450     char    *protocol;
451     char    uri_name[64];
452
453     apfw_trace("ico_apf_com_connect: Enter(type=%d)", handle->type);
454
455     snprintf(uri_name, sizeof(uri_name), "ws://%s:%d", handle->ip, handle->port);
456     if ((handle->type & ICO_APF_COM_TYPE_CONNECTION) == ICO_APF_COM_TYPE_SOUNDMGR)
457         protocol = ICO_PROTOCOL_MULTISOUNDMANAGER;
458     else
459         protocol = ICO_PROTOCOL_APPSCONTROLLER;
460     handle->uws_context = ico_uws_create_context(uri_name, protocol);
461
462     if (handle->uws_context == NULL) {
463         apfw_error("ico_apf_com_connect: ico_uws_create_context Error(%s,%s)",
464                    uri_name, protocol);
465         apfw_trace("ico_apf_com_connect: Leave(RESOURCE_E_INIT_COM_FAILD)");
466         return ICO_APF_RESOURCE_E_INIT_COM_FAILD;
467     }
468     apfw_trace("ico_apf_com_connect: create client context 0x%08x",
469                (int)handle->uws_context);
470
471     ret = ico_uws_set_event_cb(handle->uws_context, ico_apf_callback_uws, (void *)handle);
472     if (ret != ICO_UWS_ERR_NONE)    {
473         apfw_error("ico_apf_com_connect: ico_uws_set_event_cb Error(%d)", ret);
474         apfw_trace("ico_apf_com_connect: Leave(RESOURCE_E_INIT_COM_FAILD)");
475         return ICO_APF_RESOURCE_E_INIT_COM_FAILD;
476     }
477
478     /* dispatch for connection  */
479     ico_apf_com_dispatch(handle);
480
481     if (handle->fd > 0) {
482         (void)ico_apf_poll_fd_add(handle->fd, POLLIN|POLLOUT);
483     }
484
485     apfw_trace("ico_apf_com_connect: Leave(OK, fd=%d)", handle->fd);
486     return ICO_APF_RESOURCE_E_NONE;
487 }
488
489 /*--------------------------------------------------------------------------*/
490 /**
491  * @brief   ico_apf_com_isconnected
492  *          return a connection status with AppsController
493  *
494  * @param[in]   handle      AppsController's handle
495  * @return      connection status
496  * @retval      1           connect
497  * @retval      0           not connetc
498  */
499 /*--------------------------------------------------------------------------*/
500 int
501 ico_apf_com_isconnected(ico_apf_com_handle_t *handle)
502 {
503     return((handle != NULL) && (handle->service_on != 0));
504 }
505
506 /*--------------------------------------------------------------------------*/
507 /**
508  * @brief   ico_apf_com_dispatch
509  *          The accumulated transmitted and received data is processed.
510  *          Connecting AppsController program must call this function.
511  *
512  * @param[in]   handle      connect handle, if NULL target is all connect
513  * @return      non
514  */
515 /*--------------------------------------------------------------------------*/
516 void
517 ico_apf_com_dispatch(ico_apf_com_handle_t *handle)
518 {
519     int rh;
520     int n;
521     ico_apf_com_handle_t *p;
522
523     if (! handles)  {
524         /* If program has not connected, nothing is done.   */
525         apfw_warn("ico_apf_com_dispatch: handle dose not exist");
526         return;
527     }
528
529     if (handle) {
530         p = handle;
531     }
532     else    {
533         p = handles;
534     }
535
536     while (p)   {
537         ico_uws_service(p->uws_context);
538
539         /* If received data is suspended, it processes.     */
540         while (p->rtail != p->rhead)    {
541             rh = p->rhead;
542             if (p->rhead >= (ICO_APF_RESOURCE_WSOCK_BUFR-1))    {
543                 p->rhead = 0;
544             }
545             else    {
546                 p->rhead ++;
547             }
548             n = p->rtail - p->rhead;
549             if (n < 0) {
550                 n = ICO_APF_RESOURCE_WSOCK_BUFR + n;
551             }
552
553             if (p->listener != NULL) {
554                 handle->listener(p, p->rbuf[rh]->cmd, p->rbuf[rh]->res, p->rbuf[rh]->pid,
555                                  p->rbuf[rh]->appid, p->rbuf[rh]->msg, p->user_data);
556                 ico_uws_service(p->uws_context);
557             }
558             else if (global_listener != NULL) {
559                 global_listener(p, p->rbuf[rh]->cmd, p->rbuf[rh]->res, p->rbuf[rh]->pid,
560                                 p->rbuf[rh]->appid, p->rbuf[rh]->msg, global_user_data);
561                 ico_uws_service(p->uws_context);
562             }
563         }
564         if (handle) break;
565         p = p->next;
566     }
567 }
568
569 /*--------------------------------------------------------------------------*/
570 /**
571  * @brief   ico_apf_com_term_client
572  *          finish to connect to AppsController
573  *          It recommends call this function before end of program
574  *          that used AppsController.
575  *
576  * @param[in]   handle      AppsController's handle
577  * @return      result
578  * @retval      ICO_APF_RESOURCE_E_NONE             success
579  * @retval      ICO_APF_RESOURCE_E_NOT_INITIALIZED  error(already finished)
580  */
581 /*--------------------------------------------------------------------------*/
582 int
583 ico_apf_com_term_client(ico_apf_com_handle_t *handle)
584 {
585     ico_apf_com_handle_t    *p;
586
587     apfw_trace("ico_apf_com_term_client: Enter");
588
589     if ((handle == NULL) || (handles == NULL))  {
590         apfw_trace("ico_apf_com_term_client: Leave(RESOURCE_E_NOT_INITIALIZED)");
591         return ICO_APF_RESOURCE_E_NOT_INITIALIZED;
592     }
593     handle->service_on = 0;
594
595     if (handle == handles)  {
596         handles = handles->next;
597     }
598     else    {
599         p = handles;
600         while (p)   {
601             if (p->next == handle)  break;
602             p = p->next;
603         }
604         if (! p)    {
605             apfw_trace("ico_apf_com_term_client: Leave(RESOURCE_E_NOT_INITIALIZED)");
606             return ICO_APF_RESOURCE_E_NOT_INITIALIZED;
607         }
608         p->next = handle->next;
609     }
610
611     if (handle->uws_context)    {
612         ico_uws_unset_event_cb(handle->uws_context);
613         ico_uws_close(handle->uws_context);
614     }
615     handle->next = freehandles;
616     freehandles = handle;
617
618     apfw_trace("ico_apf_com_term_client: Leave(OK)");
619     return ICO_APF_RESOURCE_E_NONE;
620 }
621
622 /*--------------------------------------------------------------------------*/
623 /**
624  * @brief   ico_apf_com_term_server
625  *          finish to connect to application
626  *
627  * @param[in]   handle      AppsController's handle
628  * @return      result
629  * @retval      ICO_APF_RESOURCE_E_NONE             success
630  * @retval      ICO_APF_RESOURCE_E_NOT_INITIALIZED  error(already finished)
631  */
632 /*--------------------------------------------------------------------------*/
633 int
634 ico_apf_com_term_server(ico_apf_com_handle_t *handle)
635 {
636     ico_apf_com_handle_t    *p;
637
638     apfw_trace("ico_apf_com_term_server: Enter");
639
640     if ((handle == NULL) || (handles == NULL))  {
641         apfw_trace("ico_apf_com_term_server: Leave(RESOURCE_E_NOT_INITIALIZED)");
642         return ICO_APF_RESOURCE_E_NOT_INITIALIZED;
643     }
644     handle->service_on = 0;
645
646     if (handle == handles)  {
647         handles = handles->next;
648     }
649     else    {
650         p = handles;
651         while (p)   {
652             if (p->next == handle)  break;
653             p = p->next;
654         }
655         if (! p)    {
656             apfw_trace("ico_apf_com_term_server: Leave(RESOURCE_E_NOT_INITIALIZED)");
657             return ICO_APF_RESOURCE_E_NOT_INITIALIZED;
658         }
659         p->next = handle->next;
660     }
661
662     if (handle->uws_context)    {
663         ico_uws_unset_event_cb(handle->uws_context);
664         ico_uws_close(handle->uws_context);
665     }
666     handle->next = freehandles;
667     freehandles = handle;
668
669     apfw_trace("ico_apf_com_term_server: Leave(OK)");
670     return ICO_APF_RESOURCE_E_NONE;
671 }
672
673 /*--------------------------------------------------------------------------*/
674 /**
675  * @brief   ico_apf_com_send
676  *          Accumulates the data send to AppsController/application.
677  *
678  * @param[in]   handle      AppsController's handle
679  * @param[in]   cmd         command
680  * @param[in]   res         resource
681  * @param[in]   appid       application id
682  * @param[in]   msg         send message
683  * @return      result
684  * @retval      ICO_APF_RESOURCE_E_NONE             success
685  * @retval      ICO_APF_RESOURCE_E_NOT_INITIALIZED  error(not connect)
686  * @retval      ICO_APF_RESOURCE_E_COMMUNICATION    error(cannot send)
687  * @retval      ICO_APF_RESOURCE_E_INVAL            error(invalid parameter)
688  */
689 /*--------------------------------------------------------------------------*/
690 int
691 ico_apf_com_send(ico_apf_com_handle_t *handle,
692                  const int cmd, const int res, const char *appid, char *msg)
693 {
694     int     st;
695     int     cur;
696     int     len;
697
698     apfw_trace("ico_apf_com_send: Enter(%08x, %d, %d) callback=%d",
699                (int)handle, cmd, res, uws_callbacked);
700
701     if ((handle == NULL) || (! ico_apf_com_isconnected(handle)))    {
702         apfw_warn("ico_apf_com_send: Leave(not initialized)");
703         return ICO_APF_RESOURCE_E_NOT_INITIALIZED;
704     }
705     if ((handle->type & ICO_APF_COM_TYPE_CONNECTION) != ICO_APF_COM_TYPE_SOUNDMGR)  {
706         /* send to AppsController               */
707         if ((cmd < ICO_APF_RESOURCE_COMMAND_MIN) ||
708             (cmd > ICO_APF_RESOURCE_COMMAND_MAX) ||
709             (res < ICO_APF_RESOURCE_RESID_MIN) ||
710             (res > ICO_APF_RESOURCE_RESID_MAX))   {
711             apfw_warn("ico_apf_com_send: Leave(invalid command for resource)");
712             return ICO_APF_RESOURCE_E_INVAL;
713         }
714     }
715     else    {
716         /* send to Multi Sound Manager          */
717         if ((cmd < ICO_APF_SOUND_COMMAND_MIN) ||
718             (cmd > ICO_APF_SOUND_COMMAND_CMD))  {
719             apfw_warn("ico_apf_com_send: Leave(invalid command for sound control)");
720             return ICO_APF_RESOURCE_E_INVAL;
721         }
722     }
723
724     if (msg)    {
725         len = strlen(msg);
726         if (len >= ICO_APF_RESOURCE_MSG_LEN)    {
727             apfw_warn("ico_apf_com_send: Leave(invalid message length)");
728             return ICO_APF_RESOURCE_E_INVAL;
729         }
730     }
731     else    {
732         len = 0;
733         msg = "(NULL)";
734     }
735
736     st = handle->stail;
737     cur = st;
738
739     if (st >= (ICO_APF_RESOURCE_WSOCK_BUFS-1))  {
740         st = 0;
741     }
742     else    {
743         st ++;
744     }
745     if (st == handle->shead)    {
746         /* send buffer is full                  */
747         ico_apf_poll_write_event(handle, 3);
748
749         apfw_error("ico_apf_com_send: Leave(send buffer overflow)");
750         ico_apf_poll_fd_del(handle->fd);
751         return ICO_APF_RESOURCE_E_COMMUNICATION;
752     }
753     handle->stail = st;
754
755     /* accumulate send buffer                   */
756     if ((! appid) || (*appid == 0)) {
757         handle->sbuf[cur]->pid = getpid();
758         handle->sbuf[cur]->appid[0] = 0;
759     }
760     else    {
761         handle->sbuf[cur]->pid = 0;
762         strncpy(handle->sbuf[cur]->appid, appid, ICO_UXF_MAX_PROCESS_NAME);
763         handle->sbuf[cur]->appid[ICO_UXF_MAX_PROCESS_NAME] = 0;
764     }
765     apfw_trace("ico_apf_com_send: Send.%d:%d %d %d(%s) <%s>",
766                handle->stail, cmd, res, handle->sbuf[cur]->pid,
767                handle->sbuf[cur]->appid, msg);
768     handle->sbuf[cur]->cmd = cmd;
769     handle->sbuf[cur]->res = res;
770     memcpy(handle->sbuf[cur]->msg, msg, len);
771     handle->sbuf[cur]->msg[len] = 0;
772
773     if (uws_callbacked) {
774         /* send call from communication callback, delayed send  */
775         ico_apf_poll_write_event(handle, 1);
776     }
777     else    {
778         /* not call from callback, direct send                  */
779         apfw_trace("ico_apf_com_send: direct send(context=%08x id=%08x)",
780                    (int)handle->uws_context, (int)handle->uws_id);
781         if ((handle->uws_context != NULL) &&
782             (handle->uws_id != NULL))   {
783             st = handle->shead;
784             if (handle->shead >= (ICO_APF_RESOURCE_WSOCK_BUFS-1))  {
785                 handle->shead = 0;
786             }
787             else    {
788                 handle->shead ++;
789             }
790             if (ico_apf_com_realsend(handle, handle->sbuf[st])
791                         != ICO_APF_RESOURCE_E_NONE) {
792                 apfw_warn("ico_apf_com_send: ico_apf_com_realsend Error");
793                 handle->shead = st;
794             }
795         }
796         ico_apf_com_dispatch(handle);           /* try to service           */
797     }
798     apfw_trace("ico_apf_com_send: Leave(OK)");
799     return ICO_APF_RESOURCE_E_NONE;
800 }
801
802 /*--------------------------------------------------------------------------*/
803 /**
804  * @brief   ico_apf_com_realsend
805  *          send messege to AppsController
806  *
807  * @param[in]   handle      AppsController's handle
808  * @param[in]   msg         Send message
809  * @return      result
810  * @retval      ICO_APF_RESOURCE_E_NONE             success
811  * @retval      ICO_APF_RESOURCE_E_NOT_INITIALIZED  error(not connect)
812  * @retval      ICO_APF_RESOURCE_E_COMMUNICATION    error(cannot send)
813  * @retval      ICO_APF_RESOURCE_E_INVAL            error(invalid parameter)
814  */
815 /*--------------------------------------------------------------------------*/
816 static int
817 ico_apf_com_realsend(ico_apf_com_handle_t *handle, ico_apf_com_buffer_t *msg)
818 {
819     char    buf[256];
820
821     apfw_trace("ico_apf_com_realsend: Enter");
822     if ((handle == NULL) || (! ico_apf_com_isconnected(handle)))    {
823         apfw_warn("ico_apf_com_realsend: Leave(Not initialized)");
824         return ICO_APF_RESOURCE_E_NOT_INITIALIZED;
825     }
826
827     if ((handle->type & ICO_APF_COM_TYPE_CONNECTION) == ICO_APF_COM_TYPE_SOUNDMGR)  {
828         /* send to Multi Sound Manager          */
829         if (msg->res)   {
830             snprintf(buf, sizeof(buf), "%s %d",
831                     ico_apf_sound_table[msg->cmd-ICO_APF_SOUND_COMMAND_MIN], msg->res);
832         }
833         else    {
834             strcpy(buf, ico_apf_sound_table[msg->cmd-ICO_APF_SOUND_COMMAND_MIN]);
835         }
836     }
837     else    {
838         /* send tp AppsController               */
839         if (msg->appid[0])  {
840             snprintf(buf, sizeof(buf), "%s %s %s %s",
841                      ico_apf_cmd_table[msg->cmd-ICO_APF_RESOURCE_COMMAND_MIN],
842                      ico_apf_res_table[msg->res-ICO_APF_RESOURCE_RESID_MIN],
843                      msg->appid, msg->msg);
844         }
845         else    {
846             snprintf(buf, sizeof(buf), "%s %s %d %s",
847                      ico_apf_cmd_table[msg->cmd-ICO_APF_RESOURCE_COMMAND_MIN],
848                      ico_apf_res_table[msg->res-ICO_APF_RESOURCE_RESID_MIN],
849                      msg->pid, msg->msg);
850         }
851     }
852
853     apfw_trace("ico_apf_com_realsend: ico_uws_send[%s]", buf);
854     ico_uws_send(handle->uws_context, handle->uws_id, (unsigned char *)buf, strlen(buf));
855
856     apfw_trace("ico_apf_com_realsend: Leave(OK)");
857     return ICO_APF_RESOURCE_E_NONE;
858 }
859
860 /*--------------------------------------------------------------------------*/
861 /**
862  * @brief   ico_apf_com_addeventlistener
863  *          register a callback function called receive message from AppsController
864  *
865  * @param[in]   handle      AppsComtroller's handle
866  * @param[in]   listener    callback function
867  * @param[in]   user_data   Arbitrary data
868  * @return      result
869  * @retval      ICO_APF_RESOURCE_E_NONE             success
870  * @retval      ICO_APF_RESOURCE_E_NOT_INITIALIZED  error(not connect)
871  * @retval      ICO_APF_RESOURCE_E_INVAL            error(already registed)
872  */
873 /*--------------------------------------------------------------------------*/
874 int
875 ico_apf_com_addeventlistener(ico_apf_com_handle_t *handle,
876                              ico_apf_com_eventlistener listener, void* user_data)
877 {
878     if (handle == NULL) {
879         if (global_listener)    {
880             return ICO_APF_RESOURCE_E_INVAL;
881         }
882         global_listener = listener;
883         global_user_data = user_data;
884         return ICO_APF_RESOURCE_E_NONE;
885     }
886
887     if (handle->listener)   {
888         return ICO_APF_RESOURCE_E_INVAL;
889     }
890     handle->user_data = user_data;
891     handle->listener = listener;
892
893     if (! global_listener)  {
894         /* save listener        */
895         global_listener = listener;
896     }
897     return ICO_APF_RESOURCE_E_NONE;
898 }
899
900 /*--------------------------------------------------------------------------*/
901 /**
902  * @brief   ico_apf_com_removeeventlistener
903  *          unregister a callback function called receive message
904  *
905  * @param[in]   handle      AppsComtroller's handle
906  * @return      result
907  * @retval      ICO_APF_RESOURCE_E_NONE             success
908  * @retval      ICO_APF_RESOURCE_E_NOT_INITIALIZED  error(not connect)
909  * @retval      ICO_APF_RESOURCE_E_INVAL            error(do not registed)
910  */
911 /*--------------------------------------------------------------------------*/
912 int
913 ico_apf_com_removeeventlistener(ico_apf_com_handle_t *handle)
914 {
915     if (handle == NULL) {
916         if (! global_listener)  {
917             return ICO_APF_RESOURCE_E_INVAL;
918         }
919         global_listener = NULL;
920         global_user_data = NULL;
921         return ICO_APF_RESOURCE_E_NONE;
922     }
923
924     if (! handle->listener) {
925         return ICO_APF_RESOURCE_E_INVAL;
926     }
927     handle->listener = NULL;
928     handle->user_data = NULL;
929
930     return ICO_APF_RESOURCE_E_NONE;
931 }
932
933 /*--------------------------------------------------------------------------*/
934 /**
935  * @brief   ico_apf_callback_uws
936  *          this callback function notified from communication.
937  *
938  * @param[in]   context     communication context
939  * @param[in]   reason      event type
940  * @param[in]   id          communication management table
941  * @param[in]   detail      event detail information
942  * @param[in]   user_data   communication handle
943  * @return      none
944  */
945 /*--------------------------------------------------------------------------*/
946 static void
947 ico_apf_callback_uws(const struct ico_uws_context *context,
948                      const ico_uws_evt_e reason, const void *id,
949                      const ico_uws_detail *detail, void *user_data)
950 {
951     int     st;
952     int     cmd;
953     int     res;
954     int     pid;
955     int     i;
956     int     strlen;
957     char    *msg;
958     int     len;
959     ico_apf_com_handle_t *handle;
960     ico_apf_com_handle_t *handle2;
961     char    appid[ICO_UXF_MAX_PROCESS_NAME+1];
962     char    strname[ICO_UXF_MAX_STREAM_NAME+1];
963     int     nparam;
964     struct  {
965         short   start;
966         short   end;
967     }       param[10];
968
969     handle = (ico_apf_com_handle_t *)user_data;
970     uws_callbacked ++;
971
972     if (handle->type == ICO_APF_COM_TYPE_SVR_APPSCTL)   {
973         /* search client handle for server  */
974         handle2 = handles;
975         while (handle2)  {
976             if (handle2->uws_id == id)    break;
977             handle2 = handle2->next;
978         }
979         if (handle2)   {
980             handle = handle2;
981         }
982         else    {
983             apfw_trace("ico_apf_callback_uws: new server side client");
984
985             handle = ico_apf_alloc_handle();
986             if (! handle)   {
987                 uws_callbacked --;
988                 apfw_error("ico_apf_callback_uws: No Memory");
989                 return;
990             }
991             apfw_trace("ico_apf_callback_uws: create new handle(%08x)", (int)handle);
992             handle->type = ICO_APF_COM_TYPE_APPSCTL;
993             handle->uws_context = (struct ico_uws_context *)context;
994             handle->uws_id = (void *)id;
995             handle->service_on = 0;
996
997             strncpy(handle->ip, ico_uws_get_uri(handle->uws_context),
998                     ICO_APF_RESOURCE_IP_LEN-1);
999         }
1000     }
1001
1002     switch (reason) {
1003     case ICO_UWS_EVT_OPEN:
1004         apfw_trace("ico_apf_callback_uws: ICO_UWS_EVT_OPEN");
1005         handle->uws_id = (void *)id;
1006         handle->service_on = 1;
1007
1008         /* save receive message to receive buffer       */
1009         ico_apf_put_recvmsg(ICO_APF_RESOURCE_STATE_CONNECTED, 0,
1010                             handle->pid, "\0", NULL, 0, handle);
1011         break;
1012
1013     case ICO_UWS_EVT_ADD_FD:                /* add connection socket            */
1014         apfw_trace("ico_apf_callback_uws: ICO_UWS_EVT_ADD_FD(%d)", detail->_ico_uws_fd.fd);
1015         handle->fd = detail->_ico_uws_fd.fd;
1016         (void)ico_apf_poll_fd_add(detail->_ico_uws_fd.fd, POLLIN|POLLOUT);
1017         break;
1018
1019     case ICO_UWS_EVT_DEL_FD:                /* delete connection socket         */
1020         apfw_trace("ico_apf_callback_uws: ICO_UWS_EVT_DEL_FD(%d)", detail->_ico_uws_fd.fd);
1021         handle->fd = 0;
1022         ico_apf_poll_fd_del(detail->_ico_uws_fd.fd);
1023         break;
1024
1025     case ICO_UWS_EVT_CLOSE:
1026         apfw_trace("ico_apf_callback_uws: ICO_UWS_EVT_CLOSE pid=%d", handle->pid);
1027         handle->service_on = 0;
1028         handle->uws_id = NULL;
1029         pid = handle->pid;
1030         handle->pid = 0;
1031
1032         /* save receive message to receive buffer       */
1033         ico_apf_put_recvmsg(ICO_APF_RESOURCE_STATE_DISCONNECTED, 0,
1034                             pid, "\0", NULL, 0, handle);
1035         break;
1036
1037     case ICO_UWS_EVT_RECEIVE:
1038         msg = (char *)detail->_ico_uws_message.recv_data;
1039         len = (int)detail->_ico_uws_message.recv_len;
1040         if ((len <= 9) || (len >= (ICO_APF_RESOURCE_MSG_LEN+9)))    {
1041             uws_callbacked --;
1042             apfw_warn("ico_apf_callback_uws: Receive Length Error, Len=%d", len);
1043             return;
1044         }
1045         msg[len] = 0;
1046         apfw_trace("ico_apf_callback_uws: ICO_UWS_EVT_RECEIVE[%s]", msg);
1047
1048         /* analize event code               */
1049         if ((handle->type & ICO_APF_COM_TYPE_CONNECTION) == ICO_APF_COM_TYPE_SOUNDMGR)  {
1050             /* Multi Sound Manager          */
1051             i = 0;
1052             for (nparam = 0; nparam < 10; nparam++) {
1053                 for (; msg[i]; i++) {
1054                     if (msg[i] != ' ')  break;
1055                 }
1056                 if (msg[i] == 0)    break;
1057                 param[nparam].start = i;
1058                 for (; msg[i]; i++) {
1059                     if (msg[i] == ' ')  break;
1060                 }
1061                 param[nparam].end = i;
1062             }
1063             if (nparam <= 0)    {
1064                 uws_callbacked --;
1065                 apfw_warn("ico_apf_callback_uws: Illegal Message Format(no param)");
1066                 return;
1067             }
1068             for (cmd = ICO_APF_SOUND_COMMAND_CMD+1;
1069                  cmd <= ICO_APF_SOUND_COMMAND_MAX; cmd++)    {
1070                 if (memcmp(&msg[param[0].start],
1071                            ico_apf_sound_table[cmd-ICO_APF_SOUND_COMMAND_MIN],
1072                            param[0].end - param[0].start) == 0) break;
1073             }
1074             if (cmd > ICO_APF_SOUND_COMMAND_MAX)    {
1075                 uws_callbacked --;
1076                 apfw_warn("ico_apf_callback_uws: Receive Event Nop(cmd=%d)", cmd);
1077                 return;
1078             }
1079             res = ICO_APF_RESID_BASIC_SOUND;
1080             pid = 0;
1081             appid[0] = 0;
1082             strname[0] = 0;
1083             strlen = 0;
1084             for (i = 1; i < nparam; i++)    {
1085                 if (memcmp(&msg[param[i].start],
1086                            "#pid#", param[i].end - param[i].start) == 0)    {
1087                     i ++;
1088                     if (i < nparam) {
1089                         pid = strtol(&msg[param[i].start], (char **)0, 0);
1090                         if (ico_apf_get_app_id(pid, appid) != ICO_APP_CTL_E_NONE)   {
1091                             uws_callbacked --;
1092                             apfw_trace("ico_apf_callback_uws: Unknown pid=%d", pid);
1093                             return;
1094                         }
1095                     }
1096                 }
1097                 else if (memcmp(&msg[param[i].start],
1098                                 "#stream_name#", param[i].end - param[i].start) == 0) {
1099                     i ++;
1100                     /* no need stream name      */
1101                 }
1102                 else if (memcmp(&msg[param[i].start],
1103                                 "#app_name#", param[i].end - param[i].start) == 0) {
1104                     i ++;
1105                     if (i < nparam) {
1106                         strlen = param[i].end - param[i].start;
1107                         if (strlen >= ((int)sizeof(strname)))
1108                             strlen = sizeof(strname) - 1;
1109                         strncpy(strname, &msg[param[i].start], strlen);
1110                         strname[strlen] = 0;
1111                     }
1112                 }
1113                 else if (memcmp(&msg[param[i].start],
1114                                 "#stream_state#", param[i].end - param[i].start) == 0) {
1115                     i ++;
1116                     /* no need stream_state     */
1117                 }
1118             }
1119             if (pid > 0)    {
1120                 handle->pid = pid;
1121             }
1122             apfw_trace("ico_apf_callback_uws: SoundMgr evt=%d res=%d(%s.%d) str=%s",
1123                        cmd, res, appid, pid, strname);
1124             /* save receive message to receive buffer       */
1125             ico_apf_put_recvmsg(cmd, res, pid, appid, strname, strlen, handle);
1126         }
1127         else    {
1128             /* AppsController               */
1129             for (cmd = ICO_APF_RESOURCE_COMMAND_MIN;
1130                  cmd <= ICO_APF_RESOURCE_COMMAND_MAX; cmd++)    {
1131                 if (memcmp(msg, ico_apf_cmd_table[cmd-ICO_APF_RESOURCE_COMMAND_MIN], 3) == 0)
1132                     break;
1133             }
1134             if (cmd > ICO_APF_RESOURCE_COMMAND_MAX) {
1135                 uws_callbacked --;
1136                 apfw_warn("ico_apf_callback_appsctl: Receive Event Error(cmd=%d)",
1137                           cmd);
1138                 return;
1139             }
1140             for (res = ICO_APF_RESOURCE_RESID_MIN;
1141                  res <= ICO_APF_RESOURCE_RESID_MAX; res++)  {
1142                 if (memcmp(&msg[4],
1143                     ico_apf_res_table[res-ICO_APF_RESOURCE_RESID_MIN], 4) == 0) break;
1144             }
1145             if (res > ICO_APF_RESOURCE_RESID_MAX)   {
1146                 uws_callbacked --;
1147                 apfw_warn("ico_apf_callback_uws: Receive Resource Error(resid=%d)",
1148                           res);
1149                 return;
1150             }
1151
1152             pid = 0;
1153             for (st = 9; msg[st]; st++) {
1154                 if (msg[st] == ' ') break;
1155                 if (pid >= 0)   {
1156                     if ((msg[st] >= '0') && (msg[st] <= '9'))   {
1157                         pid = pid * 10 + msg[st] - '0';
1158                     }
1159                     else    {
1160                         pid = -1;
1161                     }
1162                 }
1163             }
1164             if (pid >= 0)   {
1165                 appid[0] = 0;
1166             }
1167             else    {
1168                 pid = st - 9;
1169                 if (pid > ICO_UXF_MAX_PROCESS_NAME )
1170                     pid = ICO_UXF_MAX_PROCESS_NAME;
1171                 strncpy(appid, &msg[9], pid);
1172                 appid[pid] = 0;
1173                 pid = 0;
1174             }
1175             if (msg[st] == ' ') st++;
1176             if (pid > 0)    {
1177                 handle->pid = pid;
1178             }
1179             apfw_trace("ico_apf_callback_uws: AppsCtl evt=%d res=%d pid=%d(%s) msg=%s",
1180                        cmd, res, pid, appid, &msg[st]);
1181             /* save receive message to receive buffer       */
1182             ico_apf_put_recvmsg(cmd, res, pid, appid, &msg[st], len-st, handle);
1183         }
1184         break;
1185     default:
1186         apfw_trace("ico_apf_callback_uws: UnKnown reason=%d", reason);
1187         break;
1188     }
1189     uws_callbacked --;
1190 }
1191
1192 /*--------------------------------------------------------------------------*/
1193 /**
1194  * @brief   ico_apf_put_recvmsg
1195  *          put receive message into receive buffer
1196  *
1197  * @param[in]   cmd         receive commnad or event
1198  * @param[in]   res         receive resource
1199  * @param[in]   pid         request pid
1200  * @param[in]   appid       application id (for Web Application)
1201  * @param[in]   msg         receive message
1202  * @param[in]   len         receive message length
1203  * @param[out]  handle      connection handle
1204  * @return      none
1205  */
1206 /*--------------------------------------------------------------------------*/
1207 static void
1208 ico_apf_put_recvmsg(const int cmd, const int res, const int pid, const char *appid,
1209                     char *msg, const int len, ico_apf_com_handle_t *handle)
1210 {
1211     int     i;
1212     int     nexttail;
1213
1214     /* check receive buffer overflow        */
1215     if (handle->rtail >= (ICO_APF_RESOURCE_WSOCK_BUFR-1))  {
1216         nexttail = 0;
1217     }
1218     else    {
1219         nexttail = handle->rtail + 1;
1220     }
1221     if (handle->rhead == nexttail)  {
1222         /* receive buffer overflow, drops all message   */
1223         apfw_warn("ico_apf_put_recvmsg: receive buffer overflow");
1224         handle->rhead = 0;
1225         handle->rtail = 0;
1226         nexttail = 1;
1227     }
1228
1229     /* receive message is put into queue.     */
1230     handle->rbuf[handle->rtail]->cmd = cmd;
1231     handle->rbuf[handle->rtail]->res = res;
1232     handle->rbuf[handle->rtail]->pid = pid;
1233     strncpy(handle->rbuf[handle->rtail]->appid, appid, ICO_UXF_MAX_PROCESS_NAME);
1234     handle->rbuf[handle->rtail]->appid[ICO_UXF_MAX_PROCESS_NAME] = 0;
1235     if (msg)    {
1236         memcpy(handle->rbuf[handle->rtail]->msg, msg, len);
1237         handle->rbuf[handle->rtail]->msg[len] = 0;
1238     }
1239     else    {
1240         handle->rbuf[handle->rtail]->msg[0] = 0;
1241     }
1242     handle->rtail = nexttail;
1243     i = handle->rtail - handle->rhead;
1244     if (i <= 0)    {
1245         i = ICO_APF_RESOURCE_WSOCK_BUFR + i;
1246     }
1247
1248     ico_apf_poll_write_event(handle, 1);
1249 }
1250
1251 /*--------------------------------------------------------------------------*/
1252 /**
1253  * @brief   apf_com_poll_fd_add: add file descriptor for poll
1254  *
1255  * @param[in]   fd          file descriptor
1256  * @param[in]   flag        POLL flag(POLLIN,POLLOUT)
1257  *                          negative means reset
1258  * @return      result
1259  * @retval      ICO_APF_RESOURCE_E_NONE             success
1260  * @retval      ICO_APF_RESOURCE_E_INVAL            error(out of memory)
1261  */
1262 /*--------------------------------------------------------------------------*/
1263 static int
1264 ico_apf_poll_fd_add(const int fd, const int flag)
1265 {
1266     ico_apf_com_poll_t      *p;
1267     ico_apf_com_poll_t      *fds[1];
1268     ico_apf_com_handle_t    *handle;
1269
1270     p = com_polls;
1271     while (p)   {
1272         if (p->fd == fd)    {
1273             break;
1274         }
1275         p = p->next;
1276     }
1277
1278     if (! p)    {
1279         /* new file descriptor              */
1280         if (freecom_polls)   {
1281             p = freecom_polls;
1282             freecom_polls = p->next;
1283             p->apf_fd_control = NULL;
1284             p->user_data = NULL;
1285         }
1286         else    {
1287             p = calloc(sizeof(ico_apf_com_poll_t), 1);
1288             if (! p)    {
1289                 /* out of memory            */
1290                 apfw_error("ico_apf_poll_fd_add: can not allocate fd control table"
1291                            "(No Memory)");
1292                 return ICO_APF_RESOURCE_E_INVAL;
1293             }
1294         }
1295
1296         p->fd = fd;
1297         p->next = com_polls;
1298         com_polls = p;
1299     }
1300     p->flags |= ICO_APF_COM_POLL_ERROR;
1301     if (flag >= 0)  {
1302         if (flag & (POLLIN|POLLPRI))    {
1303             p->flags |= ICO_APF_COM_POLL_READ;
1304         }
1305         if (flag & POLLOUT) {
1306             p->flags |= ICO_APF_COM_POLL_WRITE;
1307         }
1308     }
1309     else    {
1310         if ((-flag) & (POLLIN|POLLPRI)) {
1311             p->flags &= ~ICO_APF_COM_POLL_READ;
1312         }
1313         if ((-flag) & POLLOUT)  {
1314             p->flags &= ~ICO_APF_COM_POLL_WRITE;
1315         }
1316     }
1317
1318     handle = handles;
1319     while (handle)  {
1320         if (handle->fd == fd)   break;
1321         handle = handle->next;
1322     }
1323     if (handle) {
1324         p->apf_fd_control = (void *)handle;
1325         handle->poll = p;
1326     }
1327     else    {
1328         apfw_trace("ico_apf_poll_fd_add: fd=%d dose not exist in handles", fd);
1329         p->apf_fd_control = NULL;
1330     }
1331
1332     /* regist callback function */
1333     if (ico_apf_pollfd_func)    {
1334         fds[0] = p;
1335
1336         (*ico_apf_pollfd_func)(fds, 1);
1337     }
1338     return ICO_APF_RESOURCE_E_NONE;
1339 }
1340
1341 /*--------------------------------------------------------------------------*/
1342 /**
1343  * @brief   apf_com_poll_fd_del: delete file descriptor for poll
1344  *
1345  * @param[in]   fd          file descriptor
1346  * @return      none
1347  */
1348 /*--------------------------------------------------------------------------*/
1349 static void
1350 ico_apf_poll_fd_del(const int fd)
1351 {
1352     ico_apf_com_poll_t      *p;
1353     ico_apf_com_poll_t      *bp;
1354     ico_apf_com_poll_t      *fds[1];
1355
1356     /* search file descriptor       */
1357     p = com_polls;
1358     bp = NULL;
1359     while (p)   {
1360         if (p->fd == fd)    {
1361             if (bp) {
1362                 bp->next = p->next;
1363             }
1364             else    {
1365                 com_polls = p->next;
1366             }
1367
1368             if (p->apf_fd_control)  {
1369                 ((ico_apf_com_handle_t *)(p->apf_fd_control))->poll = NULL;
1370             }
1371
1372             /* call callback function       */
1373             if (ico_apf_pollfd_func)    {
1374                 p->flags = 0;
1375                 fds[0] = p;
1376
1377                 (*ico_apf_pollfd_func)(fds, 1);
1378             }
1379             p->next = freecom_polls;
1380             freecom_polls = p;
1381             break;
1382         }
1383         p = p->next;
1384     }
1385 }
1386
1387 /*--------------------------------------------------------------------------*/
1388 /**
1389  * @brief   ico_apf_com_poll_fd_control: Set or Unset callback of file descriptors
1390  *
1391  * @param[in]   poll_fd_cb      The callback function.
1392  * @return      result
1393  * @retval      ICO_APF_RESOURCE_E_NONE             success
1394  */
1395 /*--------------------------------------------------------------------------*/
1396 ICO_APF_API int
1397 ico_apf_com_poll_fd_control(ico_apf_com_pollfd_cb poll_fd_cb)
1398 {
1399     ico_apf_com_poll_t *p;
1400     ico_apf_com_poll_t **fds;
1401     int     nfds;
1402     int     count;
1403
1404     /* regist callback function     */
1405     ico_apf_pollfd_func = poll_fd_cb;
1406
1407     if (ico_apf_pollfd_func)    {
1408         /* if regist, call callback for all file descriptors    */
1409
1410         /* count number of file descriptors */
1411         p = com_polls;
1412         count = 0;
1413         while (p)   {
1414             count ++;
1415             p = p->next;
1416         }
1417         if (count > 0)  {
1418             fds = malloc(sizeof(ico_apf_com_poll_t *) * count);
1419         }
1420         else    {
1421             fds = NULL;
1422         }
1423
1424         p = com_polls;
1425         nfds = 0;
1426         while (fds && p)   {
1427             fds[nfds++] = p;
1428             p = p->next;
1429         }
1430
1431         if (nfds > 0)   {
1432             apfw_trace("ico_apf_com_poll_fd_control: nfds=%d:%d[%x]",
1433                        nfds, fds[0]->fd, fds[0]->flags);
1434             (*ico_apf_pollfd_func)(fds, nfds);
1435         }
1436         if (fds)    free(fds);
1437     }
1438     return ICO_APF_RESOURCE_E_NONE;
1439 }
1440
1441 /*--------------------------------------------------------------------------*/
1442 /**
1443  * @brief   ico_apf_com_poll_fd_event: Notify the changes of file descriptor's state
1444  *
1445  * @param[in]   fd_ctl      The structure of file descriptor's controller
1446  * @param[in]   flags       The user data to be passed to the callback function
1447  * @return      result
1448  * @retval      ICO_APF_RESOURCE_E_NONE             success
1449  */
1450 /*--------------------------------------------------------------------------*/
1451 ICO_APF_API int
1452 ico_apf_com_poll_fd_event(ico_apf_com_poll_t *fd_ctl, int flags)
1453 {
1454     int     st;
1455     ico_apf_com_handle_t    *handle = (ico_apf_com_handle_t *)fd_ctl->apf_fd_control;
1456
1457     uifw_trace("ico_apf_com_poll_fd_event: handle=%08x fd=%d flags=%x",
1458                (int)handle, handle ? handle->fd : 0, flags);
1459     if (handle) {
1460         ico_apf_com_dispatch(handle);           /* try to service           */
1461     }
1462     else    {
1463         ico_apf_com_dispatch(NULL);             /* try to service for server*/
1464     }
1465
1466     if (handle) {
1467         /* send if send data exist      */
1468         if ((handle->stail != handle->shead) &&
1469             (handle->uws_context != NULL) &&
1470             (handle->uws_id != NULL))   {
1471             st = handle->shead;
1472             if (handle->shead >= (ICO_APF_RESOURCE_WSOCK_BUFS-1))  {
1473                 handle->shead = 0;
1474             }
1475             else    {
1476                 handle->shead ++;
1477             }
1478             if (ico_apf_com_realsend(handle, handle->sbuf[st])
1479                         != ICO_APF_RESOURCE_E_NONE) {
1480                 apfw_warn("ico_apf_com_poll_fd_event: ico_apf_com_realsend Error");
1481                 handle->shead = st;
1482                 ico_apf_com_dispatch(handle);   /* try to service       */
1483             }
1484         }
1485
1486         /* start/stop writable event        */
1487         if ((handle->stail == handle->shead) ||
1488             (handle->uws_context == NULL) ||
1489             (handle->uws_id == NULL))   {
1490             ico_apf_poll_write_event(handle, 0);
1491         }
1492         else    {
1493             ico_apf_poll_write_event(handle, 1);
1494         }
1495     }
1496     return ICO_APF_RESOURCE_E_NONE;
1497 }
1498
1499 /*--------------------------------------------------------------------------*/
1500 /**
1501  * @brief   ico_apf_poll_write_event: Write event control for poll
1502  *
1503  * @param[in]   handle          AppsController's handle
1504  * @param[in]   write           set/reset write event
1505  *                              = 0 : reset if not reset
1506  *                              = 1 : set if not set
1507  *                              = 2 : force reset
1508  *                              = 3 : force set
1509  * @return      none
1510  */
1511 /*--------------------------------------------------------------------------*/
1512 static void
1513 ico_apf_poll_write_event(ico_apf_com_handle_t *handle, const int write)
1514 {
1515     ico_apf_com_poll_t  *fds[1];
1516
1517     if (handle->poll)   {
1518         if ((write == 3) || (write == 1)) {
1519             /* set write poll           */
1520             handle->poll->flags |= ICO_APF_COM_POLL_WRITE;
1521             if (ico_apf_pollfd_func)    {
1522                 fds[0] = handle->poll;
1523                 (*ico_apf_pollfd_func)(fds, 1);
1524             }
1525         }
1526         else if ((write == 2) || (write == 0)) {
1527             /* reset write poll         */
1528             handle->poll->flags &= ~ICO_APF_COM_POLL_WRITE;
1529             if (ico_apf_pollfd_func)    {
1530                 fds[0] = handle->poll;
1531                 (*ico_apf_pollfd_func)(fds, 1);
1532             }
1533         }
1534     }
1535 }
1536