net: lwm2m: Separate opaque content format into its own

Opaque content format is not part of clear-text, so it
should be separated into its own file.

Signed-off-by: Seppo Takalo <seppo.takalo@nordicsemi.no>
This commit is contained in:
Seppo Takalo 2023-08-08 13:31:40 +03:00 committed by Carles Cufí
commit f227b56792
6 changed files with 196 additions and 75 deletions

View file

@ -14,6 +14,7 @@ zephyr_library_sources(
lwm2m_obj_device.c
lwm2m_rw_link_format.c
lwm2m_rw_plain_text.c
lwm2m_rw_opaque.c
lwm2m_util.c
lwm2m_rd_client.c
)

View file

@ -47,6 +47,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME);
#include "lwm2m_rw_link_format.h"
#include "lwm2m_rw_oma_tlv.h"
#include "lwm2m_rw_plain_text.h"
#include "lwm2m_rw_opaque.h"
#include "lwm2m_util.h"
#include "lwm2m_rd_client.h"
#if defined(CONFIG_LWM2M_RW_SENML_JSON_SUPPORT)
@ -807,6 +808,10 @@ static int select_writer(struct lwm2m_output_context *out, uint16_t accept)
out->writer = &link_format_writer;
break;
case LWM2M_FORMAT_APP_OCTET_STREAM:
out->writer = &opaque_writer;
break;
case LWM2M_FORMAT_PLAIN_TEXT:
case LWM2M_FORMAT_OMA_PLAIN_TEXT:
out->writer = &plain_text_writer;
@ -857,6 +862,9 @@ static int select_reader(struct lwm2m_input_context *in, uint16_t format)
switch (format) {
case LWM2M_FORMAT_APP_OCTET_STREAM:
in->reader = &opaque_reader;
break;
case LWM2M_FORMAT_PLAIN_TEXT:
case LWM2M_FORMAT_OMA_PLAIN_TEXT:
in->reader = &plain_text_reader;
@ -1537,6 +1545,8 @@ static int do_read_op(struct lwm2m_message *msg, uint16_t content_format)
switch (content_format) {
case LWM2M_FORMAT_APP_OCTET_STREAM:
return do_read_op_opaque(msg, content_format);
case LWM2M_FORMAT_PLAIN_TEXT:
case LWM2M_FORMAT_OMA_PLAIN_TEXT:
return do_read_op_plain_text(msg, content_format);
@ -1919,6 +1929,8 @@ static int do_write_op(struct lwm2m_message *msg, uint16_t format)
switch (format) {
case LWM2M_FORMAT_APP_OCTET_STREAM:
return do_write_op_opaque(msg);
case LWM2M_FORMAT_PLAIN_TEXT:
case LWM2M_FORMAT_OMA_PLAIN_TEXT:
return do_write_op_plain_text(msg);

View file

@ -0,0 +1,165 @@
/*
* Copyright (c) 2023 Nordic Semiconductor
*
* SPDX-License-Identifier: Apache-2.0
*/
/*
* Copyright (c) 2015, Yanzi Networks AB.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#define LOG_MODULE_NAME net_lwm2m_opaque
#define LOG_LEVEL CONFIG_LWM2M_LOG_LEVEL
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(LOG_MODULE_NAME);
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "lwm2m_object.h"
#include "lwm2m_rw_opaque.h"
#include "lwm2m_engine.h"
#include "lwm2m_util.h"
static int get_opaque(struct lwm2m_input_context *in, uint8_t *value,
size_t buflen, struct lwm2m_opaque_context *opaque,
bool *last_block)
{
uint16_t in_len;
if (opaque->remaining == 0) {
coap_packet_get_payload(in->in_cpkt, &in_len);
if (in_len == 0) {
return -ENODATA;
}
if (in->block_ctx != NULL) {
uint32_t block_num =
in->block_ctx->ctx.current /
coap_block_size_to_bytes(
in->block_ctx->ctx.block_size);
if (block_num == 0) {
opaque->len = in->block_ctx->ctx.total_size;
}
if (opaque->len == 0) {
/* No size1 option provided, use current
* payload size. This will reset on next packet
* received.
*/
opaque->remaining = in_len;
} else {
opaque->remaining = opaque->len;
}
} else {
opaque->len = in_len;
opaque->remaining = in_len;
}
}
return lwm2m_engine_get_opaque_more(in, value, buflen,
opaque, last_block);
}
static int put_opaque(struct lwm2m_output_context *out,
struct lwm2m_obj_path *path, char *buf,
size_t buflen)
{
int ret;
ret = buf_append(CPKT_BUF_WRITE(out->out_cpkt), buf, buflen);
if (ret < 0) {
return ret;
}
return buflen;
}
const struct lwm2m_writer opaque_writer = {
.put_opaque = put_opaque,
};
const struct lwm2m_reader opaque_reader = {
.get_opaque = get_opaque,
};
int do_read_op_opaque(struct lwm2m_message *msg, int content_format)
{
/* Opaque can only return single resource (instance) */
if (msg->path.level < LWM2M_PATH_LEVEL_RESOURCE) {
return -EPERM;
} else if (msg->path.level > LWM2M_PATH_LEVEL_RESOURCE) {
if (!IS_ENABLED(CONFIG_LWM2M_VERSION_1_1)) {
return -ENOENT;
} else if (msg->path.level > LWM2M_PATH_LEVEL_RESOURCE_INST) {
return -ENOENT;
}
}
return lwm2m_perform_read_op(msg, content_format);
}
int do_write_op_opaque(struct lwm2m_message *msg)
{
struct lwm2m_engine_obj_inst *obj_inst = NULL;
struct lwm2m_engine_obj_field *obj_field;
struct lwm2m_engine_res *res = NULL;
struct lwm2m_engine_res_inst *res_inst = NULL;
int ret;
uint8_t created = 0U;
ret = lwm2m_get_or_create_engine_obj(msg, &obj_inst, &created);
if (ret < 0) {
return ret;
}
ret = lwm2m_engine_validate_write_access(msg, obj_inst, &obj_field);
if (ret < 0) {
return ret;
}
ret = lwm2m_engine_get_create_res_inst(&msg->path, &res, &res_inst);
if (ret < 0) {
return -ENOENT;
}
if (msg->path.level < LWM2M_PATH_LEVEL_RESOURCE) {
msg->path.level = LWM2M_PATH_LEVEL_RESOURCE;
}
return lwm2m_write_handler(obj_inst, res, res_inst, obj_field, msg);
}

View file

@ -0,0 +1,18 @@
/*
* Copyright (c) 2023 Nordic Semiconductor
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef LWM2M_RW_OPAQUE_H_
#define LWM2M_RW_OPAQUE_H_
#include "lwm2m_object.h"
extern const struct lwm2m_writer opaque_writer;
extern const struct lwm2m_reader opaque_reader;
int do_read_op_opaque(struct lwm2m_message *msg, int content_format);
int do_write_op_opaque(struct lwm2m_message *msg);
#endif /* LWM2M_RW_OPAQUE_H_ */

View file

@ -341,49 +341,6 @@ static int get_bool(struct lwm2m_input_context *in, bool *value)
return sizeof(uint8_t);
}
static int get_opaque(struct lwm2m_input_context *in, uint8_t *value,
size_t buflen, struct lwm2m_opaque_context *opaque,
bool *last_block)
{
uint16_t in_len;
if (opaque->remaining == 0) {
coap_packet_get_payload(in->in_cpkt, &in_len);
if (in_len == 0) {
return -ENODATA;
}
if (in->block_ctx != NULL) {
uint32_t block_num =
in->block_ctx->ctx.current /
coap_block_size_to_bytes(
in->block_ctx->ctx.block_size);
if (block_num == 0) {
opaque->len = in->block_ctx->ctx.total_size;
}
if (opaque->len == 0) {
/* No size1 option provided, use current
* payload size. This will reset on next packet
* received.
*/
opaque->remaining = in_len;
} else {
opaque->remaining = opaque->len;
}
} else {
opaque->len = in_len;
opaque->remaining = in_len;
}
}
return lwm2m_engine_get_opaque_more(in, value, buflen,
opaque, last_block);
}
static int get_objlnk(struct lwm2m_input_context *in,
struct lwm2m_objlnk *value)
{
@ -432,7 +389,6 @@ const struct lwm2m_reader plain_text_reader = {
.get_time = get_time,
.get_float = get_float,
.get_bool = get_bool,
.get_opaque = get_opaque,
.get_objlnk = get_objlnk,
};

View file

@ -470,37 +470,6 @@ ZTEST(net_content_plain_text_nodata, test_get_bool_nodata)
zassert_equal(ret, -ENODATA, "Invalid error code returned");
}
ZTEST(net_content_plain_text, test_get_opaque)
{
int ret;
const char *payload = "test_payload";
uint8_t buf[16];
bool last_block;
struct lwm2m_opaque_context ctx = { 0 };
test_payload_set(payload);
ret = plain_text_reader.get_opaque(&test_in, buf, sizeof(buf),
&ctx, &last_block);
zassert_equal(ret, strlen(payload), "Invalid length returned");
zassert_mem_equal(buf, payload, strlen(payload),
"Invalid value parsed");
zassert_equal(test_in.offset, strlen(payload) + 1,
"Invalid packet offset");
}
ZTEST(net_content_plain_text_nodata, test_get_opaque_nodata)
{
int ret;
uint8_t value[4];
bool last_block;
struct lwm2m_opaque_context ctx = { 0 };
ret = plain_text_reader.get_opaque(&test_in, value, sizeof(value),
&ctx, &last_block);
zassert_equal(ret, 0, "Invalid error code returned");
}
ZTEST(net_content_plain_text, test_get_objlnk)
{
int ret;