SOL_API bool sol_oic_map_loop_next(struct sol_oic_repr_field *repr, struct sol_oic_map_reader *iterator, enum sol_oic_map_loop_reason *reason) { CborError err; SOL_NULL_CHECK_GOTO(repr, err); SOL_NULL_CHECK_GOTO(iterator, err); sol_oic_repr_field_clear(repr); if (cbor_value_at_end((CborValue *)iterator)) return false; if (!cbor_value_is_valid((CborValue *)iterator)) goto err; err = sol_oic_cbor_repr_map_get_next_field((CborValue *)iterator, repr); if (err != CborNoError) goto err; return true; err: if (reason) *reason = SOL_OIC_MAP_LOOP_ERROR; return false; }
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 struct server_data * server_ref(int32_t opt_port) { struct server_data *idata, *sdata = NULL; uint16_t i, port; port = validate_port(opt_port); if (!servers) { servers = calloc(1, sizeof(struct sol_ptr_vector)); SOL_NULL_CHECK(servers, NULL); sol_ptr_vector_init(servers); } SOL_PTR_VECTOR_FOREACH_IDX (servers, idata, i) { if (idata->port == port) { sdata = idata; break; } } if (!sdata) { int r; sdata = calloc(1, sizeof(struct server_data)); SOL_NULL_CHECK_GOTO(sdata, err_sdata); r = sol_ptr_vector_append(servers, sdata); SOL_INT_CHECK_GOTO(r, < 0, err_vec); sdata->server = sol_http_server_new(port); SOL_NULL_CHECK_GOTO(sdata->server, err_server); sdata->port = port; }
static struct sol_mqtt_message * sol_mqtt_message_new(const char *topic, const struct sol_buffer *payload, sol_mqtt_qos qos, bool retain) { struct sol_mqtt_message *message; SOL_NULL_CHECK(topic, NULL); SOL_NULL_CHECK(payload, NULL); message = calloc(1, sizeof(struct sol_mqtt_message)); SOL_NULL_CHECK(message, NULL); message->topic = sol_util_memdup(topic, strlen(topic) + 1); SOL_NULL_CHECK_GOTO(message->topic, topic_error); message->payload = sol_buffer_copy(payload); SOL_NULL_CHECK_GOTO(message->payload, payload_error); message->qos = qos; message->retain = retain; return message; payload_error: free(message->topic); topic_error: free(message); return NULL; }
int process_subprocess_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options) { struct subprocess_data *mdata = data; struct sol_flow_node_type_process_subprocess_options *opts = (struct sol_flow_node_type_process_subprocess_options *)options; SOL_FLOW_NODE_OPTIONS_SUB_API_CHECK(options, SOL_FLOW_NODE_TYPE_PROCESS_SUBPROCESS_OPTIONS_API_VERSION, -EINVAL); mdata->node = node; sol_vector_init(&mdata->write_data, sizeof(struct write_data)); if (pipe2(mdata->pipes.out, O_NONBLOCK | O_CLOEXEC) < 0) { SOL_WRN("Failed to create out pipe"); return -errno; } if (pipe2(mdata->pipes.in, O_NONBLOCK | O_CLOEXEC) < 0) { SOL_WRN("Failed to create in pipe"); goto in_err; } if (pipe2(mdata->pipes.err, O_NONBLOCK | O_CLOEXEC) < 0) { SOL_WRN("Failed to create err pipe"); goto err_err; } mdata->command = strdup(opts->command); SOL_NULL_CHECK_GOTO(mdata->command, flags_err); if (opts->start) { if (setup_watches(mdata) < 0) goto watch_err; mdata->fork_run = sol_platform_linux_fork_run(on_fork, on_fork_exit, mdata); SOL_NULL_CHECK_GOTO(mdata->fork_run, err); } return 0; err: sol_fd_del(mdata->watches.in); sol_fd_del(mdata->watches.err); watch_err: free(mdata->command); flags_err: close(mdata->pipes.err[0]); close(mdata->pipes.err[1]); err_err: close(mdata->pipes.in[0]); close(mdata->pipes.in[1]); in_err: close(mdata->pipes.out[0]); close(mdata->pipes.out[1]); return -errno; }
int int_generator_open( struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options) { struct int_generator_data *mdata = data; const struct sol_flow_node_type_test_int_generator_options *opts = (const struct sol_flow_node_type_test_int_generator_options *)options; const char *it; char *tail; int32_t *val; if (opts->sequence == NULL || *opts->sequence == '\0') { SOL_ERR("Option 'sequence' is either NULL or empty."); return -EINVAL; } it = opts->sequence; if (opts->interval.val < 0) SOL_WRN("Option 'interval' < 0, setting it to 0."); mdata->interval = opts->interval.val >= 0 ? opts->interval.val : 0; mdata->next_index = 0; sol_vector_init(&mdata->values, sizeof(int32_t)); do { val = sol_vector_append(&mdata->values); SOL_NULL_CHECK_GOTO(val, no_memory); errno = 0; *val = strtol(it, &tail, 10); if (errno) { SOL_WRN("Failed do convert option 'sequence' to int %s: %d", it, errno); goto error; } if (it == tail) { SOL_WRN("Failed to convert option 'sequence' to int %s", it); errno = -EINVAL; goto error; } it = tail; } while (*tail != '\0'); mdata->timer = sol_timeout_add(mdata->interval, timer_tick, node); SOL_NULL_CHECK_GOTO(mdata->timer, error); return 0; no_memory: errno = -ENOMEM; error: sol_vector_clear(&mdata->values); return errno; }
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; }
void * sol_worker_thread_impl_new(const struct sol_worker_thread_config *config) { static sol_atomic_uint thr_cnt = SOL_ATOMIC_INIT(0u); struct sol_worker_thread_glib *thread; char name[16]; thread = calloc(1, sizeof(*thread)); SOL_NULL_CHECK(thread, NULL); thread->config = *config; g_mutex_init(&thread->lock); snprintf(name, 16, "thr-%u", sol_atomic_fetch_add(&thr_cnt, 1, SOL_ATOMIC_RELAXED)); thread->thread = g_thread_new(name, sol_worker_thread_do, thread); SOL_NULL_CHECK_GOTO(thread->thread, error_thread); return thread; error_thread: free(thread); return NULL; }
static int http_composed_client_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options) { struct http_composed_client_data *cdata = data; const struct http_composed_client_type *self; const struct http_composed_client_options *opts; const struct http_composed_client_port_out *out; opts = (struct http_composed_client_options *)options; if (opts->url) { cdata->url = strdup(opts->url); SOL_NULL_CHECK(cdata->url, -ENOMEM); } self = (const struct http_composed_client_type *) sol_flow_node_get_type(node); sol_ptr_vector_init(&cdata->pending_conns); cdata->inputs_len = self->ports_in.len - INPUT_FIXED_PORTS_LEN; cdata->inputs = calloc(cdata->inputs_len, sizeof(struct sol_flow_packet *)); SOL_NULL_CHECK_GOTO(cdata->inputs, err); out = sol_vector_get(&self->ports_out, 0); cdata->composed_type = out->base.packet_type; return 0; err: free(cdata->url); return -ENOMEM; }
int boolean_generator_open( struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options) { struct boolean_generator_data *mdata = data; const struct sol_flow_node_type_test_boolean_generator_options *opts = (const struct sol_flow_node_type_test_boolean_generator_options *)options; if (opts->sequence == NULL || *opts->sequence == '\0') { SOL_ERR("Option 'sequence' is either NULL or empty."); return -1; } mdata->it = mdata->sequence = strdup(opts->sequence); SOL_NULL_CHECK(mdata->sequence, -errno); if (opts->interval.val < 0) SOL_WRN("Option 'interval' < 0, setting it to 0."); mdata->interval = opts->interval.val >= 0 ? opts->interval.val : 0; mdata->timer = sol_timeout_add(mdata->interval, timer_tick, node); SOL_NULL_CHECK_GOTO(mdata->timer, error); return 0; error: free(mdata->sequence); return -ENOMEM; }
int boolean_generator_open( struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options) { struct boolean_generator_data *mdata = data; const struct sol_flow_node_type_test_boolean_generator_options *opts = (const struct sol_flow_node_type_test_boolean_generator_options *)options; SOL_FLOW_NODE_OPTIONS_SUB_API_CHECK(options, SOL_FLOW_NODE_TYPE_TEST_BOOLEAN_GENERATOR_OPTIONS_API_VERSION, -EINVAL); if (opts->sequence == NULL || *opts->sequence == '\0') { SOL_ERR("Option 'sequence' is either NULL or empty."); return -EINVAL; } mdata->it = mdata->sequence = strdup(opts->sequence); SOL_NULL_CHECK(mdata->sequence, -errno); if (opts->interval < 0) SOL_WRN("Option 'interval' < 0, setting it to 0."); mdata->interval = opts->interval >= 0 ? opts->interval : 0; mdata->timer = sol_timeout_add(mdata->interval, timer_tick, node); SOL_NULL_CHECK_GOTO(mdata->timer, error); return 0; error: free(mdata->sequence); return -ENOMEM; }
static int _populate_values(void *data, const char *sequence) { struct int_validator_data *mdata = data; char *tail; const char *it; int32_t *val; sol_vector_init(&mdata->values, sizeof(int32_t)); it = sequence; do { val = sol_vector_append(&mdata->values); SOL_NULL_CHECK_GOTO(val, no_memory); errno = 0; *val = strtol(it, &tail, 10); if (errno) { SOL_WRN("Failed do convert option 'sequence' to int %s: %d", it, errno); return -errno; } if (it == tail) { SOL_WRN("Failed to convert option 'sequence' to int %s", it); return -EINVAL; } it = tail; } while (*tail != '\0'); return 0; no_memory: sol_vector_clear(&mdata->values); return -ENOMEM; }
static void on_feed_done_cb(void *data, struct sol_message_digest *md, struct sol_blob *input) { struct update_get_hash_handle *handle = data; char buf[CHUNK_SIZE], *blob_backend = NULL; struct sol_blob *blob = NULL; size_t size; bool last; int r; size = fread(buf, 1, sizeof(buf), handle->file); if (ferror(handle->file)) { SOL_WRN("Could not read file for feed hash algorithm"); goto err; } last = feof(handle->file); /* TODO Maybe this is a bug on sol_message_digest? Keeps calling on_feed_done * after send last chunk */ if (!size && last && input) { SOL_WRN("Nothing more to feed hash algorithm, ignoring on_feed_done request"); return; } blob_backend = malloc(size); SOL_NULL_CHECK_GOTO(blob_backend, err); blob = sol_blob_new(&SOL_BLOB_TYPE_DEFAULT, NULL, blob_backend, size); SOL_NULL_CHECK_GOTO(blob, err); memcpy(blob_backend, buf, size); r = sol_message_digest_feed(md, blob, last); SOL_INT_CHECK_GOTO(r, < 0, err); sol_blob_unref(blob); return; err: SOL_WRN("Could not feed data to check update file hash"); free(blob_backend); sol_blob_unref(blob); sol_message_digest_del(md); handle->cb((void *)handle->user_data, -EINVAL, NULL); delete_handle(handle); }
struct sol_str_slice sol_file_reader_get_all(const struct sol_file_reader *fr) { return (struct sol_str_slice) { .len = fr->st.st_size, .data = fr->contents, }; } const struct stat * sol_file_reader_get_stat(const struct sol_file_reader *fr) { return &fr->st; } struct sol_blob_file_reader { struct sol_blob base; struct sol_file_reader *fr; }; static void _sol_blob_type_file_reader_close(struct sol_blob *blob) { struct sol_blob_file_reader *b = (struct sol_blob_file_reader *)blob; sol_file_reader_close(b->fr); free(blob); } static const struct sol_blob_type _SOL_BLOB_TYPE_FILE_READER = { #ifndef SOL_NO_API_VERSION .api_version = SOL_BLOB_TYPE_API_VERSION, .sub_api = 1, #endif .free = _sol_blob_type_file_reader_close }; SOL_API struct sol_blob * sol_file_reader_to_blob(struct sol_file_reader *fr) { struct sol_blob_file_reader *b; struct sol_str_slice c = sol_file_reader_get_all(fr); b = calloc(1, sizeof(struct sol_blob_file_reader)); SOL_NULL_CHECK_GOTO(b, error); sol_blob_setup(&b->base, &_SOL_BLOB_TYPE_FILE_READER, c.data, c.len); b->fr = fr; return &b->base; error: sol_file_reader_close(fr); return NULL; }
int string_generator_open( struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options) { struct string_generator_data *mdata = data; const struct sol_flow_node_type_test_string_generator_options *opts = (const struct sol_flow_node_type_test_string_generator_options *)options; SOL_FLOW_NODE_OPTIONS_SUB_API_CHECK(options, SOL_FLOW_NODE_TYPE_TEST_STRING_GENERATOR_OPTIONS_API_VERSION, -EINVAL); sol_vector_init(&mdata->values, sizeof(struct sol_str_slice)); if (opts->sequence == NULL || *opts->sequence == '\0') { SOL_ERR("Option 'sequence' is either NULL or empty."); return -EINVAL; } mdata->sequence = strdup(opts->sequence); SOL_NULL_CHECK_GOTO(mdata->sequence, no_memory); if (opts->interval < 0) SOL_WRN("Option 'interval' < 0, setting it to 0."); mdata->interval = opts->interval >= 0 ? opts->interval : 0; mdata->next_index = 0; mdata->values = sol_str_slice_split(sol_str_slice_from_str (mdata->sequence), opts->separator, SIZE_MAX); mdata->timer = sol_timeout_add(mdata->interval, timer_tick, node); SOL_NULL_CHECK_GOTO(mdata->timer, error); return 0; no_memory: errno = -ENOMEM; error: sol_vector_clear(&mdata->values); return errno; }
SOL_API bool sol_spi_transfer(struct sol_spi *spi, const uint8_t *tx_user, uint8_t *rx, size_t count, void (*transfer_cb)(void *cb_data, struct sol_spi *spi, const uint8_t *tx, uint8_t *rx, ssize_t status), const void *cb_data) { uint8_t *tx = (uint8_t *)tx_user; SOL_NULL_CHECK(spi, false); SOL_EXP_CHECK(spi->transfer.timeout, false); spi->transfer.intern_allocated_buffer_flags = 0; if (tx == NULL) { tx = calloc(count, sizeof(uint8_t)); SOL_NULL_CHECK(tx, false); spi->transfer.intern_allocated_buffer_flags = INTERN_ALLOCATED_TX_BUFFER; } if (rx == NULL) { rx = calloc(count, sizeof(uint8_t)); SOL_NULL_CHECK_GOTO(rx, rx_alloc_fail); spi->transfer.intern_allocated_buffer_flags = INTERN_ALLOCATED_RX_BUFFER; } spi->transfer.tx = tx; spi->transfer.rx = rx; spi->transfer.count = count; spi->transfer.status = -1; spi->transfer.cb = transfer_cb; spi->transfer.cb_data = cb_data; spi->transfer.timeout = sol_timeout_add(0, spi_timeout_cb, spi); SOL_NULL_CHECK_GOTO(spi->transfer.timeout, timeout_fail); return true; timeout_fail: if (spi->transfer.intern_allocated_buffer_flags & INTERN_ALLOCATED_RX_BUFFER) free(rx); rx_alloc_fail: if (spi->transfer.intern_allocated_buffer_flags & INTERN_ALLOCATED_TX_BUFFER) free(tx); return false; }
int float_validator_open( struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options) { struct float_validator_data *mdata = data; const struct sol_flow_node_type_test_float_validator_options *opts = (const struct sol_flow_node_type_test_float_validator_options *)options; const char *it; char *tail; double *val; SOL_FLOW_NODE_OPTIONS_SUB_API_CHECK(options, SOL_FLOW_NODE_TYPE_TEST_FLOAT_VALIDATOR_OPTIONS_API_VERSION, -EINVAL); mdata->done = false; if (opts->sequence == NULL || *opts->sequence == '\0') { SOL_ERR("Option 'sequence' is either NULL or empty."); return -EINVAL; } sol_vector_init(&mdata->values, sizeof(double)); it = opts->sequence; do { val = sol_vector_append(&mdata->values); SOL_NULL_CHECK_GOTO(val, no_memory); *val = sol_util_strtod_n(it, &tail, -1, false); if (errno) { SOL_WRN("Failed do convert option 'sequence' to double %s: %d", it, errno); goto error; } if (it == tail) { SOL_WRN("Failed to convert option 'sequence' to double %s", it); errno = EINVAL; goto error; } it = tail; } while (*tail != '\0'); return 0; no_memory: errno = ENOMEM; error: sol_vector_clear(&mdata->values); return -errno; }
static int file_reader_load(struct file_reader_data *mdata) { struct sol_file_reader *reader; struct sol_str_slice slice; if (!mdata->path) return 0; reader = sol_file_reader_open(mdata->path); if (!reader) { sol_flow_send_error_packet(mdata->node, errno, "Could not load \"%s\": %s", mdata->path, sol_util_strerrora(errno)); return -errno; } slice = sol_file_reader_get_all(reader); SOL_DBG("loaded path=\"%s\", data=%p, len=%zd", mdata->path, slice.data, slice.len); mdata->reader_blob = sol_blob_new(&file_reader_blob_type, NULL, reader, sizeof(reader)); SOL_NULL_CHECK_GOTO(mdata->reader_blob, err_reader); mdata->content_blob = sol_blob_new(SOL_BLOB_TYPE_NOFREE, mdata->reader_blob, slice.data, slice.len); SOL_NULL_CHECK_GOTO(mdata->content_blob, err_content); return sol_flow_send_blob_packet(mdata->node, SOL_FLOW_NODE_TYPE_FILE_READER__OUT__OUT, mdata->content_blob); err_content: sol_blob_unref(mdata->reader_blob); err_reader: sol_file_reader_close(reader); return -ENOMEM; }
static int child_read(struct sol_blob **p_blob, bool *eof, int fd) { struct sol_buffer buf = SOL_BUFFER_INIT_EMPTY; struct timespec start = sol_util_timespec_get_current(); size_t size; void *v; int ret = 0; *eof = false; do { struct timespec now = sol_util_timespec_get_current(); struct timespec elapsed; ssize_t r; sol_util_timespec_sub(&now, &start, &elapsed); if (elapsed.tv_sec > 0 || elapsed.tv_nsec > (time_t)CHUNK_MAX_TIME_NS) break; r = sol_util_fill_buffer(fd, &buf, CHUNK_READ_SIZE); if (r == 0) { *eof = true; break; } else if (r < 0) { /* Not a problem if failed because buffer could not be increased */ if (r != -ENOMEM) ret = -errno; break; } } while (1); if (ret < 0 && ret != -EAGAIN) { sol_buffer_fini(&buf); return ret; } v = sol_buffer_steal(&buf, &size); *p_blob = sol_blob_new(&SOL_BLOB_TYPE_DEFAULT, NULL, v, size); SOL_NULL_CHECK_GOTO(*p_blob, blob_error); return 0; blob_error: sol_buffer_fini(&buf); return -ENOMEM; }
static int new_bootstrap_client_info(struct sol_lwm2m_bootstrap_client_info **bs_cinfo, const struct sol_network_link_addr *cliaddr, const struct sol_str_slice client_name) { *bs_cinfo = calloc(1, sizeof(struct sol_lwm2m_bootstrap_client_info)); SOL_NULL_CHECK(bs_cinfo, -ENOMEM); memcpy(&(*bs_cinfo)->cliaddr, cliaddr, sizeof(struct sol_network_link_addr)); (*bs_cinfo)->name = sol_str_slice_to_str(client_name); SOL_NULL_CHECK_GOTO((*bs_cinfo)->name, err_no_name); return 0; err_no_name: free(*bs_cinfo); return -ENOMEM; }
SOL_API int sol_network_init(void) { struct sol_network_link *iface; struct sol_network_link_addr *addr; iface = sol_vector_append(&links); SOL_NULL_CHECK(iface, -ENOMEM); sol_vector_init(&iface->addrs, sizeof(struct sol_network_link_addr)); addr = sol_vector_append(&iface->addrs); SOL_NULL_CHECK_GOTO(addr, addr_append_error); if (!get_local_address(addr)) goto get_address_error; SOL_SET_API_VERSION(iface->api_version = SOL_NETWORK_LINK_API_VERSION; )
int test_result_open( struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options) { struct test_result_data *d = data; const struct sol_flow_node_type_test_result_options *opts = (const struct sol_flow_node_type_test_result_options *)options; d->timer = sol_timeout_add(opts->timeout.val, on_timeout, node); SOL_NULL_CHECK_GOTO(d->timer, error); node_count++; d->done = false; return 0; error: return -ENOMEM; }
int process_subprocess_start_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; if (mdata->fork_run) return 0; if (setup_watches(mdata) < 0) return -1; mdata->fork_run = sol_platform_linux_fork_run(on_fork, on_fork_exit, mdata); SOL_NULL_CHECK_GOTO(mdata->fork_run, fork_err); return 0; fork_err: sol_fd_del(mdata->watches.err); mdata->watches.err = NULL; sol_fd_del(mdata->watches.in); mdata->watches.in = NULL; return -1; }
SOL_API char * sol_util_load_file_fd_string(int fd, size_t *size) { int r; size_t size_read; char *data = NULL; struct sol_buffer buf = SOL_BUFFER_INIT_EMPTY; r = sol_util_load_file_fd_buffer(fd, &buf); SOL_INT_CHECK_GOTO(r, < 0, err); r = sol_buffer_trim(&buf); SOL_INT_CHECK_GOTO(r, < 0, err); data = sol_buffer_steal(&buf, &size_read); SOL_NULL_CHECK_GOTO(data, err); if (size) *size = size_read; return data; err: if (size) *size = 0; return NULL; }
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; }
static const struct sol_flow_node_type * _resolver_conffile_get_module(const char *type) { struct resolver_conffile_dlopen *entry; const struct sol_flow_node_type *ret; struct sol_str_slice module_name; char path[PATH_MAX]; char *name; int r; if (!resolver_conffile_dlopens) { resolver_conffile_dlopens = g_hash_table_new_full( g_str_hash, g_str_equal, NULL, (GDestroyNotify)resolver_conffile_dlopen_free); SOL_NULL_CHECK(resolver_conffile_dlopens, NULL); atexit(resolver_conffile_clear_data); } module_name = get_module_for_type(type); if (module_name.len == 0) { SOL_DBG("Invalid empty name"); return NULL; } name = strndup(module_name.data, module_name.len); SOL_NULL_CHECK(name, NULL); /* the hash entry keys are the type part only */ entry = g_hash_table_lookup(resolver_conffile_dlopens, name); if (entry) { free(name); goto found; } entry = calloc(1, sizeof(*entry)); if (!entry) { SOL_DBG("Could not alloc memory for entry"); free(name); return NULL; } entry->name = name; r = snprintf(path, sizeof(path), "%s/%s.so", FLOWMODULESDIR, name); if (r < 0 || r >= (int)sizeof(path)) goto error; entry->handle = dlopen(path, RTLD_LAZY | RTLD_LOCAL | RTLD_NODELETE); if (!entry->handle) { SOL_DBG("could not load module '%s': %s", path, dlerror()); goto error; } entry->foreach = dlsym(entry->handle, "sol_flow_foreach_module_node_type"); if (!entry->foreach) { SOL_DBG("could not find symbol " "sol_flow_foreach_module_node_type() " "in module '%s': %s", path, dlerror()); goto error; } g_hash_table_insert(resolver_conffile_dlopens, entry->name, entry); found: ret = resolve_module_type_by_component(type, entry->foreach); SOL_NULL_CHECK_GOTO(ret, wipe_entry); return ret; error: resolver_conffile_dlopen_free(entry); return NULL; wipe_entry: g_hash_table_remove(resolver_conffile_dlopens, entry->name); return NULL; }
SOL_API struct sol_lwm2m_bootstrap_server * sol_lwm2m_bootstrap_server_new(uint16_t port, const char **known_clients, uint16_t num_sec_modes, ...) { struct sol_lwm2m_bootstrap_server *server; struct sol_network_link_addr servaddr = { .family = SOL_NETWORK_FAMILY_INET6, .port = port }; int r; struct sol_lwm2m_security_psk **known_psks = NULL, *cli_psk; struct sol_lwm2m_security_rpk *my_rpk = NULL; struct sol_blob **known_pub_keys = NULL, *cli_pub_key; enum sol_lwm2m_security_mode *sec_modes; enum sol_socket_dtls_cipher *cipher_suites; uint16_t i, j; va_list ap; SOL_LOG_INTERNAL_INIT_ONCE; SOL_NULL_CHECK(known_clients, NULL); SOL_INT_CHECK(num_sec_modes, == 0, NULL); va_start(ap, num_sec_modes); cipher_suites = calloc(num_sec_modes, sizeof(enum sol_socket_dtls_cipher)); SOL_NULL_CHECK_GOTO(cipher_suites, err_va_list); sec_modes = calloc(num_sec_modes, sizeof(enum sol_lwm2m_security_mode)); SOL_NULL_CHECK_GOTO(sec_modes, err_cipher_suites); for (i = 0; i < num_sec_modes; i++) { sec_modes[i] = va_arg(ap, enum sol_lwm2m_security_mode); SOL_EXP_CHECK_GOTO(sec_mode_is_repeated(sec_modes[i], sec_modes, i), err_sec_modes); switch (sec_modes[i]) { case SOL_LWM2M_SECURITY_MODE_PRE_SHARED_KEY: known_psks = va_arg(ap, struct sol_lwm2m_security_psk **); SOL_NULL_CHECK_GOTO(known_psks, err_sec_modes); cipher_suites[i] = SOL_SOCKET_DTLS_CIPHER_PSK_AES128_CCM8; break; case SOL_LWM2M_SECURITY_MODE_RAW_PUBLIC_KEY: my_rpk = va_arg(ap, struct sol_lwm2m_security_rpk *); SOL_NULL_CHECK_GOTO(my_rpk, err_sec_modes); known_pub_keys = va_arg(ap, struct sol_blob **); SOL_NULL_CHECK_GOTO(known_pub_keys, err_sec_modes); cipher_suites[i] = SOL_SOCKET_DTLS_CIPHER_ECDHE_ECDSA_AES128_CCM8; break; case SOL_LWM2M_SECURITY_MODE_CERTIFICATE: SOL_WRN("Certificate security mode is not supported yet."); goto err_sec_modes; case SOL_LWM2M_SECURITY_MODE_NO_SEC: SOL_WRN("Bootstrap Server MUST use DTLS."); goto err_sec_modes; default: SOL_WRN("Unknown DTLS Security Mode: %d", sec_modes[i]); goto err_sec_modes; } } server = calloc(1, sizeof(struct sol_lwm2m_bootstrap_server)); SOL_NULL_CHECK_GOTO(server, err_sec_modes); //LWM2M Bootstrap Server MUST always use DTLS for (i = 0; i < num_sec_modes; i++) { if (sec_modes[i] == SOL_LWM2M_SECURITY_MODE_PRE_SHARED_KEY) { sol_vector_init(&server->known_psks, sizeof(sol_lwm2m_security_psk)); for (j = 0; known_psks[j]; j++) { cli_psk = sol_vector_append(&server->known_psks); SOL_NULL_CHECK_GOTO(cli_psk, err_copy_keys); cli_psk->id = sol_blob_ref(known_psks[j]->id); cli_psk->key = sol_blob_ref(known_psks[j]->key); } } else if (sec_modes[i] == SOL_LWM2M_SECURITY_MODE_RAW_PUBLIC_KEY) { sol_ptr_vector_init(&server->known_pub_keys); for (j = 0; known_pub_keys[j]; j++) { r = sol_ptr_vector_append(&server->known_pub_keys, sol_blob_ref(known_pub_keys[j])); SOL_INT_CHECK_GOTO(r, < 0, err_copy_keys); } server->rpk_pair.private_key = sol_blob_ref(my_rpk->private_key); server->rpk_pair.public_key = sol_blob_ref(my_rpk->public_key); } }
static void iio_direction_vector_reader_cb(void *data, struct sol_iio_device *device) { static const char *errmsg = "Could not read channel buffer values"; struct sol_flow_node *node = data; struct iio_direction_vector_data *mdata = sol_flow_node_get_private_data(node); struct sol_direction_vector out = { .min = mdata->iio_base.out_range.min, .max = mdata->iio_base.out_range.max }; int r; struct iio_node_type *type; type = (struct iio_node_type *)sol_flow_node_get_type(node); r = sol_iio_read_channel_value(mdata->channel_x, &out.x); SOL_INT_CHECK_GOTO(r, < 0, error); r = sol_iio_read_channel_value(mdata->channel_y, &out.y); SOL_INT_CHECK_GOTO(r, < 0, error); r = sol_iio_read_channel_value(mdata->channel_z, &out.z); SOL_INT_CHECK_GOTO(r, < 0, error); SOL_DBG("Before mount_calibration: %f-%f-%f", out.x, out.y, out.z); // mount correction sol_iio_mount_calibration(device, &out); sol_flow_send_direction_vector_packet(node, type->out_port, &out); return; error: sol_flow_send_error_packet_str(node, EIO, errmsg); SOL_WRN("%s", errmsg); } static void iio_double_reader_cb(void *data, struct sol_iio_device *device) { static const char *errmsg = "Could not read channel buffer values"; struct sol_flow_node *node = data; struct iio_double_data *mdata = sol_flow_node_get_private_data(node); struct sol_drange out = { .min = mdata->iio_base.out_range.min, .max = mdata->iio_base.out_range.max, .step = mdata->iio_base.out_range.step }; int r; struct iio_node_type *type; type = (struct iio_node_type *)sol_flow_node_get_type(node); r = sol_iio_read_channel_value(mdata->channel_val, &out.val); SOL_INT_CHECK_GOTO(r, < 0, error); sol_flow_send_drange_value_packet(node, type->out_port, out.val); return; error: sol_flow_send_error_packet_str(node, EIO, errmsg); SOL_WRN("%s", errmsg); } static void iio_color_reader_cb(void *data, struct sol_iio_device *device) { static const char *errmsg = "Could not read channel buffer values"; struct sol_flow_node *node = data; struct iio_color_data *mdata = sol_flow_node_get_private_data(node); struct sol_rgb out = { .red_max = mdata->iio_base.out_range.max, .green_max = mdata->iio_base.out_range.max, .blue_max = mdata->iio_base.out_range.max }; double tmp; int r; struct iio_node_type *type; type = (struct iio_node_type *)sol_flow_node_get_type(node); r = sol_iio_read_channel_value(mdata->channel_red, &tmp); if (r < 0 || tmp < 0 || tmp > UINT32_MAX) goto error; out.red = tmp; r = sol_iio_read_channel_value(mdata->channel_green, &tmp); if (r < 0 || tmp < 0 || tmp > UINT32_MAX) goto error; out.green = tmp; r = sol_iio_read_channel_value(mdata->channel_blue, &tmp); if (r < 0 || tmp < 0 || tmp > UINT32_MAX) goto error; out.blue = tmp; sol_flow_send_rgb_packet(node, type->out_port, &out); return; error: sol_flow_send_error_packet_str(node, EIO, errmsg); SOL_WRN("%s", errmsg); } static bool gyroscope_create_channels(struct iio_direction_vector_data *mdata, int device_id) { mdata->iio_base.device = sol_iio_open(device_id, &mdata->iio_base.config); SOL_NULL_CHECK(mdata->iio_base.device, false); mdata->channel_x = iio_add_channel(mdata->scale.x, mdata->offset.x, "in_anglvel_x", &mdata->iio_base); SOL_NULL_CHECK_GOTO(mdata->channel_x, error); mdata->channel_y = iio_add_channel(mdata->scale.y, mdata->offset.y, "in_anglvel_y", &mdata->iio_base); SOL_NULL_CHECK_GOTO(mdata->channel_y, error); mdata->channel_z = iio_add_channel(mdata->scale.z, mdata->offset.z, "in_anglvel_z", &mdata->iio_base); SOL_NULL_CHECK_GOTO(mdata->channel_z, error); sol_iio_device_start_buffer(mdata->iio_base.device); return true; error: SOL_WRN("Could not create iio/gyroscope node. Failed to open IIO device %d", device_id); sol_iio_close(mdata->iio_base.device); return false; } static int gyroscope_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options) { struct iio_direction_vector_data *mdata = data; const struct sol_flow_node_type_iio_gyroscope_options *opts; int device_id, ret; struct iio_node_type *type; type = (struct iio_node_type *)sol_flow_node_get_type(node); SOL_FLOW_NODE_OPTIONS_SUB_API_CHECK(options, SOL_FLOW_NODE_TYPE_IIO_GYROSCOPE_OPTIONS_API_VERSION, -EINVAL); opts = (const struct sol_flow_node_type_iio_gyroscope_options *)options; mdata->iio_base.buffer_enabled = opts->buffer_size > -1; SOL_SET_API_VERSION(mdata->iio_base.config.api_version = SOL_IIO_CONFIG_API_VERSION; ) if (opts->iio_trigger_name) { mdata->iio_base.config.trigger_name = strdup(opts->iio_trigger_name); SOL_NULL_CHECK(mdata->iio_base.config.trigger_name, -ENOMEM); } mdata->iio_base.config.buffer_size = opts->buffer_size; mdata->iio_base.config.sampling_frequency = opts->sampling_frequency; ret = snprintf(mdata->iio_base.config.sampling_frequency_name, sizeof(mdata->iio_base.config.sampling_frequency_name), "%s", "in_anglvel_"); SOL_INT_CHECK_GOTO(ret, >= (int)sizeof(mdata->iio_base.config.sampling_frequency_name), err); SOL_INT_CHECK_GOTO(ret, < 0, err); if (mdata->iio_base.buffer_enabled) { mdata->iio_base.config.sol_iio_reader_cb = type->reader_cb; mdata->iio_base.config.data = node; } mdata->iio_base.use_device_default_scale = opts->use_device_default_scale; mdata->iio_base.use_device_default_offset = opts->use_device_default_offset; mdata->scale = opts->scale; mdata->offset = opts->offset; mdata->iio_base.out_range = opts->out_range; device_id = sol_iio_address_device(opts->iio_device); if (device_id < 0) { SOL_WRN("Could not create iio/gyroscope node. Failed to open IIO device %s", opts->iio_device); goto err; } if (!gyroscope_create_channels(mdata, device_id)) goto err; return 0; err: free((char *)mdata->iio_base.config.trigger_name); return -EINVAL; } static bool magnet_create_channels(struct iio_direction_vector_data *mdata, int device_id) { mdata->iio_base.device = sol_iio_open(device_id, &mdata->iio_base.config); SOL_NULL_CHECK(mdata->iio_base.device, false); mdata->channel_x = iio_add_channel(mdata->scale.x, mdata->offset.x, "in_magn_x", &mdata->iio_base); SOL_NULL_CHECK_GOTO(mdata->channel_x, error); mdata->channel_y = iio_add_channel(mdata->scale.y, mdata->offset.y, "in_magn_y", &mdata->iio_base); SOL_NULL_CHECK_GOTO(mdata->channel_y, error); mdata->channel_z = iio_add_channel(mdata->scale.z, mdata->offset.z, "in_magn_z", &mdata->iio_base); SOL_NULL_CHECK_GOTO(mdata->channel_z, error); sol_iio_device_start_buffer(mdata->iio_base.device); return true; error: SOL_WRN("Could not create iio/magnet node. Failed to open IIO device %d", device_id); sol_iio_close(mdata->iio_base.device); return false; }
SOL_API int sol_gatt_pending_reply(struct sol_gatt_pending *pending, int error, struct sol_buffer *buf) { sd_bus_message *reply = NULL; struct context *ctx = bluetooth_get_context(); const struct sol_gatt_attr *attr; const char *interface; int r; SOL_NULL_CHECK(pending, -EINVAL); attr = pending->attr; if (error) { r = error; goto done; } switch (pending->type) { case PENDING_READ: case PENDING_WRITE: r = sd_bus_message_new_method_return(pending->m, &reply); SOL_INT_CHECK(r, < 0, r); if (pending->type == PENDING_READ) { r = -EINVAL; SOL_NULL_CHECK_GOTO(buf, done); r = sd_bus_message_append_array(reply, 'y', buf->data, buf->used); SOL_INT_CHECK_GOTO(r, < 0, done); } break; case PENDING_INDICATE: case PENDING_NOTIFY: r = -EINVAL; pending->buf = buf; SOL_NULL_CHECK_GOTO(pending->buf, done); if (attr->type == SOL_GATT_ATTR_TYPE_DESCRIPTOR) interface = "org.bluez.GattDescriptor1"; else interface = "org.bluez.GattCharacteristic1"; r = sd_bus_emit_properties_changed(sol_bus_client_get_bus(ctx->bluez), attr->_priv, interface, "Value", NULL); SOL_INT_CHECK_GOTO(r, < 0, done); break; case PENDING_REMOTE_READ: pending->read((void *)pending->user_data, true, pending->attr, buf); pending->read = NULL; destroy_pending(pending); break; case PENDING_REMOTE_WRITE: pending->write((void *)pending->user_data, true, pending->attr); pending->write = NULL; destroy_pending(pending); break; }