2 * Copyright (c) 2013, TOYOTA MOTOR CORPORATION.
4 * This program is licensed under the terms and conditions of the
5 * Apache License, version 2.0. The full text of the Apache License is at
6 * http://www.apache.org/licenses/LICENSE-2.0
10 * @brief client library for communicate to AppsController in HomeScreen
22 #include <sys/socket.h>
23 #include <netinet/in.h>
26 #include "ico_apf_private.h"
27 #include "ico_uxf_conf.h"
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);
46 /*==============================================================================*/
47 /* variable & table */
48 /*==============================================================================*/
49 /* variable that control program name in Linux */
50 extern const char *program_invocation_name;
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;
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;
62 /* global user listener */
63 static ico_apf_com_eventlistener global_listener = NULL;
64 static void *global_user_data = NULL;
66 /* flag for callback from comminucation */
67 static int uws_callbacked = 0;
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 */
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 */
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 */
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 */
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*/
108 /*--------------------------------------------------------------------------*/
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.
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)
120 /*--------------------------------------------------------------------------*/
121 ico_apf_com_handle_t *
122 ico_apf_com_init_client(const char *uri, const int type)
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;
135 apfw_trace("ico_apf_com_init_client: Enter(%s,%d)",
136 uri ? uri : "(NULL)", type);
138 ifsysconf = (Ico_Uxf_Sys_Config *)ico_uxf_ifGetSysConfig();
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;
146 /* never read a system config */
147 sysconf = (Ico_Uxf_Sys_Config *)ico_uxf_getSysConfig();
150 apfw_error("ico_apf_com_init_client: Leave(can not read configuration files)");
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));
159 address = phost->address;
162 /* If don't find host name from config, regards ipaddress is set as node.*/
163 address = (char *)uri;
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");
173 port = sysconf->misc.soundpluginport;
174 port_env = getenv("ICO_APF_SOUNDMGR_PORT");
175 host_env = getenv("ICO_APF_SOUNDMGR_HOST");
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);
190 if ((strcmp(handle->ip, address) == 0) &&
191 (handle->port == port) && (handle->type == type)) {
194 handle = handle->next;
198 apfw_trace("ico_apf_com_init_client: Leave(Connected)");
202 handle = ico_apf_alloc_handle();
204 apfw_trace("ico_apf_com_init_client: Leave(No Memory)");
210 strncpy(handle->ip, address, ICO_APF_RESOURCE_IP_LEN-1);
211 handle->ip[ICO_APF_RESOURCE_IP_LEN-1] = 0;
213 /* connect to AppsController */
214 ret = ico_apf_com_connect(handle);
217 ico_uxf_closeSysConfig();
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);
226 /* Try to connection */
227 ico_apf_com_dispatch(handle);
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);
237 if (p->fd == handle->fd) {
238 p->apf_fd_control = (void *)handle;
243 apfw_trace("ico_apf_com_init_client: Leave(OK,fd=%d)", handle->fd);
247 /*--------------------------------------------------------------------------*/
249 * @brief ico_apf_com_init_server
250 * This function connects to aplicationto in AppsController.
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)
258 /*--------------------------------------------------------------------------*/
259 ico_apf_com_handle_t *
260 ico_apf_com_init_server(const char *uri, const int type)
267 ico_apf_com_handle_t *handle;
268 Ico_Uxf_Sys_Config *sysconf;
269 Ico_Uxf_Sys_Config *ifsysconf = (Ico_Uxf_Sys_Config *)0xffffffff;
273 apfw_trace("ico_apf_com_init_server: Enter(%s,%d)",
274 uri ? uri : "(NULL)", type);
276 ifsysconf = (Ico_Uxf_Sys_Config *)ico_uxf_ifGetSysConfig();
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;
284 /* never read a system config */
285 sysconf = (Ico_Uxf_Sys_Config *)ico_uxf_getSysConfig();
288 apfw_error("ico_apf_com_init_server: Leave(can not read configuration files)");
292 /* currently server support only Application Controler */
293 svrtype = ICO_APF_COM_TYPE_SVR_APPSCTL;
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));
300 address = phost->address;
303 /* If don't find host name from config, regards ipaddress is set as node.*/
304 address = (char *)uri;
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);
311 /* environment variable for port */
312 port = sysconf->misc.appscontrollerport;
313 port_env = getenv("ICO_APF_APPSCTL_PORT");
321 if ((strcmp(address, handle->ip) == 0) &&
322 (handle->port == port) && (handle->type == svrtype)) break;
323 handle = handle->next;
327 apfw_trace("ico_apf_com_init_server: Leave(Created)");
331 handle = ico_apf_alloc_handle();
333 apfw_error("ico_apf_com_init_server: Leave(No Memory)");
337 handle->type = svrtype;
339 strncpy(handle->ip, address, ICO_APF_RESOURCE_IP_LEN-1);
340 handle->ip[ICO_APF_RESOURCE_IP_LEN-1] = 0;
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);
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);
351 apfw_trace("ico_apf_com_init_server: create server context 0x%08x",
352 (int)handle->uws_context);
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)");
361 global_uwscontext = handle->uws_context;
363 ico_apf_com_dispatch(handle);
365 apfw_trace("ico_apf_com_init_server: Leave(OK)");
369 /*--------------------------------------------------------------------------*/
371 * @brief ico_apf_alloc_handle
372 * Allocate ccommunication handle.
375 * @return handle address
376 * @retval addres success, return handle address
377 * @retval NULL error(no memory)
379 /*--------------------------------------------------------------------------*/
380 static ico_apf_com_handle_t *
381 ico_apf_alloc_handle(void)
383 ico_apf_com_handle_t *handle;
388 handle = malloc(sizeof(ico_apf_com_handle_t));
392 memset(handle, 0, sizeof(ico_apf_com_handle_t));
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]) {
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]) {
409 handle = freehandles;
410 freehandles = freehandles->next;
414 handle->uws_context = NULL;
415 handle->uws_id = NULL;
416 handle->service_on = 0;
422 handle->listener = NULL;
423 handle->user_data = NULL;
428 handle->next = handles;
435 /*--------------------------------------------------------------------------*/
437 * @brief ico_apf_com_connect
438 * This function connects to AppsController.
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)
445 /*--------------------------------------------------------------------------*/
447 ico_apf_com_connect(ico_apf_com_handle_t *handle)
453 apfw_trace("ico_apf_com_connect: Enter(type=%d)", handle->type);
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;
459 protocol = ICO_PROTOCOL_APPSCONTROLLER;
460 handle->uws_context = ico_uws_create_context(uri_name, protocol);
462 if (handle->uws_context == NULL) {
463 apfw_error("ico_apf_com_connect: ico_uws_create_context Error(%s,%s)",
465 apfw_trace("ico_apf_com_connect: Leave(RESOURCE_E_INIT_COM_FAILD)");
466 return ICO_APF_RESOURCE_E_INIT_COM_FAILD;
468 apfw_trace("ico_apf_com_connect: create client context 0x%08x",
469 (int)handle->uws_context);
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;
478 /* dispatch for connection */
479 ico_apf_com_dispatch(handle);
481 if (handle->fd > 0) {
482 (void)ico_apf_poll_fd_add(handle->fd, POLLIN|POLLOUT);
485 apfw_trace("ico_apf_com_connect: Leave(OK, fd=%d)", handle->fd);
486 return ICO_APF_RESOURCE_E_NONE;
489 /*--------------------------------------------------------------------------*/
491 * @brief ico_apf_com_isconnected
492 * return a connection status with AppsController
494 * @param[in] handle AppsController's handle
495 * @return connection status
497 * @retval 0 not connetc
499 /*--------------------------------------------------------------------------*/
501 ico_apf_com_isconnected(ico_apf_com_handle_t *handle)
503 return((handle != NULL) && (handle->service_on != 0));
506 /*--------------------------------------------------------------------------*/
508 * @brief ico_apf_com_dispatch
509 * The accumulated transmitted and received data is processed.
510 * Connecting AppsController program must call this function.
512 * @param[in] handle connect handle, if NULL target is all connect
515 /*--------------------------------------------------------------------------*/
517 ico_apf_com_dispatch(ico_apf_com_handle_t *handle)
521 ico_apf_com_handle_t *p;
524 /* If program has not connected, nothing is done. */
525 apfw_warn("ico_apf_com_dispatch: handle dose not exist");
537 ico_uws_service(p->uws_context);
539 /* If received data is suspended, it processes. */
540 while (p->rtail != p->rhead) {
542 if (p->rhead >= (ICO_APF_RESOURCE_WSOCK_BUFR-1)) {
548 n = p->rtail - p->rhead;
550 n = ICO_APF_RESOURCE_WSOCK_BUFR + n;
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);
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);
569 /*--------------------------------------------------------------------------*/
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.
576 * @param[in] handle AppsController's handle
578 * @retval ICO_APF_RESOURCE_E_NONE success
579 * @retval ICO_APF_RESOURCE_E_NOT_INITIALIZED error(already finished)
581 /*--------------------------------------------------------------------------*/
583 ico_apf_com_term_client(ico_apf_com_handle_t *handle)
585 ico_apf_com_handle_t *p;
587 apfw_trace("ico_apf_com_term_client: Enter");
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;
593 handle->service_on = 0;
595 if (handle == handles) {
596 handles = handles->next;
601 if (p->next == handle) break;
605 apfw_trace("ico_apf_com_term_client: Leave(RESOURCE_E_NOT_INITIALIZED)");
606 return ICO_APF_RESOURCE_E_NOT_INITIALIZED;
608 p->next = handle->next;
611 if (handle->uws_context) {
612 ico_uws_unset_event_cb(handle->uws_context);
613 ico_uws_close(handle->uws_context);
615 handle->next = freehandles;
616 freehandles = handle;
618 apfw_trace("ico_apf_com_term_client: Leave(OK)");
619 return ICO_APF_RESOURCE_E_NONE;
622 /*--------------------------------------------------------------------------*/
624 * @brief ico_apf_com_term_server
625 * finish to connect to application
627 * @param[in] handle AppsController's handle
629 * @retval ICO_APF_RESOURCE_E_NONE success
630 * @retval ICO_APF_RESOURCE_E_NOT_INITIALIZED error(already finished)
632 /*--------------------------------------------------------------------------*/
634 ico_apf_com_term_server(ico_apf_com_handle_t *handle)
636 ico_apf_com_handle_t *p;
638 apfw_trace("ico_apf_com_term_server: Enter");
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;
644 handle->service_on = 0;
646 if (handle == handles) {
647 handles = handles->next;
652 if (p->next == handle) break;
656 apfw_trace("ico_apf_com_term_server: Leave(RESOURCE_E_NOT_INITIALIZED)");
657 return ICO_APF_RESOURCE_E_NOT_INITIALIZED;
659 p->next = handle->next;
662 if (handle->uws_context) {
663 ico_uws_unset_event_cb(handle->uws_context);
664 ico_uws_close(handle->uws_context);
666 handle->next = freehandles;
667 freehandles = handle;
669 apfw_trace("ico_apf_com_term_server: Leave(OK)");
670 return ICO_APF_RESOURCE_E_NONE;
673 /*--------------------------------------------------------------------------*/
675 * @brief ico_apf_com_send
676 * Accumulates the data send to AppsController/application.
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
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)
689 /*--------------------------------------------------------------------------*/
691 ico_apf_com_send(ico_apf_com_handle_t *handle,
692 const int cmd, const int res, const char *appid, char *msg)
698 apfw_trace("ico_apf_com_send: Enter(%08x, %d, %d) callback=%d",
699 (int)handle, cmd, res, uws_callbacked);
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;
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;
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;
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;
739 if (st >= (ICO_APF_RESOURCE_WSOCK_BUFS-1)) {
745 if (st == handle->shead) {
746 /* send buffer is full */
747 ico_apf_poll_write_event(handle, 3);
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;
755 /* accumulate send buffer */
756 if ((! appid) || (*appid == 0)) {
757 handle->sbuf[cur]->pid = getpid();
758 handle->sbuf[cur]->appid[0] = 0;
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;
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;
773 if (uws_callbacked) {
774 /* send call from communication callback, delayed send */
775 ico_apf_poll_write_event(handle, 1);
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)) {
784 if (handle->shead >= (ICO_APF_RESOURCE_WSOCK_BUFS-1)) {
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");
796 ico_apf_com_dispatch(handle); /* try to service */
798 apfw_trace("ico_apf_com_send: Leave(OK)");
799 return ICO_APF_RESOURCE_E_NONE;
802 /*--------------------------------------------------------------------------*/
804 * @brief ico_apf_com_realsend
805 * send messege to AppsController
807 * @param[in] handle AppsController's handle
808 * @param[in] msg Send message
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)
815 /*--------------------------------------------------------------------------*/
817 ico_apf_com_realsend(ico_apf_com_handle_t *handle, ico_apf_com_buffer_t *msg)
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;
827 if ((handle->type & ICO_APF_COM_TYPE_CONNECTION) == ICO_APF_COM_TYPE_SOUNDMGR) {
828 /* send to Multi Sound Manager */
830 snprintf(buf, sizeof(buf), "%s %d",
831 ico_apf_sound_table[msg->cmd-ICO_APF_SOUND_COMMAND_MIN], msg->res);
834 strcpy(buf, ico_apf_sound_table[msg->cmd-ICO_APF_SOUND_COMMAND_MIN]);
838 /* send tp AppsController */
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);
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],
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));
856 apfw_trace("ico_apf_com_realsend: Leave(OK)");
857 return ICO_APF_RESOURCE_E_NONE;
860 /*--------------------------------------------------------------------------*/
862 * @brief ico_apf_com_addeventlistener
863 * register a callback function called receive message from AppsController
865 * @param[in] handle AppsComtroller's handle
866 * @param[in] listener callback function
867 * @param[in] user_data Arbitrary data
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)
873 /*--------------------------------------------------------------------------*/
875 ico_apf_com_addeventlistener(ico_apf_com_handle_t *handle,
876 ico_apf_com_eventlistener listener, void* user_data)
878 if (handle == NULL) {
879 if (global_listener) {
880 return ICO_APF_RESOURCE_E_INVAL;
882 global_listener = listener;
883 global_user_data = user_data;
884 return ICO_APF_RESOURCE_E_NONE;
887 if (handle->listener) {
888 return ICO_APF_RESOURCE_E_INVAL;
890 handle->user_data = user_data;
891 handle->listener = listener;
893 if (! global_listener) {
895 global_listener = listener;
897 return ICO_APF_RESOURCE_E_NONE;
900 /*--------------------------------------------------------------------------*/
902 * @brief ico_apf_com_removeeventlistener
903 * unregister a callback function called receive message
905 * @param[in] handle AppsComtroller's handle
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)
911 /*--------------------------------------------------------------------------*/
913 ico_apf_com_removeeventlistener(ico_apf_com_handle_t *handle)
915 if (handle == NULL) {
916 if (! global_listener) {
917 return ICO_APF_RESOURCE_E_INVAL;
919 global_listener = NULL;
920 global_user_data = NULL;
921 return ICO_APF_RESOURCE_E_NONE;
924 if (! handle->listener) {
925 return ICO_APF_RESOURCE_E_INVAL;
927 handle->listener = NULL;
928 handle->user_data = NULL;
930 return ICO_APF_RESOURCE_E_NONE;
933 /*--------------------------------------------------------------------------*/
935 * @brief ico_apf_callback_uws
936 * this callback function notified from communication.
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
945 /*--------------------------------------------------------------------------*/
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)
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];
969 handle = (ico_apf_com_handle_t *)user_data;
972 if (handle->type == ICO_APF_COM_TYPE_SVR_APPSCTL) {
973 /* search client handle for server */
976 if (handle2->uws_id == id) break;
977 handle2 = handle2->next;
983 apfw_trace("ico_apf_callback_uws: new server side client");
985 handle = ico_apf_alloc_handle();
988 apfw_error("ico_apf_callback_uws: No Memory");
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;
997 strncpy(handle->ip, ico_uws_get_uri(handle->uws_context),
998 ICO_APF_RESOURCE_IP_LEN-1);
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;
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);
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);
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);
1022 ico_apf_poll_fd_del(detail->_ico_uws_fd.fd);
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;
1032 /* save receive message to receive buffer */
1033 ico_apf_put_recvmsg(ICO_APF_RESOURCE_STATE_DISCONNECTED, 0,
1034 pid, "\0", NULL, 0, handle);
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))) {
1042 apfw_warn("ico_apf_callback_uws: Receive Length Error, Len=%d", len);
1046 apfw_trace("ico_apf_callback_uws: ICO_UWS_EVT_RECEIVE[%s]", msg);
1048 /* analize event code */
1049 if ((handle->type & ICO_APF_COM_TYPE_CONNECTION) == ICO_APF_COM_TYPE_SOUNDMGR) {
1050 /* Multi Sound Manager */
1052 for (nparam = 0; nparam < 10; nparam++) {
1053 for (; msg[i]; i++) {
1054 if (msg[i] != ' ') break;
1056 if (msg[i] == 0) break;
1057 param[nparam].start = i;
1058 for (; msg[i]; i++) {
1059 if (msg[i] == ' ') break;
1061 param[nparam].end = i;
1065 apfw_warn("ico_apf_callback_uws: Illegal Message Format(no param)");
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;
1074 if (cmd > ICO_APF_SOUND_COMMAND_MAX) {
1076 apfw_warn("ico_apf_callback_uws: Receive Event Nop(cmd=%d)", cmd);
1079 res = ICO_APF_RESID_BASIC_SOUND;
1084 for (i = 1; i < nparam; i++) {
1085 if (memcmp(&msg[param[i].start],
1086 "#pid#", param[i].end - param[i].start) == 0) {
1089 pid = strtol(&msg[param[i].start], (char **)0, 0);
1090 if (ico_apf_get_app_id(pid, appid) != ICO_APP_CTL_E_NONE) {
1092 apfw_trace("ico_apf_callback_uws: Unknown pid=%d", pid);
1097 else if (memcmp(&msg[param[i].start],
1098 "#stream_name#", param[i].end - param[i].start) == 0) {
1100 /* no need stream name */
1102 else if (memcmp(&msg[param[i].start],
1103 "#app_name#", param[i].end - param[i].start) == 0) {
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;
1113 else if (memcmp(&msg[param[i].start],
1114 "#stream_state#", param[i].end - param[i].start) == 0) {
1116 /* no need stream_state */
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);
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)
1134 if (cmd > ICO_APF_RESOURCE_COMMAND_MAX) {
1136 apfw_warn("ico_apf_callback_appsctl: Receive Event Error(cmd=%d)",
1140 for (res = ICO_APF_RESOURCE_RESID_MIN;
1141 res <= ICO_APF_RESOURCE_RESID_MAX; res++) {
1143 ico_apf_res_table[res-ICO_APF_RESOURCE_RESID_MIN], 4) == 0) break;
1145 if (res > ICO_APF_RESOURCE_RESID_MAX) {
1147 apfw_warn("ico_apf_callback_uws: Receive Resource Error(resid=%d)",
1153 for (st = 9; msg[st]; st++) {
1154 if (msg[st] == ' ') break;
1156 if ((msg[st] >= '0') && (msg[st] <= '9')) {
1157 pid = pid * 10 + msg[st] - '0';
1169 if (pid > ICO_UXF_MAX_PROCESS_NAME )
1170 pid = ICO_UXF_MAX_PROCESS_NAME;
1171 strncpy(appid, &msg[9], pid);
1175 if (msg[st] == ' ') st++;
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);
1186 apfw_trace("ico_apf_callback_uws: UnKnown reason=%d", reason);
1192 /*--------------------------------------------------------------------------*/
1194 * @brief ico_apf_put_recvmsg
1195 * put receive message into receive buffer
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
1206 /*--------------------------------------------------------------------------*/
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)
1214 /* check receive buffer overflow */
1215 if (handle->rtail >= (ICO_APF_RESOURCE_WSOCK_BUFR-1)) {
1219 nexttail = handle->rtail + 1;
1221 if (handle->rhead == nexttail) {
1222 /* receive buffer overflow, drops all message */
1223 apfw_warn("ico_apf_put_recvmsg: receive buffer overflow");
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;
1236 memcpy(handle->rbuf[handle->rtail]->msg, msg, len);
1237 handle->rbuf[handle->rtail]->msg[len] = 0;
1240 handle->rbuf[handle->rtail]->msg[0] = 0;
1242 handle->rtail = nexttail;
1243 i = handle->rtail - handle->rhead;
1245 i = ICO_APF_RESOURCE_WSOCK_BUFR + i;
1248 ico_apf_poll_write_event(handle, 1);
1251 /*--------------------------------------------------------------------------*/
1253 * @brief apf_com_poll_fd_add: add file descriptor for poll
1255 * @param[in] fd file descriptor
1256 * @param[in] flag POLL flag(POLLIN,POLLOUT)
1257 * negative means reset
1259 * @retval ICO_APF_RESOURCE_E_NONE success
1260 * @retval ICO_APF_RESOURCE_E_INVAL error(out of memory)
1262 /*--------------------------------------------------------------------------*/
1264 ico_apf_poll_fd_add(const int fd, const int flag)
1266 ico_apf_com_poll_t *p;
1267 ico_apf_com_poll_t *fds[1];
1268 ico_apf_com_handle_t *handle;
1279 /* new file descriptor */
1280 if (freecom_polls) {
1282 freecom_polls = p->next;
1283 p->apf_fd_control = NULL;
1284 p->user_data = NULL;
1287 p = calloc(sizeof(ico_apf_com_poll_t), 1);
1290 apfw_error("ico_apf_poll_fd_add: can not allocate fd control table"
1292 return ICO_APF_RESOURCE_E_INVAL;
1297 p->next = com_polls;
1300 p->flags |= ICO_APF_COM_POLL_ERROR;
1302 if (flag & (POLLIN|POLLPRI)) {
1303 p->flags |= ICO_APF_COM_POLL_READ;
1305 if (flag & POLLOUT) {
1306 p->flags |= ICO_APF_COM_POLL_WRITE;
1310 if ((-flag) & (POLLIN|POLLPRI)) {
1311 p->flags &= ~ICO_APF_COM_POLL_READ;
1313 if ((-flag) & POLLOUT) {
1314 p->flags &= ~ICO_APF_COM_POLL_WRITE;
1320 if (handle->fd == fd) break;
1321 handle = handle->next;
1324 p->apf_fd_control = (void *)handle;
1328 apfw_trace("ico_apf_poll_fd_add: fd=%d dose not exist in handles", fd);
1329 p->apf_fd_control = NULL;
1332 /* regist callback function */
1333 if (ico_apf_pollfd_func) {
1336 (*ico_apf_pollfd_func)(fds, 1);
1338 return ICO_APF_RESOURCE_E_NONE;
1341 /*--------------------------------------------------------------------------*/
1343 * @brief apf_com_poll_fd_del: delete file descriptor for poll
1345 * @param[in] fd file descriptor
1348 /*--------------------------------------------------------------------------*/
1350 ico_apf_poll_fd_del(const int fd)
1352 ico_apf_com_poll_t *p;
1353 ico_apf_com_poll_t *bp;
1354 ico_apf_com_poll_t *fds[1];
1356 /* search file descriptor */
1365 com_polls = p->next;
1368 if (p->apf_fd_control) {
1369 ((ico_apf_com_handle_t *)(p->apf_fd_control))->poll = NULL;
1372 /* call callback function */
1373 if (ico_apf_pollfd_func) {
1377 (*ico_apf_pollfd_func)(fds, 1);
1379 p->next = freecom_polls;
1387 /*--------------------------------------------------------------------------*/
1389 * @brief ico_apf_com_poll_fd_control: Set or Unset callback of file descriptors
1391 * @param[in] poll_fd_cb The callback function.
1393 * @retval ICO_APF_RESOURCE_E_NONE success
1395 /*--------------------------------------------------------------------------*/
1397 ico_apf_com_poll_fd_control(ico_apf_com_pollfd_cb poll_fd_cb)
1399 ico_apf_com_poll_t *p;
1400 ico_apf_com_poll_t **fds;
1404 /* regist callback function */
1405 ico_apf_pollfd_func = poll_fd_cb;
1407 if (ico_apf_pollfd_func) {
1408 /* if regist, call callback for all file descriptors */
1410 /* count number of file descriptors */
1418 fds = malloc(sizeof(ico_apf_com_poll_t *) * count);
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);
1438 return ICO_APF_RESOURCE_E_NONE;
1441 /*--------------------------------------------------------------------------*/
1443 * @brief ico_apf_com_poll_fd_event: Notify the changes of file descriptor's state
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
1448 * @retval ICO_APF_RESOURCE_E_NONE success
1450 /*--------------------------------------------------------------------------*/
1452 ico_apf_com_poll_fd_event(ico_apf_com_poll_t *fd_ctl, int flags)
1455 ico_apf_com_handle_t *handle = (ico_apf_com_handle_t *)fd_ctl->apf_fd_control;
1457 uifw_trace("ico_apf_com_poll_fd_event: handle=%08x fd=%d flags=%x",
1458 (int)handle, handle ? handle->fd : 0, flags);
1460 ico_apf_com_dispatch(handle); /* try to service */
1463 ico_apf_com_dispatch(NULL); /* try to service for server*/
1467 /* send if send data exist */
1468 if ((handle->stail != handle->shead) &&
1469 (handle->uws_context != NULL) &&
1470 (handle->uws_id != NULL)) {
1472 if (handle->shead >= (ICO_APF_RESOURCE_WSOCK_BUFS-1)) {
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");
1482 ico_apf_com_dispatch(handle); /* try to service */
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);
1493 ico_apf_poll_write_event(handle, 1);
1496 return ICO_APF_RESOURCE_E_NONE;
1499 /*--------------------------------------------------------------------------*/
1501 * @brief ico_apf_poll_write_event: Write event control for poll
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
1511 /*--------------------------------------------------------------------------*/
1513 ico_apf_poll_write_event(ico_apf_com_handle_t *handle, const int write)
1515 ico_apf_com_poll_t *fds[1];
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);
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);