static void _uiCmdProxy_io_func(void* opaque, int fd, unsigned events) { UICmdProxy* uicmd = (UICmdProxy*)opaque; AsyncReader reader; AsyncStatus status; uint8_t read_buf[1]; if (events & LOOP_IO_WRITE) { derror("Unexpected LOOP_IO_WRITE in _uiCmdProxy_io_func.\n"); return; } asyncReader_init(&reader, read_buf, sizeof(read_buf), &uicmd->io); status = asyncReader_read(&reader); if (status != ASYNC_ERROR) { derror("Unexpected read status %d in _uiCmdProxy_io_func\n", status); return; } if (errno != ECONNRESET) { derror("Unexpected read error %d (%s) in _uiCmdProxy_io_func.\n", errno, errno_str); return; } destroy_uicmd_client(); }
/* Asynchronous I/O callback for AttachUIProxy instance. * We expect this callback to be called only on UI detachment condition. In this * case the event should be LOOP_IO_READ, and read should fail with errno set * to ECONNRESET. * Param: * opaque - AttachUIProxy instance. */ static void _attachUiProxy_io_func(void* opaque, int fd, unsigned events) { AttachUIProxy* uicmd = (AttachUIProxy*)opaque; AsyncReader reader; AsyncStatus status; uint8_t read_buf[1]; if (events & LOOP_IO_WRITE) { derror("Unexpected LOOP_IO_WRITE in _attachUiProxy_io_func.\n"); return; } // Try to read asyncReader_init(&reader, read_buf, sizeof(read_buf), &uicmd->io); status = asyncReader_read(&reader); // We expect only error status here. if (status != ASYNC_ERROR) { derror("Unexpected read status %d in _attachUiProxy_io_func\n", status); return; } // We expect only socket disconnection error here. if (errno != ECONNRESET) { derror("Unexpected read error %d (%s) in _attachUiProxy_io_func.\n", errno, errno_str); return; } // Client got disconnectted. destroy_attach_ui_client(); }
int userEventsImpl_create(int fd) { _UserEventsImpl.sock = fd; _UserEventsImpl.event_header.event_type = -1; _UserEventsImpl.state = EXPECTS_HEADER; _UserEventsImpl.looper = looper_newCore(); loopIo_init(&_UserEventsImpl.io, _UserEventsImpl.looper, _UserEventsImpl.sock, _userEventsImpl_io_func, &_UserEventsImpl); asyncReader_init(&_UserEventsImpl.user_events_reader, &_UserEventsImpl.event_header, sizeof(_UserEventsImpl.event_header), &_UserEventsImpl.io); return 0; }
int coreCmdImpl_create(int fd) { _coreCmdImpl.sock = fd; _coreCmdImpl.looper = looper_newCore(); loopIo_init(&_coreCmdImpl.io, _coreCmdImpl.looper, _coreCmdImpl.sock, _coreCmdImpl_io_func, &_coreCmdImpl); _coreCmdImpl.cmd_state = EXPECTS_HEADER; _coreCmdImpl.cmd_param_buf = &_coreCmdImpl.cmd_param[0]; asyncReader_init(&_coreCmdImpl.async_reader, &_coreCmdImpl.cmd_header, sizeof(_coreCmdImpl.cmd_header), &_coreCmdImpl.io); _coreCmdImpl.sync_writer = syncsocket_init(fd); if (_coreCmdImpl.sync_writer == NULL) { derror("Unable to create writer for CoreCmdImpl instance: %s\n", errno_str); coreCmdImpl_destroy(); return -1; } return 0; }
/* Asynchronous I/O callback reading UI control commands. * Param: * opaque - CoreCmdImpl instance. * events - Lists I/O event (read or write) this callback is called for. */ static void _coreCmdImpl_io_func(void* opaque, int fd, unsigned events) { AsyncStatus status; CoreCmdImpl* corecmd; if (events & LOOP_IO_WRITE) { // We don't use async writer here, so we don't expect // any write callbacks. derror("Unexpected LOOP_IO_WRITE in _coreCmdImpl_io_func\n"); return; } corecmd = (CoreCmdImpl*)opaque; // Read whatever is expected from the socket. status = asyncReader_read(&corecmd->async_reader); switch (status) { case ASYNC_COMPLETE: switch (corecmd->cmd_state) { case EXPECTS_HEADER: // We just read the command header. Now we expect the param. if (corecmd->cmd_header.cmd_param_size != 0) { corecmd->cmd_state = EXPECTS_PARAMETERS; // Setup the reader to read expected amount of data. _alloc_cmd_param_buf(corecmd, corecmd->cmd_header.cmd_param_size); asyncReader_init(&corecmd->async_reader, corecmd->cmd_param_buf, corecmd->cmd_header.cmd_param_size, &corecmd->io); } else { // Command doesn't have param. Go ahead and handle it. _coreCmdImpl_handle_command(corecmd, &corecmd->cmd_header, NULL); // Prepare for the next header. corecmd->cmd_state = EXPECTS_HEADER; asyncReader_init(&corecmd->async_reader, &corecmd->cmd_header, sizeof(corecmd->cmd_header), &corecmd->io); } break; case EXPECTS_PARAMETERS: // Entore command is received. Handle it. _coreCmdImpl_handle_command(corecmd, &corecmd->cmd_header, corecmd->cmd_param_buf); _free_cmd_param_buf(corecmd); // Prepare for the next command. corecmd->cmd_state = EXPECTS_HEADER; asyncReader_init(&corecmd->async_reader, &corecmd->cmd_header, sizeof(corecmd->cmd_header), &corecmd->io); break; } break; case ASYNC_ERROR: loopIo_dontWantRead(&corecmd->io); if (errno == ECONNRESET) { // UI has exited. We need to destroy the service. destroy_corecmd_client(); } break; case ASYNC_NEED_MORE: // Transfer will eventually come back into this routine. return; } }
/* Asynchronous I/O callback reading user events. * Param: * opaque - UserEventsImpl instance. */ static void _userEventsImpl_io_func(void* opaque, int fd, unsigned events) { UserEventsImpl* ueimpl; AsyncStatus status; if (events & LOOP_IO_WRITE) { // We don't use async writer here, so we don't expect // any write callbacks. derror("Unexpected LOOP_IO_WRITE in _userEventsImpl_io_func\n"); return; } ueimpl = (UserEventsImpl*)opaque; // Read whatever is expected from the socket. status = asyncReader_read(&ueimpl->user_events_reader); switch (status) { case ASYNC_COMPLETE: switch (ueimpl->state) { case EXPECTS_HEADER: // We just read event header. Now we expect event parameters. ueimpl->state = EXPECTS_PARAMETERS; // Setup the reader depending on the event type. switch (ueimpl->event_header.event_type) { case AUSER_EVENT_MOUSE: asyncReader_init(&ueimpl->user_events_reader, &ueimpl->mouse_event, sizeof(ueimpl->mouse_event), &ueimpl->io); break; case AUSER_EVENT_KEYCODE: asyncReader_init(&ueimpl->user_events_reader, &ueimpl->keycode_event, sizeof(ueimpl->keycode_event), &ueimpl->io); break; case AUSER_EVENT_GENERIC: asyncReader_init(&ueimpl->user_events_reader, &ueimpl->generic_event, sizeof(ueimpl->generic_event), &ueimpl->io); break; default: derror("Unexpected user event type %d\n", ueimpl->event_header.event_type); break; } break; case EXPECTS_PARAMETERS: // We just read event parameters. Lets fire the event. switch (ueimpl->event_header.event_type) { case AUSER_EVENT_MOUSE: user_event_mouse(ueimpl->mouse_event.dx, ueimpl->mouse_event.dy, ueimpl->mouse_event.dz, ueimpl->mouse_event.buttons_state); break; case AUSER_EVENT_KEYCODE: user_event_keycode(ueimpl->keycode_event.keycode); break; case AUSER_EVENT_GENERIC: user_event_generic(ueimpl->generic_event.type, ueimpl->generic_event.code, ueimpl->generic_event.value); break; default: derror("Unexpected user event type %d\n", ueimpl->event_header.event_type); break; } // Prepare to receive the next event header. ueimpl->event_header.event_type = -1; ueimpl->state = EXPECTS_HEADER; asyncReader_init(&ueimpl->user_events_reader, &ueimpl->event_header, sizeof(ueimpl->event_header), &ueimpl->io); break; } break; case ASYNC_ERROR: loopIo_dontWantRead(&ueimpl->io); if (errno == ECONNRESET) { // UI has exited. We need to destroy user event service. destroy_user_events_client(); } else { derror("User event read error %d -> %s\n", errno, errno_str); } break; case ASYNC_NEED_MORE: // Transfer will eventually come back into this routine. return; } }