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:
parent
bb737f85ae
commit
386d708b56
@ -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
|
||||
CFLAGS += -DREST=coap_rest_implementation
|
||||
|
119
apps/er-coap/er-coap-block1.c
Normal file
119
apps/er-coap/er-coap-block1.c
Normal 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;
|
||||
}
|
47
apps/er-coap/er-coap-block1.h
Normal file
47
apps/er-coap/er-coap-block1.h
Normal 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_ */
|
@ -39,7 +39,11 @@
|
||||
#ifndef ER_COAP_CONSTANTS_H_
|
||||
#define ER_COAP_CONSTANTS_H_
|
||||
|
||||
#ifdef WITH_DTLS
|
||||
#define COAP_DEFAULT_PORT 5684
|
||||
#else
|
||||
#define COAP_DEFAULT_PORT 5683
|
||||
#endif
|
||||
|
||||
#define COAP_DEFAULT_MAX_AGE 60
|
||||
#define COAP_RESPONSE_TIMEOUT 3
|
||||
@ -85,6 +89,7 @@ typedef enum {
|
||||
VALID_2_03 = 67, /* NOT_MODIFIED */
|
||||
CHANGED_2_04 = 68, /* CHANGED */
|
||||
CONTENT_2_05 = 69, /* OK */
|
||||
CONTINUE_2_31 = 95, /* CONTINUE */
|
||||
|
||||
BAD_REQUEST_4_00 = 128, /* BAD_REQUEST */
|
||||
UNAUTHORIZED_4_01 = 129, /* UNAUTHORIZED */
|
||||
|
@ -40,6 +40,9 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "er-coap-engine.h"
|
||||
#ifdef WITH_DTLS
|
||||
#include "er-dtls.h"
|
||||
#endif
|
||||
|
||||
#define DEBUG 0
|
||||
#if DEBUG
|
||||
@ -83,8 +86,18 @@ coap_receive(void)
|
||||
PRINTF(":%u\n Length: %u\n", uip_ntohs(UIP_UDP_BUF->srcport),
|
||||
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 =
|
||||
coap_parse_message(message, uip_appdata, uip_datalen());
|
||||
#endif
|
||||
|
||||
if(erbium_status_code == NO_ERROR) {
|
||||
|
||||
@ -117,8 +130,7 @@ coap_receive(void)
|
||||
coap_init_message(response, COAP_TYPE_NON, CONTENT_2_05,
|
||||
coap_get_mid());
|
||||
/* mirror token */
|
||||
}
|
||||
if(message->token_len) {
|
||||
} if(message->token_len) {
|
||||
coap_set_token(response, message->token, message->token_len);
|
||||
/* get offset for blockwise transfers */
|
||||
}
|
||||
@ -195,17 +207,17 @@ coap_receive(void)
|
||||
} else if(new_offset != 0) {
|
||||
PRINTF
|
||||
("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,
|
||||
REST_MAX_CHUNK_SIZE);
|
||||
COAP_MAX_BLOCK_SIZE);
|
||||
coap_set_payload(response, response->payload,
|
||||
MIN(response->payload_len,
|
||||
REST_MAX_CHUNK_SIZE));
|
||||
COAP_MAX_BLOCK_SIZE));
|
||||
} /* blockwise transfer handling */
|
||||
} /* no errors/hooks */
|
||||
/* successful service callback */
|
||||
/* serialize response */
|
||||
/* serialize response */
|
||||
}
|
||||
if(erbium_status_code == NO_ERROR) {
|
||||
if((transaction->packet_len = coap_serialize_message(response,
|
||||
@ -317,14 +329,23 @@ coap_get_rest_method(void *packet)
|
||||
|
||||
/* the discover resource is automatically included for CoAP */
|
||||
extern resource_t res_well_known_core;
|
||||
#ifdef WITH_DTLS
|
||||
extern resource_t res_dtls;
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
PROCESS_THREAD(coap_engine, ev, data)
|
||||
{
|
||||
PROCESS_BEGIN();
|
||||
#ifdef WITH_DTLS
|
||||
aes_init();
|
||||
#endif
|
||||
PRINTF("Starting %s receiver...\n", coap_rest_implementation.name);
|
||||
|
||||
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_init_connection(SERVER_LISTEN_PORT);
|
||||
|
@ -51,6 +51,28 @@
|
||||
#define PRINTLLADDR(addr)
|
||||
#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 -------------------------------------------------------*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
@ -141,62 +163,16 @@ well_known_core_get_handler(void *request, void *response, uint8_t *buffer,
|
||||
strpos, *offset, bufpos);
|
||||
|
||||
if(strpos > 0) {
|
||||
if(strpos >= *offset && bufpos < preferred_size) {
|
||||
buffer[bufpos++] = ',';
|
||||
}
|
||||
++strpos;
|
||||
ADD_CHAR_IF_POSSIBLE(',');
|
||||
}
|
||||
|
||||
if(strpos >= *offset && bufpos < preferred_size) {
|
||||
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;
|
||||
ADD_CHAR_IF_POSSIBLE('<');
|
||||
ADD_CHAR_IF_POSSIBLE('/');
|
||||
ADD_STRING_IF_POSSIBLE(resource->url, >=);
|
||||
ADD_CHAR_IF_POSSIBLE('>');
|
||||
|
||||
if(resource->attributes[0]) {
|
||||
if(strpos >= *offset && bufpos < preferred_size) {
|
||||
buffer[bufpos++] = ';';
|
||||
}
|
||||
++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;
|
||||
ADD_CHAR_IF_POSSIBLE(';');
|
||||
ADD_STRING_IF_POSSIBLE(resource->attributes, >);
|
||||
}
|
||||
|
||||
/* buffer full, but resource not completed yet; or: do not break if resource exactly fills buffer. */
|
||||
|
@ -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);
|
||||
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_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 */
|
||||
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,
|
||||
separate_store->token_len);
|
||||
}
|
||||
if(separate_store->block1_size) {
|
||||
coap_set_header_block1(response, separate_store->block1_num,
|
||||
0, separate_store->block1_size);
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
@ -52,7 +52,9 @@ typedef struct coap_separate {
|
||||
uint8_t token_len;
|
||||
uint8_t token[COAP_TOKEN_LEN];
|
||||
|
||||
/* separate + blockwise is untested! */
|
||||
uint32_t block1_num;
|
||||
uint16_t block1_size;
|
||||
|
||||
uint32_t block2_num;
|
||||
uint16_t block2_size;
|
||||
} coap_separate_t;
|
||||
|
@ -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[3] = (uint8_t)(coap_pkt->mid);
|
||||
|
||||
/* empty packet, dont need to do more stuff */
|
||||
if(!coap_pkt->code) {
|
||||
return 4;
|
||||
}
|
||||
/* set Token */
|
||||
PRINTF("Token (len %u)", coap_pkt->token_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);
|
||||
udp_conn->rport = port;
|
||||
|
||||
#ifdef WITH_DTLS
|
||||
dtls_send_message(udp_conn, data, length);
|
||||
#else
|
||||
uip_udp_packet_send(udp_conn, data, length);
|
||||
#endif
|
||||
PRINTF("-sent UDP datagram (%u)-\n", length);
|
||||
|
||||
/* 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)) {
|
||||
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) {
|
||||
*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)) {
|
||||
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) {
|
||||
*num = coap_pkt->block1_num;
|
||||
}
|
||||
|
@ -54,6 +54,17 @@
|
||||
#define REST coap_rest_implementation
|
||||
#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 */
|
||||
#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
|
||||
#if UIP_CONF_IPV6
|
||||
|
@ -70,7 +70,8 @@ extern resource_t
|
||||
res_separate,
|
||||
res_push,
|
||||
res_event,
|
||||
res_sub;
|
||||
res_sub,
|
||||
res_b1_sep_b2;
|
||||
#if PLATFORM_HAS_LEDS
|
||||
extern resource_t res_leds, res_toggle;
|
||||
#endif
|
||||
@ -116,6 +117,7 @@ PROCESS_THREAD(er_example_server, ev, data)
|
||||
rest_activate_resource(&res_push, "test/push");
|
||||
/* rest_activate_resource(&res_event, "sensors/button"); */
|
||||
/* rest_activate_resource(&res_sub, "test/sub"); */
|
||||
/* rest_activate_resource(&res_b1_sep_b2, "test/b1sepb2"); */
|
||||
#if PLATFORM_HAS_LEDS
|
||||
/* rest_activate_resource(&res_leds, "actuators/leds"); */
|
||||
rest_activate_resource(&res_toggle, "actuators/toggle");
|
||||
|
@ -65,7 +65,7 @@
|
||||
|
||||
/* Increase rpl-border-router IP-buffer when using more than 64. */
|
||||
#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. */
|
||||
/*
|
||||
|
111
examples/er-rest-example/resources/res-b1-sep-b2.c
Normal file
111
examples/er-rest-example/resources/res-b1-sep-b2.c
Normal 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);
|
||||
}
|
||||
}
|
@ -62,7 +62,8 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr
|
||||
|
||||
if((len = REST.get_query(request, &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.type.TEXT_PLAIN);
|
||||
REST.set_response_payload(
|
||||
|
Loading…
Reference in New Issue
Block a user