Skip to content

Commit

Permalink
api: add oc_rep_object_* function
Browse files Browse the repository at this point in the history
Add functions to write data to an encoder object.
  • Loading branch information
Danielius1922 authored and Daniel Adam committed Oct 20, 2023
1 parent ad798a4 commit b9277a1
Show file tree
Hide file tree
Showing 27 changed files with 728 additions and 220 deletions.
6 changes: 3 additions & 3 deletions api/oc_collection.c
Original file line number Diff line number Diff line change
Expand Up @@ -761,7 +761,7 @@ oc_handle_collection_baseline_request(oc_method_t method, oc_request_t *request)
return result;
}
bool ok = collection->res.set_properties.cb.set_props(
(oc_resource_t *)collection, request->request_payload,
&collection->res, request->request_payload,
collection->res.set_properties.user_data);
if (!ok) {
OC_ERR("set properties callback failed");
Expand All @@ -785,9 +785,9 @@ oc_handle_collection_baseline_request(oc_method_t method, oc_request_t *request)
collection_encode_links(collection, request);

/* custom properties */
if (collection->res.get_properties.cb.get_props) {
if (collection->res.get_properties.cb.get_props != NULL) {
collection->res.get_properties.cb.get_props(
(oc_resource_t *)collection, OC_IF_BASELINE,
&collection->res, OC_IF_BASELINE,
collection->res.get_properties.user_data);
}
oc_rep_end_root_object();
Expand Down
6 changes: 3 additions & 3 deletions api/oc_core_res.c
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,7 @@ oc_core_platform_handler(oc_request_t *request, oc_interface_mask_t iface_mask,
switch (iface_mask) {
case OC_IF_BASELINE:
oc_process_baseline_interface(request->resource);
/* fall through */
OC_FALLTHROUGH;
case OC_IF_R: {
oc_rep_set_text_string(root, pi, pi);
oc_rep_set_text_string(root, mnmn, oc_string(g_oc_platform_info.mfg_name));
Expand Down Expand Up @@ -745,8 +745,8 @@ oc_core_get_resource_type_by_uri(const char *uri, size_t uri_len)
}
#endif /* OC_HAS_FEATURE_PLGD_TIME */
#ifdef OC_WKCORE
if (core_is_resource_uri(uri, uri_len, "/.well-known/core",
OC_CHAR_ARRAY_LEN("/.well-known/core"))) {
if (core_is_resource_uri(uri, uri_len, OC_WELLKNOWNCORE_URI,
OC_CHAR_ARRAY_LEN(OC_WELLKNOWNCORE_URI))) {
return WELLKNOWNCORE;
}
#endif /* OC_WKCORE */
Expand Down
126 changes: 110 additions & 16 deletions api/oc_rep_encode.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,8 @@ rep_buffer_realloc(oc_rep_encoder_t *encoder, size_t needed)
}
if (encoder->buffer.size + needed > encoder->buffer.max_size) {
OC_WRN("Insufficient memory: Increase OC_MAX_APP_DATA_SIZE to accomodate a "
"larger payload(+%d)",
(int)needed);
"larger payload(+%zu)",
needed);
return CborErrorOutOfMemory;
}

Expand Down Expand Up @@ -332,8 +332,8 @@ oc_rep_encoder_payload_size(oc_rep_encoder_t *encoder)
oc_rep_encoder_convert_ptr_to_offset(encoder, &encoder->ctx);
if (g_err == CborErrorOutOfMemory) {
OC_WRN("Insufficient memory: Increase OC_MAX_APP_DATA_SIZE to "
"accomodate a larger payload(+%d)",
(int)needed);
"accomodate a larger payload(+%zu)",
needed);
(void)needed;
}
if (g_err != CborNoError) {
Expand All @@ -348,43 +348,50 @@ oc_rep_get_encoded_payload_size(void)
return oc_rep_encoder_payload_size(&g_rep_encoder);
}

long
oc_rep_encoder_remaining_size(oc_rep_encoder_t *encoder)
{
if (encoder->ctx.end == NULL) {
OC_WRN("encoder has not set end pointer.");
return -1;
}
assert(encoder->buffer.size >= (size_t)encoder->ctx.data.ptr);
return (long)(encoder->buffer.size - (size_t)encoder->ctx.data.ptr);
}

CborError
oc_rep_encoder_write_raw(oc_rep_encoder_t *encoder, const uint8_t *data,
size_t len)
{
if (encoder->ctx.end == NULL) {
OC_WRN("encoder has not set end pointer.");
long remaining = oc_rep_encoder_remaining_size(encoder);
if (remaining < 0) {
return CborErrorInternalError;
}
if ((size_t)remaining < len) {
#ifdef OC_DYNAMIC_ALLOCATION
size_t remaining = encoder->buffer.size - (size_t)encoder->ctx.data.ptr;
if (remaining < len) {
size_t needed = len - remaining;
if (!encoder->buffer.enable_realloc) {
OC_WRN(
"Insufficient memory: Reallocation of the encoder buffer disabled");
return CborErrorOutOfMemory;
}
CborEncoder prevEncoder;
memcpy(&prevEncoder, &encoder->ctx, sizeof(prevEncoder));
size_t needed = len - remaining;
CborError err = rep_buffer_realloc(encoder, needed);
if (err != CborNoError) {
return err;
}
memcpy(&encoder->ctx, &prevEncoder, sizeof(prevEncoder));
}
#else /* OC_DYNAMIC_ALLOCATION */
intptr_t needed =
(intptr_t)encoder->ctx.end - (intptr_t)encoder->ctx.data.ptr;
if (needed < (intptr_t)len) {
OC_WRN("Insufficient memory: Increase OC_MAX_APP_DATA_SIZE to "
"accomodate a larger payload(+%d)",
(int)needed);
"accomodate a larger payload(+%zu)",
len - remaining);
return CborErrorOutOfMemory;
}
#endif /* !OC_DYNAMIC_ALLOCATION */
}
oc_rep_encoder_convert_offset_to_ptr(encoder, &encoder->ctx);
memcpy(encoder->ctx.data.ptr, data, len);
// TODO: this is not correct for crc encoder, add write raw interface function
encoder->ctx.data.ptr = encoder->ctx.data.ptr + len;
oc_rep_encoder_convert_ptr_to_offset(encoder, &encoder->ctx);
return CborNoError;
Expand Down Expand Up @@ -878,3 +885,90 @@ oc_rep_encoder_close_container(CborEncoder *subEncoder,
return oc_rep_encoder_write_container_close(&g_rep_encoder, subEncoder,
containerEncoder);
}

/* oc_rep_object interface */

CborError
oc_rep_object_set_null(CborEncoder *object, const char *key, size_t key_len)
{
CborError err = oc_rep_encode_text_string(object, key, key_len);
err |= oc_rep_encode_null(object);
return err;
}

CborError
oc_rep_object_set_boolean(CborEncoder *object, const char *key, size_t key_len,
bool value)
{
CborError err = oc_rep_encode_text_string(object, key, key_len);
err |= oc_rep_encode_boolean(object, value);
return err;
}

CborError
oc_rep_object_set_int(CborEncoder *object, const char *key, size_t key_len,
int64_t value)
{
CborError err = oc_rep_encode_text_string(object, key, key_len);
err |= oc_rep_encode_int(object, value);
return err;
}

CborError
oc_rep_object_set_uint(CborEncoder *object, const char *key, size_t key_len,
uint64_t value)
{
CborError err = oc_rep_encode_text_string(object, key, key_len);
err |= oc_rep_encode_uint(object, value);
return err;
}

CborError
oc_rep_object_set_double(CborEncoder *object, const char *key, size_t key_len,
double value)
{
CborError err = oc_rep_encode_text_string(object, key, key_len);
err |= oc_rep_encode_double(object, value);
return err;
}

CborError
oc_rep_object_set_text_string(CborEncoder *object, const char *key,
size_t key_len, const char *value,
size_t value_len)
{
CborError err = oc_rep_encode_text_string(object, key, key_len);
err |=
oc_rep_encode_text_string(object, value == NULL ? "" : value, value_len);
return err;
}

CborError
oc_rep_object_set_byte_string(CborEncoder *object, const char *key,
size_t key_len, const uint8_t *value,
size_t length)
{
CborError err = oc_rep_encode_text_string(object, key, key_len);
err |= oc_rep_encode_byte_string(object, value, length);
return err;
}

CborError
oc_rep_object_set_string_array(CborEncoder *object, const char *key,
size_t key_len, const oc_string_array_t *array)
{
CborError err = oc_rep_encode_text_string(object, key, key_len);
CborEncoder arrayEncoder;
memset(&arrayEncoder, 0, sizeof(arrayEncoder));
err |=
oc_rep_encoder_create_array(object, &arrayEncoder, CborIndefiniteLength);
for (size_t i = 0; i < oc_string_array_get_allocated_size(*array); ++i) {
size_t item_len = oc_string_array_get_item_size(*array, i);
if (item_len > 0) {
err |= oc_rep_encode_text_string(
&arrayEncoder, oc_string_array_get_item(*array, i), item_len);
}
}
err |= oc_rep_encoder_close_container(object, &arrayEncoder);
return err;
}
8 changes: 6 additions & 2 deletions api/oc_rep_encode_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ typedef CborError (*oc_rep_encode_double_t)(CborEncoder *encoder, double value)

typedef CborError (*oc_rep_encode_text_string_t)(CborEncoder *encoder,
const char *string,
size_t length) OC_NONNULL();
size_t length) OC_NONNULL(1);

typedef CborError (*oc_rep_encode_byte_string_t)(CborEncoder *encoder,
const uint8_t *string,
Expand All @@ -85,6 +85,7 @@ typedef CborError (*oc_rep_encoder_create_array_t)(CborEncoder *encoder,
typedef CborError (*oc_rep_encoder_create_map_t)(CborEncoder *encoder,
CborEncoder *mapEncoder,
size_t length) OC_NONNULL();

typedef CborError (*oc_rep_encoder_close_container_t)(
CborEncoder *encoder, const CborEncoder *containerEncoder) OC_NONNULL();

Expand Down Expand Up @@ -167,9 +168,12 @@ void oc_rep_encoder_buffer_realloc_init(oc_rep_encoder_t *encoder,

#endif /* OC_DYNAMIC_ALLOCATION */

/** @brief Get the size of the encoded data. */
/** @brief Get the size of the encoded data in the payload buffer. */
int oc_rep_encoder_payload_size(oc_rep_encoder_t *encoder) OC_NONNULL();

/** @brief Get the number of unwritten bytes in the payload buffer. */
long oc_rep_encoder_remaining_size(oc_rep_encoder_t *encoder) OC_NONNULL();

#ifdef OC_DYNAMIC_ALLOCATION
/** @brief Shrink encoder buffer to the payload size */
bool oc_rep_encoder_shrink_buffer(oc_rep_encoder_t *encoder) OC_NONNULL();
Expand Down
2 changes: 0 additions & 2 deletions api/oc_rep_to_json.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,6 @@ static size_t
oc_rep_to_json_format(const oc_rep_t *rep, char *buf, size_t buf_size,
int tab_depth, bool pretty_print)
{
(void)buf;
(void)buf_size;
size_t num_char_printed = 0;
size_t total_char_printed = 0;
while (rep != NULL) {
Expand Down
8 changes: 8 additions & 0 deletions api/oc_resource.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@ oc_resource_is_initialized(const oc_resource_t *resource)
return oc_string(resource->uri) != NULL;
}

bool
oc_resource_supports_interface(const oc_resource_t *resource,
oc_interface_mask_t iface)
{
assert(resource != NULL);
return (resource->interfaces & iface) == iface;
}

void
oc_resources_iterate_platform(oc_resource_iterate_fn_t fn, void *data)
{
Expand Down
11 changes: 11 additions & 0 deletions api/oc_resource_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,17 @@ extern "C" {
*/
bool oc_resource_is_initialized(const oc_resource_t *resource) OC_NONNULL();

/**
* @brief Check if resource supports given interface.
*
* @param resource resource to check (cannot be NULL)
* @param iface interface to check
* @return true resource supports given interface
* @return false resource does not support given interface
*/
bool oc_resource_supports_interface(const oc_resource_t *resource,
oc_interface_mask_t iface) OC_NONNULL();

/**
* @brief Callback invoked for each resource iterated by oc_resources_iterate.
*
Expand Down
49 changes: 23 additions & 26 deletions api/oc_ri.c
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,6 @@ oc_status_code_unsafe(oc_status_t key)
int
oc_status_code(oc_status_t key)
{
assert(key >= 0);
if (key >= __NUM_OC_STATUS_CODES__) {
if (OC_IGNORE == key) {
return CLEAR_TRANSACTION;
Expand Down Expand Up @@ -730,12 +729,6 @@ oc_ri_get_interface_mask(const char *iface, size_t iface_len)
strncmp(iface, OC_IF_STARTUP_REVERT_STR, iface_len) == 0) {
return OC_IF_STARTUP_REVERT;
}
#ifdef OC_HAS_FEATURE_ETAG_INTERFACE
if (OC_CHAR_ARRAY_LEN(PLGD_IF_ETAG_STR) == iface_len &&
strncmp(iface, PLGD_IF_ETAG_STR, iface_len) == 0) {
return PLGD_IF_ETAG;
}
#endif /* OC_HAS_FEATURE_ETAG_INTERFACE */
return 0;
}

Expand All @@ -751,10 +744,6 @@ does_interface_support_method(oc_interface_mask_t iface_mask,
case OC_IF_LL:
case OC_IF_S:
case OC_IF_R:
#ifdef OC_HAS_FEATURE_ETAG_INTERFACE
/* Special retrieve-only interface to calculate checksum for a resource */
case PLGD_IF_ETAG:
#endif /* OC_HAS_FEATURE_ETAG_INTERFACE */
if (method != OC_GET)
supported = false;
break;
Expand Down Expand Up @@ -1131,6 +1120,7 @@ ri_invoke_coap_entity_set_response_etag(
uint8_t etag_len = ctx->response_obj->response_buffer->etag.length;
#ifdef OC_BLOCK_WISE
if (ctx->response_obj->response_buffer->response_length > 0) {
assert(*ctx->response_state != NULL);
oc_blockwise_response_state_t *bw_response_buffer =
(oc_blockwise_response_state_t *)*ctx->response_state;
memcpy(&bw_response_buffer->etag.value[0], &etag[0], etag_len);
Expand Down Expand Up @@ -1344,23 +1334,30 @@ oc_ri_invoke_coap_entity_handler(coap_make_response_ctx_t *ctx,

bool bad_request = false;
bool entity_too_large = false;
if (payload_len > 0 && oc_rep_decoder_set_by_content_format(cf)) {
/* Attempt to parse request payload using tinyCBOR via oc_rep helper
* functions. The result of this parse is a tree of oc_rep_t structures
* which will reflect the schema of the payload.
* Any failures while parsing the payload is viewed as an erroneous
* request and results in a 4.00 response being sent.
*/
int parse_error =
oc_parse_rep(payload, payload_len, &request_obj.request_payload);
if (parse_error != 0) {
OC_WRN("ocri: error parsing request payload; tinyCBOR error code: %d",
parse_error);
if (parse_error == CborErrorUnexpectedEOF) {
entity_too_large = true;
}
if (payload_len > 0) {
if (!oc_rep_decoder_set_by_content_format(cf)) {
OC_WRN("ocri: unsupported content format (%d)", (int)cf);
bad_request = true;
}

if (!bad_request) {
/* Attempt to parse request payload using tinyCBOR via oc_rep helper
* functions. The result of this parse is a tree of oc_rep_t structures
* which will reflect the schema of the payload.
* Any failures while parsing the payload is viewed as an erroneous
* request and results in a 4.00 response being sent.
*/
int parse_error =
oc_parse_rep(payload, payload_len, &request_obj.request_payload);
if (parse_error != 0) {
OC_WRN("ocri: error parsing request payload; tinyCBOR error code: %d",
parse_error);
if (parse_error == CborErrorUnexpectedEOF) {
entity_too_large = true;
}
bad_request = true;
}
}
}

oc_resource_t *cur_resource = NULL;
Expand Down
Loading

0 comments on commit b9277a1

Please sign in to comment.