static void test_coap_parse_simple_pdu(void) { uint8_t pdu[] = { 0x55, 0xA5, 0x12, 0x34, 't', 'o', 'k', 'e', 'n', 0x00, 0xc1, 0x00, 0xff, 'p', 'a', 'y', 'l', 'o', 'a', 'd', 0x00 }; struct sol_str_slice options[16]; struct sol_coap_packet *pkt; struct sol_buffer *buf; uint8_t *token; int count = 16; size_t offset; uint8_t tkl, code, ver, type; uint16_t id; pkt = sol_coap_packet_new(NULL); ASSERT(pkt); ASSERT(!sol_coap_packet_get_payload(pkt, &buf, &offset)); ASSERT(!sol_buffer_remove_data(buf, 0, offset)); ASSERT(!sol_buffer_insert_bytes(buf, 0, pdu, sizeof(pdu))); ASSERT(!coap_packet_parse(pkt)); sol_coap_header_get_version(pkt, &ver); sol_coap_header_get_type(pkt, &type); ASSERT_INT_EQ(ver, 1); ASSERT_INT_EQ(type, SOL_COAP_MESSAGE_TYPE_NON_CON); token = sol_coap_header_get_token(pkt, &tkl); ASSERT(token); ASSERT_INT_EQ(tkl, 5); ASSERT(!strcmp((char *)token, "token")); sol_coap_header_get_code(pkt, &code); sol_coap_header_get_id(pkt, &id); ASSERT_INT_EQ(code, SOL_COAP_RESPONSE_CODE_PROXYING_NOT_SUPPORTED); ASSERT_INT_EQ(id, 0x1234); count = sol_coap_find_options(pkt, SOL_COAP_OPTION_CONTENT_FORMAT, options, count); ASSERT_INT_EQ(count, 1); ASSERT_INT_EQ(options[0].len, 1); ASSERT_INT_EQ((uint8_t)options[0].data[0], 0); /* Not existent. */ count = sol_coap_find_options(pkt, SOL_COAP_OPTION_ETAG, options, count); ASSERT_INT_EQ(count, 0); ASSERT(!sol_coap_packet_get_payload(pkt, &buf, &offset)); ASSERT_INT_EQ(offset + sizeof("payload"), buf->used); ASSERT(!strcmp((char *)buf->data + offset, "payload")); sol_coap_packet_unref(pkt); }
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; }
static int light_method_get(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) { struct sol_coap_packet *resp; struct sol_buffer *buf; int r; 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, SOL_COAP_RSPCODE_CONTENT); SOL_INT_CHECK_GOTO(r, < 0, err); r = sol_coap_packet_get_payload(resp, &buf, NULL); SOL_INT_CHECK_GOTO(r, < 0, err); r = light_resource_to_rep(resource, get_scrolllock_led(), buf); SOL_INT_CHECK_GOTO(r, < 0, err); return sol_coap_send_packet(server, resp, cliaddr); err: sol_coap_packet_unref(resp); return r; }
static bool update_light(void *data) { struct light_context *context = data; struct sol_coap_server *server = context->server; struct sol_coap_resource *resource = context->resource; struct sol_coap_packet *pkt; struct sol_buffer *buf; int r; SOL_INF("Emitting notification"); pkt = sol_coap_packet_notification_new(server, resource); SOL_NULL_CHECK(pkt, false); r = sol_coap_header_set_code(pkt, SOL_COAP_RSPCODE_CONTENT); SOL_INT_CHECK_GOTO(r, < 0, err); r = sol_coap_packet_get_payload(pkt, &buf, NULL); SOL_INT_CHECK_GOTO(r, < 0, err); r = light_resource_to_rep(resource, get_scrolllock_led(), buf); SOL_INT_CHECK_GOTO(r, < 0, err); return !sol_coap_packet_send_notification(server, resource, pkt); err: sol_coap_packet_unref(pkt); return false; }
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 }
CborError sol_oic_decode_cbor_repr(struct sol_coap_packet *pkt, struct sol_vector *reprs) { CborParser parser; CborError err; CborValue root, array, repr; uint8_t *payload; uint16_t size; int payload_type; if (sol_coap_packet_get_payload(pkt, &payload, &size) < 0) return CborErrorUnknownLength; err = cbor_parser_init(payload, size, 0, &parser, &root); if (err != CborNoError) return err; if (!cbor_value_is_array(&root)) return CborErrorIllegalType; err |= cbor_value_enter_container(&root, &array); err |= cbor_value_get_int(&array, &payload_type); err |= cbor_value_advance_fixed(&array); if (err != CborNoError) return err; if (payload_type != SOL_OIC_PAYLOAD_REPRESENTATION) return CborErrorIllegalType; if (cbor_value_map_find_value(&array, SOL_OIC_KEY_REPRESENTATION, &repr) != CborNoError) return CborErrorIllegalType; /* We're done with this CborParser, no need to close the container. */ return sol_oic_decode_cbor_repr_map(&repr, reprs); }
static bool _platform_info_reply_cb(struct sol_coap_server *server, struct sol_coap_packet *req, const struct sol_network_link_addr *addr, void *data) { struct server_info_ctx *ctx = data; uint8_t *payload; uint16_t payload_len; struct sol_oic_platform_information info = { 0 }; if (!req || !addr) { ctx->cb(ctx->client, NULL, (char *)ctx->data); goto free_ctx; } if (!ctx->cb) { SOL_WRN("No user callback provided"); goto free_ctx; } if (!_pkt_has_same_token(req, ctx->token)) { goto free_ctx; } if (!sol_oic_pkt_has_cbor_content(req)) { goto free_ctx; } if (sol_coap_packet_get_payload(req, &payload, &payload_len) < 0) { SOL_WRN("Could not get pkt payload"); goto free_ctx; } if (_parse_platform_info_payload(&info, payload, payload_len)) { SOL_SET_API_VERSION(info.api_version = SOL_OIC_PLATFORM_INFORMATION_API_VERSION; )
static void test_coap_find_options(void) { uint8_t pdu[] = { 0x55, 0xA5, 0x12, 0x34, 't', 'o', 'k', 'e', 'n', 0x00, 0xC1, 0x00, 0xff, 'p', 'a', 'y', 'l', 'o', 'a', 'd', 0x00 }; struct sol_str_slice options[16]; struct sol_coap_packet *pkt; struct sol_buffer *buf; int count = 16; size_t offset; pkt = sol_coap_packet_new(NULL); ASSERT(pkt); ASSERT(!sol_coap_packet_get_payload(pkt, &buf, &offset)); ASSERT(!sol_buffer_remove_data(buf, 0, offset)); ASSERT(!sol_buffer_insert_bytes(buf, 0, pdu, sizeof(pdu))); ASSERT(!coap_packet_parse(pkt)); count = sol_coap_find_options(pkt, SOL_COAP_OPTION_CONTENT_FORMAT, options, count); ASSERT_INT_EQ(count, 1); ASSERT_INT_EQ(options[0].len, 1); ASSERT_INT_EQ((uint8_t)options[0].data[0], 0); count = sol_coap_find_options(pkt, SOL_COAP_OPTION_IF_MATCH, options, count); ASSERT_INT_EQ(count, 0); sol_coap_packet_unref(pkt); }
static void test_coap_parse_empty_pdu(void) { uint8_t pdu[] = { 0x40, 0x01, 0, 0 }; struct sol_coap_packet *pkt; struct sol_buffer *buf; size_t offset; uint8_t ver, type, code; uint16_t id; pkt = sol_coap_packet_new(NULL); ASSERT(pkt); ASSERT(!sol_coap_packet_get_payload(pkt, &buf, &offset)); ASSERT(!sol_buffer_remove_data(buf, 0, offset)); ASSERT(!sol_buffer_insert_bytes(buf, 0, pdu, sizeof(pdu))); ASSERT(!coap_packet_parse(pkt)); sol_coap_header_get_version(pkt, &ver); sol_coap_header_get_type(pkt, &type); sol_coap_header_get_code(pkt, &code); sol_coap_header_get_id(pkt, &id); ASSERT_INT_EQ(ver, 1); ASSERT_INT_EQ(type, SOL_COAP_MESSAGE_TYPE_CON); ASSERT_INT_EQ(code, SOL_COAP_METHOD_GET); ASSERT_INT_EQ(id, 0); sol_coap_packet_unref(pkt); }
static void test_coap_parse_illegal_token_length(void) { uint8_t pdu[] = { 0x59, 0x69, 0x12, 0x34, 't', 'o', 'k', 'e', 'n', '1', '2', '3', '4' }; struct sol_coap_packet *pkt; struct sol_buffer *buf; size_t offset; pkt = sol_coap_packet_new(NULL); ASSERT(pkt); ASSERT(!sol_coap_packet_get_payload(pkt, &buf, &offset)); ASSERT(!sol_buffer_remove_data(buf, 0, offset)); ASSERT(!sol_buffer_insert_bytes(buf, 0, pdu, sizeof(pdu))); ASSERT(coap_packet_parse(pkt)); pdu[0] = 0x5f; ASSERT(!sol_buffer_remove_data(buf, 0, offset)); ASSERT(!sol_buffer_insert_bytes(buf, 0, pdu, sizeof(pdu))); ASSERT(coap_packet_parse(pkt)); sol_coap_packet_unref(pkt); }
static void test_coap_parse_simple_pdu(void) { uint8_t pdu[] = { 0x55, 0xA5, 0x12, 0x34, 't', 'o', 'k', 'e', 'n', 0x00, 0xc1, 0x00, 0xff, 'p', 'a', 'y', 'l', 'o', 'a', 'd', 0x00 }; struct sol_coap_packet *pkt; struct sol_str_slice options[16]; uint8_t *payload, *token; uint16_t len; int count = 16; uint8_t tkl; pkt = sol_coap_packet_new(NULL); ASSERT(pkt); memcpy(pkt->buf, pdu, sizeof(pdu)); pkt->payload.size = sizeof(pdu); ASSERT(!coap_packet_parse(pkt)); ASSERT_INT_EQ(sol_coap_header_get_ver(pkt), 1); ASSERT_INT_EQ(sol_coap_header_get_type(pkt), SOL_COAP_TYPE_NONCON); token = sol_coap_header_get_token(pkt, &tkl); ASSERT(token); ASSERT_INT_EQ(tkl, 5); ASSERT(!strcmp((char *)token, "token")); ASSERT_INT_EQ(sol_coap_header_get_code(pkt), SOL_COAP_RSPCODE_PROXYING_NOT_SUPPORTED); ASSERT_INT_EQ(sol_coap_header_get_id(pkt), 0x1234); count = sol_coap_find_options(pkt, SOL_COAP_OPTION_CONTENT_FORMAT, options, count); ASSERT_INT_EQ(count, 1); ASSERT_INT_EQ(options[0].len, 1); ASSERT_INT_EQ((uint8_t)options[0].data[0], 0); /* Not existent. */ count = sol_coap_find_options(pkt, SOL_COAP_OPTION_ETAG, options, count); ASSERT_INT_EQ(count, 0); ASSERT(!sol_coap_packet_get_payload(pkt, &payload, &len)); ASSERT_INT_EQ(len, sizeof("payload")); ASSERT(!strcmp((char *)payload, "payload")); sol_coap_packet_unref(pkt); }
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; }
static void test_coap_parse_options_that_exceed_pdu(void) { uint8_t pdu[] = { 0x55, 0x73, 0x12, 0x34, 't', 'o', 'k', 'e', 'n', 0x00, 0xc1, 0x00, 0xae, 0xf0, 0x03 }; struct sol_coap_packet *pkt; struct sol_buffer *buf; size_t offset; pkt = sol_coap_packet_new(NULL); ASSERT(pkt); ASSERT(!sol_coap_packet_get_payload(pkt, &buf, &offset)); ASSERT(!sol_buffer_remove_data(buf, 0, offset)); ASSERT(!sol_buffer_insert_bytes(buf, 0, pdu, sizeof(pdu))); ASSERT(coap_packet_parse(pkt)); sol_coap_packet_unref(pkt); }
static void test_coap_parse_without_options_with_payload(void) { uint8_t pdu[] = { 0x50, 0x73, 0x12, 0x34, 0xff, 'p', 'a', 'y', 'l', 'o', 'a', 'd' }; struct sol_coap_packet *pkt; struct sol_buffer *buf; size_t offset; pkt = sol_coap_packet_new(NULL); ASSERT(pkt); ASSERT(!sol_coap_packet_get_payload(pkt, &buf, &offset)); ASSERT(!sol_buffer_remove_data(buf, 0, offset)); ASSERT(!sol_buffer_insert_bytes(buf, 0, pdu, sizeof(pdu))); ASSERT(!coap_packet_parse(pkt)); sol_coap_packet_unref(pkt); }
static void test_coap_payload_simple(void) { uint8_t pdu[] = { 0x50, 0x73, 0x12, 0x34, 0xff, 'p', 'a', 'y', 'l', 'o', 'a', 'd', 0x00 }; struct sol_coap_packet *pkt; struct sol_buffer *buf; size_t offset; pkt = sol_coap_packet_new(NULL); ASSERT(pkt); ASSERT(!sol_coap_packet_get_payload(pkt, &buf, &offset)); ASSERT(!sol_buffer_remove_data(buf, 0, offset)); ASSERT(!sol_buffer_insert_bytes(buf, 0, pdu, sizeof(pdu))); ASSERT_INT_EQ(buf->used - offset, sizeof("payload")); ASSERT(streq((char *)buf->data + offset, "payload")); ASSERT(!coap_packet_parse(pkt)); sol_coap_packet_unref(pkt); }
static int light_method_put(const struct sol_coap_resource *resource, struct sol_coap_packet *req, const struct sol_network_link_addr *cliaddr, void *data) { struct sol_coap_server *server = (void *)data; struct sol_coap_packet *resp; char *sub = NULL; uint8_t *p; uint16_t len; bool value; sol_coap_responsecode_t code = SOL_COAP_RSPCODE_CONTENT; sol_coap_packet_get_payload(req, &p, &len); if (p) sub = strstr((char *)p, "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; } sol_coap_header_set_type(resp, SOL_COAP_TYPE_ACK); sol_coap_header_set_code(resp, code); return sol_coap_send_packet(server, resp, cliaddr); }
static int light_method_get(const struct sol_coap_resource *resource, struct sol_coap_packet *req, const struct sol_network_link_addr *cliaddr, void *data) { struct sol_coap_server *server = (void *)data; struct sol_coap_packet *resp; uint8_t *payload; uint16_t len; resp = sol_coap_packet_new(req); if (!resp) { SOL_WRN("Could not build response packet"); return -1; } sol_coap_header_set_type(resp, SOL_COAP_TYPE_ACK); sol_coap_header_set_code(resp, SOL_COAP_RSPCODE_CONTENT); sol_coap_packet_get_payload(resp, &payload, &len); len = light_resource_to_rep(resource, get_scrolllock_led(), (char *)payload, len); sol_coap_packet_set_payload_used(resp, len); return sol_coap_send_packet(server, resp, cliaddr); }
static bool update_light(void *data) { struct light_context *context = data; struct sol_coap_server *server = context->server; struct sol_coap_resource *resource = context->resource; struct sol_coap_packet *pkt; uint8_t *payload; uint16_t len; SOL_INF("Emitting notification"); pkt = sol_coap_packet_notification_new(server, resource); SOL_NULL_CHECK(pkt, false); sol_coap_header_set_code(pkt, SOL_COAP_RSPCODE_CONTENT); sol_coap_packet_get_payload(pkt, &payload, &len); len = light_resource_to_rep(resource, get_scrolllock_led(), (char *)payload, len); sol_coap_packet_set_payload_used(pkt, len); return !sol_coap_packet_send_notification(server, resource, pkt); }
static void test_coap_payload_simple(void) { uint8_t pdu[] = { 0x50, 0x73, 0x12, 0x34, 0xff, 'p', 'a', 'y', 'l', 'o', 'a', 'd', 0x00 }; uint16_t payload_length; uint8_t *payload_ptr; struct sol_coap_packet *pkt; pkt = sol_coap_packet_new(NULL); ASSERT(pkt); memcpy(pkt->buf, pdu, sizeof(pdu)); pkt->payload.size = sizeof(pdu); ASSERT(!sol_coap_packet_get_payload(pkt, &payload_ptr, &payload_length)); ASSERT(payload_ptr); ASSERT_INT_EQ(payload_length, sizeof("payload")); ASSERT(streq((char *)payload_ptr, "payload")); ASSERT(!coap_packet_parse(pkt)); sol_coap_packet_unref(pkt); }
CborError sol_oic_encode_cbor_repr(struct sol_coap_packet *pkt, const char *href, const struct sol_vector *repr_vec) { CborEncoder encoder, rep_map, array, map; CborError err; uint8_t *payload; uint16_t size; if (!repr_vec) return CborNoError; if (sol_coap_packet_get_payload(pkt, &payload, &size) < 0) { SOL_WRN("Could not get CoAP payload"); return CborUnknownError; } cbor_encoder_init(&encoder, payload, size, 0); err = cbor_encoder_create_array(&encoder, &array, CborIndefiniteLength); err |= cbor_encode_uint(&array, SOL_OIC_PAYLOAD_REPRESENTATION); err |= cbor_encoder_create_map(&array, &map, CborIndefiniteLength); err |= cbor_encode_text_stringz(&map, SOL_OIC_KEY_HREF); err |= cbor_encode_text_stringz(&map, href); err |= cbor_encode_text_stringz(&map, SOL_OIC_KEY_REPRESENTATION); err |= cbor_encoder_create_map(&map, &rep_map, CborIndefiniteLength); if (repr_vec) { struct sol_oic_repr_field *repr; uint16_t idx; SOL_VECTOR_FOREACH_IDX (repr_vec, repr, idx) { if (err != CborNoError) break; err |= cbor_encode_text_stringz(&rep_map, repr->key); switch (repr->type) { case SOL_OIC_REPR_TYPE_UINT: err |= cbor_encode_uint(&rep_map, repr->v_uint); break; case SOL_OIC_REPR_TYPE_INT: err |= cbor_encode_int(&rep_map, repr->v_int); break; case SOL_OIC_REPR_TYPE_SIMPLE: err |= cbor_encode_simple_value(&rep_map, repr->v_simple); break; case SOL_OIC_REPR_TYPE_TEXT_STRING: { const char *p = repr->v_slice.data ? repr->v_slice.data : ""; err |= cbor_encode_text_string(&rep_map, p, repr->v_slice.len); break; } case SOL_OIC_REPR_TYPE_BYTE_STRING: { const uint8_t *empty = (const uint8_t *)""; const uint8_t *p = repr->v_slice.data ? (const uint8_t *)repr->v_slice.data : empty; err |= cbor_encode_byte_string(&rep_map, p, repr->v_slice.len); break; } case SOL_OIC_REPR_TYPE_HALF_FLOAT: err |= cbor_encode_half_float(&rep_map, repr->v_voidptr); break; case SOL_OIC_REPR_TYPE_FLOAT: err |= cbor_encode_float(&rep_map, repr->v_float); break; case SOL_OIC_REPR_TYPE_DOUBLE: err |= cbor_encode_double(&rep_map, repr->v_double); break; case SOL_OIC_REPR_TYPE_BOOLEAN: err |= cbor_encode_boolean(&rep_map, repr->v_boolean); break; default: if (err == CborNoError) err = CborErrorUnknownType; } } } err |= cbor_encoder_close_container(&map, &rep_map); err |= cbor_encoder_close_container(&array, &map); err |= cbor_encoder_close_container(&encoder, &array); if (err == CborNoError) sol_coap_packet_set_payload_used(pkt, encoder.ptr - payload); return err; }