Added function for easy block1 usage.

Fixed blocksize calculation when REST_MAX_CHUNK_SIZE != 2^x.
Added example for block1 + separate + block2.
This commit is contained in:
Lars Schmertmann 2014-04-23 10:13:10 +02:00 committed by Matthias Kovatsch
parent bb737f85ae
commit 386d708b56
14 changed files with 377 additions and 67 deletions

View file

@ -1,4 +1,4 @@
er-coap_src = er-coap.c er-coap-engine.c er-coap-transactions.c er-coap-observe.c er-coap-separate.c er-coap-res-well-known-core.c er-coap_src = er-coap.c er-coap-engine.c er-coap-transactions.c er-coap-observe.c er-coap-separate.c er-coap-res-well-known-core.c er-coap-block1.c
# Erbium will implement the REST Engine # Erbium will implement the REST Engine
CFLAGS += -DREST=coap_rest_implementation CFLAGS += -DREST=coap_rest_implementation

View file

@ -0,0 +1,119 @@
/*
* Copyright (c) 2014, Lars Schmertmann <SmallLars@t-online.de>.
* 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 Institute 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 INSTITUTE 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 INSTITUTE 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.
*
* This file is part of the Contiki operating system.
*/
/**
* \file
* CoAP module for block 1 handling
* \author
* Lars Schmertmann <SmallLars@t-online.de>
*/
#include <stdio.h>
#include <string.h>
#include "er-coap.h"
#include "er-coap-block1.h"
#define DEBUG 0
#if DEBUG
#define PRINTF(...) printf(__VA_ARGS__)
#define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15])
#define PRINTLLADDR(lladdr) PRINTF("[%02x:%02x:%02x:%02x:%02x:%02x]", (lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3], (lladdr)->addr[4], (lladdr)->addr[5])
#else
#define PRINTF(...)
#define PRINT6ADDR(addr)
#define PRINTLLADDR(addr)
#endif
/*----------------------------------------------------------------------------*/
/**
* \brief Block 1 support within a coap-ressource
*
* This function will help you to use block 1. If target is null
* error handling and response configuration is active. On return
* value 0, the last block was recived, while on return value 1
* more blocks will follow. With target, len and maxlen this
* function will assemble the blocks.
*
* You can find an example in:
* examples/er-rest-example/resources/res-b1-sep-b2.c
*
* \param request Request pointer from the handler
* \param response Response pointer from the handler
* \param target Pointer to the buffer where the request payload can be assembled
* \param len Pointer to the variable, where the function stores the actual length
* \param max_len Length of the "target"-Buffer
*
* \return 0 if initialisation was successful
* -1 if initialisation failed
*/
int
coap_block1_handler(void *request, void *response, uint8_t *target, size_t *len, size_t max_len)
{
const uint8_t *payload = 0;
int pay_len = REST.get_request_payload(request, &payload);
if(!pay_len || !payload) {
erbium_status_code = REST.status.BAD_REQUEST;
coap_error_message = "NoPayload";
return -1;
}
coap_packet_t *packet = (coap_packet_t *)request;
if(packet->block1_offset + pay_len > max_len) {
erbium_status_code = REST.status.REQUEST_ENTITY_TOO_LARGE;
coap_error_message = "Message to big";
return -1;
}
if(target && len) {
memcpy(target + packet->block1_offset, payload, pay_len);
*len = packet->block1_offset + pay_len;
}
if(IS_OPTION(packet, COAP_OPTION_BLOCK1)) {
PRINTF("Blockwise: block 1 request: Num: %u, More: %u, Size: %u, Offset: %u\n",
packet->block1_num,
packet->block1_more,
packet->block1_size,
packet->block1_offset);
coap_set_header_block1(response, packet->block1_num, packet->block1_more, packet->block1_size);
if(packet->block1_more) {
coap_set_status_code(response, CONTINUE_2_31);
return 1;
}
}
return 0;
}

View file

@ -0,0 +1,47 @@
/*
* Copyright (c) 2014, Lars Schmertmann <SmallLars@t-online.de>.
* 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 Institute 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 INSTITUTE 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 INSTITUTE 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.
*
* This file is part of the Contiki operating system.
*/
/**
* \file
* CoAP module for block 1 handling
* \author
* Lars Schmertmann <SmallLars@t-online.de>
*/
#ifndef COAP_BLOCK1_H_
#define COAP_BLOCK1_H_
#include <stddef.h>
#include <stdint.h>
int coap_block1_handler(void *request, void *response, uint8_t *target, size_t *len, size_t max_len);
#endif /* COAP_BLOCK1_H_ */

View file

@ -39,7 +39,11 @@
#ifndef ER_COAP_CONSTANTS_H_ #ifndef ER_COAP_CONSTANTS_H_
#define ER_COAP_CONSTANTS_H_ #define ER_COAP_CONSTANTS_H_
#ifdef WITH_DTLS
#define COAP_DEFAULT_PORT 5684
#else
#define COAP_DEFAULT_PORT 5683 #define COAP_DEFAULT_PORT 5683
#endif
#define COAP_DEFAULT_MAX_AGE 60 #define COAP_DEFAULT_MAX_AGE 60
#define COAP_RESPONSE_TIMEOUT 3 #define COAP_RESPONSE_TIMEOUT 3
@ -85,6 +89,7 @@ typedef enum {
VALID_2_03 = 67, /* NOT_MODIFIED */ VALID_2_03 = 67, /* NOT_MODIFIED */
CHANGED_2_04 = 68, /* CHANGED */ CHANGED_2_04 = 68, /* CHANGED */
CONTENT_2_05 = 69, /* OK */ CONTENT_2_05 = 69, /* OK */
CONTINUE_2_31 = 95, /* CONTINUE */
BAD_REQUEST_4_00 = 128, /* BAD_REQUEST */ BAD_REQUEST_4_00 = 128, /* BAD_REQUEST */
UNAUTHORIZED_4_01 = 129, /* UNAUTHORIZED */ UNAUTHORIZED_4_01 = 129, /* UNAUTHORIZED */

View file

@ -40,6 +40,9 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "er-coap-engine.h" #include "er-coap-engine.h"
#ifdef WITH_DTLS
#include "er-dtls.h"
#endif
#define DEBUG 0 #define DEBUG 0
#if DEBUG #if DEBUG
@ -83,8 +86,18 @@ coap_receive(void)
PRINTF(":%u\n Length: %u\n", uip_ntohs(UIP_UDP_BUF->srcport), PRINTF(":%u\n Length: %u\n", uip_ntohs(UIP_UDP_BUF->srcport),
uip_datalen()); uip_datalen());
#ifdef WITH_DTLS
CoapData_t coapdata = { 0, NULL, 0 };
dtls_parse_message(uip_appdata, uip_datalen(), &coapdata);
if(!coapdata.valid) {
return NO_ERROR;
}
erbium_status_code =
coap_parse_message(message, coapdata.data, coapdata.data_len);
#else
erbium_status_code = erbium_status_code =
coap_parse_message(message, uip_appdata, uip_datalen()); coap_parse_message(message, uip_appdata, uip_datalen());
#endif
if(erbium_status_code == NO_ERROR) { if(erbium_status_code == NO_ERROR) {
@ -117,8 +130,7 @@ coap_receive(void)
coap_init_message(response, COAP_TYPE_NON, CONTENT_2_05, coap_init_message(response, COAP_TYPE_NON, CONTENT_2_05,
coap_get_mid()); coap_get_mid());
/* mirror token */ /* mirror token */
} } if(message->token_len) {
if(message->token_len) {
coap_set_token(response, message->token, message->token_len); coap_set_token(response, message->token, message->token_len);
/* get offset for blockwise transfers */ /* get offset for blockwise transfers */
} }
@ -195,13 +207,13 @@ coap_receive(void)
} else if(new_offset != 0) { } else if(new_offset != 0) {
PRINTF PRINTF
("Blockwise: no block option for blockwise resource, using block size %u\n", ("Blockwise: no block option for blockwise resource, using block size %u\n",
REST_MAX_CHUNK_SIZE); COAP_MAX_BLOCK_SIZE);
coap_set_header_block2(response, 0, new_offset != -1, coap_set_header_block2(response, 0, new_offset != -1,
REST_MAX_CHUNK_SIZE); COAP_MAX_BLOCK_SIZE);
coap_set_payload(response, response->payload, coap_set_payload(response, response->payload,
MIN(response->payload_len, MIN(response->payload_len,
REST_MAX_CHUNK_SIZE)); COAP_MAX_BLOCK_SIZE));
} /* blockwise transfer handling */ } /* blockwise transfer handling */
} /* no errors/hooks */ } /* no errors/hooks */
/* successful service callback */ /* successful service callback */
@ -317,14 +329,23 @@ coap_get_rest_method(void *packet)
/* the discover resource is automatically included for CoAP */ /* the discover resource is automatically included for CoAP */
extern resource_t res_well_known_core; extern resource_t res_well_known_core;
#ifdef WITH_DTLS
extern resource_t res_dtls;
#endif
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
PROCESS_THREAD(coap_engine, ev, data) PROCESS_THREAD(coap_engine, ev, data)
{ {
PROCESS_BEGIN(); PROCESS_BEGIN();
#ifdef WITH_DTLS
aes_init();
#endif
PRINTF("Starting %s receiver...\n", coap_rest_implementation.name); PRINTF("Starting %s receiver...\n", coap_rest_implementation.name);
rest_activate_resource(&res_well_known_core, ".well-known/core"); rest_activate_resource(&res_well_known_core, ".well-known/core");
#ifdef WITH_DTLS
rest_activate_resource(&res_dtls, "dtls");
#endif
coap_register_as_transaction_handler(); coap_register_as_transaction_handler();
coap_init_connection(SERVER_LISTEN_PORT); coap_init_connection(SERVER_LISTEN_PORT);

View file

@ -51,6 +51,28 @@
#define PRINTLLADDR(addr) #define PRINTLLADDR(addr)
#endif #endif
#define ADD_CHAR_IF_POSSIBLE(char) \
if(strpos >= *offset && bufpos < preferred_size) { \
buffer[bufpos++] = char; \
} \
++strpos
#define ADD_STRING_IF_POSSIBLE(string, op) \
tmplen = strlen(string); \
if(strpos + tmplen > *offset) { \
bufpos += snprintf((char *)buffer + bufpos, \
preferred_size - bufpos + 1, \
"%s", \
string \
+ (*offset - (int32_t)strpos > 0 ? \
*offset - (int32_t)strpos : 0)); \
if(bufpos op preferred_size) { \
PRINTF("res: BREAK at %s (%p)\n", string, resource); \
break; \
} \
} \
strpos += tmplen
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/*- Resource Handlers -------------------------------------------------------*/ /*- Resource Handlers -------------------------------------------------------*/
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
@ -141,62 +163,16 @@ well_known_core_get_handler(void *request, void *response, uint8_t *buffer,
strpos, *offset, bufpos); strpos, *offset, bufpos);
if(strpos > 0) { if(strpos > 0) {
if(strpos >= *offset && bufpos < preferred_size) { ADD_CHAR_IF_POSSIBLE(',');
buffer[bufpos++] = ',';
} }
++strpos; ADD_CHAR_IF_POSSIBLE('<');
} ADD_CHAR_IF_POSSIBLE('/');
ADD_STRING_IF_POSSIBLE(resource->url, >=);
if(strpos >= *offset && bufpos < preferred_size) { ADD_CHAR_IF_POSSIBLE('>');
buffer[bufpos++] = '<';
}
++strpos;
if(strpos >= *offset && bufpos < preferred_size) {
buffer[bufpos++] = '/';
}
++strpos;
tmplen = strlen(resource->url);
if(strpos + tmplen > *offset) {
bufpos += snprintf((char *)buffer + bufpos,
preferred_size - bufpos + 1,
"%s",
resource->url +
((*offset - (int32_t)strpos >
0) ? (*offset - (int32_t)strpos) : 0));
/* native requires these casts */
if(bufpos >= preferred_size) {
PRINTF("res: BREAK at %s (%p)\n", resource->url, resource);
break;
}
}
strpos += tmplen;
if(strpos >= *offset && bufpos < preferred_size) {
buffer[bufpos++] = '>';
}
++strpos;
if(resource->attributes[0]) { if(resource->attributes[0]) {
if(strpos >= *offset && bufpos < preferred_size) { ADD_CHAR_IF_POSSIBLE(';');
buffer[bufpos++] = ';'; ADD_STRING_IF_POSSIBLE(resource->attributes, >);
}
++strpos;
tmplen = strlen(resource->attributes);
if(strpos + tmplen > *offset) {
bufpos += snprintf((char *)buffer + bufpos,
preferred_size - bufpos + 1,
resource->attributes
+ (*offset - (int32_t)strpos > 0 ?
*offset - (int32_t)strpos : 0));
if(bufpos > preferred_size) {
PRINTF("res: BREAK at %s (%p)\n", resource->url, resource);
break;
}
}
strpos += tmplen;
} }
/* buffer full, but resource not completed yet; or: do not break if resource exactly fills buffer. */ /* buffer full, but resource not completed yet; or: do not break if resource exactly fills buffer. */

View file

@ -116,8 +116,11 @@ coap_separate_accept(void *request, coap_separate_t *separate_store)
memcpy(separate_store->token, coap_req->token, coap_req->token_len); memcpy(separate_store->token, coap_req->token, coap_req->token_len);
separate_store->token_len = coap_req->token_len; separate_store->token_len = coap_req->token_len;
separate_store->block1_num = coap_req->block1_num;
separate_store->block1_size = coap_req->block1_size;
separate_store->block2_num = coap_req->block2_num; separate_store->block2_num = coap_req->block2_num;
separate_store->block2_size = coap_req->block2_size; separate_store->block2_size = coap_req->block2_size > 0 ? MIN(COAP_MAX_BLOCK_SIZE, coap_req->block2_size) : COAP_MAX_BLOCK_SIZE;
/* signal the engine to skip automatic response and clear transaction by engine */ /* signal the engine to skip automatic response and clear transaction by engine */
erbium_status_code = MANUAL_RESPONSE; erbium_status_code = MANUAL_RESPONSE;
@ -137,5 +140,9 @@ coap_separate_resume(void *response, coap_separate_t *separate_store,
coap_set_token(response, separate_store->token, coap_set_token(response, separate_store->token,
separate_store->token_len); separate_store->token_len);
} }
if(separate_store->block1_size) {
coap_set_header_block1(response, separate_store->block1_num,
0, separate_store->block1_size);
}
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/

View file

@ -52,7 +52,9 @@ typedef struct coap_separate {
uint8_t token_len; uint8_t token_len;
uint8_t token[COAP_TOKEN_LEN]; uint8_t token[COAP_TOKEN_LEN];
/* separate + blockwise is untested! */ uint32_t block1_num;
uint16_t block1_size;
uint32_t block2_num; uint32_t block2_num;
uint16_t block2_size; uint16_t block2_size;
} coap_separate_t; } coap_separate_t;

View file

@ -329,6 +329,10 @@ coap_serialize_message(void *packet, uint8_t *buffer)
coap_pkt->buffer[2] = (uint8_t)((coap_pkt->mid) >> 8); coap_pkt->buffer[2] = (uint8_t)((coap_pkt->mid) >> 8);
coap_pkt->buffer[3] = (uint8_t)(coap_pkt->mid); coap_pkt->buffer[3] = (uint8_t)(coap_pkt->mid);
/* empty packet, dont need to do more stuff */
if(!coap_pkt->code) {
return 4;
}
/* set Token */ /* set Token */
PRINTF("Token (len %u)", coap_pkt->token_len); PRINTF("Token (len %u)", coap_pkt->token_len);
option = coap_pkt->buffer + COAP_HEADER_LEN; option = coap_pkt->buffer + COAP_HEADER_LEN;
@ -419,7 +423,11 @@ coap_send_message(uip_ipaddr_t *addr, uint16_t port, uint8_t *data,
uip_ipaddr_copy(&udp_conn->ripaddr, addr); uip_ipaddr_copy(&udp_conn->ripaddr, addr);
udp_conn->rport = port; udp_conn->rport = port;
#ifdef WITH_DTLS
dtls_send_message(udp_conn, data, length);
#else
uip_udp_packet_send(udp_conn, data, length); uip_udp_packet_send(udp_conn, data, length);
#endif
PRINTF("-sent UDP datagram (%u)-\n", length); PRINTF("-sent UDP datagram (%u)-\n", length);
/* restore server socket to allow data from any node */ /* restore server socket to allow data from any node */
@ -1032,8 +1040,8 @@ coap_get_header_block2(void *packet, uint32_t *num, uint8_t *more,
if(!IS_OPTION(coap_pkt, COAP_OPTION_BLOCK2)) { if(!IS_OPTION(coap_pkt, COAP_OPTION_BLOCK2)) {
return 0; return 0;
}
/* pointers may be NULL to get only specific block parameters */ /* pointers may be NULL to get only specific block parameters */
}
if(num != NULL) { if(num != NULL) {
*num = coap_pkt->block2_num; *num = coap_pkt->block2_num;
} }
@ -1079,8 +1087,8 @@ coap_get_header_block1(void *packet, uint32_t *num, uint8_t *more,
if(!IS_OPTION(coap_pkt, COAP_OPTION_BLOCK1)) { if(!IS_OPTION(coap_pkt, COAP_OPTION_BLOCK1)) {
return 0; return 0;
}
/* pointers may be NULL to get only specific block parameters */ /* pointers may be NULL to get only specific block parameters */
}
if(num != NULL) { if(num != NULL) {
*num = coap_pkt->block1_num; *num = coap_pkt->block1_num;
} }

View file

@ -54,6 +54,17 @@
#define REST coap_rest_implementation #define REST coap_rest_implementation
#include "rest-engine.h" #include "rest-engine.h"
/* REST_MAX_CHUNK_SIZE can be different from 2^x so we need to get next lower 2^x for COAP_MAX_BLOCK_SIZE */
#ifndef COAP_MAX_BLOCK_SIZE
#define COAP_MAX_BLOCK_SIZE (REST_MAX_CHUNK_SIZE < 32 ? 16 : \
(REST_MAX_CHUNK_SIZE < 64 ? 32 : \
(REST_MAX_CHUNK_SIZE < 128 ? 64 : \
(REST_MAX_CHUNK_SIZE < 256 ? 128 : \
(REST_MAX_CHUNK_SIZE < 512 ? 256 : \
(REST_MAX_CHUNK_SIZE < 1024 ? 512 : \
(REST_MAX_CHUNK_SIZE < 2048 ? 1024 : 2048)))))))
#endif /* COAP_MAX_BLOCK_SIZE */
/* direct access into the buffer */ /* direct access into the buffer */
#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
#if UIP_CONF_IPV6 #if UIP_CONF_IPV6

View file

@ -70,7 +70,8 @@ extern resource_t
res_separate, res_separate,
res_push, res_push,
res_event, res_event,
res_sub; res_sub,
res_b1_sep_b2;
#if PLATFORM_HAS_LEDS #if PLATFORM_HAS_LEDS
extern resource_t res_leds, res_toggle; extern resource_t res_leds, res_toggle;
#endif #endif
@ -116,6 +117,7 @@ PROCESS_THREAD(er_example_server, ev, data)
rest_activate_resource(&res_push, "test/push"); rest_activate_resource(&res_push, "test/push");
/* rest_activate_resource(&res_event, "sensors/button"); */ /* rest_activate_resource(&res_event, "sensors/button"); */
/* rest_activate_resource(&res_sub, "test/sub"); */ /* rest_activate_resource(&res_sub, "test/sub"); */
/* rest_activate_resource(&res_b1_sep_b2, "test/b1sepb2"); */
#if PLATFORM_HAS_LEDS #if PLATFORM_HAS_LEDS
/* rest_activate_resource(&res_leds, "actuators/leds"); */ /* rest_activate_resource(&res_leds, "actuators/leds"); */
rest_activate_resource(&res_toggle, "actuators/toggle"); rest_activate_resource(&res_toggle, "actuators/toggle");

View file

@ -65,7 +65,7 @@
/* Increase rpl-border-router IP-buffer when using more than 64. */ /* Increase rpl-border-router IP-buffer when using more than 64. */
#undef REST_MAX_CHUNK_SIZE #undef REST_MAX_CHUNK_SIZE
#define REST_MAX_CHUNK_SIZE 64 #define REST_MAX_CHUNK_SIZE 48
/* Estimate your header size, especially when using Proxy-Uri. */ /* Estimate your header size, especially when using Proxy-Uri. */
/* /*

View file

@ -0,0 +1,111 @@
/*
* Copyright (c) 2014, Lars Schmertmann <SmallLars@t-online.de>.
* 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 Institute 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 INSTITUTE 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 INSTITUTE 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.
*
* This file is part of the Contiki operating system.
*/
/**
* \file
* Example resource
* \author
* Lars Schmertmann <SmallLars@t-online.de>
*/
#include <string.h>
#include "rest-engine.h"
#include "er-coap-block1.h"
#include "er-coap-separate.h"
#include "er-coap-transactions.h"
static void res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
SEPARATE_RESOURCE(res_b1_sep_b2, "title=\"Block1 + Separate + Block2 demo\"", NULL, res_post_handler, NULL, NULL, NULL);
#define MAX_DATA_LEN 256
static uint8_t big_msg[MAX_DATA_LEN];
static size_t big_msg_len = 0;
static coap_separate_t request_metadata;
static void
res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
/* Example allows only one request on time. There are no checks for multiply access !!! */
if(*offset == 0) {
/* Incoming Data */
if(coap_block1_handler(request, response, big_msg, &big_msg_len, MAX_DATA_LEN)) {
/* More Blocks will follow. Example waits for
* the last block and stores data into big_msg.
*/
return;
}
/* Last block was received. */
coap_separate_accept(request, &request_metadata);
/* Need Time for calculation now */
uint32_t i;
for(i = 0; i <= 4096; i++) {
printf("\r% 4u\r", i);
}
printf("\n");
/* Send first block */
coap_transaction_t *transaction = NULL;
if((transaction = coap_new_transaction(request_metadata.mid, &request_metadata.addr, request_metadata.port))) {
coap_packet_t resp[1]; /* This way the packet can be treated as pointer as usual. */
/* Restore the request information for the response. */
coap_separate_resume(resp, &request_metadata, CONTENT_2_05);
/* Set payload and block info */
coap_set_payload(resp, big_msg, big_msg_len > request_metadata.block2_size ? request_metadata.block2_size : big_msg_len);
if(big_msg_len > request_metadata.block2_size) {
coap_set_header_block2(resp, 0, 1, request_metadata.block2_size);
}
/* Warning: No check for serialization error. */
transaction->packet_len = coap_serialize_message(resp, transaction->packet);
coap_send_transaction(transaction);
}
} else {
/* request for more blocks */
if(*offset >= big_msg_len) {
coap_set_status_code(response, BAD_OPTION_4_02);
coap_set_payload(response, "BlockOutOfScope", 15);
return;
}
memcpy(buffer, big_msg + *offset, 32);
if(big_msg_len - *offset < preferred_size) {
preferred_size = big_msg_len - *offset;
*offset = -1;
} else {
*offset += preferred_size;
}
coap_set_payload(response, buffer, preferred_size);
}
}

View file

@ -62,7 +62,8 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr
if((len = REST.get_query(request, &query))) { if((len = REST.get_query(request, &query))) {
PRINTF("Query: %.*s\n", len, query); PRINTF("Query: %.*s\n", len, query);
} /* Code 2.05 CONTENT is default. */ /* Code 2.05 CONTENT is default. */
}
REST.set_header_content_type(response, REST.set_header_content_type(response,
REST.type.TEXT_PLAIN); REST.type.TEXT_PLAIN);
REST.set_response_payload( REST.set_response_payload(