Example #1
0
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;
}
Example #2
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;
}
Example #3
0
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;
}
Example #5
0
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;
}
Example #6
0
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;
}
Example #7
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);

    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;
}
Example #10
0
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;
}
Example #11
0
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;
}
Example #12
0
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;
}
Example #13
0
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);
}
Example #14
0
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;
}
Example #15
0
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;
}
Example #16
0
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;
}
Example #17
0
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;
}
Example #18
0
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;
}
Example #19
0
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;
}
Example #20
0
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; )
Example #22
0
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;
}
Example #23
0
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;
}
Example #24
0
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;
}
Example #25
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;
}
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;
}
Example #27
0
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);
        }
    }
Example #28
0
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;
    }