net: lwm2m: refactor lwm2m_engine_context into lwm2m_message

The relationship between lwm2m_engine_context and lwm2m_message
has always been a tenuous one.  Let's merge the 2 structures
into lwm2m_message and remove all of the extra stack variables.

This change increases SRAM usage slightly due to the
addition of the context structures to the multiple lwm2m_messages.
However, the way lwm2m_engine_context was being used off the stack
was probably creating hard to debug issues in the longterm.

Also, having all of the structures in 1 place makes sharing them
much easier later.

Signed-off-by: Michael Scott <mike@foundries.io>
This commit is contained in:
Michael Scott 2019-01-24 14:40:23 -08:00 committed by Jukka Rissanen
commit 44e9b5ed44
9 changed files with 330 additions and 392 deletions

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2017 Linaro Limited
* Copyright (c) 2018 Foundries.io
* Copyright (c) 2018-2019 Foundries.io
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -45,36 +45,6 @@
#define COAP_REPLY_STATUS_NONE 0
#define COAP_REPLY_STATUS_ERROR 1
struct lwm2m_message;
/* Establish a message timeout callback */
typedef void (*lwm2m_message_timeout_cb_t)(struct lwm2m_message *msg);
/* Internal LwM2M message structure to track in-flight messages. */
struct lwm2m_message {
/** LwM2M context related to this message */
struct lwm2m_ctx *ctx;
/** CoAP packet data related to this message */
struct coap_packet cpkt;
/** Message transmission handling for TYPE_CON */
struct coap_pending *pending;
struct coap_reply *reply;
/** Message configuration */
u8_t *token;
coap_reply_t reply_cb;
lwm2m_message_timeout_cb_t message_timeout_cb;
u16_t mid;
u8_t type;
u8_t code;
u8_t tkl;
/** Counter for message re-send / abort handling */
u8_t send_attempts;
};
/* Establish a request handler callback type */
typedef int (*udp_request_handler_cb_t)(struct coap_packet *request,
struct lwm2m_message *msg);
@ -91,7 +61,7 @@ lwm2m_get_engine_obj_field(struct lwm2m_engine_obj *obj, int res_id);
int lwm2m_create_obj_inst(u16_t obj_id, u16_t obj_inst_id,
struct lwm2m_engine_obj_inst **obj_inst);
int lwm2m_delete_obj_inst(u16_t obj_id, u16_t obj_inst_id);
int lwm2m_get_or_create_engine_obj(struct lwm2m_engine_context *context,
int lwm2m_get_or_create_engine_obj(struct lwm2m_message *msg,
struct lwm2m_engine_obj_inst **obj_inst,
u8_t *created);
@ -107,13 +77,12 @@ int lwm2m_send_message(struct lwm2m_message *msg);
u16_t lwm2m_get_rd_data(u8_t *client_data, u16_t size);
int lwm2m_perform_read_op(struct lwm2m_engine_obj *obj,
struct lwm2m_engine_context *context,
u16_t content_format);
struct lwm2m_message *msg, u16_t content_format);
int lwm2m_write_handler(struct lwm2m_engine_obj_inst *obj_inst,
struct lwm2m_engine_res_inst *res,
struct lwm2m_engine_obj_field *obj_field,
struct lwm2m_engine_context *context);
struct lwm2m_message *msg);
void lwm2m_udp_receive(struct lwm2m_ctx *client_ctx, struct net_pkt *pkt,
bool handle_separate_response,

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2017 Linaro Limited
* Copyright (c) 2018 Foundries.io
* Copyright (c) 2018-2019 Foundries.io
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -47,12 +47,14 @@
/* stdint conversions */
#include <zephyr/types.h>
#include <stddef.h>
#include <kernel.h>
#include <net/net_ip.h>
#include <net/coap.h>
#include <net/lwm2m.h>
#include <misc/printk.h>
#include <misc/util.h>
#include <kernel.h>
#include <net/coap.h>
#include <net/lwm2m.h>
/* #####/###/#####/### + NULL */
#define MAX_RESOURCE_LEN 20
@ -126,7 +128,7 @@
#define WRITER_RESOURCE_INSTANCE 2
struct lwm2m_engine_obj;
struct lwm2m_engine_context;
struct lwm2m_message;
/* path representing object instances */
struct lwm2m_obj_path {
@ -283,6 +285,44 @@ struct lwm2m_input_context {
u16_t opaque_len;
};
/* Establish a message timeout callback */
typedef void (*lwm2m_message_timeout_cb_t)(struct lwm2m_message *msg);
/* Internal LwM2M message structure to track in-flight messages. */
struct lwm2m_message {
/** LwM2M context related to this message */
struct lwm2m_ctx *ctx;
/** Incoming / outgoing contexts */
struct lwm2m_input_context in;
struct lwm2m_output_context out;
/** Incoming path */
struct lwm2m_obj_path path;
/** CoAP packet data related to the outgoing message */
struct coap_packet cpkt;
/** Message transmission handling for TYPE_CON */
struct coap_pending *pending;
struct coap_reply *reply;
/** Message configuration */
u8_t *token;
coap_reply_t reply_cb;
lwm2m_message_timeout_cb_t message_timeout_cb;
u16_t mid;
u8_t type;
u8_t code;
u8_t tkl;
/** Incoming message action */
u8_t operation;
/** Counter for message re-send / abort handling */
u8_t send_attempts;
};
/* LWM2M format writer for the various formats supported */
struct lwm2m_writer {
size_t (*put_begin)(struct lwm2m_output_context *out,
@ -347,14 +387,6 @@ struct lwm2m_reader {
u8_t *buf, size_t buflen, bool *last_block);
};
/* LWM2M engine context */
struct lwm2m_engine_context {
struct lwm2m_input_context *in;
struct lwm2m_output_context *out;
struct lwm2m_obj_path *path;
u8_t operation;
};
/* output user_data management functions */
static inline void engine_set_out_user_data(struct lwm2m_output_context *out,

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2017 Linaro Limited
* Copyright (c) 2018 Foundries.io
* Copyright (c) 2018-2019 Foundries.io
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -522,19 +522,18 @@ const struct lwm2m_writer json_writer = {
.put_bool = put_bool,
};
int do_read_op_json(struct lwm2m_engine_obj *obj,
struct lwm2m_engine_context *context,
int do_read_op_json(struct lwm2m_engine_obj *obj, struct lwm2m_message *msg,
int content_format)
{
struct json_out_formatter_data fd;
int ret;
(void)memset(&fd, 0, sizeof(fd));
engine_set_out_user_data(context->out, &fd);
engine_set_out_user_data(&msg->out, &fd);
/* save the level for output processing */
fd.path_level = context->path->level;
ret = lwm2m_perform_read_op(obj, context, content_format);
engine_clear_out_user_data(context->out);
fd.path_level = msg->path.level;
ret = lwm2m_perform_read_op(obj, msg, content_format);
engine_clear_out_user_data(&msg->out);
return ret;
}
@ -582,11 +581,8 @@ static int parse_path(const u8_t *buf, u16_t buflen,
return ret;
}
int do_write_op_json(struct lwm2m_engine_obj *obj,
struct lwm2m_engine_context *context)
int do_write_op_json(struct lwm2m_engine_obj *obj, struct lwm2m_message *msg)
{
struct lwm2m_input_context *in = context->in;
struct lwm2m_obj_path *path = context->path;
struct lwm2m_engine_obj_field *obj_field;
struct lwm2m_engine_obj_inst *obj_inst = NULL;
struct lwm2m_engine_res_inst *res = NULL;
@ -596,16 +592,17 @@ int do_write_op_json(struct lwm2m_engine_obj *obj,
int i, r;
u8_t mode = MODE_NONE;
olv = path->level;
olv = msg->path.level;
while (json_next_token(in, &json)) {
while (json_next_token(&msg->in, &json)) {
i = 0;
created = 0U;
if (json.name[0] == 'n') {
path->level = parse_path(json.value, json.value_len,
path);
msg->path.level = parse_path(json.value,
json.value_len,
&msg->path);
if (i > 0) {
r = lwm2m_get_or_create_engine_obj(context,
r = lwm2m_get_or_create_engine_obj(msg,
&obj_inst,
&created);
if (r < 0) {
@ -616,7 +613,7 @@ int do_write_op_json(struct lwm2m_engine_obj *obj,
} else {
/* HACK: assume value node: can it be anything else? */
mode |= MODE_VALUE;
/* FIXME swap in->cpkt.pkt->frag w/ value buffer */
/* FIXME swap msg->in.cpkt.pkt->frag w/ value buffer */
}
if (mode == MODE_READY) {
@ -625,7 +622,7 @@ int do_write_op_json(struct lwm2m_engine_obj *obj,
}
obj_field = lwm2m_get_engine_obj_field(obj,
path->res_id);
msg->path.res_id);
/*
* if obj_field is not found,
* treat as an optional resource
@ -635,7 +632,7 @@ int do_write_op_json(struct lwm2m_engine_obj *obj,
* TODO: support BOOTSTRAP WRITE where optional
* resources are ignored
*/
if (context->operation != LWM2M_OP_CREATE) {
if (msg->operation != LWM2M_OP_CREATE) {
return -ENOENT;
}
@ -653,7 +650,7 @@ int do_write_op_json(struct lwm2m_engine_obj *obj,
for (i = 0; i < obj_inst->resource_count; i++) {
if (obj_inst->resources[i].res_id ==
path->res_id) {
msg->path.res_id) {
res = &obj_inst->resources[i];
break;
}
@ -663,12 +660,12 @@ int do_write_op_json(struct lwm2m_engine_obj *obj,
return -ENOENT;
}
lwm2m_write_handler(obj_inst, res, obj_field, context);
lwm2m_write_handler(obj_inst, res, obj_field, msg);
skip_optional:
mode = MODE_NONE;
/* FIXME: swap back original in->cpkt.pkt->frag */
path->level = olv;
/* FIXME: swap back original msg->in.cpkt.pkt->frag */
msg->path.level = olv;
}
}

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2017 Linaro Limited
* Copyright (c) 2018 Foundries.io
* Copyright (c) 2018-2019 Foundries.io
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -47,10 +47,8 @@
extern const struct lwm2m_writer json_writer;
int do_read_op_json(struct lwm2m_engine_obj *obj,
struct lwm2m_engine_context *context,
int do_read_op_json(struct lwm2m_engine_obj *obj, struct lwm2m_message *msg,
int content_format);
int do_write_op_json(struct lwm2m_engine_obj *obj,
struct lwm2m_engine_context *context);
int do_write_op_json(struct lwm2m_engine_obj *obj, struct lwm2m_message *msg);
#endif /* LWM2M_RW_JSON_H_ */

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2017 Linaro Limited
* Copyright (c) 2018 Foundries.io
* Copyright (c) 2018-2019 Foundries.io
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -812,36 +812,34 @@ const struct lwm2m_reader oma_tlv_reader = {
.get_opaque = get_opaque,
};
int do_read_op_tlv(struct lwm2m_engine_obj *obj,
struct lwm2m_engine_context *context,
int do_read_op_tlv(struct lwm2m_engine_obj *obj, struct lwm2m_message *msg,
int content_format)
{
struct tlv_out_formatter_data fd;
int ret;
(void)memset(&fd, 0, sizeof(fd));
engine_set_out_user_data(context->out, &fd);
ret = lwm2m_perform_read_op(obj, context, content_format);
engine_clear_out_user_data(context->out);
engine_set_out_user_data(&msg->out, &fd);
ret = lwm2m_perform_read_op(obj, msg, content_format);
engine_clear_out_user_data(&msg->out);
return ret;
}
static int do_write_op_tlv_dummy_read(struct lwm2m_engine_context *context)
static int do_write_op_tlv_dummy_read(struct lwm2m_message *msg)
{
struct lwm2m_input_context *in = context->in;
struct oma_tlv tlv;
u8_t read_char;
oma_tlv_get(&tlv, in, false);
while (in->frag && tlv.length--) {
in->frag = net_frag_read_u8(in->frag, in->offset, &in->offset,
&read_char);
oma_tlv_get(&tlv, &msg->in, false);
while (msg->in.frag && tlv.length--) {
msg->in.frag = net_frag_read_u8(msg->in.frag, msg->in.offset,
&msg->in.offset, &read_char);
}
return 0;
}
static int do_write_op_tlv_item(struct lwm2m_engine_context *context)
static int do_write_op_tlv_item(struct lwm2m_message *msg)
{
struct lwm2m_engine_obj_inst *obj_inst = NULL;
struct lwm2m_engine_res_inst *res = NULL;
@ -849,13 +847,13 @@ static int do_write_op_tlv_item(struct lwm2m_engine_context *context)
u8_t created = 0U;
int ret, i;
ret = lwm2m_get_or_create_engine_obj(context, &obj_inst, &created);
ret = lwm2m_get_or_create_engine_obj(msg, &obj_inst, &created);
if (ret < 0) {
goto error;
}
obj_field = lwm2m_get_engine_obj_field(obj_inst->obj,
context->path->res_id);
msg->path.res_id);
if (!obj_field) {
ret = -ENOENT;
goto error;
@ -872,7 +870,7 @@ static int do_write_op_tlv_item(struct lwm2m_engine_context *context)
}
for (i = 0; i < obj_inst->resource_count; i++) {
if (obj_inst->resources[i].res_id == context->path->res_id) {
if (obj_inst->resources[i].res_id == msg->path.res_id) {
res = &obj_inst->resources[i];
break;
}
@ -880,7 +878,7 @@ static int do_write_op_tlv_item(struct lwm2m_engine_context *context)
if (!res) {
/* if OPTIONAL and OP_CREATE use ENOTSUP */
if (context->operation == LWM2M_OP_CREATE &&
if (msg->operation == LWM2M_OP_CREATE &&
LWM2M_HAS_PERM(obj_field, BIT(LWM2M_FLAG_OPTIONAL))) {
ret = -ENOTSUP;
goto error;
@ -890,25 +888,22 @@ static int do_write_op_tlv_item(struct lwm2m_engine_context *context)
goto error;
}
ret = lwm2m_write_handler(obj_inst, res, obj_field, context);
ret = lwm2m_write_handler(obj_inst, res, obj_field, msg);
if (ret == -EACCES || ret == -ENOENT) {
/* if read-only or non-existent data buffer move on */
do_write_op_tlv_dummy_read(context);
do_write_op_tlv_dummy_read(msg);
ret = 0;
}
return ret;
error:
do_write_op_tlv_dummy_read(context);
do_write_op_tlv_dummy_read(msg);
return ret;
}
int do_write_op_tlv(struct lwm2m_engine_obj *obj,
struct lwm2m_engine_context *context)
int do_write_op_tlv(struct lwm2m_engine_obj *obj, struct lwm2m_message *msg)
{
struct lwm2m_input_context *in = context->in;
struct lwm2m_obj_path *path = context->path;
struct lwm2m_engine_obj_inst *obj_inst = NULL;
size_t len;
struct oma_tlv tlv;
@ -919,7 +914,7 @@ int do_write_op_tlv(struct lwm2m_engine_obj *obj,
* This initial read of TLV data won't advance frag/offset.
* We need tlv.type to determine how to proceed.
*/
len = oma_tlv_get(&tlv, in, true);
len = oma_tlv_get(&tlv, &msg->in, true);
if (len == 0) {
break;
}
@ -929,31 +924,32 @@ int do_write_op_tlv(struct lwm2m_engine_obj *obj,
int len2;
int pos = 0;
oma_tlv_get(&tlv, in, false);
path->obj_inst_id = tlv.id;
oma_tlv_get(&tlv, &msg->in, false);
msg->path.obj_inst_id = tlv.id;
if (tlv.length == 0) {
/* Create only - no data */
ret = lwm2m_create_obj_inst(path->obj_id,
path->obj_inst_id,
&obj_inst);
ret = lwm2m_create_obj_inst(
msg->path.obj_id,
msg->path.obj_inst_id,
&obj_inst);
if (ret < 0) {
return ret;
}
}
while (pos < tlv.length &&
(len2 = oma_tlv_get(&tlv2, in, true))) {
(len2 = oma_tlv_get(&tlv2, &msg->in, true))) {
if (tlv2.type == OMA_TLV_TYPE_RESOURCE) {
path->res_id = tlv2.id;
path->level = 3;
ret = do_write_op_tlv_item(context);
msg->path.res_id = tlv2.id;
msg->path.level = 3;
ret = do_write_op_tlv_item(msg);
/*
* ignore errors for CREATE op
* TODO: support BOOTSTRAP WRITE where
* optional resources are ignored
*/
if (ret < 0 &&
(context->operation !=
(msg->operation !=
LWM2M_OP_CREATE ||
ret != -ENOTSUP)) {
return ret;
@ -963,15 +959,15 @@ int do_write_op_tlv(struct lwm2m_engine_obj *obj,
pos += len2;
}
} else if (tlv.type == OMA_TLV_TYPE_RESOURCE) {
path->res_id = tlv.id;
path->level = 3;
ret = do_write_op_tlv_item(context);
msg->path.res_id = tlv.id;
msg->path.level = 3;
ret = do_write_op_tlv_item(msg);
/*
* ignore errors for CREATE op
* TODO: support BOOTSTRAP WRITE where optional
* resources are ignored
*/
if (ret < 0 && (context->operation != LWM2M_OP_CREATE ||
if (ret < 0 && (msg->operation != LWM2M_OP_CREATE ||
ret != -ENOTSUP)) {
return ret;
}

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2017 Linaro Limited
* Copyright (c) 2018 Foundries.io
* Copyright (c) 2018-2019 Foundries.io
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -49,10 +49,8 @@
extern const struct lwm2m_writer oma_tlv_writer;
extern const struct lwm2m_reader oma_tlv_reader;
int do_read_op_tlv(struct lwm2m_engine_obj *obj,
struct lwm2m_engine_context *context,
int do_read_op_tlv(struct lwm2m_engine_obj *obj, struct lwm2m_message *msg,
int content_format);
int do_write_op_tlv(struct lwm2m_engine_obj *obj,
struct lwm2m_engine_context *context);
int do_write_op_tlv(struct lwm2m_engine_obj *obj, struct lwm2m_message *msg);
#endif /* LWM2M_RW_OMA_TLV_H_ */

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2017 Linaro Limited
* Copyright (c) 2018 Foundries.io
* Copyright (c) 2018-2019 Foundries.io
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -334,33 +334,31 @@ const struct lwm2m_reader plain_text_reader = {
};
int do_read_op_plain_text(struct lwm2m_engine_obj *obj,
struct lwm2m_engine_context *context,
int content_format)
struct lwm2m_message *msg, int content_format)
{
/* Plain text can only return single resource */
if (context->path->level != 3) {
if (msg->path.level != 3) {
return -EPERM; /* NOT_ALLOWED */
}
return lwm2m_perform_read_op(obj, context, content_format);
return lwm2m_perform_read_op(obj, msg, content_format);
}
int do_write_op_plain_text(struct lwm2m_engine_obj *obj,
struct lwm2m_engine_context *context)
struct lwm2m_message *msg)
{
struct lwm2m_obj_path *path = context->path;
struct lwm2m_engine_obj_inst *obj_inst = NULL;
struct lwm2m_engine_obj_field *obj_field;
struct lwm2m_engine_res_inst *res = NULL;
int ret, i;
u8_t created = 0U;
ret = lwm2m_get_or_create_engine_obj(context, &obj_inst, &created);
ret = lwm2m_get_or_create_engine_obj(msg, &obj_inst, &created);
if (ret < 0) {
return ret;
}
obj_field = lwm2m_get_engine_obj_field(obj, path->res_id);
obj_field = lwm2m_get_engine_obj_field(obj, msg->path.res_id);
if (!obj_field) {
return -ENOENT;
}
@ -374,7 +372,7 @@ int do_write_op_plain_text(struct lwm2m_engine_obj *obj,
}
for (i = 0; i < obj_inst->resource_count; i++) {
if (obj_inst->resources[i].res_id == path->res_id) {
if (obj_inst->resources[i].res_id == msg->path.res_id) {
res = &obj_inst->resources[i];
break;
}
@ -384,6 +382,6 @@ int do_write_op_plain_text(struct lwm2m_engine_obj *obj,
return -ENOENT;
}
context->path->level = 3U;
return lwm2m_write_handler(obj_inst, res, obj_field, context);
msg->path.level = 3;
return lwm2m_write_handler(obj_inst, res, obj_field, msg);
}

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2017 Linaro Limited
* Copyright (c) 2018 Foundries.io
* Copyright (c) 2018-2019 Foundries.io
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -53,9 +53,8 @@ size_t plain_text_put_format(struct lwm2m_output_context *out,
const char *format, ...);
int do_read_op_plain_text(struct lwm2m_engine_obj *obj,
struct lwm2m_engine_context *context,
int content_format);
struct lwm2m_message *msg, int content_format);
int do_write_op_plain_text(struct lwm2m_engine_obj *obj,
struct lwm2m_engine_context *context);
struct lwm2m_message *msg);
#endif /* LWM2M_RW_PLAIN_TEXT_H_ */