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
|
# Erbium will implement the REST Engine
|
||||||
CFLAGS += -DREST=coap_rest_implementation
|
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_
|
#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 */
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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. */
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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. */
|
||||||
/*
|
/*
|
||||||
|
|
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))) {
|
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(
|
||||||
|
|
Loading…
Reference in a new issue