static int setup_watches(struct subprocess_data *mdata) { mdata->watches.in = sol_fd_add(mdata->pipes.in[0], SOL_FD_FLAGS_IN | SOL_FD_FLAGS_ERR, on_in_read, mdata); SOL_NULL_CHECK(mdata->watches.in, -1); mdata->watches.err = sol_fd_add(mdata->pipes.err[0], SOL_FD_FLAGS_IN | SOL_FD_FLAGS_ERR, on_err_read, mdata); if (!mdata->watches.err) { sol_fd_del(mdata->watches.in); return -1; } return 0; }
int process_subprocess_in_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet) { struct subprocess_data *mdata = data; struct sol_blob *blob; struct write_data *w; int ret; SOL_NULL_CHECK(mdata->fork_run, -EINVAL); ret = sol_flow_packet_get_blob(packet, &blob); SOL_INT_CHECK(ret, < 0, ret); w = sol_vector_append(&mdata->write_data); SOL_NULL_CHECK(w, -ENOMEM); w->offset = 0; w->blob = sol_blob_ref(blob); if (mdata->write_data.len > 1) return 0; mdata->watches.out = sol_fd_add(mdata->pipes.out[1], SOL_FD_FLAGS_OUT | SOL_FD_FLAGS_ERR, on_write, mdata); if (!mdata->watches.out) { sol_blob_unref(w->blob); sol_vector_del_last(&mdata->write_data); return -1; } return 0; }
static struct sol_mainloop_source * event_create_source(sd_event *event) { struct sol_mainloop_source *source; struct source_ctx *ctx; ctx = malloc(sizeof(*ctx)); SOL_NULL_CHECK(ctx, NULL); ctx->event = sd_event_ref(event); ctx->fd_handler = sol_fd_add(sd_event_get_fd(event), SOL_FD_FLAGS_IN | SOL_FD_FLAGS_HUP | SOL_FD_FLAGS_ERR, on_sd_event_fd, ctx); SOL_NULL_CHECK_GOTO(ctx->fd_handler, error_fd); source = sol_mainloop_source_add(&source_type, ctx); SOL_NULL_CHECK_GOTO(source, error_source); return source; error_source: sol_fd_del(ctx->fd_handler); error_fd: sd_event_unref(ctx->event); free(ctx); return NULL; }
static int udev_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options) { struct udev_data *mdata = data; struct udev_device *device; bool value; const struct sol_flow_node_type_udev_boolean_options *opts = (const struct sol_flow_node_type_udev_boolean_options *)options; SOL_FLOW_NODE_OPTIONS_SUB_API_CHECK(options, SOL_FLOW_NODE_TYPE_UDEV_BOOLEAN_OPTIONS_API_VERSION, -EINVAL); mdata->udev = udev_new(); SOL_NULL_CHECK(mdata->udev, -EINVAL); mdata->monitor = udev_monitor_new_from_netlink(mdata->udev, "udev"); if (!mdata->monitor) { SOL_WRN("Fail on create the udev monitor"); goto monitor_error; } if (udev_monitor_enable_receiving(mdata->monitor) < 0) { SOL_WRN("error: unable to subscribe to udev events"); goto receive_error; } mdata->addr = strdup(opts->address); mdata->node = node; mdata->watch = sol_fd_add(udev_monitor_get_fd(mdata->monitor), SOL_FD_FLAGS_IN | SOL_FD_FLAGS_ERR | SOL_FD_FLAGS_HUP, _on_event, mdata); device = udev_device_new_from_syspath(mdata->udev, mdata->addr); if (device) { value = true; udev_device_unref(device); } else { value = false; } return sol_flow_send_boolean_packet(node, SOL_FLOW_NODE_TYPE_UDEV_BOOLEAN__OUT__OUT, value); receive_error: mdata->monitor = udev_monitor_unref(mdata->monitor); monitor_error: mdata->udev = udev_unref(mdata->udev); return -EINVAL; }
SOL_API struct sol_mavlink * sol_mavlink_connect(const char *addr, const struct sol_mavlink_config *config, const void *data) { struct sol_mavlink *mavlink; struct sol_str_slice address; int port; int (*init) (struct sol_mavlink *mavlink); SOL_NULL_CHECK(addr, NULL); init = sol_mavlink_parse_addr_protocol(addr, &address, &port); SOL_NULL_CHECK(init, NULL); mavlink = calloc(1, sizeof(*mavlink)); SOL_NULL_CHECK(mavlink, NULL); mavlink->address = &address; SOL_NULL_CHECK_GOTO(mavlink->address, err); mavlink->port = port; SOL_NULL_CHECK_GOTO(mavlink->port, err); mavlink->config = config; mavlink->data = data; memset(&mavlink->curr_position, 0, sizeof(mavlink->curr_position)); memset(&mavlink->home_position, 0, sizeof(mavlink->home_position)); if (init(mavlink) < 0) { SOL_ERR("Could not initialize mavlink connection."); goto err; } mavlink->watch = sol_fd_add(mavlink->fd, SOL_FD_FLAGS_IN, sol_mavlink_fd_handler, mavlink); SOL_NULL_CHECK_GOTO(mavlink->watch, err); if (!setup_data_stream(mavlink)) { SOL_ERR("Could not setup data stream"); goto err; } return mavlink; err: sol_mavlink_free(mavlink); return NULL; }
int hijack_main_loop() { int returnValue; uv_loop_t *uv_loop = NULL; SOL_DBG("Entering with state %s", RESOLVE_MAINLOOP_STATE(mainloopState)); if (mainloopState == MAINLOOP_HIJACKED || mainloopState == MAINLOOP_HIJACKING_STARTED) { return 0; } uv_loop = uv_default_loop(); // The actual hijacking starts here, inspired by node-gtk. The plan: // 1. uv has two ways of letting us know that it needs to run its loop. One // is that its backend timeout is >= 0, and the other is a file // descriptor which can become readable/writable/errored. So, attach a // source to the soletta main loop which will run the uv main loop in // a non-blocking fashion. Also attach a file descriptor watch via which // uv can signal that it needs to run an iteration. // 2. Attach an idler to the uv main loop and call sol_run() from it when // it first runs. This interrupts the uv main loop, because sol_run() // doesn't return but, since we've already added the above sources to // the soletta main loop in the first step, the source or the file // descriptor watch will end up running one non-blocking iteration of // the uv main loop which, in turn, will recursively call the idler we // added. At that point, the idler can remove itself from the uv main // loop. After that, only the soletta main loop runs, but it runs an // iteration of the uv main loop in a non-blocking fashion whenever the // uv main loop signals to the soletta main loop via the attached // source or the attached file descriptor watch. // 3. Attach a token handle to the uv main loop which represents all // soletta open handles. This is necessary because the uv main loop // would otherwise quit when it runs out of its own handles. We remove // this token handle when we release the uv main loop so that if, at // that point, it has no more handles, it is free to cause the node.js // process to quit. // We allocate the various needed structures only once. After that, we // reuse them. We never free them, even if we release the uv main loop. if (!uv_loop_source) { uv_loop_source = sol_mainloop_add_source(&uv_loop_source_funcs, uv_loop); if (!uv_loop_source) { return -ENOMEM; } } if (!uv_loop_fd) { uv_loop_fd = sol_fd_add(uv_backend_fd(uv_loop), SOL_FD_FLAGS_IN | SOL_FD_FLAGS_OUT | SOL_FD_FLAGS_ERR, uv_loop_fd_changed, uv_loop); if (!uv_loop_fd) { return -ENOMEM; } } returnValue = uv_prepare_init(uv_loop, &uv_token_handle); if (returnValue) { return returnValue; } returnValue = uv_idle_init(uv_loop, &uv_idle); if (returnValue) { return returnValue; } SOL_DBG("Starting token handle"); returnValue = uv_prepare_start(&uv_token_handle, uv_token_callback); if (returnValue) { return returnValue; } SOL_DBG("Starting idler"); returnValue = uv_idle_start(&uv_idle, uv_idle_callback); if (returnValue) { return returnValue; } mainloopState = MAINLOOP_HIJACKING_STARTED; return 0; }
SOL_API struct sol_mavlink * sol_mavlink_connect(const char *addr, const struct sol_mavlink_config *config, const void *data) { struct sol_mavlink *mavlink; struct sol_str_slice address; int port; int (*init) (struct sol_mavlink *mavlink); SOL_NULL_CHECK(addr, NULL); SOL_NULL_CHECK(config, NULL); #ifndef SOL_NO_API_VERSION if (SOL_UNLIKELY(config->api_version != SOL_MAVLINK_CONFIG_API_VERSION)) { SOL_ERR("Unexpected API version (config is %" PRIu16 ", expected %" PRIu16 ")", config->api_version, SOL_MAVLINK_CONFIG_API_VERSION); return NULL; } SOL_NULL_CHECK(config->handlers, NULL); if (SOL_UNLIKELY(config->handlers->api_version != SOL_MAVLINK_HANDLERS_API_VERSION)) { SOL_ERR("Unexpected API version (config is %" PRIu16 ", expected %" PRIu16 ")", config->handlers->api_version, SOL_MAVLINK_HANDLERS_API_VERSION); return NULL; } #else SOL_NULL_CHECK(config->handlers, NULL); #endif init = sol_mavlink_parse_addr_protocol(addr, &address, &port); SOL_NULL_CHECK(init, NULL); mavlink = calloc(1, sizeof(*mavlink)); SOL_NULL_CHECK(mavlink, NULL); mavlink->address = &address; SOL_NULL_CHECK_GOTO(mavlink->address, err); mavlink->port = port; SOL_NULL_CHECK_GOTO(mavlink->port, err); mavlink->config = config; mavlink->data = data; memset(&mavlink->curr_position, 0, sizeof(mavlink->curr_position)); memset(&mavlink->home_position, 0, sizeof(mavlink->home_position)); if (init(mavlink) < 0) { SOL_ERR("Could not initialize mavlink connection."); goto err; } mavlink->watch = sol_fd_add(mavlink->fd, SOL_FD_FLAGS_IN, sol_mavlink_fd_handler, mavlink); SOL_NULL_CHECK_GOTO(mavlink->watch, err); if (!setup_data_stream(mavlink)) { SOL_ERR("Could not setup data stream"); goto err; } return mavlink; err: sol_mavlink_free(mavlink); return NULL; }