Merge pull request #1652 from gebart/pr/lwm2m-accept

oma-lwm2m: Use Accept header to determine writer object
This commit is contained in:
Nicolas Tsiftes 2016-05-30 15:33:08 +02:00
commit 2ad6d18c9d

View file

@ -50,6 +50,7 @@
#include "er-coap-constants.h" #include "er-coap-constants.h"
#include "er-coap-engine.h" #include "er-coap-engine.h"
#include "oma-tlv.h" #include "oma-tlv.h"
#include "oma-tlv-reader.h"
#include "oma-tlv-writer.h" #include "oma-tlv-writer.h"
#include "net/ipv6/uip-ds6.h" #include "net/ipv6/uip-ds6.h"
#include <stdio.h> #include <stdio.h>
@ -707,6 +708,59 @@ write_rd_json_data(const lwm2m_context_t *context,
return rdlen; 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 void
lwm2m_engine_handler(const lwm2m_object_t *object, lwm2m_engine_handler(const lwm2m_object_t *object,
void *request, void *response, void *request, void *response,
@ -716,6 +770,8 @@ lwm2m_engine_handler(const lwm2m_object_t *object,
int len; int len;
const char *url; const char *url;
unsigned int format; unsigned int format;
unsigned int accept;
unsigned int content_type;
int depth; int depth;
lwm2m_context_t context; lwm2m_context_t context;
rest_resource_flags_t method; 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 */ /* CoAP content format text plain - assume LWM2M text plain */
format = 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); depth = lwm2m_engine_parse_context(object, url, len, &context);
PRINTF("Context: %u/%u/%u found: %d\n", context.object_id, PRINTF("Context: %u/%u/%u found: %d\n", context.object_id,
context.object_instance_id, context.resource_id, depth); 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 #if (DEBUG) & DEBUG_PRINT
/* for debugging */ /* for debugging */
if(method == METHOD_GET) { if(method == METHOD_GET) {
@ -861,7 +925,7 @@ lwm2m_engine_handler(const lwm2m_object_t *object,
if(depth == 3) { if(depth == 3) {
const lwm2m_resource_t *resource = get_resource(instance, &context); const lwm2m_resource_t *resource = get_resource(instance, &context);
size_t tlvlen = 0; size_t content_len = 0;
if(resource == NULL) { if(resource == NULL) {
PRINTF("Error - do not have resource %d\n", context.resource_id); PRINTF("Error - do not have resource %d\n", context.resource_id);
REST.set_response_status(response, NOT_FOUND_4_04); 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; context.reader = &lwm2m_plain_text_reader;
PRINTF("PUT Callback with data: '%.*s'\n", plen, data); PRINTF("PUT Callback with data: '%.*s'\n", plen, data);
/* no specific reader for plain text */ /* 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); 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); REST.set_response_status(response, CHANGED_2_04);
} else { } else {
PRINTF("PUT callback with format %d\n", format); 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) { } else if(method == METHOD_GET) {
if(lwm2m_object_is_resource_string(resource)) { if(lwm2m_object_is_resource_string(resource)) {
const uint8_t *value; const uint8_t *value;
uint16_t len;
value = lwm2m_object_get_resource_string(resource, &context); value = lwm2m_object_get_resource_string(resource, &context);
len = lwm2m_object_get_resource_strlen(resource, &context);
if(value != NULL) { if(value != NULL) {
uint16_t len = lwm2m_object_get_resource_strlen(resource, &context);
PRINTF("Get string value: %.*s\n", (int)len, (char *)value); PRINTF("Get string value: %.*s\n", (int)len, (char *)value);
/* TODO check format */ content_len = context.writer->write_string(&context, buffer,
REST.set_response_payload(response, value, len); preferred_size, (const char *)value, len);
REST.set_header_content_type(response, LWM2M_TEXT_PLAIN);
/* Done */
return;
} }
} else if(lwm2m_object_is_resource_int(resource)) { } else if(lwm2m_object_is_resource_int(resource)) {
int32_t value; int32_t value;
if(lwm2m_object_get_resource_int(resource, &context, &value)) { if(lwm2m_object_get_resource_int(resource, &context, &value)) {
/* export INT as TLV */ content_len = context.writer->write_int(&context, buffer, preferred_size, value);
tlvlen = oma_tlv_write_int32(resource->id, value, buffer, preferred_size);
PRINTF("Exporting int as TLV: %" PRId32 ", len: %u\n",
value, (unsigned int)tlvlen);
} }
} else if(lwm2m_object_is_resource_floatfix(resource)) { } else if(lwm2m_object_is_resource_floatfix(resource)) {
int32_t value; int32_t value;
if(lwm2m_object_get_resource_floatfix(resource, &context, &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", PRINTF("Exporting %d-bit fix as float: %" PRId32 "\n",
LWM2M_FLOAT32_BITS, value); LWM2M_FLOAT32_BITS, value);
tlvlen = oma_tlv_write_float32(resource->id, content_len = context.writer->write_float32fix(&context, buffer,
value, LWM2M_FLOAT32_BITS, preferred_size, value, LWM2M_FLOAT32_BITS);
buffer, preferred_size);
PRINTF("Exporting as TLV: len:%u\n", (unsigned int)tlvlen);
} }
} else if(lwm2m_object_is_resource_callback(resource)) { } else if(lwm2m_object_is_resource_callback(resource)) {
if(resource->value.callback.read != NULL) { if(resource->value.callback.read != NULL) {
tlvlen = resource->value.callback.read(&context, content_len = resource->value.callback.read(&context,
buffer, preferred_size); buffer, preferred_size);
} else { } else {
REST.set_response_status(response, METHOD_NOT_ALLOWED_4_05); REST.set_response_status(response, METHOD_NOT_ALLOWED_4_05);
return; return;
} }
} }
if(tlvlen > 0) { if(content_len > 0) {
REST.set_response_payload(response, buffer, tlvlen); REST.set_response_payload(response, buffer, content_len);
REST.set_header_content_type(response, LWM2M_TLV); REST.set_header_content_type(response, content_type);
} else { } else {
/* failed to produce output - it is an internal error */ /* failed to produce output - it is an internal error */
REST.set_response_status(response, INTERNAL_SERVER_ERROR_5_00); 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; const uint8_t *data;
int plen = REST.get_request_payload(request, &data); int plen = REST.get_request_payload(request, &data);
PRINTF("Execute Callback with data: '%.*s'\n", plen, 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, data, plen,
buffer, preferred_size); buffer, preferred_size);
REST.set_response_status(response, CHANGED_2_04); 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); REST.set_response_status(response, NOT_FOUND_4_04);
} else { } else {
int rdlen; int rdlen;
if(format == APPLICATION_LINK_FORMAT) { if(accept == APPLICATION_LINK_FORMAT) {
rdlen = write_rd_link_data(object, instance, rdlen = write_rd_link_data(object, instance,
(char *)buffer, preferred_size); (char *)buffer, preferred_size);
} else { } else {
@ -986,10 +1041,10 @@ lwm2m_engine_handler(const lwm2m_object_t *object,
return; return;
} }
REST.set_response_payload(response, buffer, rdlen); 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); REST.set_header_content_type(response, REST.type.APPLICATION_LINK_FORMAT);
} else { } else {
REST.set_header_content_type(response, REST.type.APPLICATION_JSON); REST.set_header_content_type(response, LWM2M_JSON);
} }
} }
} }