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
21 #include <sys/socket.h>
22 #include <netinet/in.h>
24 #include <libwebsockets.h>
25 #include "ico_apf_private.h"
26 #include "ico_uxf_conf.h"
28 /*==============================================================================*/
29 /* define static function prototype */
30 /*==============================================================================*/
31 static ico_apf_com_handle_t *ico_apf_alloc_handle(void);
32 static int ico_apf_com_connect(ico_apf_com_handle_t *handle);
33 static int ico_apf_com_realsend(ico_apf_com_handle_t *handle,
34 ico_apf_com_buffer_t *msg);
35 static int ico_apf_callback_http(struct libwebsocket_context *context,
36 struct libwebsocket *wsi,
37 enum libwebsocket_callback_reasons reason,
38 void *user, void *in, size_t len);
39 static int ico_apf_callback_websock(struct libwebsocket_context *this,
40 struct libwebsocket *wsi,
41 enum libwebsocket_callback_reasons reason,
42 void *user, void *in, size_t len);
43 static void ico_apf_put_recvmsg(const int cmd, const int res, const int pid,
44 const char *appid, char *msg, const int len,
45 ico_apf_com_handle_t *handle);
46 static int ico_apf_poll_fd_add(const int fd, const int flag);
47 static void ico_apf_poll_fd_del(const int fd);
48 static void ico_apf_poll_write_event(ico_apf_com_handle_t *handle, const int write);
50 /*==============================================================================*/
51 /* variable & table */
52 /*==============================================================================*/
53 /* variable that control program name in Linux */
54 extern const char *program_invocation_name;
56 /* application framework control handle */
57 static struct libwebsocket_context *global_lwscontext = NULL;
58 static ico_apf_com_handle_t *handles = NULL;
59 static ico_apf_com_handle_t *freehandles = NULL;
61 /* file descriptor controll table */
62 static ico_apf_com_poll_t *com_polls = NULL;
63 static ico_apf_com_poll_t *freecom_polls = NULL;
64 static ico_apf_com_pollfd_cb ico_apf_pollfd_func = NULL;
66 /* global user listener */
67 static ico_apf_com_eventlistener global_listener = NULL;
68 static void *global_user_data = NULL;
70 /* flag for callback from libwebsockets */
71 static int lws_callbacked = 0;
73 /* libwebsockets's protocol number */
74 enum appsctl_protocols {
75 PROTOCOL_HTTP, /* HTTP handshake(Certainly required) */
76 PROTOCOL_APPSCONTROLLER, /* AppsController protocol */
77 PROTOCOL_APPSEND /* everytime means final */
79 enum soundmgr_protocols {
80 PROTOCOL_SOUNDMGR, /* Multi Sound Manager protocol */
81 PROTOCOL_SOUNDEND /* everytime means final */
84 /* list of libwebsockets protocol for AppsController */
85 static struct libwebsocket_protocols apps_protocols[] = {
86 /* HTTP handshake(Certainly required) */
87 { "http_only", ico_apf_callback_http, 0 },
88 /* callback from websocket to appscontroller*/
89 { ICO_PROTOCOL_APPSCONTROLLER, ico_apf_callback_websock, sizeof(void *) },
90 { NULL, NULL, 0 } /* everytime means final */
93 /* list of libwebsockets protocol for pulse-audio plugin */
94 static struct libwebsocket_protocols sound_protocols[] = {
95 /* callback from websocket to soundmanager*/
96 { ICO_PROTOCOL_MULTISOUNDMANAGER, ico_apf_callback_websock, sizeof(void *) },
97 { NULL, NULL, 0 } /* everytime means final */
100 /* command/event string */
101 const char *ico_apf_cmd_table[] = {
102 ICO_APF_SRESOURCE_STATE_ACQUIRED, /* acquired */
103 ICO_APF_SRESOURCE_STATE_DEPRIVED, /* deprived */
104 ICO_APF_SRESOURCE_STATE_WAITTING, /* waitting */
105 ICO_APF_SRESOURCE_STATE_RELEASED, /* released */
107 ICO_APF_SRESOURCE_COMMAND_GET, /* get command */
108 ICO_APF_SRESOURCE_COMMAND_RELEASE, /* release command */
109 ICO_APF_SRESOURCE_COMMAND_ADD, /* add command */
110 ICO_APF_SRESOURCE_COMMAND_CHANGE, /* change command */
111 ICO_APF_SRESOURCE_COMMAND_DELETE, /* delete command */
113 ICO_APF_SRESOURCE_REPLY_OK, /* OK reply */
114 ICO_APF_SRESOURCE_REPLY_NG, /* NG reply */
115 ICO_APF_SRESOURCE_STATE_CONNECTED, /* connected */
116 ICO_APF_SRESOURCE_STATE_DISCONNECTED /* disconnected */
118 const char *ico_apf_res_table[] = {
119 ICO_APF_SRESID_BASIC_SCREEN, /* basic screen */
120 ICO_APF_SRESID_INT_SCREEN, /* interrupt screen */
121 ICO_APF_SRESID_ON_SCREEN, /* onscreeen */
122 ICO_APF_SRESID_BASIC_SOUND, /* basic sound */
123 ICO_APF_SRESID_INT_SOUND, /* interrupt sound */
124 ICO_APF_SRESID_INPUT_DEV /* input device */
126 const char *ico_apf_sound_table[] = {
127 ICO_APF_SSOUND_COMMAND_MUTEON, /* mute on */
128 ICO_APF_SSOUND_COMMAND_MUTEOFF, /* mute off */
129 ICO_APF_SSOUND_COMMAND_CANCEL, /* cancel */
130 ICO_APF_SSOUND_COMMAND_GETLIST, /* get stream list */
131 ICO_APF_SSOUND_COMMAND_FRESH, /* fresh */
132 ICO_APF_SSOUND_COMMAND_ALLMUTEON, /* mute set all stream*/
133 ICO_APF_SSOUND_COMMAND_ALLMUTEOFF, /* mute reset all stream*/
134 ICO_APF_SSOUND_EVENT_NEW, /* created new stream*/
135 ICO_APF_SSOUND_EVENT_FREE, /* destoryed stream */
136 ICO_APF_SSOUND_REPLY_LIST /* reply of stream list*/
139 /*--------------------------------------------------------------------------*/
141 * @brief ico_apf_com_init_client
142 * This function connects to AppsController in HomeScreen.
143 * If you use AppsController's function, you must call this function.
145 * @param[in] uri connection URI, NULL is host myself
146 * @param[in] type connection type
147 * @return handle address
148 * @retval handle address success
149 * @retval NULL error(failed connect AppsController)
151 /*--------------------------------------------------------------------------*/
152 ico_apf_com_handle_t *
153 ico_apf_com_init_client(const char *uri, const int type)
158 ico_apf_com_poll_t *p;
159 ico_apf_com_handle_t *handle;
160 Ico_Uxf_Sys_Config *sysconf;
161 Ico_Uxf_Sys_Config *ifsysconf = (Ico_Uxf_Sys_Config *)0xffffffff;
165 apfw_trace("ico_apf_com_init_client: Enter(%s,%d)",
166 uri ? uri : "(NULL)", type);
168 ifsysconf = (Ico_Uxf_Sys_Config *)ico_uxf_ifGetSysConfig();
171 /* Another module already reads config file */
172 /* In this case, you don't release sysconf at finished this function. */
173 sysconf = (Ico_Uxf_Sys_Config *)ifsysconf;
176 /* never read a system config */
177 sysconf = (Ico_Uxf_Sys_Config *)ico_uxf_getSysConfig();
180 apfw_error("ico_apf_com_init_client: Leave(can not read configuration files)");
184 /* If URI is host name, find address from config. */
185 /* If node is a null character string, it regards NULL. */
186 Ico_Uxf_conf_host *phost =
187 (Ico_Uxf_conf_host *) ico_uxf_getSysHostById(ico_uxf_getSysHostByName(uri));
189 address = phost->address;
192 /* If don't find host name from config, regards ipaddress is set as node.*/
193 address = (char *)uri;
196 /* environment variable for port & host */
197 if (type == ICO_APF_COM_TYPE_APPSCTL) {
198 port = sysconf->misc.appscontrollerport;
199 port_env = getenv("ICO_APF_APPSCTL_PORT");
200 host_env = getenv("ICO_APF_APPSCTL_HOST");
203 port = sysconf->misc.soundpluginport;
204 port_env = getenv("ICO_APF_SOUNDMGR_PORT");
205 host_env = getenv("ICO_APF_SOUNDMGR_HOST");
215 /* get a port number from system configuration(system/system.conf) */
216 apfw_trace("ico_apf_com_init_client: connect Host=%s Port=%d", address, port);
220 if ((strcmp(handle->ip, address) == 0) &&
221 (handle->port == port) && (handle->type == type)) {
224 handle = handle->next;
228 apfw_trace("ico_apf_com_init_client: Leave(Connected)");
232 handle = ico_apf_alloc_handle();
234 apfw_trace("ico_apf_com_init_client: Leave(No Memory)");
240 strncpy(handle->ip, address, ICO_APF_RESOURCE_IP_LEN-1);
241 handle->ip[ICO_APF_RESOURCE_IP_LEN-1] = 0;
243 /* connect to AppsController */
244 i = ico_apf_com_connect(handle);
247 ico_uxf_closeSysConfig();
250 if (i != ICO_APF_RESOURCE_E_NONE) {
251 apfw_error("ico_apf_com_init_client: Leave(RESOURCE_E_INIT_COM_FAILD)");
252 (void) ico_apf_com_term_client(handle);
256 /* Try to connection */
257 ico_apf_com_dispatch(handle, 0);
258 handle->fd = libwebsocket_get_socket_fd(handle->wsi_connection);
260 /* add poll callback if fd is exist */
261 if (handle->fd > 0) {
262 handle->service_on = 1;
263 (void)ico_apf_poll_fd_add(handle->fd, POLLIN);
268 if (p->fd == handle->fd) {
269 p->apf_fd_control = (void *)handle;
274 apfw_trace("ico_apf_com_init_client: Leave(OK,fd=%d)", handle->fd);
278 /*--------------------------------------------------------------------------*/
280 * @brief ico_apf_com_init_server
281 * This function connects to aplicationto in AppsController.
283 * @param[in] uri my URI, NULL is host myself
284 * @param[in] type connection type
285 * @return handle address
286 * @retval handle address success
287 * @retval NULL error(failed connect AppsController)
289 /*--------------------------------------------------------------------------*/
290 ico_apf_com_handle_t *
291 ico_apf_com_init_server(const char *uri, const int type)
297 ico_apf_com_handle_t *handle;
298 Ico_Uxf_Sys_Config *sysconf;
299 Ico_Uxf_Sys_Config *ifsysconf = (Ico_Uxf_Sys_Config *)0xffffffff;
302 apfw_trace("ico_apf_com_init_server: Enter(%s,%d)",
303 uri ? uri : "(NULL)", type);
305 ifsysconf = (Ico_Uxf_Sys_Config *)ico_uxf_ifGetSysConfig();
308 /* Another module already reads config file */
309 /* In this case, you don't release sysconf at finished this function. */
310 sysconf = (Ico_Uxf_Sys_Config *)ifsysconf;
313 /* never read a system config */
314 sysconf = (Ico_Uxf_Sys_Config *)ico_uxf_getSysConfig();
317 apfw_error("ico_apf_com_init_server: Leave(can not read configuration files)");
321 /* currently server support only Application Controler */
322 svrtype = ICO_APF_COM_TYPE_SVR_APPSCTL;
324 /* If URI is host name, find address from config. */
325 /* If node is a null character string, it regards NULL. */
326 Ico_Uxf_conf_host *phost =
327 (Ico_Uxf_conf_host *) ico_uxf_getSysHostById(ico_uxf_getSysHostByName(uri));
329 address = phost->address;
332 /* If don't find host name from config, regards ipaddress is set as node.*/
333 address = (char *)uri;
336 /* get a port number from system configuration(system/system.conf) */
337 port = sysconf->misc.appscontrollerport;
338 apfw_trace("ico_apf_com_init_server: Config, Host=%s Port=%d", address, port);
340 /* environment variable for port */
341 port = sysconf->misc.appscontrollerport;
342 port_env = getenv("ICO_APF_APPSCTL_PORT");
350 if ((strcmp(address, handle->ip) == 0) &&
351 (handle->port == port) && (handle->type == svrtype)) break;
352 handle = handle->next;
356 apfw_trace("ico_apf_com_init_server: Leave(Created)");
360 handle = ico_apf_alloc_handle();
362 apfw_error("ico_apf_com_init_server: Leave(No Memory)");
366 handle->type = svrtype;
368 strncpy(handle->ip, address, ICO_APF_RESOURCE_IP_LEN-1);
369 handle->ip[ICO_APF_RESOURCE_IP_LEN-1] = 0;
371 /* connect to AppsController */
372 handle->wsi_context = libwebsocket_create_context(port, NULL, apps_protocols,
373 libwebsocket_internal_extensions,
374 NULL, NULL, -1, -1, 0);
375 if (! handle->wsi_context) {
376 apfw_error("ico_apf_com_init_server: Leave(libwebsockets create Error)");
377 (void) ico_apf_com_term_server(handle);
380 apfw_trace("ico_apf_com_init_server: create server context 0x%08x",
381 (int)handle->wsi_context);
383 global_lwscontext = handle->wsi_context;
385 ico_apf_com_dispatch(handle, 0);
387 apfw_trace("ico_apf_com_init_server: Leave(OK)");
391 /*--------------------------------------------------------------------------*/
393 * @brief ico_apf_alloc_handle
394 * Allocate ccommunication handle.
397 * @return handle address
398 * @retval addres success, return handle address
399 * @retval NULL error(no memory)
401 /*--------------------------------------------------------------------------*/
402 static ico_apf_com_handle_t *
403 ico_apf_alloc_handle(void)
405 ico_apf_com_handle_t *handle;
410 handle = malloc(sizeof(ico_apf_com_handle_t));
414 memset(handle, 0, sizeof(ico_apf_com_handle_t));
416 /* Queue buffers initialize. */
417 for (i = 0; i < ICO_APF_RESOURCE_WSOCK_BUFR; i++) {
418 handle->rbuf[i] = calloc(sizeof(ico_apf_com_buffer_t), 1);
419 if (! handle->rbuf[i]) {
423 for (i = 0; i < ICO_APF_RESOURCE_WSOCK_BUFS; i++) {
424 handle->sbuf[i] = calloc(sizeof(ico_apf_com_buffer_t), 1);
425 if (! handle->sbuf[i]) {
431 handle = freehandles;
432 freehandles = freehandles->next;
436 handle->wsi_context = NULL;
437 handle->wsi_connection = NULL;
438 handle->service_on = 0;
440 handle->stoprecv = 0;
445 handle->listener = NULL;
446 handle->user_data = NULL;
451 handle->next = handles;
458 /*--------------------------------------------------------------------------*/
460 * @brief ico_apf_com_connect
461 * This function connects to AppsController.
463 * @param[in] handle Communication handle
464 * @return result status
465 * @retval ICO_APF_RESOURCE_E_NONE success
466 * @retval ICO_APF_RESOURCE_E_INIT_COM_FAILD error(connect failed)
468 /*--------------------------------------------------------------------------*/
470 ico_apf_com_connect(ico_apf_com_handle_t *handle)
474 apfw_trace("ico_apf_com_connect: Enter(type=%d)", handle->type);
476 int ietf_version = -1; /* latest */
478 sprintf(origin,"%d %s",getpid(),program_invocation_name);
480 apfw_trace("ico_apf_com_connect: libwebsocket_create_context");
481 handle->wsi_context = libwebsocket_create_context(
482 CONTEXT_PORT_NO_LISTEN, NULL,
483 (handle->type & ICO_APF_COM_TYPE_CONNECTION)
484 == ICO_APF_COM_TYPE_SOUNDMGR ?
485 sound_protocols : apps_protocols,
486 libwebsocket_internal_extensions,
487 NULL, NULL, -1, -1, 0);
488 if (handle->wsi_context == NULL) {
489 apfw_error("ico_apf_com_connect: Leave(RESOURCE_E_INIT_COM_FAILD)");
490 return ICO_APF_RESOURCE_E_INIT_COM_FAILD;
492 apfw_trace("ico_apf_com_connect: create client context 0x%08x",
493 (int)handle->wsi_context);
495 /* connect to Application Manager by WebSocket */
496 apfw_trace("ico_apf_com_connect: libwebsocket_client_connect %s:%d",
497 handle->ip, handle->port);
498 for (rep = 0; rep < (1000/50); rep++) {
499 handle->wsi_connection = libwebsocket_client_connect(
501 handle->ip, handle->port, 0,
502 "/", handle->ip, origin,
503 (handle->type == ICO_APF_COM_TYPE_APPSCTL) ?
504 apps_protocols[PROTOCOL_APPSCONTROLLER].name :
505 sound_protocols[PROTOCOL_SOUNDMGR].name,
507 if (handle->wsi_connection) break;
510 if (handle->wsi_connection == NULL) {
511 apfw_warn("ico_apf_com_connect: Leave(RESOURCE_E_INIT_COM_FAILD)");
512 return ICO_APF_RESOURCE_E_INIT_COM_FAILD;
514 handle->fd = libwebsocket_get_socket_fd(handle->wsi_connection);
515 if (handle->fd > 0) {
516 (void)ico_apf_poll_fd_add(handle->fd, POLLIN|POLLOUT);
518 ico_apf_com_dispatch(handle, 0);
520 apfw_trace("ico_apf_com_connect: Leave(OK, fd=%d)", handle->fd);
521 return ICO_APF_RESOURCE_E_NONE;
524 /*--------------------------------------------------------------------------*/
526 * @brief ico_apf_com_isconnected
527 * return a connection status with AppsController
529 * @param[in] handle AppsController's handle
530 * @return connection status
532 * @retval 0 not connetc
534 /*--------------------------------------------------------------------------*/
536 ico_apf_com_isconnected(ico_apf_com_handle_t *handle)
538 return((handle != NULL) && (handle->service_on != 0));
541 /*--------------------------------------------------------------------------*/
543 * @brief ico_apf_com_dispatch
544 * The accumulated transmitted and received data is processed.
545 * Connecting AppsController program must call this function.
547 * @param[in] handle connect handle, if NULL target is all connect
548 * @param[in] timeoutms maximum wait time on miri-sec.
549 * 0 is no wait, -1 is wait forever.
552 /*--------------------------------------------------------------------------*/
554 ico_apf_com_dispatch(ico_apf_com_handle_t *handle, const int timeoutms)
558 ico_apf_com_handle_t *p;
561 /* If program has not connected, nothing is done. */
562 apfw_warn("ico_apf_com_dispatch: handle dose not exist");
574 if (libwebsocket_service(p->wsi_context, timeoutms) < 0) {
575 apfw_warn("ico_apf_com_dispatch: fd=%d is done", p->fd);
578 /* If received data is suspended, it processes. */
579 while (p->rtail != p->rhead) {
581 if (p->rhead >= (ICO_APF_RESOURCE_WSOCK_BUFR-1)) {
587 n = p->rtail - p->rhead;
589 n = ICO_APF_RESOURCE_WSOCK_BUFR + n;
591 if ((p->stoprecv != 0) &&
592 (n < (ICO_APF_RESOURCE_WSOCK_BUFR/2))) {
593 /* If suspending received data is bellow half, request a send process */
595 apfw_trace("ico_apf_com_dispatch: Flow Control(Start) %d", n);
596 libwebsocket_rx_flow_control(p->wsi_connection, 1);
597 libwebsocket_service(p->wsi_context, 0);
600 if (p->listener != NULL) {
601 handle->listener(p, p->rbuf[rh]->cmd, p->rbuf[rh]->res, p->rbuf[rh]->pid,
602 p->rbuf[rh]->appid, p->rbuf[rh]->msg, p->user_data);
603 libwebsocket_service(p->wsi_context, 0);
605 else if (global_listener != NULL) {
606 global_listener(p, p->rbuf[rh]->cmd, p->rbuf[rh]->res, p->rbuf[rh]->pid,
607 p->rbuf[rh]->appid, p->rbuf[rh]->msg, global_user_data);
608 libwebsocket_service(p->wsi_context, 0);
616 /*--------------------------------------------------------------------------*/
618 * @brief ico_apf_com_term_client
619 * finish to connect to AppsController
620 * It recommends call this function before end of program
621 * that used AppsController.
623 * @param[in] handle AppsController's handle
625 * @retval ICO_APF_RESOURCE_E_NONE success
626 * @retval ICO_APF_RESOURCE_E_NOT_INITIALIZED error(already finished)
628 /*--------------------------------------------------------------------------*/
630 ico_apf_com_term_client(ico_apf_com_handle_t *handle)
632 ico_apf_com_handle_t *p;
634 apfw_trace("ico_apf_com_term_client: Enter");
636 if ((handle == NULL) || (handles == NULL)) {
637 apfw_trace("ico_apf_com_term_client: Leave(RESOURCE_E_NOT_INITIALIZED)");
638 return ICO_APF_RESOURCE_E_NOT_INITIALIZED;
640 handle->service_on = 0;
642 if (handle == handles) {
643 handles = handles->next;
648 if (p->next == handle) break;
652 apfw_trace("ico_apf_com_term_client: Leave(RESOURCE_E_NOT_INITIALIZED)");
653 return ICO_APF_RESOURCE_E_NOT_INITIALIZED;
655 p->next = handle->next;
658 if (handle->wsi_context) {
659 libwebsocket_context_destroy(handle->wsi_context);
661 handle->next = freehandles;
662 freehandles = handle;
664 apfw_trace("ico_apf_com_term_client: Leave(OK)");
665 return ICO_APF_RESOURCE_E_NONE;
668 /*--------------------------------------------------------------------------*/
670 * @brief ico_apf_com_term_server
671 * finish to connect to application
673 * @param[in] handle AppsController's handle
675 * @retval ICO_APF_RESOURCE_E_NONE success
676 * @retval ICO_APF_RESOURCE_E_NOT_INITIALIZED error(already finished)
678 /*--------------------------------------------------------------------------*/
680 ico_apf_com_term_server(ico_apf_com_handle_t *handle)
682 ico_apf_com_handle_t *p;
684 apfw_trace("ico_apf_com_term_server: Enter");
686 if ((handle == NULL) || (handles == NULL)) {
687 apfw_trace("ico_apf_com_term_server: Leave(RESOURCE_E_NOT_INITIALIZED)");
688 return ICO_APF_RESOURCE_E_NOT_INITIALIZED;
690 handle->service_on = 0;
692 if (handle == handles) {
693 handles = handles->next;
698 if (p->next == handle) break;
702 apfw_trace("ico_apf_com_term_server: Leave(RESOURCE_E_NOT_INITIALIZED)");
703 return ICO_APF_RESOURCE_E_NOT_INITIALIZED;
705 p->next = handle->next;
708 if (handle->wsi_context) {
709 libwebsocket_context_destroy(handle->wsi_context);
711 handle->next = freehandles;
712 freehandles = handle;
714 apfw_trace("ico_apf_com_term_server: Leave(OK)");
715 return ICO_APF_RESOURCE_E_NONE;
718 /*--------------------------------------------------------------------------*/
720 * @brief ico_apf_com_send
721 * Accumulates the data send to AppsController/application.
723 * @param[in] handle AppsController's handle
724 * @param[in] cmd command
725 * @param[in] res resource
726 * @param[in] appid application id
727 * @param[in] msg send message
729 * @retval ICO_APF_RESOURCE_E_NONE success
730 * @retval ICO_APF_RESOURCE_E_NOT_INITIALIZED error(not connect)
731 * @retval ICO_APF_RESOURCE_E_COMMUNICATION error(cannot send)
732 * @retval ICO_APF_RESOURCE_E_INVAL error(invalid parameter)
734 /*--------------------------------------------------------------------------*/
736 ico_apf_com_send(ico_apf_com_handle_t *handle,
737 const int cmd, const int res, const char *appid, char *msg)
742 apfw_trace("ico_apf_com_send: Enter(%08x, %d, %d)", (int)handle, cmd, res);
744 if ((handle == NULL) || (! ico_apf_com_isconnected(handle))) {
745 apfw_warn("ico_apf_com_send: Leave(not initialized)");
746 return ICO_APF_RESOURCE_E_NOT_INITIALIZED;
748 if ((handle->type & ICO_APF_COM_TYPE_CONNECTION) != ICO_APF_COM_TYPE_SOUNDMGR) {
749 /* send to AppsController */
750 if ((cmd < ICO_APF_RESOURCE_COMMAND_MIN) ||
751 (cmd > ICO_APF_RESOURCE_COMMAND_MAX) ||
752 (res < ICO_APF_RESOURCE_RESID_MIN) ||
753 (res > ICO_APF_RESOURCE_RESID_MAX)) {
754 apfw_warn("ico_apf_com_send: Leave(invalid command for resource)");
755 return ICO_APF_RESOURCE_E_INVAL;
759 /* send to Multi Sound Manager */
760 if ((cmd < ICO_APF_SOUND_COMMAND_MIN) ||
761 (cmd > ICO_APF_SOUND_COMMAND_CMD)) {
762 apfw_warn("ico_apf_com_send: Leave(invalid command for sound control)");
763 return ICO_APF_RESOURCE_E_INVAL;
769 if (len >= ICO_APF_RESOURCE_MSG_LEN) {
770 apfw_warn("ico_apf_com_send: Leave(invalid message length)");
771 return ICO_APF_RESOURCE_E_INVAL;
781 if (st >= (ICO_APF_RESOURCE_WSOCK_BUFS-1)) {
787 if (st == handle->shead) {
788 /* send buffer is full */
789 ico_apf_poll_write_event(handle, 3);
791 apfw_error("ico_apf_com_send: Leave(send buffer overflow)");
792 ico_apf_poll_fd_del(handle->fd);
793 return ICO_APF_RESOURCE_E_COMMUNICATION;
796 /* accumulate send buffer */
797 if ((! appid) || (*appid == 0)) {
798 handle->sbuf[handle->stail]->pid = getpid();
799 handle->sbuf[handle->stail]->appid[0] = 0;
802 handle->sbuf[handle->stail]->pid = 0;
803 strncpy(handle->sbuf[handle->stail]->appid, appid, ICO_UXF_MAX_PROCESS_NAME);
804 handle->sbuf[handle->stail]->appid[ICO_UXF_MAX_PROCESS_NAME] = 0;
806 apfw_trace("ico_apf_com_send: Send.%d:%d %d %d(%s) <%s>",
807 handle->stail, cmd, res, handle->sbuf[handle->stail]->pid,
808 handle->sbuf[handle->stail]->appid, msg);
809 handle->sbuf[handle->stail]->cmd = cmd;
810 handle->sbuf[handle->stail]->res = res;
811 memcpy(handle->sbuf[handle->stail]->msg, msg, len);
812 handle->sbuf[handle->stail]->msg[len] = 0;
815 libwebsocket_callback_on_writable(handle->wsi_context, handle->wsi_connection);
817 if (lws_callbacked) {
818 /* send call from libwensockets callback, delayed send */
819 ico_apf_poll_write_event(handle, 1);
822 /* not call from callback, direct send */
823 ico_apf_com_dispatch(handle, 0); /* try to service */
825 apfw_trace("ico_apf_com_send: Leave(OK)");
826 return ICO_APF_RESOURCE_E_NONE;
829 /*--------------------------------------------------------------------------*/
831 * @brief ico_apf_com_realsend
832 * send messege to AppsController
834 * @param[in] handle AppsController's handle
835 * @param[in] msg Send message
837 * @retval ICO_APF_RESOURCE_E_NONE success
838 * @retval ICO_APF_RESOURCE_E_NOT_INITIALIZED error(not connect)
839 * @retval ICO_APF_RESOURCE_E_COMMUNICATION error(cannot send)
840 * @retval ICO_APF_RESOURCE_E_INVAL error(invalid parameter)
842 /*--------------------------------------------------------------------------*/
844 ico_apf_com_realsend(ico_apf_com_handle_t *handle, ico_apf_com_buffer_t *msg)
846 unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 512 +
847 LWS_SEND_BUFFER_POST_PADDING];
848 unsigned char *pt = &buf[LWS_SEND_BUFFER_PRE_PADDING];
851 apfw_trace("ico_apf_com_realsend: Enter");
852 if ((handle == NULL) || (! ico_apf_com_isconnected(handle))) {
853 apfw_warn("ico_apf_com_realsend: Leave(Not initialized)");
854 return ICO_APF_RESOURCE_E_NOT_INITIALIZED;
857 if ((handle->type & ICO_APF_COM_TYPE_CONNECTION) == ICO_APF_COM_TYPE_SOUNDMGR) {
858 /* send to Multi Sound Manager */
860 sprintf((char *)pt, "%s %d",
861 ico_apf_sound_table[msg->cmd-ICO_APF_SOUND_COMMAND_MIN], msg->res);
864 strcpy((char *)pt, ico_apf_sound_table[msg->cmd-ICO_APF_SOUND_COMMAND_MIN]);
868 /* send tp AppsController */
870 sprintf((char *)pt, "%s %s %s %s",
871 ico_apf_cmd_table[msg->cmd-ICO_APF_RESOURCE_COMMAND_MIN],
872 ico_apf_res_table[msg->res-ICO_APF_RESOURCE_RESID_MIN],
873 msg->appid, msg->msg);
876 sprintf((char *)pt, "%s %s %d %s",
877 ico_apf_cmd_table[msg->cmd-ICO_APF_RESOURCE_COMMAND_MIN],
878 ico_apf_res_table[msg->res-ICO_APF_RESOURCE_RESID_MIN],
883 apfw_trace("ico_apf_com_realsend: libwebsocket_write[%s]", pt);
884 n = libwebsocket_write(handle->wsi_connection,
885 pt, strlen((char *)pt), LWS_WRITE_TEXT);
887 apfw_error("ico_apf_com_realsend: write error[%d]", n);
888 ico_apf_poll_fd_del(handle->fd);
889 return ICO_APF_RESOURCE_E_COMMUNICATION;
891 usleep(200); /* According to libwebsockets's sample, this is required */
892 apfw_trace("ico_apf_com_realsend: Leave(OK)");
893 return ICO_APF_RESOURCE_E_NONE;
896 /*--------------------------------------------------------------------------*/
898 * @brief ico_apf_com_addeventlistener
899 * register a callback function called receive message from AppsController
901 * @param[in] handle AppsComtroller's handle
902 * @param[in] listener callback function
903 * @param[in] user_data Arbitrary data
905 * @retval ICO_APF_RESOURCE_E_NONE success
906 * @retval ICO_APF_RESOURCE_E_NOT_INITIALIZED error(not connect)
907 * @retval ICO_APF_RESOURCE_E_INVAL error(already registed)
909 /*--------------------------------------------------------------------------*/
911 ico_apf_com_addeventlistener(ico_apf_com_handle_t *handle,
912 ico_apf_com_eventlistener listener, void* user_data)
914 if (handle == NULL) {
915 if (global_listener) {
916 return ICO_APF_RESOURCE_E_INVAL;
918 global_listener = listener;
919 global_user_data = user_data;
920 return ICO_APF_RESOURCE_E_NONE;
923 if (handle->listener) {
924 return ICO_APF_RESOURCE_E_INVAL;
926 handle->user_data = user_data;
927 handle->listener = listener;
929 if (! global_listener) {
931 global_listener = listener;
933 return ICO_APF_RESOURCE_E_NONE;
936 /*--------------------------------------------------------------------------*/
938 * @brief ico_apf_com_removeeventlistener
939 * unregister a callback function called receive message
941 * @param[in] handle AppsComtroller's handle
943 * @retval ICO_APF_RESOURCE_E_NONE success
944 * @retval ICO_APF_RESOURCE_E_NOT_INITIALIZED error(not connect)
945 * @retval ICO_APF_RESOURCE_E_INVAL error(do not registed)
947 /*--------------------------------------------------------------------------*/
949 ico_apf_com_removeeventlistener(ico_apf_com_handle_t *handle)
951 if (handle == NULL) {
952 if (! global_listener) {
953 return ICO_APF_RESOURCE_E_INVAL;
955 global_listener = NULL;
956 global_user_data = NULL;
957 return ICO_APF_RESOURCE_E_NONE;
960 if (! handle->listener) {
961 return ICO_APF_RESOURCE_E_INVAL;
963 handle->listener = NULL;
964 handle->user_data = NULL;
966 return ICO_APF_RESOURCE_E_NONE;
969 /*--------------------------------------------------------------------------*/
971 * @brief ico_apf_callback_http
972 * Connection status is notified from libwebsockets.
974 * @param[in] context libwebsockets context
975 * @param[in] wsi libwebsockets management table
976 * @param[in] reason event type
977 * @param[in] user intact
978 * @param[in] in receive message
979 * @param[in] len message size[BYTE]
984 /*--------------------------------------------------------------------------*/
986 ico_apf_callback_http(struct libwebsocket_context *context,
987 struct libwebsocket *wsi,
988 enum libwebsocket_callback_reasons reason,
989 void *user, void *in, size_t len)
993 fd = libwebsocket_get_socket_fd(wsi);
997 case LWS_CALLBACK_FILTER_NETWORK_CONNECTION:
998 /* a connection demand is received */
999 apfw_trace("ico_apf_callback_http: LWS_CALLBACK_FILTER_NETWORK_CONNECTION fd=%d", fd);
1001 /* If connection is refused, it will return with values other than zero.*/
1002 /* At present, since access control is not introduced, */
1003 /* connection is always permitted. */
1006 case LWS_CALLBACK_ADD_POLL_FD: /* add connection socket */
1007 apfw_trace("ico_apf_callback_http: LWS_CALLBACK_ADD_POLL_FD(%d) %d,%x", fd,
1009 (void)ico_apf_poll_fd_add((int)user, (int)len);
1012 case LWS_CALLBACK_DEL_POLL_FD: /* delete connection socket */
1013 apfw_trace("ico_apf_callback_http: LWS_CALLBACK_DEL_POLL_FD(%d) %d,%x", fd,
1015 ico_apf_poll_fd_del((int)user);
1018 case LWS_CALLBACK_SET_MODE_POLL_FD: /* set status */
1019 apfw_trace("ico_apf_callback_http: LWS_CALLBACK_SET_MODE_POLL_FD(%d) %d,%x", fd,
1021 (void)ico_apf_poll_fd_add((int)user, (int)len);
1024 case LWS_CALLBACK_CLEAR_MODE_POLL_FD: /* clear status */
1025 apfw_trace("ico_apf_callback_http: LWS_CALLBACK_CLEAR_MODE_POLL_FD(%d) %d,%x", fd,
1027 (void)ico_apf_poll_fd_add((int)user, -((int)len));
1031 apfw_trace("ico_apf_callback_http: Unknown reason(%d, fd=%d)", reason, fd);
1039 /*--------------------------------------------------------------------------*/
1041 * @brief ico_apf_callback_websock
1042 * this callback function notified from libwebsockets.
1044 * @param[in] context libwebsockets context
1045 * @param[in] wsi libwebsockets management table
1046 * @param[in] reason event type
1047 * @param[in] user intact
1048 * @param[in] in receive message
1049 * @param[in] len message size[BYTE]
1051 * @retval =0 success
1054 /*--------------------------------------------------------------------------*/
1056 ico_apf_callback_websock(struct libwebsocket_context * this,
1057 struct libwebsocket *wsi,
1058 enum libwebsocket_callback_reasons reason,
1059 void *user, void *in, size_t len)
1069 ico_apf_com_poll_t *p;
1070 ico_apf_com_handle_t *handle;
1071 struct sockaddr_in sin;
1072 unsigned int sin_len;
1073 char appid[ICO_UXF_MAX_PROCESS_NAME+1];
1074 char strname[ICO_UXF_MAX_STREAM_NAME+1];
1081 wsifd = libwebsocket_get_socket_fd(wsi);
1085 if (reason == LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION) {
1086 apfw_trace("ico_apf_callback_websock: server side connected from client");
1088 /* connect from client */
1091 if (handle->fd == wsifd) break;
1092 handle = handle->next;
1095 handle = ico_apf_alloc_handle();
1098 apfw_error("ico_apf_callback_websock: No Memory");
1102 handle->type = ICO_APF_COM_TYPE_APPSCTL;
1103 handle->wsi_context = global_lwscontext;
1104 handle->wsi_connection = wsi;
1106 handle->service_on = 0;
1107 handle->stoprecv = 0;
1109 sin_len = sizeof(sin);
1110 if (getpeername(wsifd, (struct sockaddr *) &sin, &sin_len) >= 0) {
1111 sprintf(handle->ip, "%u.%u.%u.%u",
1112 (sin.sin_addr.s_addr) & 0x0ff,
1113 (sin.sin_addr.s_addr >> 8) & 0x0ff,
1114 (sin.sin_addr.s_addr >> 16) & 0x0ff,
1115 (sin.sin_addr.s_addr >> 24) & 0x0ff);
1118 strcpy(handle->ip, "127.0.0.1");
1123 if (p->fd == handle->fd) {
1124 p->apf_fd_control = (void *)handle;
1130 apfw_trace("ico_apf_callback_websock: server side connected");
1136 if (handle->wsi_connection == wsi) break;
1137 handle = handle->next;
1142 apfw_trace("ico_apf_callback_websock: Handle not exist");
1147 case LWS_CALLBACK_CLIENT_ESTABLISHED:
1148 case LWS_CALLBACK_ESTABLISHED:
1149 apfw_trace("ico_apf_callback_websock: LWS_CALLBACK_ESTABLISHED");
1150 handle->service_on = 1;
1151 handle->stoprecv = 0;
1153 /* save receive message to receive buffer */
1154 ico_apf_put_recvmsg(ICO_APF_RESOURCE_STATE_CONNECTED, 0,
1155 handle->pid, "\0", NULL, 0, handle);
1158 case LWS_CALLBACK_ADD_POLL_FD: /* add connection socket */
1159 (void)ico_apf_poll_fd_add((int)user, (int)len);
1162 case LWS_CALLBACK_DEL_POLL_FD: /* delete connection socket */
1163 ico_apf_poll_fd_del((int)user);
1166 case LWS_CALLBACK_SET_MODE_POLL_FD: /* set status */
1167 (void)ico_apf_poll_fd_add((int)user, (int)len);
1170 case LWS_CALLBACK_CLEAR_MODE_POLL_FD: /* clear status */
1171 (void)ico_apf_poll_fd_add((int)user, -((int)len));
1174 case LWS_CALLBACK_CLOSED:
1175 apfw_trace("ico_apf_callback_websock: LWS_CALLBACK_CLOSED");
1176 handle->service_on = 0;
1178 /* save receive message to receive buffer */
1179 ico_apf_put_recvmsg(ICO_APF_RESOURCE_STATE_DISCONNECTED, 0,
1180 handle->pid, "\0", NULL, 0, handle);
1183 case LWS_CALLBACK_CLIENT_WRITEABLE:
1184 case LWS_CALLBACK_SERVER_WRITEABLE:
1185 if (handle->stail != handle->shead) {
1187 if (handle->shead >= (ICO_APF_RESOURCE_WSOCK_BUFS-1)) {
1193 if (ico_apf_com_realsend(handle, handle->sbuf[st])
1194 != ICO_APF_RESOURCE_E_NONE) {
1195 apfw_warn("ico_apf_callback_websock: ico_apf_com_realsend Error");
1198 if (handle->stail != handle->shead) {
1199 libwebsocket_callback_on_writable(handle->wsi_context,
1200 handle->wsi_connection);
1205 case LWS_CALLBACK_CLIENT_RECEIVE:
1206 case LWS_CALLBACK_RECEIVE:
1209 if ((len <= 9) || (len >= (ICO_APF_RESOURCE_MSG_LEN+9))) {
1211 apfw_warn("ico_apf_callback_websock: Receive Length Error, Len=%d", len);
1214 apfw_trace("ico_apf_callback_websock: LWS_CALLBACK_RECEIVE[%s]", msg);
1216 /* analize event code */
1217 if ((handle->type & ICO_APF_COM_TYPE_CONNECTION)
1218 == ICO_APF_COM_TYPE_SOUNDMGR) {
1219 /* Multi Sound Manager */
1221 for (nparam = 0; nparam < 10; nparam++) {
1222 for (; msg[i]; i++) {
1223 if (msg[i] != ' ') break;
1225 if (msg[i] == 0) break;
1226 param[nparam].start = i;
1227 for (; msg[i]; i++) {
1228 if (msg[i] == ' ') break;
1230 param[nparam].end = i;
1234 apfw_warn("ico_apf_callback_websock: Illegal Message Format(no param)");
1237 for (cmd = ICO_APF_SOUND_COMMAND_CMD+1;
1238 cmd <= ICO_APF_SOUND_COMMAND_MAX; cmd++) {
1239 if (memcmp(&msg[param[0].start],
1240 ico_apf_sound_table[cmd-ICO_APF_SOUND_COMMAND_MIN],
1241 param[0].end - param[0].start) == 0) break;
1243 if (cmd > ICO_APF_SOUND_COMMAND_MAX) {
1245 apfw_warn("ico_apf_callback_websock: Receive Event Error(cmd=%d)", cmd);
1248 res = ICO_APF_RESID_BASIC_SOUND;
1253 for (i = 1; i < nparam; i++) {
1254 if (memcmp(&msg[param[i].start],
1255 "#pid#", param[i].end - param[i].start) == 0) {
1258 pid = strtol(&msg[param[i].start], (char **)0, 0);
1259 if (ico_apf_get_app_id(pid, appid) != ICO_APP_CTL_E_NONE) {
1261 apfw_trace("ico_apf_callback_websock: Unknown pid=%d", pid);
1266 else if (memcmp(&msg[param[i].start],
1267 "#stream_name#", param[i].end - param[i].start) == 0) {
1269 /* no need stream name */
1271 else if (memcmp(&msg[param[i].start],
1272 "#app_name#", param[i].end - param[i].start) == 0) {
1275 strlen = param[i].end - param[i].start;
1276 if (strlen >= ((int)sizeof(strname)))
1277 strlen = sizeof(strname) - 1;
1278 strncpy(strname, &msg[param[i].start], strlen);
1279 strname[strlen] = 0;
1282 else if (memcmp(&msg[param[i].start],
1283 "#stream_state#", param[i].end - param[i].start) == 0) {
1285 /* no need stream_state */
1288 apfw_trace("ico_apf_callback_websock: SoundMgr evt=%d res=%d(%s.%d) str=%s",
1289 cmd, res, appid, pid, strname);
1290 /* save receive message to receive buffer */
1291 ico_apf_put_recvmsg(cmd, res, pid, appid, strname, strlen, handle);
1294 /* AppsController */
1295 for (cmd = ICO_APF_RESOURCE_COMMAND_MIN;
1296 cmd <= ICO_APF_RESOURCE_COMMAND_MAX; cmd++) {
1298 ico_apf_cmd_table[cmd-ICO_APF_RESOURCE_COMMAND_MIN], 3)
1301 if (cmd > ICO_APF_RESOURCE_COMMAND_MAX) {
1303 apfw_warn("ico_apf_callback_appsctl: Receive Event Error(cmd=%d)", cmd);
1306 for (res = ICO_APF_RESOURCE_RESID_MIN;
1307 res <= ICO_APF_RESOURCE_RESID_MAX; res++) {
1309 ico_apf_res_table[res-ICO_APF_RESOURCE_RESID_MIN], 4) == 0) break;
1311 if (res > ICO_APF_RESOURCE_RESID_MAX) {
1313 apfw_warn("ico_apf_callback_websock: Receive Resource Error(resid=%d)",
1319 for (st = 9; msg[st]; st++) {
1320 if (msg[st] == ' ') break;
1322 if ((msg[st] >= '0') && (msg[st] <= '9')) {
1323 pid = pid * 10 + msg[st] - '0';
1335 if (pid > ICO_UXF_MAX_PROCESS_NAME )
1336 pid = ICO_UXF_MAX_PROCESS_NAME;
1337 strncpy(appid, &msg[9], pid);
1341 if (msg[st] == ' ') st++;
1342 apfw_trace("ico_apf_callback_websock: AppsCtl evt=%d res=%d pid=%d(%s) msg=%s",
1343 cmd, res, pid, appid, &msg[st]);
1344 /* save receive message to receive buffer */
1345 ico_apf_put_recvmsg(cmd, res, pid, appid, &msg[st], len-st, handle);
1349 apfw_trace("ico_apf_callback_websock: UnKnown reason=%d", reason);
1357 /*--------------------------------------------------------------------------*/
1359 * @brief ico_apf_put_recvmsg
1360 * put receive message into receive buffer
1362 * @param[in] cmd receive commnad or event
1363 * @param[in] res receive resource
1364 * @param[in] pid request pid
1365 * @param[in] appid application id (for Web Application)
1366 * @param[in] msg receive message
1367 * @param[in] len receive message length
1368 * @param[out] handle connection handle
1371 /*--------------------------------------------------------------------------*/
1373 ico_apf_put_recvmsg(const int cmd, const int res, const int pid, const char *appid,
1374 char *msg, const int len, ico_apf_com_handle_t *handle)
1379 /* check receive buffer overflow */
1380 if (handle->rtail >= (ICO_APF_RESOURCE_WSOCK_BUFR-1)) {
1384 nexttail = handle->rtail + 1;
1386 if (handle->rhead == nexttail) {
1387 /* receive buffer overflow, drops all message */
1388 apfw_warn("ico_apf_put_recvmsg: receive buffer overflow");
1394 /* receive message is put into queue. */
1395 handle->rbuf[handle->rtail]->cmd = cmd;
1396 handle->rbuf[handle->rtail]->res = res;
1397 handle->rbuf[handle->rtail]->pid = pid;
1398 strncpy(handle->rbuf[handle->rtail]->appid, appid, ICO_UXF_MAX_PROCESS_NAME);
1399 handle->rbuf[handle->rtail]->appid[ICO_UXF_MAX_PROCESS_NAME] = 0;
1401 memcpy(handle->rbuf[handle->rtail]->msg, msg, len);
1402 handle->rbuf[handle->rtail]->msg[len] = 0;
1405 handle->rbuf[handle->rtail]->msg[0] = 0;
1407 handle->rtail = nexttail;
1408 i = handle->rtail - handle->rhead;
1410 i = ICO_APF_RESOURCE_WSOCK_BUFR + i;
1412 if ((handle->stoprecv == 0) &&
1413 (i > ((ICO_APF_RESOURCE_WSOCK_BUFR * 3) / 4))) {
1414 /* request to stop sending if an opening is less than 25%. */
1415 handle->stoprecv = 1;
1416 apfw_trace("ico_apf_put_recvmsg: Flow Control(Stop) %d", i);
1417 libwebsocket_rx_flow_control(handle->wsi_connection, 0);
1419 ico_apf_poll_write_event(handle, 1);
1422 /*--------------------------------------------------------------------------*/
1424 * @brief apf_com_poll_fd_add: add file descriptor for poll
1426 * @param[in] fd file descriptor
1427 * @param[in] flag POLL flag(POLLIN,POLLOUT)
1428 * negative means reset
1430 * @retval ICO_APF_RESOURCE_E_NONE success
1431 * @retval ICO_APF_RESOURCE_E_INVAL error(out of memory)
1433 /*--------------------------------------------------------------------------*/
1435 ico_apf_poll_fd_add(const int fd, const int flag)
1437 ico_apf_com_poll_t *p;
1438 ico_apf_com_poll_t *fds[1];
1439 ico_apf_com_handle_t *handle;
1450 /* new file descriptor */
1451 if (freecom_polls) {
1453 freecom_polls = p->next;
1454 p->apf_fd_control = NULL;
1455 p->user_data = NULL;
1458 p = calloc(sizeof(ico_apf_com_poll_t), 1);
1461 apfw_error("ico_apf_poll_fd_add: can not allocate fd control table"
1463 return ICO_APF_RESOURCE_E_INVAL;
1468 p->next = com_polls;
1471 p->flags |= ICO_APF_COM_POLL_ERROR;
1473 if (flag & (POLLIN|POLLPRI)) {
1474 p->flags |= ICO_APF_COM_POLL_READ;
1476 if (flag & POLLOUT) {
1477 p->flags |= ICO_APF_COM_POLL_WRITE;
1481 if ((-flag) & (POLLIN|POLLPRI)) {
1482 p->flags &= ~ICO_APF_COM_POLL_READ;
1484 if ((-flag) & POLLOUT) {
1485 p->flags &= ~ICO_APF_COM_POLL_WRITE;
1491 if (handle->fd == fd) break;
1492 handle = handle->next;
1495 p->apf_fd_control = (void *)handle;
1499 apfw_trace("ico_apf_poll_fd_add: fd=%d dose not exist in handles", fd);
1500 p->apf_fd_control = NULL;
1503 /* regist callback function */
1504 if (ico_apf_pollfd_func) {
1507 (*ico_apf_pollfd_func)(fds, 1);
1509 return ICO_APF_RESOURCE_E_NONE;
1512 /*--------------------------------------------------------------------------*/
1514 * @brief apf_com_poll_fd_del: delete file descriptor for poll
1516 * @param[in] fd file descriptor
1519 /*--------------------------------------------------------------------------*/
1521 ico_apf_poll_fd_del(const int fd)
1523 ico_apf_com_poll_t *p;
1524 ico_apf_com_poll_t *bp;
1525 ico_apf_com_poll_t *fds[1];
1527 /* search file descriptor */
1536 com_polls = p->next;
1539 if (p->apf_fd_control) {
1540 ((ico_apf_com_handle_t *)(p->apf_fd_control))->poll = NULL;
1543 /* call callback function */
1544 if (ico_apf_pollfd_func) {
1548 (*ico_apf_pollfd_func)(fds, 1);
1550 p->next = freecom_polls;
1558 /*--------------------------------------------------------------------------*/
1560 * @brief ico_apf_com_poll_fd_control: Set or Unset callback of file descriptors
1562 * @param[in] poll_fd_cb The callback function.
1564 * @retval ICO_APF_RESOURCE_E_NONE success
1566 /*--------------------------------------------------------------------------*/
1568 ico_apf_com_poll_fd_control(ico_apf_com_pollfd_cb poll_fd_cb)
1570 ico_apf_com_poll_t *p;
1571 ico_apf_com_poll_t **fds;
1575 /* regist callback function */
1576 ico_apf_pollfd_func = poll_fd_cb;
1578 if (ico_apf_pollfd_func) {
1579 /* if regist, call callback for all file descriptors */
1581 /* count number of file descriptors */
1589 fds = malloc(sizeof(ico_apf_com_poll_t *) * count);
1602 apfw_trace("ico_apf_com_poll_fd_control: nfds=%d", nfds);
1604 (*ico_apf_pollfd_func)(fds, nfds);
1608 return ICO_APF_RESOURCE_E_NONE;
1611 /*--------------------------------------------------------------------------*/
1613 * @brief ico_apf_com_poll_fd_event: Notify the changes of file descriptor's state
1615 * @param[in] fd_ctl The structure of file descriptor's controller
1616 * @param[in] flags The user data to be passed to the callback function
1618 * @retval ICO_APF_RESOURCE_E_NONE success
1620 /*--------------------------------------------------------------------------*/
1622 ico_apf_com_poll_fd_event(ico_apf_com_poll_t *fd_ctl, int flags)
1625 ico_apf_com_handle_t *handle = (ico_apf_com_handle_t *)fd_ctl->apf_fd_control;
1628 ico_apf_com_dispatch(handle, 0); /* try to service */
1631 ico_apf_com_dispatch(NULL, 0); /* try to service for server*/
1635 /* send if send data exist */
1636 if ((handle->stail != handle->shead) &&
1637 (handle->wsi_context != NULL) &&
1638 (handle->wsi_connection != NULL)) {
1640 if (handle->shead >= (ICO_APF_RESOURCE_WSOCK_BUFS-1)) {
1646 if (ico_apf_com_realsend(handle, handle->sbuf[st])
1647 != ICO_APF_RESOURCE_E_NONE) {
1648 apfw_warn("ico_apf_com_poll_fd_event: ico_apf_com_realsend Error");
1650 ico_apf_com_dispatch(handle, 10); /* try to service */
1652 if (handle->stail != handle->shead) {
1653 libwebsocket_callback_on_writable(handle->wsi_context,
1654 handle->wsi_connection);
1658 /* start/stop writable event */
1659 if ((handle->stail == handle->shead) ||
1660 (handle->wsi_context == NULL) ||
1661 (handle->wsi_connection == NULL)) {
1662 ico_apf_poll_write_event(handle, 0);
1665 libwebsocket_callback_on_writable(handle->wsi_context,
1666 handle->wsi_connection);
1667 ico_apf_poll_write_event(handle, 1);
1670 return ICO_APF_RESOURCE_E_NONE;
1673 /*--------------------------------------------------------------------------*/
1675 * @brief ico_apf_poll_write_event: Write event control for poll
1677 * @param[in] handle AppsController's handle
1678 * @param[in] write set/reset write event
1679 * = 0 : reset if not reset
1680 * = 1 : set if not set
1685 /*--------------------------------------------------------------------------*/
1687 ico_apf_poll_write_event(ico_apf_com_handle_t *handle, const int write)
1689 ico_apf_com_poll_t *fds[1];
1692 if ((write == 3) || (write == 1)) {
1693 /* set write poll */
1694 handle->poll->flags |= ICO_APF_COM_POLL_WRITE;
1695 if (ico_apf_pollfd_func) {
1696 fds[0] = handle->poll;
1697 (*ico_apf_pollfd_func)(fds, 1);
1700 else if ((write == 2) || (write == 0)) {
1701 /* reset write poll */
1702 handle->poll->flags &= ~ICO_APF_COM_POLL_WRITE;
1703 if (ico_apf_pollfd_func) {
1704 fds[0] = handle->poll;
1705 (*ico_apf_pollfd_func)(fds, 1);