oma-lwm2m: Use Accept header to determine the writer object for the content

master-31012017
Joakim Nohlgård 2016-05-04 19:13:51 +02:00
parent 8d6a290382
commit 9832b356ba
1 changed files with 82 additions and 27 deletions

View File

@ -50,6 +50,7 @@
#include "er-coap-constants.h"
#include "er-coap-engine.h"
#include "oma-tlv.h"
#include "oma-tlv-reader.h"
#include "oma-tlv-writer.h"
#include "net/ipv6/uip-ds6.h"
#include <stdio.h>
@ -707,6 +708,59 @@ write_rd_json_data(const lwm2m_context_t *context,
return rdlen;
}
/*---------------------------------------------------------------------------*/
/**
* @brief Set the writer pointer to the proper writer based on the Accept: header
*
* @param[in] context LWM2M context to operate on
* @param[in] accept Accept type number from CoAP headers
*
* @return The content type of the response if the selected writer is used
*/
static unsigned int
lwm2m_engine_select_writer(lwm2m_context_t *context, unsigned int accept)
{
switch(accept) {
case LWM2M_TLV:
context->writer = &oma_tlv_writer;
break;
case LWM2M_TEXT_PLAIN:
case TEXT_PLAIN:
context->writer = &lwm2m_plain_text_writer;
break;
default:
PRINTF("Unknown Accept type %u, using LWM2M plain text\n", accept);
context->writer = &lwm2m_plain_text_writer;
/* Set the response type to plain text */
accept = LWM2M_TEXT_PLAIN;
break;
}
return accept;
}
/*---------------------------------------------------------------------------*/
/**
* @brief Set the reader pointer to the proper reader based on the Content-format: header
*
* @param[in] context LWM2M context to operate on
* @param[in] content_format Content-type type number from CoAP headers
*/
static void
lwm2m_engine_select_reader(lwm2m_context_t *context, unsigned int content_format)
{
switch(content_format) {
case LWM2M_TLV:
context->reader = &oma_tlv_reader;
break;
case LWM2M_TEXT_PLAIN:
case TEXT_PLAIN:
context->reader = &lwm2m_plain_text_reader;
break;
default:
PRINTF("Unknown content type %u, using LWM2M plain text\n", accept);
context->reader = &lwm2m_plain_text_reader;
break;
}
}
/*---------------------------------------------------------------------------*/
void
lwm2m_engine_handler(const lwm2m_object_t *object,
void *request, void *response,
@ -716,6 +770,8 @@ lwm2m_engine_handler(const lwm2m_object_t *object,
int len;
const char *url;
unsigned int format;
unsigned int accept;
unsigned int content_type;
int depth;
lwm2m_context_t context;
rest_resource_flags_t method;
@ -734,11 +790,19 @@ lwm2m_engine_handler(const lwm2m_object_t *object,
/* CoAP content format text plain - assume LWM2M text plain */
format = LWM2M_TEXT_PLAIN;
}
if(!REST.get_header_accept(request, &accept)) {
PRINTF("No Accept header, using same as Content-format...\n");
accept = format;
}
depth = lwm2m_engine_parse_context(object, url, len, &context);
PRINTF("Context: %u/%u/%u found: %d\n", context.object_id,
context.object_instance_id, context.resource_id, depth);
/* Select reader and writer based on provided Content type and Accept headers */
lwm2m_engine_select_reader(&context, format);
content_type = lwm2m_engine_select_writer(&context, accept);
#if (DEBUG) & DEBUG_PRINT
/* for debugging */
if(method == METHOD_GET) {
@ -861,7 +925,7 @@ lwm2m_engine_handler(const lwm2m_object_t *object,
if(depth == 3) {
const lwm2m_resource_t *resource = get_resource(instance, &context);
size_t tlvlen = 0;
size_t content_len = 0;
if(resource == NULL) {
PRINTF("Error - do not have resource %d\n", context.resource_id);
REST.set_response_status(response, NOT_FOUND_4_04);
@ -879,9 +943,9 @@ lwm2m_engine_handler(const lwm2m_object_t *object,
context.reader = &lwm2m_plain_text_reader;
PRINTF("PUT Callback with data: '%.*s'\n", plen, data);
/* no specific reader for plain text */
tlvlen = resource->value.callback.write(&context, data, plen,
content_len = resource->value.callback.write(&context, data, plen,
buffer, preferred_size);
PRINTF("tlvlen:%u\n", (unsigned int)tlvlen);
PRINTF("content_len:%u\n", (unsigned int)content_len);
REST.set_response_status(response, CHANGED_2_04);
} else {
PRINTF("PUT callback with format %d\n", format);
@ -899,48 +963,39 @@ lwm2m_engine_handler(const lwm2m_object_t *object,
} else if(method == METHOD_GET) {
if(lwm2m_object_is_resource_string(resource)) {
const uint8_t *value;
uint16_t len;
value = lwm2m_object_get_resource_string(resource, &context);
len = lwm2m_object_get_resource_strlen(resource, &context);
if(value != NULL) {
uint16_t len = lwm2m_object_get_resource_strlen(resource, &context);
PRINTF("Get string value: %.*s\n", (int)len, (char *)value);
/* TODO check format */
REST.set_response_payload(response, value, len);
REST.set_header_content_type(response, LWM2M_TEXT_PLAIN);
/* Done */
return;
content_len = context.writer->write_string(&context, buffer,
preferred_size, (const char *)value, len);
}
} else if(lwm2m_object_is_resource_int(resource)) {
int32_t value;
if(lwm2m_object_get_resource_int(resource, &context, &value)) {
/* export INT as TLV */
tlvlen = oma_tlv_write_int32(resource->id, value, buffer, preferred_size);
PRINTF("Exporting int as TLV: %" PRId32 ", len: %u\n",
value, (unsigned int)tlvlen);
content_len = context.writer->write_int(&context, buffer, preferred_size, value);
}
} else if(lwm2m_object_is_resource_floatfix(resource)) {
int32_t value;
if(lwm2m_object_get_resource_floatfix(resource, &context, &value)) {
/* export FLOATFIX as TLV */
/* export FLOATFIX */
PRINTF("Exporting %d-bit fix as float: %" PRId32 "\n",
LWM2M_FLOAT32_BITS, value);
tlvlen = oma_tlv_write_float32(resource->id,
value, LWM2M_FLOAT32_BITS,
buffer, preferred_size);
PRINTF("Exporting as TLV: len:%u\n", (unsigned int)tlvlen);
content_len = context.writer->write_float32fix(&context, buffer,
preferred_size, value, LWM2M_FLOAT32_BITS);
}
} else if(lwm2m_object_is_resource_callback(resource)) {
if(resource->value.callback.read != NULL) {
tlvlen = resource->value.callback.read(&context,
content_len = resource->value.callback.read(&context,
buffer, preferred_size);
} else {
REST.set_response_status(response, METHOD_NOT_ALLOWED_4_05);
return;
}
}
if(tlvlen > 0) {
REST.set_response_payload(response, buffer, tlvlen);
REST.set_header_content_type(response, LWM2M_TLV);
if(content_len > 0) {
REST.set_response_payload(response, buffer, content_len);
REST.set_header_content_type(response, content_type);
} else {
/* failed to produce output - it is an internal error */
REST.set_response_status(response, INTERNAL_SERVER_ERROR_5_00);
@ -952,7 +1007,7 @@ lwm2m_engine_handler(const lwm2m_object_t *object,
const uint8_t *data;
int plen = REST.get_request_payload(request, &data);
PRINTF("Execute Callback with data: '%.*s'\n", plen, data);
tlvlen = resource->value.callback.exec(&context,
content_len = resource->value.callback.exec(&context,
data, plen,
buffer, preferred_size);
REST.set_response_status(response, CHANGED_2_04);
@ -973,7 +1028,7 @@ lwm2m_engine_handler(const lwm2m_object_t *object,
REST.set_response_status(response, NOT_FOUND_4_04);
} else {
int rdlen;
if(format == APPLICATION_LINK_FORMAT) {
if(accept == APPLICATION_LINK_FORMAT) {
rdlen = write_rd_link_data(object, instance,
(char *)buffer, preferred_size);
} else {
@ -986,10 +1041,10 @@ lwm2m_engine_handler(const lwm2m_object_t *object,
return;
}
REST.set_response_payload(response, buffer, rdlen);
if(format == APPLICATION_LINK_FORMAT) {
if(accept == APPLICATION_LINK_FORMAT) {
REST.set_header_content_type(response, REST.type.APPLICATION_LINK_FORMAT);
} else {
REST.set_header_content_type(response, REST.type.APPLICATION_JSON);
REST.set_header_content_type(response, LWM2M_JSON);
}
}
}