Example #1
0
int
coap_parse_option(struct option_context *context,
    uint8_t **value, uint16_t *vlen)
{
    uint16_t delta, len;
    uint8_t start;
    int r;

    if (context->buf->used - context->pos < 1)
        return 0;

    start = ((uint8_t *)sol_buffer_at(context->buf, context->pos))[0];

    /* This indicates that options have ended */
    if (start == COAP_MARKER)
        return 0;

    delta = coap_option_header_get_delta(start);
    len = coap_option_header_get_len(start);
    context->pos += 1;
    context->used += 1;

    /* In case 'delta' doesn't fit the option fixed header. */
    r = decode_delta(delta, sol_buffer_at(context->buf, context->pos),
        context->buf->used - context->pos, &delta);
    if (r < 0)
        return r;

    context->pos += r;
    context->used += r;

    /* In case 'len' doesn't fit the option fixed header. */
    r = decode_delta(len, sol_buffer_at(context->buf, context->pos),
        context->buf->used - context->pos, &len);
    if (r < 0)
        return r;

    if (context->buf->used - context->pos < (size_t)(r + len))
        return -EINVAL;

    if (value)
        *value = sol_buffer_at(context->buf, context->pos + r);

    if (vlen)
        *vlen = len;

    context->pos += r + len;
    context->used += r + len;

    context->delta += delta;

    return context->used;
}
SOL_API int
sol_buffer_insert_char(struct sol_buffer *buf, size_t pos, const char c)
{
    char *p;
    size_t new_size;
    int err;

    SOL_NULL_CHECK(buf, -EINVAL);
    SOL_INT_CHECK(pos, > buf->used, -EINVAL);

    if (pos == buf->used)
        return sol_buffer_append_char(buf, c);

    err = sol_util_size_add(buf->used, 1, &new_size);
    if (err < 0)
        return err;

    err = sol_buffer_ensure(buf, new_size);
    if (err < 0)
        return err;

    p = sol_buffer_at(buf, pos);
    memmove(p + 1, p, buf->used - pos);
    *p = c;
    buf->used++;

    if (nul_byte_size(buf))
        return sol_buffer_ensure_nul_byte(buf);
    return 0;
}
Example #3
0
SOL_API void
sol_oic_payload_debug(struct sol_coap_packet *pkt)
{
    SOL_NULL_CHECK(pkt);

#ifdef HAVE_STDOUT
    struct sol_buffer *buf;
    CborParser parser;
    CborValue root;
    CborError err;
    size_t offset;

    if (!sol_oic_pkt_has_cbor_content(pkt) ||
        !sol_coap_packet_has_payload(pkt)) {
        return;
    }
    if (sol_coap_packet_get_payload(pkt, &buf, &offset) < 0) {
        SOL_DBG("Failed to get packet payload");
        return;
    }

    err = cbor_parser_init(sol_buffer_at(buf, offset),
        buf->used - offset, 0, &parser, &root);
    if (err != CborNoError) {
        SOL_DBG("Failed to get cbor payload");
        return;
    }

    cbor_value_to_pretty(stdout, &root);
    fprintf(stdout, "\n");
#else
    SOL_DBG("Failed to log oic payload: stdout not available");
#endif
}
Example #4
0
static bool
reply_cb(struct sol_coap_server *server, struct sol_coap_packet *req,
    const struct sol_network_link_addr *cliaddr, void *data)
{
    struct sol_str_slice *path = data;
    static int count;
    struct sol_buffer *buf;
    size_t offset;

    SOL_BUFFER_DECLARE_STATIC(addr, SOL_INET_ADDR_STRLEN);

    if (!req || !cliaddr) //timeout
        return false;

    sol_network_link_addr_to_str(cliaddr, &addr);

    SOL_INF("Got response from %.*s\n", SOL_STR_SLICE_PRINT(sol_buffer_get_slice(&addr)));

    sol_coap_packet_get_payload(req, &buf, &offset);
    SOL_INF("Payload: %.*s\n", (int)(buf->used - offset),
        (char *)sol_buffer_at(buf, offset));

    if (++count == 10)
        disable_observing(req, server, path, cliaddr);

    return true;
}
Example #5
0
SOL_API int
sol_buffer_insert_from_base16(struct sol_buffer *buf, size_t pos, const struct sol_str_slice slice, enum sol_decode_case decode_case)
{
    char *p;
    size_t new_size;
    ssize_t decoded_size, r;
    const size_t nul_size = nul_byte_size(buf);
    int err;

    SOL_NULL_CHECK(buf, -EINVAL);
    SOL_INT_CHECK(pos, > buf->used, -EINVAL);

    if (slice.len == 0)
        return 0;

    if (pos == buf->used)
        return sol_buffer_append_from_base16(buf, slice, decode_case);

    decoded_size = sol_util_base16_calculate_decoded_len(slice);
    if (decoded_size < 0)
        return decoded_size;

    err = sol_util_size_add(buf->used, decoded_size, &new_size);
    if (err < 0)
        return err;

    if (nul_size) {
        err = sol_util_size_add(new_size, nul_size, &new_size);
        if (err < 0)
            return err;
    }

    err = sol_buffer_ensure(buf, new_size);
    if (err < 0)
        return err;

    p = sol_buffer_at(buf, pos);
    memmove(p + decoded_size, p, buf->used - pos);
    r = sol_util_base16_decode(p, decoded_size, slice, decode_case);
    if (r != decoded_size) {
        memmove(p, p + decoded_size, buf->used - pos);
        if (nul_size)
            sol_buffer_ensure_nul_byte(buf);
        if (r < 0)
            return r;
        else
            return -EINVAL;
    }

    buf->used += decoded_size;

    if (nul_size)
        return sol_buffer_ensure_nul_byte(buf);
    return 0;
}
Example #6
0
SOL_API int
sol_buffer_insert_as_base64(struct sol_buffer *buf, size_t pos, const struct sol_str_slice slice, const char base64_map[SOL_STATIC_ARRAY_SIZE(65)])
{
    char *p;
    size_t new_size;
    ssize_t encoded_size, r;
    const size_t nul_size = nul_byte_size(buf);
    int err;

    SOL_NULL_CHECK(buf, -EINVAL);
    SOL_INT_CHECK(pos, > buf->used, -EINVAL);

    if (slice.len == 0)
        return 0;

    if (pos == buf->used)
        return sol_buffer_append_as_base64(buf, slice, base64_map);

    encoded_size = sol_util_base64_calculate_encoded_len(slice, base64_map);
    if (encoded_size < 0)
        return encoded_size;

    err = sol_util_size_add(buf->used, encoded_size, &new_size);
    if (err < 0)
        return err;

    if (nul_size) {
        err = sol_util_size_add(new_size, nul_size, &new_size);
        if (err < 0)
            return err;
    }

    err = sol_buffer_ensure(buf, new_size);
    if (err < 0)
        return err;

    p = sol_buffer_at(buf, pos);
    memmove(p + encoded_size, p, buf->used - pos);
    r = sol_util_base64_encode(p, encoded_size, slice, base64_map);
    if (r != encoded_size) {
        memmove(p, p + encoded_size, buf->used - pos);
        if (nul_size)
            sol_buffer_ensure_nul_byte(buf);
        if (r < 0)
            return r;
        else
            return -EINVAL;
    }

    buf->used += encoded_size;

    if (nul_size)
        return sol_buffer_ensure_nul_byte(buf);
    return 0;
}
Example #7
0
static int
light_method_put(struct sol_coap_server *server,
    const struct sol_coap_resource *resource, struct sol_coap_packet *req,
    const struct sol_network_link_addr *cliaddr, void *data)
{
    sol_coap_responsecode_t code = SOL_COAP_RSPCODE_CONTENT;
    struct sol_coap_packet *resp;
    struct sol_buffer *buf;
    char *sub = NULL;
    size_t offset;
    bool value;
    int r;

    sol_coap_packet_get_payload(req, &buf, &offset);

    if (buf)
        sub = strstr((char *)sol_buffer_at(buf, offset), "state\":");
    if (!sub) {
        code = SOL_COAP_RSPCODE_BAD_REQUEST;
        goto done;
    }

    value = !memcmp(sub + strlen("state\":"), "true", sizeof("true") - 1);

    SOL_INF("Changing light state to %s", value ? "on" : "off");

    set_scrolllock_led(value);

done:
    resp = sol_coap_packet_new(req);
    if (!resp) {
        SOL_WRN("Could not build response packet");
        return -1;
    }
    r = sol_coap_header_set_type(resp, SOL_COAP_TYPE_ACK);
    SOL_INT_CHECK_GOTO(r, < 0, err);
    r = sol_coap_header_set_code(resp, code);
    SOL_INT_CHECK_GOTO(r, < 0, err);

    return sol_coap_send_packet(server, resp, cliaddr);

err:
    sol_coap_packet_unref(resp);
    return r;
}
SOL_API int
sol_buffer_insert_slice(struct sol_buffer *buf, size_t pos, const struct sol_str_slice slice)
{
    const size_t nul_size = nul_byte_size(buf);
    char *p;
    size_t new_size;
    int err;

    SOL_NULL_CHECK(buf, -EINVAL);
    SOL_INT_CHECK(pos, > buf->used, -EINVAL);

    if (pos == buf->used)
        return sol_buffer_append_slice(buf, slice);

    err = sol_util_size_add(buf->used, slice.len, &new_size);
    if (err < 0)
        return err;

    /* Extra room for the ending NUL-byte. */
    if (new_size >= SIZE_MAX - nul_size)
        return -EOVERFLOW;
    err = sol_buffer_ensure(buf, new_size + nul_size);
    if (err < 0)
        return err;

    p = sol_buffer_at(buf, pos);
    memmove(p + slice.len, p, buf->used - pos);
    memcpy(p, slice.data, slice.len);
    buf->used += slice.len;

    if (nul_size) {
        p = sol_buffer_at_end(buf);
        p[0] = '\0';
    }

    return 0;
}
Example #9
0
static int
coap_parse_options(struct sol_coap_packet *pkt, unsigned int offset)
{
    struct option_context context = { .delta = 0,
                                      .used = 0,
                                      .buf = &pkt->buf,
                                      .pos = offset };

    while (true) {
        int r = coap_parse_option(&context, NULL, NULL);
        if (r < 0)
            return -EINVAL;

        if (r == 0)
            break;
    }
    return context.used;
}

int
coap_get_header_len(const struct sol_coap_packet *pkt)
{
    struct coap_header *hdr;
    unsigned int hdrlen;
    uint8_t tkl;

    hdrlen = sizeof(struct coap_header);

    if (pkt->buf.used < hdrlen)
        return -EINVAL;

    hdr = (struct coap_header *)sol_buffer_at(&pkt->buf, 0);
    tkl = hdr->tkl;

    // Token lenghts 9-15 are reserved.
    if (tkl > 8)
        return -EINVAL;

    if (pkt->buf.used < hdrlen + tkl)
        return -EINVAL;

    return hdrlen + tkl;
}

int
coap_packet_parse(struct sol_coap_packet *pkt)
{
    int optlen, hdrlen;

    SOL_NULL_CHECK(pkt, -EINVAL);

    hdrlen = coap_get_header_len(pkt);
    if (hdrlen < 0)
        return hdrlen;

    optlen = coap_parse_options(pkt, hdrlen);
    if (optlen < 0)
        return optlen;

    if (pkt->buf.used < (size_t)(hdrlen + optlen))
        return -EINVAL;

    /* +1 for COAP_MARKER */
    if (pkt->buf.used <= (size_t)(hdrlen + optlen + 1)) {
        pkt->payload_start = 0;
        return 0;
    }

    pkt->payload_start = hdrlen + optlen + 1;
    return 0;
}