From a0ec1a4065ce595fe5301321450a36d5cfc84491 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Wed, 25 Oct 2017 00:52:56 +0200 Subject: [PATCH 01/51] Added tinyDTLS standalone as submodule --- .gitmodules | 3 +++ os/net/security/tinydtls | 1 + 2 files changed, 4 insertions(+) create mode 160000 os/net/security/tinydtls diff --git a/.gitmodules b/.gitmodules index f2cd29451..a20bff843 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,3 +13,6 @@ [submodule "tools/cooja"] path = tools/cooja url = https://github.com/contiki-ng/cooja.git +[submodule "os/net/security/tinydtls"] + path = os/net/security/tinydtls + url = https://github.com/contiki-ng/tinydtls.git diff --git a/os/net/security/tinydtls b/os/net/security/tinydtls new file mode 160000 index 000000000..55fbfa86a --- /dev/null +++ b/os/net/security/tinydtls @@ -0,0 +1 @@ +Subproject commit 55fbfa86a2c6586501e36631c6d7f1cd7a83f0bc From ee8d85bde8897851127027cfe41f3b7b5541c134 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Wed, 25 Oct 2017 01:46:28 +0200 Subject: [PATCH 02/51] Imported CoAP from lwm2m-contiki at https://github.com/sics-iot/lwm2m-contiki --- os/net/app-layer/coap/Makefile.coap | 16 + os/net/app-layer/coap/coap-block1.c | 35 +- os/net/app-layer/coap/coap-block1.h | 4 +- os/net/app-layer/coap/coap-blocking-api.c | 131 +++ os/net/app-layer/coap/coap-blocking-api.h | 67 ++ os/net/app-layer/coap/coap-callback-api.c | 156 ++++ os/net/app-layer/coap/coap-callback-api.h | 67 ++ os/net/app-layer/coap/coap-conf.h | 26 +- os/net/app-layer/coap/coap-constants.h | 26 +- os/net/app-layer/coap/coap-endpoint.h | 71 ++ os/net/app-layer/coap/coap-engine.c | 866 +++++++++--------- os/net/app-layer/coap/coap-engine.h | 170 +++- os/net/app-layer/coap/coap-keystore-simple.c | 90 ++ os/net/app-layer/coap/coap-keystore-simple.h | 44 + os/net/app-layer/coap/coap-keystore.h | 55 ++ os/net/app-layer/coap/coap-observe-client.c | 89 +- os/net/app-layer/coap/coap-observe-client.h | 15 +- os/net/app-layer/coap/coap-observe.c | 116 ++- os/net/app-layer/coap/coap-observe.h | 32 +- .../app-layer/coap/coap-res-well-known-core.c | 20 +- os/net/app-layer/coap/coap-separate.c | 45 +- os/net/app-layer/coap/coap-separate.h | 14 +- os/net/app-layer/coap/coap-timer-default.c | 131 +++ os/net/app-layer/coap/coap-timer.c | 189 ++++ os/net/app-layer/coap/coap-timer.h | 139 +++ os/net/app-layer/coap/coap-transactions.c | 85 +- os/net/app-layer/coap/coap-transactions.h | 21 +- os/net/app-layer/coap/coap-transport.h | 51 ++ os/net/app-layer/coap/coap-uip.c | 534 +++++++++++ os/net/app-layer/coap/coap.c | 365 +++----- os/net/app-layer/coap/coap.h | 204 +++-- os/net/app-layer/coap/rest-constants.h | 118 --- os/net/app-layer/coap/rest-engine.c | 239 ----- os/net/app-layer/coap/rest-engine.h | 252 ----- .../coap/tinydtls-support/dtls-support-conf.h | 27 + .../coap/tinydtls-support/dtls-support.c | 259 ++++++ 36 files changed, 3117 insertions(+), 1652 deletions(-) create mode 100644 os/net/app-layer/coap/Makefile.coap create mode 100644 os/net/app-layer/coap/coap-blocking-api.c create mode 100644 os/net/app-layer/coap/coap-blocking-api.h create mode 100644 os/net/app-layer/coap/coap-callback-api.c create mode 100644 os/net/app-layer/coap/coap-callback-api.h create mode 100644 os/net/app-layer/coap/coap-endpoint.h create mode 100644 os/net/app-layer/coap/coap-keystore-simple.c create mode 100644 os/net/app-layer/coap/coap-keystore-simple.h create mode 100644 os/net/app-layer/coap/coap-keystore.h create mode 100644 os/net/app-layer/coap/coap-timer-default.c create mode 100644 os/net/app-layer/coap/coap-timer.c create mode 100644 os/net/app-layer/coap/coap-timer.h create mode 100644 os/net/app-layer/coap/coap-transport.h create mode 100644 os/net/app-layer/coap/coap-uip.c delete mode 100644 os/net/app-layer/coap/rest-constants.h delete mode 100644 os/net/app-layer/coap/rest-engine.c delete mode 100644 os/net/app-layer/coap/rest-engine.h create mode 100644 os/net/app-layer/coap/tinydtls-support/dtls-support-conf.h create mode 100644 os/net/app-layer/coap/tinydtls-support/dtls-support.c diff --git a/os/net/app-layer/coap/Makefile.coap b/os/net/app-layer/coap/Makefile.coap new file mode 100644 index 000000000..4f1d2cd9f --- /dev/null +++ b/os/net/app-layer/coap/Makefile.coap @@ -0,0 +1,16 @@ +MAKE_WITH_DTLS ?= 0 + +ifeq ($(MAKE_WITH_DTLS),1) + + TINYDTLS_PATH := os/net/security/tinydtls + + ifeq (${wildcard $(CONTIKI)/$(TINYDTLS_PATH)/Makefile},) + ${error Could not find the tinyDTLS submodule. Please run "git submodule update --init" and try again} + endif + + CFLAGS += -DWITH_DTLS=1 + + MODULES += os/net/app-layer/coap/tinydtls-support + MODULES += $(TINYDTLS_PATH) ${addprefix $(TINYDTLS_PATH)/,aes sha2 ecc} + +endif diff --git a/os/net/app-layer/coap/coap-block1.c b/os/net/app-layer/coap/coap-block1.c index 6ecdce7c6..ca32f51b9 100644 --- a/os/net/app-layer/coap/coap-block1.c +++ b/os/net/app-layer/coap/coap-block1.c @@ -45,12 +45,8 @@ #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 /*----------------------------------------------------------------------------*/ @@ -77,39 +73,38 @@ * -1 if initialisation failed */ int -coap_block1_handler(void *request, void *response, uint8_t *target, size_t *len, size_t max_len) +coap_block1_handler(coap_packet_t *request, coap_packet_t *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); + int pay_len = coap_get_payload(request, &payload); if(!pay_len || !payload) { - erbium_status_code = REST.status.BAD_REQUEST; + coap_status_code = BAD_REQUEST_4_00; 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; + if(request->block1_offset + pay_len > max_len) { + coap_status_code = REQUEST_ENTITY_TOO_LARGE_4_13; 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; + memcpy(target + request->block1_offset, payload, pay_len); + *len = request->block1_offset + pay_len; } - if(IS_OPTION(packet, COAP_OPTION_BLOCK1)) { + if(coap_is_option(request, 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); + request->block1_num, + request->block1_more, + request->block1_size, + request->block1_offset); - coap_set_header_block1(response, packet->block1_num, packet->block1_more, packet->block1_size); - if(packet->block1_more) { + coap_set_header_block1(response, request->block1_num, request->block1_more, request->block1_size); + if(request->block1_more) { coap_set_status_code(response, CONTINUE_2_31); return 1; } diff --git a/os/net/app-layer/coap/coap-block1.h b/os/net/app-layer/coap/coap-block1.h index a6b1de5ab..86ccda52a 100644 --- a/os/net/app-layer/coap/coap-block1.h +++ b/os/net/app-layer/coap/coap-block1.h @@ -39,9 +39,11 @@ #ifndef COAP_BLOCK1_H_ #define COAP_BLOCK1_H_ +#include "coap.h" #include #include -int coap_block1_handler(void *request, void *response, uint8_t *target, size_t *len, size_t max_len); +int coap_block1_handler(coap_packet_t *request, coap_packet_t *response, + uint8_t *target, size_t *len, size_t max_len); #endif /* COAP_BLOCK1_H_ */ diff --git a/os/net/app-layer/coap/coap-blocking-api.c b/os/net/app-layer/coap/coap-blocking-api.c new file mode 100644 index 000000000..a49d46902 --- /dev/null +++ b/os/net/app-layer/coap/coap-blocking-api.c @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich + * 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 implementation for the REST Engine. + * \author + * Matthias Kovatsch + */ + +#include "coap-engine.h" +#include "coap-blocking-api.h" +#include "sys/cc.h" +#include +#include +#include + +#define DEBUG 0 +#if DEBUG +#include +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif + +/*---------------------------------------------------------------------------*/ +/*- Client Part -------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +void +coap_blocking_request_callback(void *callback_data, coap_packet_t *response) +{ + coap_request_state_t *state = (coap_request_state_t *)callback_data; + + state->response = response; + process_poll(state->process); +} +/*---------------------------------------------------------------------------*/ +PT_THREAD(coap_blocking_request + (coap_request_state_t *state, process_event_t ev, + coap_endpoint_t *remote_ep, + coap_packet_t *request, + coap_blocking_response_handler_t request_callback)) +{ + PT_BEGIN(&state->pt); + + static uint32_t res_block; + static uint8_t more; + static uint8_t block_error; + + state->block_num = 0; + state->response = NULL; + state->process = PROCESS_CURRENT(); + + more = 0; + res_block = 0; + block_error = 0; + + do { + request->mid = coap_get_mid(); + if((state->transaction = coap_new_transaction(request->mid, remote_ep))) { + state->transaction->callback = coap_blocking_request_callback; + state->transaction->callback_data = state; + + if(state->block_num > 0) { + coap_set_header_block2(request, state->block_num, 0, + COAP_MAX_CHUNK_SIZE); + } + state->transaction->packet_len = coap_serialize_message(request, + state-> + transaction-> + packet); + + coap_send_transaction(state->transaction); + PRINTF("Requested #%lu (MID %u)\n", state->block_num, request->mid); + + PT_YIELD_UNTIL(&state->pt, ev == PROCESS_EVENT_POLL); + + if(!state->response) { + PRINTF("Server not responding\n"); + PT_EXIT(&state->pt); + } + + coap_get_header_block2(state->response, &res_block, &more, NULL, NULL); + + PRINTF("Received #%lu%s (%u bytes)\n", res_block, more ? "+" : "", + state->response->payload_len); + + if(res_block == state->block_num) { + request_callback(state->response); + ++(state->block_num); + } else { + PRINTF("WRONG BLOCK %lu/%lu\n", res_block, state->block_num); + ++block_error; + } + } else { + PRINTF("Could not allocate transaction buffer"); + PT_EXIT(&state->pt); + } + } while(more && block_error < COAP_MAX_ATTEMPTS); + + PT_END(&state->pt); +} +/*---------------------------------------------------------------------------*/ diff --git a/os/net/app-layer/coap/coap-blocking-api.h b/os/net/app-layer/coap/coap-blocking-api.h new file mode 100644 index 000000000..c6ba82552 --- /dev/null +++ b/os/net/app-layer/coap/coap-blocking-api.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich + * 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. + */ + +#ifndef COAP_BLOCKING_API_H_ +#define COAP_BLOCKING_API_H_ + +#include "sys/pt.h" +#include "coap-transactions.h" + +/*---------------------------------------------------------------------------*/ +/*- Client Part -------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +typedef struct coap_request_state { + struct pt pt; + struct process *process; + coap_transaction_t *transaction; + coap_packet_t *response; + uint32_t block_num; +} coap_request_state_t; + +typedef void (* coap_blocking_response_handler_t)(coap_packet_t *response); + +PT_THREAD(coap_blocking_request + (coap_request_state_t *state, process_event_t ev, + coap_endpoint_t *remote, + coap_packet_t *request, + coap_blocking_response_handler_t request_callback)); + +#define COAP_BLOCKING_REQUEST(server_endpoint, request, chunk_handler) \ + { \ + static coap_request_state_t request_state; \ + PT_SPAWN(process_pt, &request_state.pt, \ + coap_blocking_request(&request_state, ev, \ + server_endpoint, \ + request, chunk_handler) \ + ); \ + } + +#endif /* COAP_BLOCKING_API_H_ */ diff --git a/os/net/app-layer/coap/coap-callback-api.c b/os/net/app-layer/coap/coap-callback-api.c new file mode 100644 index 000000000..dd8289b69 --- /dev/null +++ b/os/net/app-layer/coap/coap-callback-api.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2016, SICS Swedish ICT + * 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. + * + * + */ + +/** + * \file + * Callback API for doing CoAP requests + * Adapted from the blocking API + * \author + * Joakim Eriksson, joakime@sics.se + */ + + +#include "coap-engine.h" +#include "coap-callback-api.h" +#include "coap-transactions.h" +#include "sys/cc.h" +#include +#include + +#define DEBUG 0 +#if DEBUG +#include +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif + +/* These should go into the state struct so that we can have multiple + requests */ + +static uint32_t res_block; +static uint8_t more; +static uint8_t block_error; + +static void coap_request_callback(void *callback_data, coap_packet_t *response); + +/*---------------------------------------------------------------------------*/ + +static void +progress_request(coap_request_state_t *state) { + coap_packet_t *request = state->request; + request->mid = coap_get_mid(); + if((state->transaction = + coap_new_transaction(request->mid, state->remote_endpoint))) { + state->transaction->callback = coap_request_callback; + state->transaction->callback_data = state; + + if(state->block_num > 0) { + coap_set_header_block2(request, state->block_num, 0, + COAP_MAX_CHUNK_SIZE); + } + state->transaction->packet_len = + coap_serialize_message(request, state->transaction->packet); + + coap_send_transaction(state->transaction); + PRINTF("Requested #%lu (MID %u)\n", (unsigned long) state->block_num, + request->mid); + } +} + +/*---------------------------------------------------------------------------*/ + +static void +coap_request_callback(void *callback_data, coap_packet_t *response) +{ + coap_request_state_t *state = (coap_request_state_t *)callback_data; + uint32_t res_block1; + + state->response = response; + + PRINTF("COAP: request callback\n"); + + if(!state->response) { + PRINTF("Server not responding giving up...\n"); + state->callback(state); + return; + } + + /* Got a response */ + coap_get_header_block2(state->response, &res_block, &more, NULL, NULL); + coap_get_header_block1(state->response, &res_block1, NULL, NULL, NULL); + + PRINTF("Received #%lu%s B1:%lu (%u bytes)\n", + (unsigned long) res_block, (unsigned) more ? "+" : "", + (unsigned long) res_block1, + state->response->payload_len); + + if(res_block == state->block_num) { + /* Call the callback function as we have more data */ + state->callback(state); + /* this is only for counting BLOCK2 blocks.*/ + ++(state->block_num); + } else { + PRINTF("WRONG BLOCK %lu/%lu\n", (unsigned long) res_block, + (unsigned long) state->block_num); + ++block_error; + } + + if(more && block_error < COAP_MAX_ATTEMPTS) { + progress_request(state); + } else { + /* failure - now we give up and notify the callback */ + state->response = NULL; + state->callback(state); + } +} + +/*---------------------------------------------------------------------------*/ + +void +coap_send_request(coap_request_state_t *state, coap_endpoint_t *endpoint, + coap_packet_t *request, + void (*callback)(coap_request_state_t *state)) +{ + /* can we have these variables shared between multiple requests? */ + /* ripped from blocking request */ + more = 0; + res_block = 0; + block_error = 0; + + state->block_num = 0; + state->response = NULL; + state->request = request; + state->remote_endpoint = endpoint; + state->callback = callback; + + progress_request(state); +} diff --git a/os/net/app-layer/coap/coap-callback-api.h b/os/net/app-layer/coap/coap-callback-api.h new file mode 100644 index 000000000..455c1ebab --- /dev/null +++ b/os/net/app-layer/coap/coap-callback-api.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2016, SICS Swedish ICT + * 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. + * + * + */ + +/** + * \file + * Callback API for doing CoAP requests + * Adapted from the blocking API + * \author + * Joakim Eriksson, joakime@sics.se + */ + +#ifndef COAP_CALLBACK_API_H_ +#define COAP_CALLBACK_API_H_ + +#include "coap-engine.h" +#include "coap-transactions.h" +#include "sys/cc.h" + +/*---------------------------------------------------------------------------*/ +/*- Client Part -------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +typedef struct coap_request_state coap_request_state_t; + +struct coap_request_state { + coap_transaction_t *transaction; + coap_packet_t *response; + coap_packet_t *request; + coap_endpoint_t *remote_endpoint; + uint32_t block_num; + void *user_data; + coap_timer_t coap_timer; + void (*callback)(coap_request_state_t *state); +}; + +void coap_send_request(coap_request_state_t *state, coap_endpoint_t *endpoint, + coap_packet_t *request, + void (*callback)(coap_request_state_t *state)); + +#endif /* COAP_CALLBACK_API_H_ */ diff --git a/os/net/app-layer/coap/coap-conf.h b/os/net/app-layer/coap/coap-conf.h index 2aabc4be4..17f140243 100644 --- a/os/net/app-layer/coap/coap-conf.h +++ b/os/net/app-layer/coap/coap-conf.h @@ -36,8 +36,28 @@ * Matthias Kovatsch */ -#ifndef ER_COAP_CONF_H_ -#define ER_COAP_CONF_H_ +#ifndef COAP_CONF_H_ +#define COAP_CONF_H_ + +#include "contiki.h" + +/* + * The maximum buffer size that is provided for resource responses and must be + * respected due to the limited IP buffer. Larger data must be handled by the + * resource and will be sent chunk-wise through a TCP stream or CoAP blocks. + */ +#ifndef COAP_MAX_CHUNK_SIZE +#ifdef REST_MAX_CHUNK_SIZE +#define COAP_MAX_CHUNK_SIZE REST_MAX_CHUNK_SIZE +#else /* REST_MAX_CHUNK_SIZE */ +#define COAP_MAX_CHUNK_SIZE 64 +#endif /* REST_MAX_CHUNK_SIZE */ +#endif /* COAP_MAX_CHUNK_SIZE */ + +/* Define REST_MAX_CHUNK_SIZE for backward compatibility */ +#ifndef REST_MAX_CHUNK_SIZE +#define REST_MAX_CHUNK_SIZE COAP_MAX_CHUNK_SIZE +#endif /* REST_MAX_CHUNK_SIZE */ /* Features that can be disabled to achieve smaller memory footprint */ #ifndef COAP_LINK_FORMAT_FILTERING @@ -78,4 +98,4 @@ #define COAP_OBSERVE_REFRESH_INTERVAL 20 #endif /* COAP_OBSERVE_REFRESH_INTERVAL */ -#endif /* ER_COAP_CONF_H_ */ +#endif /* COAP_CONF_H_ */ diff --git a/os/net/app-layer/coap/coap-constants.h b/os/net/app-layer/coap/coap-constants.h index cfa73abcf..574da4759 100644 --- a/os/net/app-layer/coap/coap-constants.h +++ b/os/net/app-layer/coap/coap-constants.h @@ -36,10 +36,11 @@ * Matthias Kovatsch */ -#ifndef ER_COAP_CONSTANTS_H_ -#define ER_COAP_CONSTANTS_H_ +#ifndef COAP_CONSTANTS_H_ +#define COAP_CONSTANTS_H_ #define COAP_DEFAULT_PORT 5683 +#define COAP_DEFAULT_SECURE_PORT 5684 #define COAP_DEFAULT_MAX_AGE 60 #define COAP_RESPONSE_TIMEOUT 3 @@ -163,4 +164,23 @@ typedef enum { APPLICATION_X_OBIX_BINARY = 51 } coap_content_format_t; -#endif /* ER_COAP_CONSTANTS_H_ */ +/** + * Resource flags for allowed methods and special functionalities. + */ +typedef enum { + NO_FLAGS = 0, + + /* methods to handle */ + METHOD_GET = (1 << 0), + METHOD_POST = (1 << 1), + METHOD_PUT = (1 << 2), + METHOD_DELETE = (1 << 3), + + /* special flags */ + HAS_SUB_RESOURCES = (1 << 4), + IS_SEPARATE = (1 << 5), + IS_OBSERVABLE = (1 << 6), + IS_PERIODIC = (1 << 7) +} coap_resource_flags_t; + +#endif /* COAP_CONSTANTS_H_ */ diff --git a/os/net/app-layer/coap/coap-endpoint.h b/os/net/app-layer/coap/coap-endpoint.h new file mode 100644 index 000000000..208eb49a7 --- /dev/null +++ b/os/net/app-layer/coap/coap-endpoint.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2016, SICS, Swedish ICT AB. + * 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. + */ + +/** + * \file + * API to address CoAP endpoints + * \author + * Niclas Finne + * Joakim Eriksson + */ + +#ifndef COAP_ENDPOINT_H_ +#define COAP_ENDPOINT_H_ + +#include "contiki.h" +#include + +#ifndef COAP_ENDPOINT_CUSTOM +#include "net/ipv6/uip.h" + +typedef struct { + uip_ipaddr_t ipaddr; + uint16_t port; + uint8_t secure; +} coap_endpoint_t; +#endif /* COAP_ENDPOINT_CUSTOM */ + +void coap_endpoint_copy(coap_endpoint_t *destination, + const coap_endpoint_t *from); + +int coap_endpoint_cmp(const coap_endpoint_t *e1, const coap_endpoint_t *e2); + +void coap_endpoint_print(const coap_endpoint_t *ep); + +int coap_endpoint_parse(const char *text, size_t size, coap_endpoint_t *ep); + +int coap_endpoint_is_secure(const coap_endpoint_t *ep); + +int coap_endpoint_is_connected(const coap_endpoint_t *ep); + +int coap_endpoint_connect(coap_endpoint_t *ep); + +void coap_endpoint_disconnect(coap_endpoint_t *ep); + +#endif /* COAP_ENDPOINT_H_ */ diff --git a/os/net/app-layer/coap/coap-engine.c b/os/net/app-layer/coap/coap-engine.c index 8cde3b836..18dc79392 100644 --- a/os/net/app-layer/coap/coap-engine.c +++ b/os/net/app-layer/coap/coap-engine.c @@ -31,490 +31,488 @@ /** * \file - * CoAP implementation for the REST Engine. + * CoAP implementation Engine. * \author * Matthias Kovatsch */ +#include "coap-engine.h" #include "sys/cc.h" +#include "lib/list.h" #include #include +#include #include -#include "coap-engine.h" #define DEBUG 0 #if DEBUG #include #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]) +#define PRINTS(l,s,f) do { int i; \ + for(i = 0; i < l; i++) printf(f, s[i]); \ + } while(0) #else #define PRINTF(...) -#define PRINT6ADDR(addr) -#define PRINTLLADDR(addr) +#define PRINTS(l,s,f) #endif -PROCESS(coap_engine, "CoAP Engine"); +static void process_callback(coap_timer_t *t); + +/* + * To be called by HTTP/COAP server as a callback function when a new service + * request appears. This function dispatches the corresponding CoAP service. + */ +static int invoke_coap_resource_service(coap_packet_t *request, + coap_packet_t *response, + uint8_t *buffer, uint16_t buffer_size, + int32_t *offset); /*---------------------------------------------------------------------------*/ /*- Variables ---------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ -static service_callback_t service_cbk = NULL; +LIST(coap_handlers); +LIST(coap_resource_services); +LIST(coap_resource_periodic_services); +static uint8_t is_initialized = 0; /*---------------------------------------------------------------------------*/ -/*- Internal API ------------------------------------------------------------*/ +/*- CoAP service handlers---------------------------------------------------*/ /*---------------------------------------------------------------------------*/ -static int -coap_receive(void) +void +coap_add_handler(coap_handler_t *handler) { - erbium_status_code = NO_ERROR; + list_add(coap_handlers, handler); +} +/*---------------------------------------------------------------------------*/ +void +coap_remove_handler(coap_handler_t *handler) +{ + list_remove(coap_handlers, handler); +} +/*---------------------------------------------------------------------------*/ +coap_handler_status_t +coap_call_handlers(coap_packet_t *request, coap_packet_t *response, + uint8_t *buffer, uint16_t buffer_size, int32_t *offset) +{ + coap_handler_status_t status; + coap_handler_t *r; + for(r = list_head(coap_handlers); r != NULL; r = r->next) { + if(r->handler) { + status = r->handler(request, response, buffer, buffer_size, offset); + if(status != COAP_HANDLER_STATUS_CONTINUE) { + /* Request handled. */ - PRINTF("handle_incoming_data(): received uip_datalen=%u \n", - (uint16_t)uip_datalen()); - - /* static declaration reduces stack peaks and program code size */ - static coap_packet_t message[1]; /* this way the packet can be treated as pointer as usual */ - static coap_packet_t response[1]; - static coap_transaction_t *transaction = NULL; - - if(uip_newdata()) { - - PRINTF("receiving UDP datagram from: "); - PRINT6ADDR(&UIP_IP_BUF->srcipaddr); - PRINTF(":%u\n Length: %u\n", uip_ntohs(UIP_UDP_BUF->srcport), - uip_datalen()); - - erbium_status_code = - coap_parse_message(message, uip_appdata, uip_datalen()); - - if(erbium_status_code == NO_ERROR) { - - /*TODO duplicates suppression, if required by application */ - - PRINTF(" Parsed: v %u, t %u, tkl %u, c %u, mid %u\n", message->version, - message->type, message->token_len, message->code, message->mid); - PRINTF(" URL: %.*s\n", message->uri_path_len, message->uri_path); - PRINTF(" Payload: %.*s\n", message->payload_len, message->payload); - - /* handle requests */ - if(message->code >= COAP_GET && message->code <= COAP_DELETE) { - - /* use transaction buffer for response to confirmable request */ - if((transaction = - coap_new_transaction(message->mid, &UIP_IP_BUF->srcipaddr, - UIP_UDP_BUF->srcport))) { - uint32_t block_num = 0; - uint16_t block_size = COAP_MAX_BLOCK_SIZE; - uint32_t block_offset = 0; - int32_t new_offset = 0; - - /* prepare response */ - if(message->type == COAP_TYPE_CON) { - /* reliable CON requests are answered with an ACK */ - coap_init_message(response, COAP_TYPE_ACK, CONTENT_2_05, - message->mid); - } else { - /* unreliable NON requests are answered with a NON as well */ - coap_init_message(response, COAP_TYPE_NON, CONTENT_2_05, - coap_get_mid()); - /* mirror token */ - } if(message->token_len) { - coap_set_token(response, message->token, message->token_len); - /* get offset for blockwise transfers */ - } - if(coap_get_header_block2 - (message, &block_num, NULL, &block_size, &block_offset)) { - PRINTF("Blockwise: block request %lu (%u/%u) @ %lu bytes\n", - block_num, block_size, COAP_MAX_BLOCK_SIZE, block_offset); - block_size = MIN(block_size, COAP_MAX_BLOCK_SIZE); - new_offset = block_offset; - } - - /* invoke resource handler */ - if(service_cbk) { - - /* call REST framework and check if found and allowed */ - if(service_cbk - (message, response, transaction->packet + COAP_MAX_HEADER_SIZE, - block_size, &new_offset)) { - - if(erbium_status_code == NO_ERROR) { - - /* TODO coap_handle_blockwise(request, response, start_offset, end_offset); */ - - /* resource is unaware of Block1 */ - if(IS_OPTION(message, COAP_OPTION_BLOCK1) - && response->code < BAD_REQUEST_4_00 - && !IS_OPTION(response, COAP_OPTION_BLOCK1)) { - PRINTF("Block1 NOT IMPLEMENTED\n"); - - erbium_status_code = NOT_IMPLEMENTED_5_01; - coap_error_message = "NoBlock1Support"; - - /* client requested Block2 transfer */ - } else if(IS_OPTION(message, COAP_OPTION_BLOCK2)) { - - /* unchanged new_offset indicates that resource is unaware of blockwise transfer */ - if(new_offset == block_offset) { - PRINTF - ("Blockwise: unaware resource with payload length %u/%u\n", - response->payload_len, block_size); - if(block_offset >= response->payload_len) { - PRINTF - ("handle_incoming_data(): block_offset >= response->payload_len\n"); - - response->code = BAD_OPTION_4_02; - coap_set_payload(response, "BlockOutOfScope", 15); /* a const char str[] and sizeof(str) produces larger code size */ - } else { - coap_set_header_block2(response, block_num, - response->payload_len - - block_offset > block_size, - block_size); - coap_set_payload(response, - response->payload + block_offset, - MIN(response->payload_len - - block_offset, block_size)); - } /* if(valid offset) */ - - /* resource provides chunk-wise data */ - } else { - PRINTF("Blockwise: blockwise resource, new offset %ld\n", - new_offset); - coap_set_header_block2(response, block_num, - new_offset != -1 - || response->payload_len > - block_size, block_size); - - if(response->payload_len > block_size) { - coap_set_payload(response, response->payload, - block_size); - } - } /* if(resource aware of blockwise) */ - - /* Resource requested Block2 transfer */ - } else if(new_offset != 0) { - PRINTF - ("Blockwise: no block option for blockwise resource, using block size %u\n", - COAP_MAX_BLOCK_SIZE); - - coap_set_header_block2(response, 0, new_offset != -1, - COAP_MAX_BLOCK_SIZE); - coap_set_payload(response, response->payload, - MIN(response->payload_len, - COAP_MAX_BLOCK_SIZE)); - } /* blockwise transfer handling */ - } /* no errors/hooks */ - /* successful service callback */ - /* serialize response */ - } - if(erbium_status_code == NO_ERROR) { - if((transaction->packet_len = coap_serialize_message(response, - transaction-> - packet)) == - 0) { - erbium_status_code = PACKET_SERIALIZATION_ERROR; - } - } - } else { - erbium_status_code = NOT_IMPLEMENTED_5_01; - coap_error_message = "NoServiceCallbck"; /* no 'a' to fit into 16 bytes */ - } /* if(service callback) */ - } else { - erbium_status_code = SERVICE_UNAVAILABLE_5_03; - coap_error_message = "NoFreeTraBuffer"; - } /* if(transaction buffer) */ - - /* handle responses */ - } else { - - if(message->type == COAP_TYPE_CON && message->code == 0) { - PRINTF("Received Ping\n"); - erbium_status_code = PING_RESPONSE; - } else if(message->type == COAP_TYPE_ACK) { - /* transactions are closed through lookup below */ - PRINTF("Received ACK\n"); - } else if(message->type == COAP_TYPE_RST) { - PRINTF("Received RST\n"); - /* cancel possible subscriptions */ - coap_remove_observer_by_mid(&UIP_IP_BUF->srcipaddr, - UIP_UDP_BUF->srcport, message->mid); + /* Check response code before doing observe! */ + if(request->code == COAP_GET) { + coap_observe_handler(NULL, request, response); } - if((transaction = coap_get_transaction_by_mid(message->mid))) { - /* free transaction memory before callback, as it may create a new transaction */ - restful_response_handler callback = transaction->callback; - void *callback_data = transaction->callback_data; - - coap_clear_transaction(transaction); - - /* check if someone registered for the response */ - if(callback) { - callback(callback_data, message); - } - } - /* if(ACKed transaction) */ - transaction = NULL; - -#if COAP_OBSERVE_CLIENT - /* if observe notification */ - if((message->type == COAP_TYPE_CON || message->type == COAP_TYPE_NON) - && IS_OPTION(message, COAP_OPTION_OBSERVE)) { - PRINTF("Observe [%u]\n", message->observe); - coap_handle_notification(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport, - message); - } -#endif /* COAP_OBSERVE_CLIENT */ - } /* request or response */ - } /* parsed correctly */ - - /* if(parsed correctly) */ - if(erbium_status_code == NO_ERROR) { - if(transaction) { - coap_send_transaction(transaction); + return status; } - } else if(erbium_status_code == MANUAL_RESPONSE) { - PRINTF("Clearing transaction for manual response"); - coap_clear_transaction(transaction); - } else { - coap_message_type_t reply_type = COAP_TYPE_ACK; - - PRINTF("ERROR %u: %s\n", erbium_status_code, coap_error_message); - coap_clear_transaction(transaction); - - if(erbium_status_code == PING_RESPONSE) { - erbium_status_code = 0; - reply_type = COAP_TYPE_RST; - } else if(erbium_status_code >= 192) { - /* set to sendable error code */ - erbium_status_code = INTERNAL_SERVER_ERROR_5_00; - /* reuse input buffer for error message */ - } - coap_init_message(message, reply_type, erbium_status_code, - message->mid); - coap_set_payload(message, coap_error_message, - strlen(coap_error_message)); - coap_send_message(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport, - uip_appdata, coap_serialize_message(message, - uip_appdata)); } } + return COAP_HANDLER_STATUS_CONTINUE; +} +/*---------------------------------------------------------------------------*/ +static CC_INLINE coap_handler_status_t +call_service(coap_packet_t *request, coap_packet_t *response, + uint8_t *buffer, uint16_t buffer_size, int32_t *offset) +{ + coap_handler_status_t status; + status = coap_call_handlers(request, response, buffer, buffer_size, offset); + if(status != COAP_HANDLER_STATUS_CONTINUE) { + return status; + } + status = invoke_coap_resource_service(request, response, buffer, buffer_size, offset); + if(status != COAP_HANDLER_STATUS_CONTINUE) { + return status; + } - /* if(new data) */ - return erbium_status_code; -} -/*---------------------------------------------------------------------------*/ -void -coap_init_engine(void) -{ - process_start(&coap_engine, NULL); -} -/*---------------------------------------------------------------------------*/ -void -coap_set_service_callback(service_callback_t callback) -{ - service_cbk = callback; -} -/*---------------------------------------------------------------------------*/ -rest_resource_flags_t -coap_get_rest_method(void *packet) -{ - return (rest_resource_flags_t)(1 << - (((coap_packet_t *)packet)->code - 1)); + coap_set_status_code(response, NOT_FOUND_4_04); + + return COAP_HANDLER_STATUS_CONTINUE; } + /*---------------------------------------------------------------------------*/ /*- Server Part -------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* the discover resource is automatically included for CoAP */ -extern resource_t res_well_known_core; -#ifdef WITH_DTLS -extern resource_t res_dtls; -#endif +extern coap_resource_t res_well_known_core; /*---------------------------------------------------------------------------*/ -PROCESS_THREAD(coap_engine, ev, data) +/*- Internal API ------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +int +coap_receive(const coap_endpoint_t *src, + uint8_t *payload, uint16_t payload_length) { - PROCESS_BEGIN(); - PRINTF("Starting %s receiver...\n", coap_rest_implementation.name); + /* static declaration reduces stack peaks and program code size */ + static coap_packet_t message[1]; /* this way the packet can be treated as pointer as usual */ + static coap_packet_t response[1]; + coap_transaction_t *transaction = NULL; + coap_handler_status_t status; - rest_activate_resource(&res_well_known_core, ".well-known/core"); + coap_status_code = coap_parse_message(message, payload, payload_length); + coap_set_src_endpoint(message, src); - coap_register_as_transaction_handler(); - coap_init_connection(SERVER_LISTEN_PORT); + if(coap_status_code == NO_ERROR) { - while(1) { - PROCESS_YIELD(); + /*TODO duplicates suppression, if required by application */ - if(ev == tcpip_event) { - coap_receive(); - } else if(ev == PROCESS_EVENT_TIMER) { - /* retransmissions are handled here */ - coap_check_transactions(); + PRINTF(" Parsed: v %u, t %u, tkl %u, c %u, mid %u\n", message->version, + message->type, message->token_len, message->code, message->mid); + PRINTF(" URL:"); + PRINTS(message->uri_path_len, message->uri_path, "%c"); + PRINTF("\n Payload: "); + PRINTS(message->payload_len, message->payload, "%c"); + PRINTF("\n"); + + /* handle requests */ + if(message->code >= COAP_GET && message->code <= COAP_DELETE) { + + /* use transaction buffer for response to confirmable request */ + if((transaction = coap_new_transaction(message->mid, src))) { + uint32_t block_num = 0; + uint16_t block_size = COAP_MAX_BLOCK_SIZE; + uint32_t block_offset = 0; + int32_t new_offset = 0; + + /* prepare response */ + if(message->type == COAP_TYPE_CON) { + /* reliable CON requests are answered with an ACK */ + coap_init_message(response, COAP_TYPE_ACK, CONTENT_2_05, + message->mid); + } else { + /* unreliable NON requests are answered with a NON as well */ + coap_init_message(response, COAP_TYPE_NON, CONTENT_2_05, + coap_get_mid()); + /* mirror token */ + } + if(message->token_len) { + coap_set_token(response, message->token, message->token_len); + /* get offset for blockwise transfers */ + } + if(coap_get_header_block2 + (message, &block_num, NULL, &block_size, &block_offset)) { + PRINTF("Blockwise: block request %"PRIu32" (%u/%u) @ %"PRIu32" bytes\n", + block_num, block_size, COAP_MAX_BLOCK_SIZE, block_offset); + block_size = MIN(block_size, COAP_MAX_BLOCK_SIZE); + new_offset = block_offset; + } + + /* call CoAP framework and check if found and allowed */ + status = call_service(message, response, + transaction->packet + COAP_MAX_HEADER_SIZE, + block_size, &new_offset); + if(status != COAP_HANDLER_STATUS_CONTINUE) { + + if(coap_status_code == NO_ERROR) { + + /* TODO coap_handle_blockwise(request, response, start_offset, end_offset); */ + + /* resource is unaware of Block1 */ + if(coap_is_option(message, COAP_OPTION_BLOCK1) + && response->code < BAD_REQUEST_4_00 + && !coap_is_option(response, COAP_OPTION_BLOCK1)) { + PRINTF("Block1 NOT IMPLEMENTED\n"); + + coap_status_code = NOT_IMPLEMENTED_5_01; + coap_error_message = "NoBlock1Support"; + + /* client requested Block2 transfer */ + } else if(coap_is_option(message, COAP_OPTION_BLOCK2)) { + + /* unchanged new_offset indicates that resource is unaware of blockwise transfer */ + if(new_offset == block_offset) { + PRINTF + ("Blockwise: unaware resource with payload length %u/%u\n", + response->payload_len, block_size); + if(block_offset >= response->payload_len) { + PRINTF + ("handle_incoming_data(): block_offset >= response->payload_len\n"); + + response->code = BAD_OPTION_4_02; + coap_set_payload(response, "BlockOutOfScope", 15); /* a const char str[] and sizeof(str) produces larger code size */ + } else { + coap_set_header_block2(response, block_num, + response->payload_len - + block_offset > block_size, + block_size); + coap_set_payload(response, + response->payload + block_offset, + MIN(response->payload_len - + block_offset, block_size)); + } /* if(valid offset) */ + + /* resource provides chunk-wise data */ + } else { + PRINTF("Blockwise: blockwise resource, new offset %"PRId32"\n", + new_offset); + coap_set_header_block2(response, block_num, + new_offset != -1 + || response->payload_len > + block_size, block_size); + + if(response->payload_len > block_size) { + coap_set_payload(response, response->payload, + block_size); + } + } /* if(resource aware of blockwise) */ + + /* Resource requested Block2 transfer */ + } else if(new_offset != 0) { + PRINTF + ("Blockwise: no block option for blockwise resource, using block size %u\n", + COAP_MAX_BLOCK_SIZE); + + coap_set_header_block2(response, 0, new_offset != -1, + COAP_MAX_BLOCK_SIZE); + coap_set_payload(response, response->payload, + MIN(response->payload_len, + COAP_MAX_BLOCK_SIZE)); + } /* blockwise transfer handling */ + } /* no errors/hooks */ + /* successful service callback */ + /* serialize response */ + } + if(coap_status_code == NO_ERROR) { + if((transaction->packet_len = coap_serialize_message(response, + transaction-> + packet)) == + 0) { + coap_status_code = PACKET_SERIALIZATION_ERROR; + } + } + } else { + coap_status_code = SERVICE_UNAVAILABLE_5_03; + coap_error_message = "NoFreeTraBuffer"; + } /* if(transaction buffer) */ + + /* handle responses */ + } else { + + if(message->type == COAP_TYPE_CON && message->code == 0) { + PRINTF("Received Ping\n"); + coap_status_code = PING_RESPONSE; + } else if(message->type == COAP_TYPE_ACK) { + /* transactions are closed through lookup below */ + PRINTF("Received ACK\n"); + } else if(message->type == COAP_TYPE_RST) { + PRINTF("Received RST\n"); + /* cancel possible subscriptions */ + coap_remove_observer_by_mid(src, message->mid); + } + + if((transaction = coap_get_transaction_by_mid(message->mid))) { + /* free transaction memory before callback, as it may create a new transaction */ + coap_resource_response_handler_t callback = transaction->callback; + void *callback_data = transaction->callback_data; + + coap_clear_transaction(transaction); + + /* check if someone registered for the response */ + if(callback) { + callback(callback_data, message); + } + } + /* if(ACKed transaction) */ + transaction = NULL; + +#if COAP_OBSERVE_CLIENT + /* if observe notification */ + if((message->type == COAP_TYPE_CON || message->type == COAP_TYPE_NON) + && coap_is_option(message, COAP_OPTION_OBSERVE)) { + PRINTF("Observe [%u]\n", message->observe); + coap_handle_notification(src, message); + } +#endif /* COAP_OBSERVE_CLIENT */ + } /* request or response */ + } /* parsed correctly */ + + /* if(parsed correctly) */ + if(coap_status_code == NO_ERROR) { + if(transaction) { + coap_send_transaction(transaction); } - } /* while (1) */ + } else if(coap_status_code == MANUAL_RESPONSE) { + PRINTF("Clearing transaction for manual response"); + coap_clear_transaction(transaction); + } else { + coap_message_type_t reply_type = COAP_TYPE_ACK; - PROCESS_END(); + PRINTF("ERROR %u: %s\n", coap_status_code, coap_error_message); + coap_clear_transaction(transaction); + + if(coap_status_code == PING_RESPONSE) { + coap_status_code = 0; + reply_type = COAP_TYPE_RST; + } else if(coap_status_code >= 192) { + /* set to sendable error code */ + coap_status_code = INTERNAL_SERVER_ERROR_5_00; + /* reuse input buffer for error message */ + } + coap_init_message(message, reply_type, coap_status_code, + message->mid); + coap_set_payload(message, coap_error_message, + strlen(coap_error_message)); + coap_send_message(src, payload, coap_serialize_message(message, payload)); + } + + /* if(new data) */ + return coap_status_code; } /*---------------------------------------------------------------------------*/ -/*- Client Part -------------------------------------------------------------*/ -/*---------------------------------------------------------------------------*/ void -coap_blocking_request_callback(void *callback_data, void *response) +coap_engine_init(void) { - struct request_state_t *state = (struct request_state_t *)callback_data; - - state->response = (coap_packet_t *)response; - process_poll(state->process); -} -/*---------------------------------------------------------------------------*/ -PT_THREAD(coap_blocking_request - (struct request_state_t *state, process_event_t ev, - uip_ipaddr_t *remote_ipaddr, uint16_t remote_port, - coap_packet_t *request, - blocking_response_handler request_callback)) -{ - PT_BEGIN(&state->pt); - - static uint8_t more; - static uint32_t res_block; - static uint8_t block_error; - - state->block_num = 0; - state->response = NULL; - state->process = PROCESS_CURRENT(); - - more = 0; - res_block = 0; - block_error = 0; - - do { - request->mid = coap_get_mid(); - if((state->transaction = coap_new_transaction(request->mid, remote_ipaddr, - remote_port))) { - state->transaction->callback = coap_blocking_request_callback; - state->transaction->callback_data = state; - - if(state->block_num > 0) { - coap_set_header_block2(request, state->block_num, 0, - REST_MAX_CHUNK_SIZE); - } - state->transaction->packet_len = coap_serialize_message(request, - state-> - transaction-> - packet); - - coap_send_transaction(state->transaction); - PRINTF("Requested #%lu (MID %u)\n", state->block_num, request->mid); - - PT_YIELD_UNTIL(&state->pt, ev == PROCESS_EVENT_POLL); - - if(!state->response) { - PRINTF("Server not responding\n"); - PT_EXIT(&state->pt); - } - - coap_get_header_block2(state->response, &res_block, &more, NULL, NULL); - - PRINTF("Received #%lu%s (%u bytes)\n", res_block, more ? "+" : "", - state->response->payload_len); - - if(res_block == state->block_num) { - request_callback(state->response); - ++(state->block_num); - } else { - PRINTF("WRONG BLOCK %lu/%lu\n", res_block, state->block_num); - ++block_error; - } - } else { - PRINTF("Could not allocate transaction buffer"); - PT_EXIT(&state->pt); - } - } while(more && block_error < COAP_MAX_ATTEMPTS); - - PT_END(&state->pt); -} -/*---------------------------------------------------------------------------*/ -/*- REST Engine Interface ---------------------------------------------------*/ -/*---------------------------------------------------------------------------*/ -const struct rest_implementation coap_rest_implementation = { - "CoAP-18", - - coap_init_engine, - coap_set_service_callback, - - coap_get_header_uri_path, - coap_get_rest_method, - coap_set_status_code, - - coap_get_header_content_format, - coap_set_header_content_format, - coap_get_header_accept, - coap_get_header_size2, - coap_set_header_size2, - coap_get_header_max_age, - coap_set_header_max_age, - coap_set_header_etag, - coap_get_header_if_match, - coap_get_header_if_none_match, - coap_get_header_uri_host, - coap_set_header_location_path, - - coap_get_payload, - coap_set_payload, - - coap_get_header_uri_query, - coap_get_query_variable, - coap_get_post_variable, - - coap_notify_observers, - coap_observe_handler, - - { - CONTENT_2_05, - CREATED_2_01, - CHANGED_2_04, - DELETED_2_02, - VALID_2_03, - BAD_REQUEST_4_00, - UNAUTHORIZED_4_01, - BAD_OPTION_4_02, - FORBIDDEN_4_03, - NOT_FOUND_4_04, - METHOD_NOT_ALLOWED_4_05, - NOT_ACCEPTABLE_4_06, - REQUEST_ENTITY_TOO_LARGE_4_13, - UNSUPPORTED_MEDIA_TYPE_4_15, - INTERNAL_SERVER_ERROR_5_00, - NOT_IMPLEMENTED_5_01, - BAD_GATEWAY_5_02, - SERVICE_UNAVAILABLE_5_03, - GATEWAY_TIMEOUT_5_04, - PROXYING_NOT_SUPPORTED_5_05 - }, - - { - TEXT_PLAIN, - TEXT_XML, - TEXT_CSV, - TEXT_HTML, - IMAGE_GIF, - IMAGE_JPEG, - IMAGE_PNG, - IMAGE_TIFF, - AUDIO_RAW, - VIDEO_RAW, - APPLICATION_LINK_FORMAT, - APPLICATION_XML, - APPLICATION_OCTET_STREAM, - APPLICATION_RDF_XML, - APPLICATION_SOAP_XML, - APPLICATION_ATOM_XML, - APPLICATION_XMPP_XML, - APPLICATION_EXI, - APPLICATION_FASTINFOSET, - APPLICATION_SOAP_FASTINFOSET, - APPLICATION_JSON, - APPLICATION_X_OBIX_BINARY + /* avoid initializing twice */ + if(is_initialized) { + PRINTF("CoAP engine process already running - double initialization?\n"); + return; } -}; + is_initialized = 1; + + PRINTF("Starting CoAP engine...\n"); + + list_init(coap_handlers); + list_init(coap_resource_services); + list_init(coap_resource_periodic_services); + + coap_activate_resource(&res_well_known_core, ".well-known/core"); + + coap_transport_init(); + coap_init_connection(); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Makes a resource available under the given URI path + * \param resource A pointer to a resource implementation + * \param path The URI path string for this resource + * + * The resource implementation must be imported first using the + * extern keyword. The build system takes care of compiling every + * *.c file in the ./resources/ sub-directory (see example Makefile). + */ +void +coap_activate_resource(coap_resource_t *resource, const char *path) +{ + coap_periodic_resource_t *periodic; + resource->url = path; + list_add(coap_resource_services, resource); + + PRINTF("Activating: %s\n", resource->url); + + /* Only add periodic resources with a periodic_handler and a period > 0. */ + if(resource->flags & IS_PERIODIC && resource->periodic + && resource->periodic->periodic_handler + && resource->periodic->period) { + PRINTF("Periodic resource: %p (%s)\n", resource->periodic, + resource->periodic->resource->url); + list_add(coap_resource_periodic_services, resource->periodic); + periodic = resource->periodic; + coap_timer_set_callback(&periodic->periodic_timer, process_callback); + coap_timer_set_user_data(&periodic->periodic_timer, resource); + coap_timer_set(&periodic->periodic_timer, periodic->period); + } +} +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/*- Internal API ------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +coap_resource_t * +coap_get_first_resource(void) +{ + return list_head(coap_resource_services); +} +/*---------------------------------------------------------------------------*/ +coap_resource_t * +coap_get_next_resource(coap_resource_t *resource) +{ + return list_item_next(resource); +} +/*---------------------------------------------------------------------------*/ +static int +invoke_coap_resource_service(coap_packet_t *request, coap_packet_t *response, + uint8_t *buffer, uint16_t buffer_size, + int32_t *offset) +{ + uint8_t found = 0; + uint8_t allowed = 1; + + coap_resource_t *resource = NULL; + const char *url = NULL; + int url_len, res_url_len; + + url_len = coap_get_header_uri_path(request, &url); + for(resource = list_head(coap_resource_services); + resource; resource = resource->next) { + + /* if the web service handles that kind of requests and urls matches */ + res_url_len = strlen(resource->url); + if((url_len == res_url_len + || (url_len > res_url_len + && (resource->flags & HAS_SUB_RESOURCES) + && url[res_url_len] == '/')) + && strncmp(resource->url, url, res_url_len) == 0) { + coap_resource_flags_t method = coap_get_method_type(request); + found = 1; + + PRINTF("/%s, method %u, resource->flags %u\n", resource->url, + (uint16_t)method, resource->flags); + + if((method & METHOD_GET) && resource->get_handler != NULL) { + /* call handler function */ + resource->get_handler(request, response, buffer, buffer_size, offset); + } else if((method & METHOD_POST) && resource->post_handler != NULL) { + /* call handler function */ + resource->post_handler(request, response, buffer, buffer_size, + offset); + } else if((method & METHOD_PUT) && resource->put_handler != NULL) { + /* call handler function */ + resource->put_handler(request, response, buffer, buffer_size, offset); + } else if((method & METHOD_DELETE) && resource->delete_handler != NULL) { + /* call handler function */ + resource->delete_handler(request, response, buffer, buffer_size, + offset); + } else { + allowed = 0; + coap_set_status_code(response, METHOD_NOT_ALLOWED_4_05); + } + break; + } + } + if(!found) { + coap_set_status_code(response, NOT_FOUND_4_04); + } else if(allowed) { + /* final handler for special flags */ + if(resource->flags & IS_OBSERVABLE) { + coap_observe_handler(resource, request, response); + } + } + return found & allowed; +} +/*---------------------------------------------------------------------------*/ +/* This callback occurs when t is expired */ +static void +process_callback(coap_timer_t *t) +{ + coap_resource_t *resource; + resource = coap_timer_get_user_data(t); + if(resource != NULL && (resource->flags & IS_PERIODIC) + && resource->periodic != NULL && resource->periodic->period) { + PRINTF("Periodic: timer expired for /%s (period: %lu)\n", + resource->url, resource->periodic->period); + + if(!is_initialized) { + /* CoAP has not yet been initialized. */ + } else if(resource->periodic->periodic_handler) { + /* Call the periodic_handler function. */ + resource->periodic->periodic_handler(); + } + + coap_timer_set(t, resource->periodic->period); + } +} /*---------------------------------------------------------------------------*/ diff --git a/os/net/app-layer/coap/coap-engine.h b/os/net/app-layer/coap/coap-engine.h index 8b3ae1d2c..0d3c2ea64 100644 --- a/os/net/app-layer/coap/coap-engine.h +++ b/os/net/app-layer/coap/coap-engine.h @@ -31,56 +31,142 @@ /** * \file - * CoAP implementation for the REST Engine. + * CoAP engine implementation. * \author * Matthias Kovatsch */ -#ifndef ER_COAP_ENGINE_H_ -#define ER_COAP_ENGINE_H_ +#ifndef COAP_ENGINE_H_ +#define COAP_ENGINE_H_ + +typedef struct coap_resource_s coap_resource_t; +typedef struct coap_periodic_resource_s coap_periodic_resource_t; -#include "pt.h" #include "coap.h" +#include "coap-timer.h" + +typedef enum { + COAP_HANDLER_STATUS_CONTINUE, + COAP_HANDLER_STATUS_PROCESSED +} coap_handler_status_t; + +typedef coap_handler_status_t +(* coap_handler_callback_t)(coap_packet_t *request, + coap_packet_t *response, + uint8_t *buffer, uint16_t buffer_size, + int32_t *offset); + +typedef struct coap_handler coap_handler_t; + +struct coap_handler { + coap_handler_t *next; + coap_handler_callback_t handler; +}; + +#define COAP_HANDLER(name, handler) \ + coap_handler_t name = { NULL, handler } + +void coap_add_handler(coap_handler_t *handler); +void coap_remove_handler(coap_handler_t *handler); + +void coap_engine_init(void); + +int coap_receive(const coap_endpoint_t *src, + uint8_t *payload, uint16_t payload_length); + +coap_handler_status_t coap_call_handlers(coap_packet_t *request, + coap_packet_t *response, + uint8_t *buffer, + uint16_t buffer_size, + int32_t *offset); +/*---------------------------------------------------------------------------*/ +/* signatures of handler functions */ +typedef void (* coap_resource_handler_t)(coap_packet_t *request, + coap_packet_t *response, + uint8_t *buffer, + uint16_t preferred_size, + int32_t *offset); +typedef void (* coap_resource_periodic_handler_t)(void); +typedef void (* coap_resource_response_handler_t)(void *data, + coap_packet_t *response); +typedef void (* coap_resource_trigger_handler_t)(void); + +/* data structure representing a resource in CoAP */ +struct coap_resource_s { + coap_resource_t *next; /* for LIST, points to next resource defined */ + const char *url; /*handled URL */ + coap_resource_flags_t flags; /* handled CoAP methods */ + const char *attributes; /* link-format attributes */ + coap_resource_handler_t get_handler; /* handler function */ + coap_resource_handler_t post_handler; /* handler function */ + coap_resource_handler_t put_handler; /* handler function */ + coap_resource_handler_t delete_handler; /* handler function */ + union { + coap_periodic_resource_t *periodic; /* special data depending on flags */ + coap_resource_trigger_handler_t trigger; + coap_resource_trigger_handler_t resume; + }; +}; + +struct coap_periodic_resource_s { + uint32_t period; + coap_timer_t periodic_timer; + const coap_resource_periodic_handler_t periodic_handler; +}; + +/* + * Macro to define a CoAP resource. + * Resources are statically defined for the sake of efficiency and better memory management. + */ +#define RESOURCE(name, attributes, get_handler, post_handler, put_handler, delete_handler) \ + coap_resource_t name = { NULL, NULL, NO_FLAGS, attributes, get_handler, post_handler, put_handler, delete_handler, { NULL } } + +#define PARENT_RESOURCE(name, attributes, get_handler, post_handler, put_handler, delete_handler) \ + coap_resource_t name = { NULL, NULL, HAS_SUB_RESOURCES, attributes, get_handler, post_handler, put_handler, delete_handler, { NULL } } + +#define SEPARATE_RESOURCE(name, attributes, get_handler, post_handler, put_handler, delete_handler, resume_handler) \ + coap_resource_t name = { NULL, NULL, IS_SEPARATE, attributes, get_handler, post_handler, put_handler, delete_handler, { .resume = resume_handler } } + +#define EVENT_RESOURCE(name, attributes, get_handler, post_handler, put_handler, delete_handler, event_handler) \ + coap_resource_t name = { NULL, NULL, IS_OBSERVABLE, attributes, get_handler, post_handler, put_handler, delete_handler, { .trigger = event_handler } } + +/* + * Macro to define a periodic resource. + * The corresponding [name]_periodic_handler() function will be called every period. + * For instance polling a sensor and publishing a changed value to subscribed clients would be done there. + */ +#define PERIODIC_RESOURCE(name, attributes, get_handler, post_handler, put_handler, delete_handler, period, periodic_handler) \ + static coap_periodic_resource_t periodic_##name = { period, { 0 }, periodic_handler }; \ + coap_resource_t name = { NULL, NULL, IS_OBSERVABLE | IS_PERIODIC, attributes, get_handler, post_handler, put_handler, delete_handler, { .periodic = &periodic_##name } } + +/*---------------------------------------------------------------------------*/ +/** + * + * \brief Resources wanted to be accessible should be activated with the following code. + * \param resource + * A CoAP resource defined through the RESOURCE macros. + * \param path + * The local URI path where to provide the resource. + */ +void coap_activate_resource(coap_resource_t *resource, const char *path); +/*---------------------------------------------------------------------------*/ +/** + * \brief Returns the first of registered CoAP resources. + * \return The first registered CoAP resource or NULL if none exists. + */ +coap_resource_t *coap_get_first_resource(void); +/*---------------------------------------------------------------------------*/ +/** + * \brief Returns the next registered CoAP resource. + * \return The next resource or NULL if no more exists. + */ +coap_resource_t *coap_get_next_resource(coap_resource_t *resource); +/*---------------------------------------------------------------------------*/ + #include "coap-transactions.h" #include "coap-observe.h" #include "coap-separate.h" #include "coap-observe-client.h" +#include "coap-transport.h" -#define SERVER_LISTEN_PORT UIP_HTONS(COAP_SERVER_PORT) - -typedef coap_packet_t rest_request_t; -typedef coap_packet_t rest_response_t; - -void coap_init_engine(void); - -/*---------------------------------------------------------------------------*/ -/*- Client Part -------------------------------------------------------------*/ -/*---------------------------------------------------------------------------*/ -struct request_state_t { - struct pt pt; - struct process *process; - coap_transaction_t *transaction; - coap_packet_t *response; - uint32_t block_num; -}; - -typedef void (*blocking_response_handler)(void *response); - -PT_THREAD(coap_blocking_request - (struct request_state_t *state, process_event_t ev, - uip_ipaddr_t *remote_ipaddr, uint16_t remote_port, - coap_packet_t *request, - blocking_response_handler request_callback)); - -#define COAP_BLOCKING_REQUEST(server_addr, server_port, request, chunk_handler) \ - { \ - static struct request_state_t request_state; \ - PT_SPAWN(process_pt, &request_state.pt, \ - coap_blocking_request(&request_state, ev, \ - server_addr, server_port, \ - request, chunk_handler) \ - ); \ - } -/*---------------------------------------------------------------------------*/ - -#endif /* ER_COAP_ENGINE_H_ */ +#endif /* COAP_ENGINE_H_ */ diff --git a/os/net/app-layer/coap/coap-keystore-simple.c b/os/net/app-layer/coap/coap-keystore-simple.c new file mode 100644 index 000000000..1d3ded722 --- /dev/null +++ b/os/net/app-layer/coap/coap-keystore-simple.c @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2017, RISE SICS AB. + * 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 copyright holder 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 COPYRIGHT HOLDER 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 + * COPYRIGHT HOLDER 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. + */ + +/** + * \file + * A simple keystore with fixed credentials. + * \author + * Niclas Finne + * Joakim Eriksson + */ + +#include "coap-endpoint.h" +#include "coap-keystore.h" +#include + +/* #ifndef PSK_DEFAULT_IDENTITY */ +/* #define PSK_DEFAULT_IDENTITY "Client_identity" */ +/* #endif /\* PSK_DEFAULT_IDENTITY *\/ */ + +/* #ifndef PSK_DEFAULT_KEY */ +/* #define PSK_DEFAULT_KEY "secretPSK" */ +/* #endif /\* PSK_DEFAULT_KEY *\/ */ +/*---------------------------------------------------------------------------*/ +#ifdef WITH_DTLS +#if defined(PSK_DEFAULT_IDENTITY) && defined(PSK_DEFAULT_KEY) +static int +get_default_psk_info(const coap_endpoint_t *address_info, + coap_keystore_psk_entry_t *info) +{ + if(info != NULL) { + if(info->identity == NULL || info->identity_len == 0) { + /* Identity requested */ + info->identity = (uint8_t *)PSK_DEFAULT_IDENTITY; + info->identity_len = strlen(PSK_DEFAULT_IDENTITY); + return 1; + } + if(info->identity_len != strlen(PSK_DEFAULT_IDENTITY) || + memcmp(info->identity, PSK_DEFAULT_IDENTITY, info->identity_len) != 0) { + /* Identity not matching */ + return 0; + } + info->key = (uint8_t *)PSK_DEFAULT_KEY; + info->key_len = strlen(PSK_DEFAULT_KEY); + return 1; + } + return 0; +} +static const coap_keystore_t simple_key_store = { + .coap_get_psk_info = get_default_psk_info +}; +#endif /* defined(PSK_DEFAULT_IDENTITY) && defined(PSK_DEFAULT_KEY) */ +#endif /* WITH_DTLS */ +/*---------------------------------------------------------------------------*/ +void +coap_store_simple_init(void) +{ +#ifdef WITH_DTLS +#if defined(PSK_DEFAULT_IDENTITY) && defined(PSK_DEFAULT_KEY) + coap_set_keystore(&simple_key_store); +#endif /* defined(PSK_DEFAULT_IDENTITY) && defined(PSK_DEFAULT_KEY) */ +#endif /* WITH_DTLS */ +} +/*---------------------------------------------------------------------------*/ diff --git a/os/net/app-layer/coap/coap-keystore-simple.h b/os/net/app-layer/coap/coap-keystore-simple.h new file mode 100644 index 000000000..7f13853fb --- /dev/null +++ b/os/net/app-layer/coap/coap-keystore-simple.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2017, RISE SICS AB. + * 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 copyright holder 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 COPYRIGHT HOLDER 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 + * COPYRIGHT HOLDER 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. + */ + +/** + * \file + * A simple keystore with fixed credentials. + * \author + * Niclas Finne + * Joakim Eriksson + */ + +#ifndef COAP_KEYSTORE_SIMPLE_H_ +#define COAP_KEYSTORE_SIMPLE_H_ + +void coap_keystore_simple(void); + +#endif /* COAP_KEYSTORE_SIMPLE_H_ */ diff --git a/os/net/app-layer/coap/coap-keystore.h b/os/net/app-layer/coap/coap-keystore.h new file mode 100644 index 000000000..ecf45315c --- /dev/null +++ b/os/net/app-layer/coap/coap-keystore.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2017, RISE SICS + * 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. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * + */ + +#ifndef COAP_KEYSTORE_H_ +#define COAP_KEYSTORE_H_ + +#include "coap-endpoint.h" + +/* Pre-shared key info */ +typedef struct { + const uint8_t *identity_hint; + uint16_t identity_hint_len; + const uint8_t *identity; + uint16_t identity_len; + const uint8_t *key; + uint16_t key_len; +} coap_keystore_psk_entry_t; + +/* the function for getting the data from a keystore */ +typedef struct coap_keystore { + int (* coap_get_psk_info)(const coap_endpoint_t *address_info, + coap_keystore_psk_entry_t *info); +} coap_keystore_t; + +void coap_set_keystore(const coap_keystore_t *keystore); + +#endif /* COAP_KEYSTORE_H_ */ diff --git a/os/net/app-layer/coap/coap-observe-client.c b/os/net/app-layer/coap/coap-observe-client.c index 84edec98e..569a6bc83 100644 --- a/os/net/app-layer/coap/coap-observe-client.c +++ b/os/net/app-layer/coap/coap-observe-client.c @@ -37,36 +37,24 @@ * Daniele Alessandrelli */ -#include -#include - #include "coap.h" #include "coap-observe-client.h" +#include "sys/cc.h" +#include "lib/memb.h" +#include "lib/list.h" +#include +#include /* Compile this code only if client-side support for CoAP Observe is required */ #if COAP_OBSERVE_CLIENT -#define DEBUG 1 +#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]) +#define PRINTEP(ep) coap_endpoint_print(ep) #else #define PRINTF(...) -#define PRINT6ADDR(addr) -#define PRINTLLADDR(addr) +#define PRINTEP(ep) #endif MEMB(obs_subjects_memb, coap_observee_t, COAP_MAX_OBSERVEES); @@ -74,20 +62,16 @@ LIST(obs_subjects_list); /*----------------------------------------------------------------------------*/ static size_t -get_token(void *packet, const uint8_t **token) +get_token(coap_packet_t *coap_pkt, const uint8_t **token) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - *token = coap_pkt->token; return coap_pkt->token_len; } /*----------------------------------------------------------------------------*/ static int -set_token(void *packet, const uint8_t *token, size_t token_len) +set_token(coap_packet_t *coap_pkt, const uint8_t *token, size_t token_len) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - coap_pkt->token_len = MIN(COAP_TOKEN_LEN, token_len); memcpy(coap_pkt->token, token, coap_pkt->token_len); @@ -95,7 +79,7 @@ set_token(void *packet, const uint8_t *token, size_t token_len) } /*----------------------------------------------------------------------------*/ coap_observee_t * -coap_obs_add_observee(uip_ipaddr_t *addr, uint16_t port, +coap_obs_add_observee(const coap_endpoint_t *endpoint, const uint8_t *token, size_t token_len, const char *url, notification_callback_t notification_callback, void *data) @@ -103,18 +87,16 @@ coap_obs_add_observee(uip_ipaddr_t *addr, uint16_t port, coap_observee_t *o; /* Remove existing observe relationship, if any. */ - coap_obs_remove_observee_by_url(addr, port, url); + coap_obs_remove_observee_by_url(endpoint, url); o = memb_alloc(&obs_subjects_memb); if(o) { o->url = url; - uip_ipaddr_copy(&o->addr, addr); - o->port = port; + coap_endpoint_copy(&o->endpoint, endpoint); o->token_len = token_len; memcpy(o->token, token, token_len); /* o->last_mid = 0; */ o->notification_callback = notification_callback; o->data = data; - /* stimer_set(&o->refresh_timer, COAP_OBSERVING_REFRESH_INTERVAL); */ PRINTF("Adding obs_subject for /%s [0x%02X%02X]\n", o->url, o->token[0], o->token[1]); list_add(obs_subjects_list, o); @@ -150,7 +132,7 @@ coap_get_obs_subject_by_token(const uint8_t *token, size_t token_len) } /*----------------------------------------------------------------------------*/ int -coap_obs_remove_observee_by_token(uip_ipaddr_t *addr, uint16_t port, +coap_obs_remove_observee_by_token(const coap_endpoint_t *endpoint, uint8_t *token, size_t token_len) { int removed = 0; @@ -159,8 +141,7 @@ coap_obs_remove_observee_by_token(uip_ipaddr_t *addr, uint16_t port, for(obs = (coap_observee_t *)list_head(obs_subjects_list); obs; obs = obs->next) { PRINTF("Remove check Token 0x%02X%02X\n", token[0], token[1]); - if(uip_ipaddr_cmp(&obs->addr, addr) - && obs->port == port + if(coap_endpoint_cmp(&obs->endpoint, endpoint) && obs->token_len == token_len && memcmp(obs->token, token, token_len) == 0) { coap_obs_remove_observee(obs); @@ -171,7 +152,7 @@ coap_obs_remove_observee_by_token(uip_ipaddr_t *addr, uint16_t port, } /*----------------------------------------------------------------------------*/ int -coap_obs_remove_observee_by_url(uip_ipaddr_t *addr, uint16_t port, +coap_obs_remove_observee_by_url(const coap_endpoint_t *endpoint, const char *url) { int removed = 0; @@ -180,8 +161,7 @@ coap_obs_remove_observee_by_url(uip_ipaddr_t *addr, uint16_t port, for(obs = (coap_observee_t *)list_head(obs_subjects_list); obs; obs = obs->next) { PRINTF("Remove check URL %s\n", url); - if(uip_ipaddr_cmp(&obs->addr, addr) - && obs->port == port + if(coap_endpoint_cmp(&obs->endpoint, endpoint) && (obs->url == url || memcmp(obs->url, url, strlen(obs->url)) == 0)) { coap_obs_remove_observee(obs); removed++; @@ -191,33 +171,30 @@ coap_obs_remove_observee_by_url(uip_ipaddr_t *addr, uint16_t port, } /*----------------------------------------------------------------------------*/ static void -simple_reply(coap_message_type_t type, uip_ip6addr_t *addr, uint16_t port, +simple_reply(coap_message_type_t type, const coap_endpoint_t *endpoint, coap_packet_t *notification) { static coap_packet_t response[1]; size_t len; coap_init_message(response, type, NO_ERROR, notification->mid); - len = coap_serialize_message(response, uip_appdata); - coap_send_message(addr, port, uip_appdata, len); + len = coap_serialize_message(response, coap_databuf()); + coap_send_message(endpoint, coap_databuf(), len); } /*----------------------------------------------------------------------------*/ static coap_notification_flag_t -classify_notification(void *response, int first) +classify_notification(coap_packet_t *response, int first) { - coap_packet_t *pkt; - - pkt = (coap_packet_t *)response; - if(!pkt) { + if(!response) { PRINTF("no response\n"); return NO_REPLY_FROM_SERVER; } PRINTF("server replied\n"); - if(!IS_RESPONSE_CODE_2_XX(pkt)) { + if(!IS_RESPONSE_CODE_2_XX(response)) { PRINTF("error response code\n"); return ERROR_RESPONSE_CODE; } - if(!IS_OPTION(pkt, COAP_OPTION_OBSERVE)) { + if(!coap_is_option(response, COAP_OPTION_OBSERVE)) { PRINTF("server does not support observe\n"); return OBSERVE_NOT_SUPPORTED; } @@ -228,10 +205,9 @@ classify_notification(void *response, int first) } /*----------------------------------------------------------------------------*/ void -coap_handle_notification(uip_ipaddr_t *addr, uint16_t port, +coap_handle_notification(const coap_endpoint_t *endpoint, coap_packet_t *notification) { - coap_packet_t *pkt; const uint8_t *token; int token_len; coap_observee_t *obs; @@ -239,8 +215,7 @@ coap_handle_notification(uip_ipaddr_t *addr, uint16_t port, uint32_t observe; PRINTF("coap_handle_notification()\n"); - pkt = (coap_packet_t *)notification; - token_len = get_token(pkt, &token); + token_len = get_token(notification, &token); PRINTF("Getting token\n"); if(0 == token_len) { PRINTF("Error while handling coap observe notification: " @@ -252,11 +227,11 @@ coap_handle_notification(uip_ipaddr_t *addr, uint16_t port, if(NULL == obs) { PRINTF("Error while handling coap observe notification: " "no matching token found\n"); - simple_reply(COAP_TYPE_RST, addr, port, notification); + simple_reply(COAP_TYPE_RST, endpoint, notification); return; } if(notification->type == COAP_TYPE_CON) { - simple_reply(COAP_TYPE_ACK, addr, port, notification); + simple_reply(COAP_TYPE_ACK, endpoint, notification); } if(obs->notification_callback != NULL) { flag = classify_notification(notification, 0); @@ -275,7 +250,7 @@ coap_handle_notification(uip_ipaddr_t *addr, uint16_t port, } /*----------------------------------------------------------------------------*/ static void -handle_obs_registration_response(void *data, void *response) +handle_obs_registration_response(void *data, coap_packet_t *response) { coap_observee_t *obs; notification_callback_t notification_callback; @@ -305,7 +280,7 @@ coap_generate_token(uint8_t **token_ptr) } /*----------------------------------------------------------------------------*/ coap_observee_t * -coap_obs_request_registration(uip_ipaddr_t *addr, uint16_t port, char *uri, +coap_obs_request_registration(const coap_endpoint_t *endpoint, char *uri, notification_callback_t notification_callback, void *data) { @@ -321,9 +296,9 @@ coap_obs_request_registration(uip_ipaddr_t *addr, uint16_t port, char *uri, coap_set_header_observe(request, 0); token_len = coap_generate_token(&token); set_token(request, token, token_len); - t = coap_new_transaction(request->mid, addr, port); + t = coap_new_transaction(request->mid, endpoint); if(t) { - obs = coap_obs_add_observee(addr, port, (uint8_t *)token, token_len, uri, + obs = coap_obs_add_observee(endpoint, (uint8_t *)token, token_len, uri, notification_callback, data); if(obs) { t->callback = handle_obs_registration_response; diff --git a/os/net/app-layer/coap/coap-observe-client.h b/os/net/app-layer/coap/coap-observe-client.h index c0ea0c5a2..adbc859a4 100644 --- a/os/net/app-layer/coap/coap-observe-client.h +++ b/os/net/app-layer/coap/coap-observe-client.h @@ -79,8 +79,7 @@ typedef void (*notification_callback_t)(coap_observee_t *subject, struct coap_observee_s { coap_observee_t *next; /* for LIST */ - uip_ipaddr_t addr; - uint16_t port; + coap_endpoint_t endpoint; const char *url; uint8_t token_len; uint8_t token[COAP_TOKEN_LEN]; @@ -90,7 +89,7 @@ struct coap_observee_s { }; /*----------------------------------------------------------------------------*/ -coap_observee_t *coap_obs_add_observee(uip_ipaddr_t *addr, uint16_t port, +coap_observee_t *coap_obs_add_observee(const coap_endpoint_t *endpoint, const uint8_t *token, size_t token_len, const char *url, notification_callback_t @@ -101,17 +100,17 @@ void coap_obs_remove_observee(coap_observee_t *o); coap_observee_t *coap_obs_get_observee_by_token(const uint8_t *token, size_t token_len); -int coap_obs_remove_observee_by_token(uip_ipaddr_t *addr, uint16_t port, +int coap_obs_remove_observee_by_token(const coap_endpoint_t *endpoint, uint8_t *token, size_t token_len); -int coap_obs_remove_observee_by_url(uip_ipaddr_t *addr, uint16_t port, +int coap_obs_remove_observee_by_url(const coap_endpoint_t *endpoint, const char *url); -void coap_handle_notification(uip_ipaddr_t *addr, uint16_t port, +void coap_handle_notification(const coap_endpoint_t *endpoint, coap_packet_t *notification); -coap_observee_t *coap_obs_request_registration(uip_ipaddr_t *addr, - uint16_t port, char *uri, +coap_observee_t *coap_obs_request_registration(const coap_endpoint_t *endpoint, + char *uri, notification_callback_t notification_callback, void *data); diff --git a/os/net/app-layer/coap/coap-observe.c b/os/net/app-layer/coap/coap-observe.c index 2237e4e25..791f8929b 100644 --- a/os/net/app-layer/coap/coap-observe.c +++ b/os/net/app-layer/coap/coap-observe.c @@ -39,17 +39,18 @@ #include #include #include "coap-observe.h" +#include "coap-engine.h" +#include "lib/memb.h" +#include "lib/list.h" #define DEBUG 0 #if DEBUG #include #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]) +#define PRINTEP(ep) coap_endpoint_print(ep) #else #define PRINTF(...) -#define PRINT6ADDR(addr) -#define PRINTLLADDR(addr) +#define PRINTEP(ep) #endif /*---------------------------------------------------------------------------*/ @@ -59,11 +60,11 @@ LIST(observers_list); /*- Internal API ------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ static coap_observer_t * -add_observer(uip_ipaddr_t *addr, uint16_t port, const uint8_t *token, +add_observer(const coap_endpoint_t *endpoint, const uint8_t *token, size_t token_len, const char *uri, int uri_len) { /* Remove existing observe relationship, if any. */ - coap_remove_observer_by_uri(addr, port, uri); + coap_remove_observer_by_uri(endpoint, uri); coap_observer_t *o = memb_alloc(&observers_memb); @@ -74,8 +75,7 @@ add_observer(uip_ipaddr_t *addr, uint16_t port, const uint8_t *token, } memcpy(o->url, uri, max); o->url[max] = 0; - uip_ipaddr_copy(&o->addr, addr); - o->port = port; + coap_endpoint_copy(&o->endpoint, endpoint); o->token_len = token_len; memcpy(o->token, token, token_len); o->last_mid = 0; @@ -102,17 +102,17 @@ coap_remove_observer(coap_observer_t *o) } /*---------------------------------------------------------------------------*/ int -coap_remove_observer_by_client(uip_ipaddr_t *addr, uint16_t port) +coap_remove_observer_by_client(const coap_endpoint_t *endpoint) { int removed = 0; coap_observer_t *obs = NULL; + PRINTF("Remove check client "); + PRINTEP(endpoint); + PRINTF("\n"); for(obs = (coap_observer_t *)list_head(observers_list); obs; obs = obs->next) { - PRINTF("Remove check client "); - PRINT6ADDR(addr); - PRINTF(":%u\n", port); - if(uip_ipaddr_cmp(&obs->addr, addr) && obs->port == port) { + if(coap_endpoint_cmp(&obs->endpoint, endpoint)) { coap_remove_observer(obs); removed++; } @@ -121,7 +121,7 @@ coap_remove_observer_by_client(uip_ipaddr_t *addr, uint16_t port) } /*---------------------------------------------------------------------------*/ int -coap_remove_observer_by_token(uip_ipaddr_t *addr, uint16_t port, +coap_remove_observer_by_token(const coap_endpoint_t *endpoint, uint8_t *token, size_t token_len) { int removed = 0; @@ -130,7 +130,7 @@ coap_remove_observer_by_token(uip_ipaddr_t *addr, uint16_t port, for(obs = (coap_observer_t *)list_head(observers_list); obs; obs = obs->next) { PRINTF("Remove check Token 0x%02X%02X\n", token[0], token[1]); - if(uip_ipaddr_cmp(&obs->addr, addr) && obs->port == port + if(coap_endpoint_cmp(&obs->endpoint, endpoint) && obs->token_len == token_len && memcmp(obs->token, token, token_len) == 0) { coap_remove_observer(obs); @@ -141,7 +141,7 @@ coap_remove_observer_by_token(uip_ipaddr_t *addr, uint16_t port, } /*---------------------------------------------------------------------------*/ int -coap_remove_observer_by_uri(uip_ipaddr_t *addr, uint16_t port, +coap_remove_observer_by_uri(const coap_endpoint_t *endpoint, const char *uri) { int removed = 0; @@ -150,8 +150,8 @@ coap_remove_observer_by_uri(uip_ipaddr_t *addr, uint16_t port, for(obs = (coap_observer_t *)list_head(observers_list); obs; obs = obs->next) { PRINTF("Remove check URL %p\n", uri); - if((addr == NULL - || (uip_ipaddr_cmp(&obs->addr, addr) && obs->port == port)) + if((endpoint == NULL + || (coap_endpoint_cmp(&obs->endpoint, endpoint))) && (obs->url == uri || memcmp(obs->url, uri, strlen(obs->url)) == 0)) { coap_remove_observer(obs); removed++; @@ -161,7 +161,7 @@ coap_remove_observer_by_uri(uip_ipaddr_t *addr, uint16_t port, } /*---------------------------------------------------------------------------*/ int -coap_remove_observer_by_mid(uip_ipaddr_t *addr, uint16_t port, uint16_t mid) +coap_remove_observer_by_mid(const coap_endpoint_t *endpoint, uint16_t mid) { int removed = 0; coap_observer_t *obs = NULL; @@ -169,7 +169,7 @@ coap_remove_observer_by_mid(uip_ipaddr_t *addr, uint16_t port, uint16_t mid) for(obs = (coap_observer_t *)list_head(observers_list); obs; obs = obs->next) { PRINTF("Remove check MID %u\n", mid); - if(uip_ipaddr_cmp(&obs->addr, addr) && obs->port == port + if(coap_endpoint_cmp(&obs->endpoint, endpoint) && obs->last_mid == mid) { coap_remove_observer(obs); removed++; @@ -181,12 +181,14 @@ coap_remove_observer_by_mid(uip_ipaddr_t *addr, uint16_t port, uint16_t mid) /*- Notification ------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ void -coap_notify_observers(resource_t *resource) +coap_notify_observers(coap_resource_t *resource) { coap_notify_observers_sub(resource, NULL); } +/* Can be used either for sub - or when there is not resource - just + a handler */ void -coap_notify_observers_sub(resource_t *resource, const char *subpath) +coap_notify_observers_sub(coap_resource_t *resource, const char *subpath) { /* build notification */ coap_packet_t notification[1]; /* this way the packet can be treated as pointer as usual */ @@ -194,12 +196,21 @@ coap_notify_observers_sub(resource_t *resource, const char *subpath) coap_observer_t *obs = NULL; int url_len, obs_url_len; char url[COAP_OBSERVER_URL_LEN]; + uint8_t sub_ok = 0; - url_len = strlen(resource->url); - strncpy(url, resource->url, COAP_OBSERVER_URL_LEN - 1); - if(url_len < COAP_OBSERVER_URL_LEN - 1 && subpath != NULL) { - strncpy(&url[url_len], subpath, COAP_OBSERVER_URL_LEN - url_len - 1); + if(resource != NULL) { + url_len = strlen(resource->url); + strncpy(url, resource->url, COAP_OBSERVER_URL_LEN - 1); + if(url_len < COAP_OBSERVER_URL_LEN - 1 && subpath != NULL) { + strncpy(&url[url_len], subpath, COAP_OBSERVER_URL_LEN - url_len - 1); + } + } else if(subpath != NULL) { + strncpy(url, subpath, COAP_OBSERVER_URL_LEN - 1); + } else { + /* No resource, no subpath */ + return; } + /* Ensure url is null terminated because strncpy does not guarantee this */ url[COAP_OBSERVER_URL_LEN - 1] = '\0'; /* url now contains the notify URL that needs to match the observer */ @@ -212,30 +223,35 @@ coap_notify_observers_sub(resource_t *resource, const char *subpath) /* iterate over observers */ url_len = strlen(url); + /* Assumes lazy evaluation... */ + sub_ok = (resource == NULL) || (resource->flags & HAS_SUB_RESOURCES); for(obs = (coap_observer_t *)list_head(observers_list); obs; obs = obs->next) { obs_url_len = strlen(obs->url); /* Do a match based on the parent/sub-resource match so that it is possible to do parent-node observe */ + + /***** TODO fix here so that we handle the notofication correctly ******/ + /* All the new-style ... is assuming that the URL might be within */ if((obs_url_len == url_len || (obs_url_len > url_len - && (resource->flags & HAS_SUB_RESOURCES) + && sub_ok && obs->url[url_len] == '/')) && strncmp(url, obs->url, url_len) == 0) { coap_transaction_t *transaction = NULL; /*TODO implement special transaction for CON, sharing the same buffer to allow for more observers */ - if((transaction = coap_new_transaction(coap_get_mid(), &obs->addr, obs->port))) { + if((transaction = coap_new_transaction(coap_get_mid(), &obs->endpoint))) { if(obs->obs_counter % COAP_OBSERVE_REFRESH_INTERVAL == 0) { PRINTF(" Force Confirmable for\n"); notification->type = COAP_TYPE_CON; } PRINTF(" Observer "); - PRINT6ADDR(&obs->addr); - PRINTF(":%u\n", obs->port); + PRINTEP(&obs->endpoint); + PRINTF("\n"); /* update last MID for RST matching */ obs->last_mid = transaction->mid; @@ -243,9 +259,21 @@ coap_notify_observers_sub(resource_t *resource, const char *subpath) /* prepare response */ notification->mid = transaction->mid; - resource->get_handler(request, notification, - transaction->packet + COAP_MAX_HEADER_SIZE, - REST_MAX_CHUNK_SIZE, NULL); + /* Either old style get_handler or the full handler */ + if(coap_call_handlers(request, notification, transaction->packet + + COAP_MAX_HEADER_SIZE, COAP_MAX_CHUNK_SIZE, + NULL) > 0) { + PRINTF("Notification on new handlers\n"); + } else { + if(resource != NULL) { + resource->get_handler(request, notification, + transaction->packet + COAP_MAX_HEADER_SIZE, + COAP_MAX_CHUNK_SIZE, NULL); + } else { + /* What to do here? */ + notification->code = BAD_REQUEST_4_00; + } + } if(notification->code < BAD_REQUEST_4_00) { coap_set_header_observe(notification, (obs->obs_counter)++); @@ -264,16 +292,21 @@ coap_notify_observers_sub(resource_t *resource, const char *subpath) } /*---------------------------------------------------------------------------*/ void -coap_observe_handler(resource_t *resource, void *request, void *response) +coap_observe_handler(coap_resource_t *resource, coap_packet_t *coap_req, + coap_packet_t *coap_res) { - coap_packet_t *const coap_req = (coap_packet_t *)request; - coap_packet_t *const coap_res = (coap_packet_t *)response; + const coap_endpoint_t *src_ep; coap_observer_t *obs; + PRINTF("CoAP observer handler rsc: %d\n", resource != NULL); + if(coap_req->code == COAP_GET && coap_res->code < 128) { /* GET request and response without error code */ - if(IS_OPTION(coap_req, COAP_OPTION_OBSERVE)) { - if(coap_req->observe == 0) { - obs = add_observer(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport, + if(coap_is_option(coap_req, COAP_OPTION_OBSERVE)) { + src_ep = coap_get_src_endpoint(coap_req); + if(src_ep == NULL) { + /* No source endpoint, can not add */ + } else if(coap_req->observe == 0) { + obs = add_observer(src_ep, coap_req->token, coap_req->token_len, coap_req->uri_path, coap_req->uri_path_len); if(obs) { @@ -300,9 +333,8 @@ coap_observe_handler(resource_t *resource, void *request, void *response) } else if(coap_req->observe == 1) { /* remove client if it is currently observe */ - coap_remove_observer_by_token(&UIP_IP_BUF->srcipaddr, - UIP_UDP_BUF->srcport, coap_req->token, - coap_req->token_len); + coap_remove_observer_by_token(src_ep, + coap_req->token, coap_req->token_len); } } } diff --git a/os/net/app-layer/coap/coap-observe.h b/os/net/app-layer/coap/coap-observe.h index 7ff2bb502..e6138426f 100644 --- a/os/net/app-layer/coap/coap-observe.h +++ b/os/net/app-layer/coap/coap-observe.h @@ -41,48 +41,38 @@ #include "coap.h" #include "coap-transactions.h" -#include "stimer.h" +#include "coap-engine.h" #define COAP_OBSERVER_URL_LEN 20 -typedef struct coap_observable { - uint32_t observe_clock; - struct stimer orphan_timer; - list_t observers; - coap_packet_t notification; - uint8_t buffer[COAP_MAX_PACKET_SIZE + 1]; -} coap_observable_t; - typedef struct coap_observer { struct coap_observer *next; /* for LIST */ char url[COAP_OBSERVER_URL_LEN]; - uip_ipaddr_t addr; - uint16_t port; + coap_endpoint_t endpoint; uint8_t token_len; uint8_t token[COAP_TOKEN_LEN]; uint16_t last_mid; int32_t obs_counter; - struct etimer retrans_timer; + coap_timer_t retrans_timer; uint8_t retrans_counter; } coap_observer_t; -list_t coap_get_observers(void); void coap_remove_observer(coap_observer_t *o); -int coap_remove_observer_by_client(uip_ipaddr_t *addr, uint16_t port); -int coap_remove_observer_by_token(uip_ipaddr_t *addr, uint16_t port, +int coap_remove_observer_by_client(const coap_endpoint_t *ep); +int coap_remove_observer_by_token(const coap_endpoint_t *ep, uint8_t *token, size_t token_len); -int coap_remove_observer_by_uri(uip_ipaddr_t *addr, uint16_t port, +int coap_remove_observer_by_uri(const coap_endpoint_t *ep, const char *uri); -int coap_remove_observer_by_mid(uip_ipaddr_t *addr, uint16_t port, +int coap_remove_observer_by_mid(const coap_endpoint_t *ep, uint16_t mid); -void coap_notify_observers(resource_t *resource); -void coap_notify_observers_sub(resource_t *resource, const char *subpath); +void coap_notify_observers(coap_resource_t *resource); +void coap_notify_observers_sub(coap_resource_t *resource, const char *subpath); -void coap_observe_handler(resource_t *resource, void *request, - void *response); +void coap_observe_handler(coap_resource_t *resource, coap_packet_t *request, + coap_packet_t *response); #endif /* COAP_OBSERVE_H_ */ diff --git a/os/net/app-layer/coap/coap-res-well-known-core.c b/os/net/app-layer/coap/coap-res-well-known-core.c index 117e362ab..80577b6a6 100644 --- a/os/net/app-layer/coap/coap-res-well-known-core.c +++ b/os/net/app-layer/coap/coap-res-well-known-core.c @@ -36,19 +36,16 @@ * Matthias Kovatsch */ -#include #include "coap-engine.h" +#include +#include #define DEBUG 0 #if DEBUG #include #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 #define ADD_CHAR_IF_POSSIBLE(char) \ @@ -76,14 +73,15 @@ /*---------------------------------------------------------------------------*/ /*- Resource Handlers -------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ -void -well_known_core_get_handler(void *request, void *response, uint8_t *buffer, - uint16_t preferred_size, int32_t *offset) +static void +well_known_core_get_handler(coap_packet_t *request, coap_packet_t *response, + uint8_t *buffer, uint16_t preferred_size, + int32_t *offset) { size_t strpos = 0; /* position in overall string (which is larger than the buffer) */ size_t bufpos = 0; /* position within buffer (bytes written) */ size_t tmplen = 0; - resource_t *resource = NULL; + coap_resource_t *resource = NULL; #if COAP_LINK_FORMAT_FILTERING /* For filtering. */ @@ -113,8 +111,8 @@ well_known_core_get_handler(void *request, void *response, uint8_t *buffer, } #endif - for(resource = (resource_t *)list_head(rest_get_resources()); resource; - resource = resource->next) { + for(resource = coap_get_first_resource(); resource; + resource = coap_get_next_resource(resource)) { #if COAP_LINK_FORMAT_FILTERING /* Filtering */ if(len) { diff --git a/os/net/app-layer/coap/coap-separate.c b/os/net/app-layer/coap/coap-separate.c index 03f95c411..45793f505 100644 --- a/os/net/app-layer/coap/coap-separate.c +++ b/os/net/app-layer/coap/coap-separate.c @@ -36,22 +36,18 @@ * Matthias Kovatsch */ -#include "sys/cc.h" -#include -#include +#include "coap.h" #include "coap-separate.h" #include "coap-transactions.h" +#include "sys/cc.h" +#include #define DEBUG 0 #if DEBUG #include #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 /*---------------------------------------------------------------------------*/ @@ -69,7 +65,7 @@ void coap_separate_reject() { /* TODO: Accept string pointer for custom error message */ - erbium_status_code = SERVICE_UNAVAILABLE_5_03; + coap_status_code = SERVICE_UNAVAILABLE_5_03; coap_error_message = "AlreadyInUse"; } /*----------------------------------------------------------------------------*/ @@ -85,29 +81,32 @@ coap_separate_reject() * then retry later. */ void -coap_separate_accept(void *request, coap_separate_t *separate_store) +coap_separate_accept(coap_packet_t *coap_req, coap_separate_t *separate_store) { - coap_packet_t *const coap_req = (coap_packet_t *)request; coap_transaction_t *const t = coap_get_transaction_by_mid(coap_req->mid); - PRINTF("Separate ACCEPT: /%.*s MID %u\n", coap_req->uri_path_len, + PRINTF("Separate ACCEPT: /%.*s MID %u\n", (int)coap_req->uri_path_len, coap_req->uri_path, coap_req->mid); if(t) { /* send separate ACK for CON */ if(coap_req->type == COAP_TYPE_CON) { coap_packet_t ack[1]; + const coap_endpoint_t *ep; - /* ACK with empty code (0) */ - coap_init_message(ack, COAP_TYPE_ACK, 0, coap_req->mid); - /* serializing into IPBUF: Only overwrites header parts that are already parsed into the request struct */ - coap_send_message(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport, - (uip_appdata), coap_serialize_message(ack, - uip_appdata)); + ep = coap_get_src_endpoint(coap_req); + if(ep == NULL) { + PRINTF("ERROR: no endpoint in request\n"); + } else { + /* ACK with empty code (0) */ + coap_init_message(ack, COAP_TYPE_ACK, 0, coap_req->mid); + /* serializing into IPBUF: Only overwrites header parts that are already parsed into the request struct */ + coap_send_message(ep, coap_databuf(), + coap_serialize_message(ack, coap_databuf())); + } } - /* store remote address */ - uip_ipaddr_copy(&separate_store->addr, &t->addr); - separate_store->port = t->port; + /* store remote endpoint address */ + coap_endpoint_copy(&separate_store->endpoint, &t->endpoint); /* store correct response type */ separate_store->type = @@ -124,15 +123,15 @@ coap_separate_accept(void *request, coap_separate_t *separate_store) 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; + coap_status_code = MANUAL_RESPONSE; } else { PRINTF("ERROR: Response transaction for separate request not found!\n"); - erbium_status_code = INTERNAL_SERVER_ERROR_5_00; + coap_status_code = INTERNAL_SERVER_ERROR_5_00; } } /*----------------------------------------------------------------------------*/ void -coap_separate_resume(void *response, coap_separate_t *separate_store, +coap_separate_resume(coap_packet_t *response, coap_separate_t *separate_store, uint8_t code) { coap_init_message(response, separate_store->type, code, diff --git a/os/net/app-layer/coap/coap-separate.h b/os/net/app-layer/coap/coap-separate.h index 1a89ed434..c8b36de48 100644 --- a/os/net/app-layer/coap/coap-separate.h +++ b/os/net/app-layer/coap/coap-separate.h @@ -40,11 +40,11 @@ #define COAP_SEPARATE_H_ #include "coap.h" +#include "coap-engine.h" typedef struct coap_separate { - uip_ipaddr_t addr; - uint16_t port; + coap_endpoint_t endpoint; coap_message_type_t type; uint16_t mid; @@ -59,11 +59,13 @@ typedef struct coap_separate { uint16_t block2_size; } coap_separate_t; -int coap_separate_handler(resource_t *resource, void *request, - void *response); +int coap_separate_handler(coap_resource_t *resource, coap_packet_t *request, + coap_packet_t *response); void coap_separate_reject(void); -void coap_separate_accept(void *request, coap_separate_t *separate_store); -void coap_separate_resume(void *response, coap_separate_t *separate_store, +void coap_separate_accept(coap_packet_t *request, + coap_separate_t *separate_store); +void coap_separate_resume(coap_packet_t *response, + coap_separate_t *separate_store, uint8_t code); #endif /* COAP_SEPARATE_H_ */ diff --git a/os/net/app-layer/coap/coap-timer-default.c b/os/net/app-layer/coap/coap-timer-default.c new file mode 100644 index 000000000..707d6367d --- /dev/null +++ b/os/net/app-layer/coap/coap-timer-default.c @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2016, SICS, Swedish ICT AB. + * 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. + */ + +/** + * \file + * CoAP timer driver implementation based on Contiki etimers + * \author + * Niclas Finne + * Joakim Eriksson + */ + +#include "coap-timer.h" +#include "sys/clock.h" +#include "sys/etimer.h" +#include "sys/process.h" + +#define DEBUG 0 +#if DEBUG +#include +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif + +PROCESS(coap_timer_process, "coap timer process"); + +static uint64_t current_time; +static struct etimer timer; +/*---------------------------------------------------------------------------*/ +static void +update_timer(void) +{ + uint64_t remaining; + remaining = coap_timer_time_to_next_expiration(); + PRINTF("coap-timer-default: remaining %lu msec\n", (unsigned long)remaining); + if(remaining == 0) { + /* Run as soon as possible */ + process_poll(&coap_timer_process); + } else { + remaining *= CLOCK_SECOND; + remaining /= 1000; + if(remaining > CLOCK_SECOND * 60) { + /* Make sure the CoAP timer clock is updated at least once per minute */ + remaining = CLOCK_SECOND * 60; + } else if(remaining < 1) { + /* Wait minimum one system clock tick */ + remaining = 1; + } + etimer_set(&timer, (clock_time_t)remaining); + } +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(coap_timer_process, ev, data) +{ + PROCESS_BEGIN(); + + etimer_set(&timer, CLOCK_SECOND); + while(1) { + PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_TIMER || + ev == PROCESS_EVENT_POLL); + + if(coap_timer_run()) { + /* Needs to run again */ + process_poll(&coap_timer_process); + } else { + update_timer(); + } + } + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +static uint64_t +uptime(void) +{ + static clock_time_t last; + clock_time_t now; + uint64_t diff; + + now = clock_time(); + diff = (clock_time_t)(now - last); + if(diff > 0) { + current_time += (diff * 1000) / CLOCK_SECOND; + last = now; + } + return current_time; +} +/*---------------------------------------------------------------------------*/ +static void +init(void) +{ + process_start(&coap_timer_process, NULL); +} +/*---------------------------------------------------------------------------*/ +static void +update(void) +{ + process_poll(&coap_timer_process); +} +/*---------------------------------------------------------------------------*/ +const coap_timer_driver_t coap_timer_default_driver = { + .init = init, + .uptime = uptime, + .update = update, +}; +/*---------------------------------------------------------------------------*/ diff --git a/os/net/app-layer/coap/coap-timer.c b/os/net/app-layer/coap/coap-timer.c new file mode 100644 index 000000000..6e2b15616 --- /dev/null +++ b/os/net/app-layer/coap/coap-timer.c @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2016, SICS, Swedish ICT AB. + * 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. + */ + +/** + * \file + * CoAP timer implementation. + * \author + * Niclas Finne + * Joakim Eriksson + */ + +#include "coap-timer.h" +#include "lib/list.h" + +#define DEBUG 0 +#if DEBUG +#include +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif + +#ifndef NULL +#define NULL 0 +#endif + +LIST(timer_list); +static uint8_t is_initialized; +/*---------------------------------------------------------------------------*/ +static void +add_timer(coap_timer_t *timer) +{ + coap_timer_t *n, *l, *p; + + if(!is_initialized) { + /* The coap_timer system has not yet been initialized */ + coap_timer_init(); + } + + PRINTF("coap-timer: adding timer %p at %lu\n", timer, + (unsigned long)timer->expiration_time); + + p = list_head(timer_list); + + /* Make sure the timer is not already added to the timer list */ + list_remove(timer_list, timer); + + for(l = NULL, n = list_head(timer_list); n != NULL; l = n, n = n->next) { + if(timer->expiration_time < n->expiration_time) { + list_insert(timer_list, l, timer); + timer = NULL; + break; + } + } + + if(timer != NULL) { + list_insert(timer_list, l, timer); + } + + if(p != list_head(timer_list)) { + /* The next timer to expire has changed so we need to notify the driver */ + COAP_TIMER_DRIVER.update(); + } +} +/*---------------------------------------------------------------------------*/ +void +coap_timer_stop(coap_timer_t *timer) +{ + PRINTF("coap-timer: stopping timer %p\n", timer); + + /* Mark timer as expired right now */ + timer->expiration_time = coap_timer_uptime(); + + list_remove(timer_list, timer); +} +/*---------------------------------------------------------------------------*/ +void +coap_timer_set(coap_timer_t *timer, uint64_t time) +{ + timer->expiration_time = coap_timer_uptime() + time; + add_timer(timer); +} +/*---------------------------------------------------------------------------*/ +void +coap_timer_reset(coap_timer_t *timer, uint64_t time) +{ + timer->expiration_time += time; + add_timer(timer); +} +/*---------------------------------------------------------------------------*/ +uint64_t +coap_timer_time_to_next_expiration(void) +{ + uint64_t now; + coap_timer_t *next; + + next = list_head(timer_list); + if(next == NULL) { + /* No pending timers - return a time in the future */ + return 60000; + } + + now = coap_timer_uptime(); + if(now < next->expiration_time) { + return next->expiration_time - now; + } + /* The next timer should already have expired */ + return 0; +} +/*---------------------------------------------------------------------------*/ +int +coap_timer_run(void) +{ + uint64_t now; + coap_timer_t *next; + + /* Always get the current time because it might trigger clock updates */ + now = coap_timer_uptime(); + + next = list_head(timer_list); + if(next == NULL) { + /* No pending timers */ + return 0; + } + + if(next->expiration_time <= now) { + PRINTF("coap-timer: timer %p expired at %lu\n", next, + (unsigned long)now); + + /* This timer should expire now */ + list_remove(timer_list, next); + + if(next->callback) { + next->callback(next); + } + + /* The next timer has changed */ + COAP_TIMER_DRIVER.update(); + + /* Check if there is another pending timer */ + next = list_head(timer_list); + if(next != NULL && next->expiration_time <= coap_timer_uptime()) { + /* Need to run again */ + return 1; + } + } + + return 0; +} +/*---------------------------------------------------------------------------*/ +void +coap_timer_init(void) +{ + if(is_initialized) { + return; + } + is_initialized = 1; + list_init(timer_list); + if(COAP_TIMER_DRIVER.init) { + COAP_TIMER_DRIVER.init(); + } +} +/*---------------------------------------------------------------------------*/ diff --git a/os/net/app-layer/coap/coap-timer.h b/os/net/app-layer/coap/coap-timer.h new file mode 100644 index 000000000..a0aec4b16 --- /dev/null +++ b/os/net/app-layer/coap/coap-timer.h @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2016, SICS, Swedish ICT AB. + * 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. + */ + +/** + * \file + * CoAP timer API. + * \author + * Niclas Finne + * Joakim Eriksson + */ + +#ifndef COAP_TIMER_H_ +#define COAP_TIMER_H_ + +#include "contiki.h" +#include + +typedef struct coap_timer coap_timer_t; +struct coap_timer { + coap_timer_t *next; + void (* callback)(coap_timer_t *); + void *user_data; + uint64_t expiration_time; +}; + +typedef struct { + void (* init)(void); + uint64_t (* uptime)(void); + void (* update)(void); +} coap_timer_driver_t; + +#ifndef COAP_TIMER_DRIVER +#ifdef COAP_TIMER_CONF_DRIVER +#define COAP_TIMER_DRIVER COAP_TIMER_CONF_DRIVER +#else /* COAP_TIMER_CONF_DRIVER */ +#define COAP_TIMER_DRIVER coap_timer_default_driver +#endif /* COAP_TIMER_CONF_DRIVER */ +#endif /* COAP_TIMER_DRIVER */ + +extern const coap_timer_driver_t COAP_TIMER_DRIVER; + +/* + * milliseconds since boot + */ +static inline uint64_t +coap_timer_uptime(void) +{ + return COAP_TIMER_DRIVER.uptime(); +} + +/* + * seconds since boot + */ +static inline uint32_t +coap_timer_seconds(void) +{ + return (uint32_t)(COAP_TIMER_DRIVER.uptime() / 1000); +} + +static inline void +coap_timer_set_callback(coap_timer_t *timer, void (* callback)(coap_timer_t *)) +{ + timer->callback = callback; +} + +static inline void * +coap_timer_get_user_data(coap_timer_t *timer) +{ + return timer->user_data; +} + +static inline void +coap_timer_set_user_data(coap_timer_t *timer, void *data) +{ + timer->user_data = data; +} + +static inline int +coap_timer_expired(const coap_timer_t *timer) +{ + return timer->expiration_time <= coap_timer_uptime(); +} + +void coap_timer_stop(coap_timer_t *timer); + +void coap_timer_set(coap_timer_t *timer, uint64_t time); + +/** + * Set the CoAP timer to expire the specified time after the previous + * expiration time. If the new expiration time has already passed, the + * timer will expire as soon as possible. + * + * If the timer has not yet expired when this function is called, the + * time until the timer expires will be extended by the specified time. + */ +void coap_timer_reset(coap_timer_t *timer, uint64_t time); + +/** + * Returns the time until next timer expires or 0 if there already + * exists expired timers that have not yet been processed. + * Returns a time in the future if there are no timers pending. + */ +uint64_t coap_timer_time_to_next_expiration(void); + +/** + * Must be called periodically to process any expired CoAP timers. + * Returns non-zero if it needs to run again to process more timers. + */ +int coap_timer_run(void); + +void coap_timer_init(void); + +#endif /* COAP_TIMER_H_ */ diff --git a/os/net/app-layer/coap/coap-transactions.c b/os/net/app-layer/coap/coap-transactions.c index 613557f4d..60f4f7f72 100644 --- a/os/net/app-layer/coap/coap-transactions.c +++ b/os/net/app-layer/coap/coap-transactions.c @@ -36,39 +36,47 @@ * Matthias Kovatsch */ -#include "contiki.h" -#include "contiki-net.h" #include "coap-transactions.h" #include "coap-observe.h" +#include "coap-timer.h" +#include "lib/memb.h" +#include "lib/list.h" +#include #define DEBUG 0 #if DEBUG #include #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]) +#define PRINTEP(ep) coap_endpoint_print(ep) #else #define PRINTF(...) -#define PRINT6ADDR(addr) -#define PRINTLLADDR(addr) +#define PRINTEP(ep) #endif /*---------------------------------------------------------------------------*/ MEMB(transactions_memb, coap_transaction_t, COAP_MAX_OPEN_TRANSACTIONS); LIST(transactions_list); -static struct process *transaction_handler_process = NULL; +/*---------------------------------------------------------------------------*/ +static void +coap_retransmit_transaction(coap_timer_t *nt) +{ + coap_transaction_t *t = coap_timer_get_user_data(nt); + if(t == NULL) { + PRINTF("No retransmission data in coap_timer!\n"); + return; + } + ++(t->retrans_counter); + PRINTF("Retransmitting %u (%u)\n", t->mid, t->retrans_counter); + coap_send_transaction(t); +} +/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /*- Internal API ------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ -void -coap_register_as_transaction_handler() -{ - transaction_handler_process = PROCESS_CURRENT(); -} coap_transaction_t * -coap_new_transaction(uint16_t mid, uip_ipaddr_t *addr, uint16_t port) +coap_new_transaction(uint16_t mid, const coap_endpoint_t *endpoint) { coap_transaction_t *t = memb_alloc(&transactions_memb); @@ -77,8 +85,7 @@ coap_new_transaction(uint16_t mid, uip_ipaddr_t *addr, uint16_t port) t->retrans_counter = 0; /* save client address */ - uip_ipaddr_copy(&t->addr, addr); - t->port = port; + coap_endpoint_copy(&t->endpoint, endpoint); list_add(transactions_list, t); /* list itself makes sure same element is not added twice */ } @@ -91,7 +98,7 @@ coap_send_transaction(coap_transaction_t *t) { PRINTF("Sending transaction %u\n", t->mid); - coap_send_message(&t->addr, t->port, t->packet, t->packet_len); + coap_send_message(&t->endpoint, t->packet, t->packet_len); if(COAP_TYPE_CON == ((COAP_HEADER_TYPE_MASK & t->packet[0]) >> COAP_HEADER_TYPE_POSITION)) { @@ -100,32 +107,29 @@ coap_send_transaction(coap_transaction_t *t) PRINTF("Keeping transaction %u\n", t->mid); if(t->retrans_counter == 0) { - t->retrans_timer.timer.interval = - COAP_RESPONSE_TIMEOUT_TICKS + (random_rand() - % - (clock_time_t) + coap_timer_set_callback(&t->retrans_timer, coap_retransmit_transaction); + coap_timer_set_user_data(&t->retrans_timer, t); + t->retrans_interval = + COAP_RESPONSE_TIMEOUT_TICKS + (rand() % COAP_RESPONSE_TIMEOUT_BACKOFF_MASK); - PRINTF("Initial interval %f\n", - (float)t->retrans_timer.timer.interval / CLOCK_SECOND); + PRINTF("Initial interval %lu msec\n", + (unsigned long)t->retrans_interval); } else { - t->retrans_timer.timer.interval <<= 1; /* double */ - PRINTF("Doubled (%u) interval %f\n", t->retrans_counter, - (float)t->retrans_timer.timer.interval / CLOCK_SECOND); + t->retrans_interval <<= 1; /* double */ + PRINTF("Doubled (%u) interval %d s\n", t->retrans_counter, + t->retrans_interval / 1000); } - PROCESS_CONTEXT_BEGIN(transaction_handler_process); - etimer_restart(&t->retrans_timer); /* interval updated above */ - PROCESS_CONTEXT_END(transaction_handler_process); - - t = NULL; + /* interval updated above */ + coap_timer_set(&t->retrans_timer, t->retrans_interval); } else { /* timed out */ PRINTF("Timeout\n"); - restful_response_handler callback = t->callback; + coap_resource_response_handler_t callback = t->callback; void *callback_data = t->callback_data; /* handle observers */ - coap_remove_observer_by_client(&t->addr, t->port); + coap_remove_observer_by_client(&t->endpoint); coap_clear_transaction(t); @@ -144,11 +148,12 @@ coap_clear_transaction(coap_transaction_t *t) if(t) { PRINTF("Freeing transaction %u: %p\n", t->mid, t); - etimer_stop(&t->retrans_timer); + coap_timer_stop(&t->retrans_timer); list_remove(transactions_list, t); memb_free(&transactions_memb, t); } } +/*---------------------------------------------------------------------------*/ coap_transaction_t * coap_get_transaction_by_mid(uint16_t mid) { @@ -163,17 +168,3 @@ coap_get_transaction_by_mid(uint16_t mid) return NULL; } /*---------------------------------------------------------------------------*/ -void -coap_check_transactions() -{ - coap_transaction_t *t = NULL; - - for(t = (coap_transaction_t *)list_head(transactions_list); t; t = t->next) { - if(etimer_expired(&t->retrans_timer)) { - ++(t->retrans_counter); - PRINTF("Retransmitting %u (%u)\n", t->mid, t->retrans_counter); - coap_send_transaction(t); - } - } -} -/*---------------------------------------------------------------------------*/ diff --git a/os/net/app-layer/coap/coap-transactions.h b/os/net/app-layer/coap/coap-transactions.h index 49e35c0f2..0e054ce6c 100644 --- a/os/net/app-layer/coap/coap-transactions.h +++ b/os/net/app-layer/coap/coap-transactions.h @@ -40,26 +40,28 @@ #define COAP_TRANSACTIONS_H_ #include "coap.h" +#include "coap-engine.h" +#include "coap-timer.h" /* * Modulo mask (thus +1) for a random number to get the tick number for the random * retransmission time between COAP_RESPONSE_TIMEOUT and COAP_RESPONSE_TIMEOUT*COAP_RESPONSE_RANDOM_FACTOR. */ -#define COAP_RESPONSE_TIMEOUT_TICKS (CLOCK_SECOND * COAP_RESPONSE_TIMEOUT) -#define COAP_RESPONSE_TIMEOUT_BACKOFF_MASK (long)((CLOCK_SECOND * COAP_RESPONSE_TIMEOUT * ((float)COAP_RESPONSE_RANDOM_FACTOR - 1.0)) + 0.5) + 1 +#define COAP_RESPONSE_TIMEOUT_TICKS (1000 * COAP_RESPONSE_TIMEOUT) +#define COAP_RESPONSE_TIMEOUT_BACKOFF_MASK (uint32_t)(((1000 * COAP_RESPONSE_TIMEOUT * ((float)COAP_RESPONSE_RANDOM_FACTOR - 1.0)) + 0.5) + 1) /* container for transactions with message buffer and retransmission info */ typedef struct coap_transaction { struct coap_transaction *next; /* for LIST */ uint16_t mid; - struct etimer retrans_timer; + coap_timer_t retrans_timer; + uint32_t retrans_interval; uint8_t retrans_counter; - uip_ipaddr_t addr; - uint16_t port; + coap_endpoint_t endpoint; - restful_response_handler callback; + coap_resource_response_handler_t callback; void *callback_data; uint16_t packet_len; @@ -67,14 +69,9 @@ typedef struct coap_transaction { * Use snprintf(buf, len+1, "", ...) to completely fill payload */ } coap_transaction_t; -void coap_register_as_transaction_handler(void); - -coap_transaction_t *coap_new_transaction(uint16_t mid, uip_ipaddr_t *addr, - uint16_t port); +coap_transaction_t *coap_new_transaction(uint16_t mid, const coap_endpoint_t *ep); void coap_send_transaction(coap_transaction_t *t); void coap_clear_transaction(coap_transaction_t *t); coap_transaction_t *coap_get_transaction_by_mid(uint16_t mid); -void coap_check_transactions(void); - #endif /* COAP_TRANSACTIONS_H_ */ diff --git a/os/net/app-layer/coap/coap-transport.h b/os/net/app-layer/coap/coap-transport.h new file mode 100644 index 000000000..693081402 --- /dev/null +++ b/os/net/app-layer/coap/coap-transport.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2016, SICS, Swedish ICT AB. + * 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. + */ + +/** + * \file + * API for CoAP transport + * \author + * Niclas Finne + * Joakim Eriksson + */ + +#ifndef COAP_TRANSPORT_H_ +#define COAP_TRANSPORT_H_ + +#include "coap-endpoint.h" + +void coap_transport_init(void); + +void coap_send_message(const coap_endpoint_t *ep, const uint8_t *data, + uint16_t length); + +uint8_t *coap_databuf(void); +uint16_t coap_datalen(void); + +#endif /* COAP_TRANSPORT_H_ */ diff --git a/os/net/app-layer/coap/coap-uip.c b/os/net/app-layer/coap/coap-uip.c new file mode 100644 index 000000000..b6ab6064f --- /dev/null +++ b/os/net/app-layer/coap/coap-uip.c @@ -0,0 +1,534 @@ +/* + * Copyright (c) 2016, SICS, Swedish ICT AB. + * 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. + */ + +/** + * \file + * CoAP transport implementation for uIPv6 + * \author + * Niclas Finne + * Joakim Eriksson + */ + +#include "contiki.h" +#include "sys/cc.h" +#include "net/ipv6/uip-udp-packet.h" +#include "net/ipv6/uiplib.h" +#include "coap.h" +#include "coap-engine.h" +#include "coap-endpoint.h" +#include "coap-transport.h" +#include "coap-transactions.h" +#include "coap-constants.h" +#include "coap-keystore.h" + + +#if UIP_CONF_IPV6_RPL +#include "rpl.h" +#endif /* UIP_CONF_IPV6_RPL */ + +#define DEBUG DEBUG_FULL +#include "net/ipv6/uip-debug.h" + +#if DEBUG +#define PRINTEP(X) coap_endpoint_print(X) +#else +#define PRINTEP(X) +#endif + +#ifdef WITH_DTLS +#include "tinydtls.h" +#include "dtls.h" +#include "dtls_debug.h" +#endif /* WITH_DTLS */ + + +/* sanity check for configured values */ +#if COAP_MAX_PACKET_SIZE > (UIP_BUFSIZE - UIP_IPH_LEN - UIP_UDPH_LEN) +#error "UIP_CONF_BUFFER_SIZE too small for COAP_MAX_CHUNK_SIZE" +#endif + +#define SERVER_LISTEN_PORT UIP_HTONS(COAP_DEFAULT_PORT) +#define SERVER_LISTEN_SECURE_PORT UIP_HTONS(COAP_DEFAULT_SECURE_PORT) + +/* direct access into the buffer */ +#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) +#if NETSTACK_CONF_WITH_IPV6 +#define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[uip_l2_l3_hdr_len]) +#else +#define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[UIP_LLH_LEN + UIP_IPH_LEN]) +#endif + +#ifdef WITH_DTLS +static dtls_handler_t cb; +static dtls_context_t *dtls_context = NULL; + +static const coap_keystore_t *dtls_keystore = NULL; +static struct uip_udp_conn *dtls_conn = NULL; +#endif /* WITH_DTLS */ + +PROCESS(coap_engine, "CoAP Engine"); + +static struct uip_udp_conn *udp_conn = NULL; + +/*---------------------------------------------------------------------------*/ +void +coap_endpoint_print(const coap_endpoint_t *ep) +{ + if(ep->secure) { + printf("coaps:"); + } else { + printf("coap:"); + } + printf("//["); + uip_debug_ipaddr_print(&ep->ipaddr); + printf("]:%u", uip_ntohs(ep->port)); +} +/*---------------------------------------------------------------------------*/ +void +coap_endpoint_copy(coap_endpoint_t *destination, + const coap_endpoint_t *from) +{ + uip_ipaddr_copy(&destination->ipaddr, &from->ipaddr); + destination->port = from->port; + destination->secure = from->secure; + + PRINTF("EP copy: from sec:%d to sec:%d\n", from->secure, + destination->secure); +} +/*---------------------------------------------------------------------------*/ +int +coap_endpoint_cmp(const coap_endpoint_t *e1, const coap_endpoint_t *e2) +{ + if(!uip_ipaddr_cmp(&e1->ipaddr, &e2->ipaddr)) { + return 0; + } + return e1->port == e2->port && e1->secure == e2->secure; +} +/*---------------------------------------------------------------------------*/ +static int +index_of(const char *data, int offset, int len, uint8_t c) +{ + if(offset < 0) { + return offset; + } + for(; offset < len; offset++) { + if(data[offset] == c) { + return offset; + } + } + return -1; +} +/*---------------------------------------------------------------------------*/ +static int +get_port(const char *inbuf, size_t len, uint32_t *value) +{ + int i; + *value = 0; + for(i = 0; i < len; i++) { + if(inbuf[i] >= '0' && inbuf[i] <= '9') { + *value = *value * 10 + (inbuf[i] - '0'); + } else { + break; + } + } + return i; +} +/*---------------------------------------------------------------------------*/ +int +coap_endpoint_parse(const char *text, size_t size, coap_endpoint_t *ep) +{ + /* Only IPv6 supported */ + int start = index_of(text, 0, size, '['); + int end = index_of(text, start, size, ']'); + int secure = strncmp((const char *)text, "coaps:", 6) == 0; + uint32_t port; + if(start > 0 && end > start && + uiplib_ipaddrconv((const char *)&text[start], &ep->ipaddr)) { + if(text[end + 1] == ':' && + get_port(text + end + 2, size - end - 2, &port)) { + ep->port = UIP_HTONS(port); + } else if(secure) { + /** + * Secure CoAP should use a different port but for now + * the same port is used. + */ + PRINTF("Using secure port (coaps)\n"); + ep->port = SERVER_LISTEN_SECURE_PORT; + ep->secure = 1; + } else { + ep->port = SERVER_LISTEN_PORT; + ep->secure = 0; + } + return 1; + } else { + if(uiplib_ipaddrconv((const char *)&text, &ep->ipaddr)) { + ep->port = SERVER_LISTEN_PORT; + ep->secure = 0; + return 1; + } + } + return 0; +} +/*---------------------------------------------------------------------------*/ +static const coap_endpoint_t * +get_src_endpoint(uint8_t secure) +{ + static coap_endpoint_t src; + uip_ipaddr_copy(&src.ipaddr, &UIP_IP_BUF->srcipaddr); + src.port = UIP_UDP_BUF->srcport; + src.secure = secure; + return &src; +} +/*---------------------------------------------------------------------------*/ +int +coap_endpoint_is_secure(const coap_endpoint_t *ep) +{ + return ep->secure; +} +/*---------------------------------------------------------------------------*/ +int +coap_endpoint_is_connected(const coap_endpoint_t *ep) +{ +#if UIP_CONF_IPV6_RPL + if(rpl_get_any_dag() == NULL) { + return 0; + } +#endif /* UIP_CONF_IPV6_RPL */ + +#ifdef WITH_DTLS + if(ep != NULL && ep->secure != 0 && dtls_context != NULL) { + dtls_peer_t *peer; + peer = dtls_get_peer(dtls_context, ep); + if(peer != NULL) { + /* only if handshake is done! */ + PRINTF("peer state for "); + PRINTEP(ep); + PRINTF(" is %d %d\n", peer->state, dtls_peer_is_connected(peer)); + return dtls_peer_is_connected(peer); + } else { + PRINTF("Did not find peer "); + PRINTEP(ep); + PRINTF("\n"); + } + } +#endif /* WITH_DTLS */ + + /* Assume connected */ + return 1; +} +/*---------------------------------------------------------------------------*/ +int +coap_endpoint_connect(coap_endpoint_t *ep) +{ + if(ep->secure == 0) { + PRINTF("Connect - Non secure EP:"); + PRINTEP(ep); + PRINTF("\n"); + return 1; + } + +#ifdef WITH_DTLS + PRINTF("Connect - DTLS EP:"); + PRINTEP(ep); + PRINTF(" len:%d\n", sizeof(ep)); + + /* setup all address info here... should be done to connect */ + if(dtls_context) { + dtls_connect(dtls_context, ep); + } +#endif /* WITH_DTLS */ + + return 1; +} +/*---------------------------------------------------------------------------*/ +void +coap_endpoint_disconnect(coap_endpoint_t *ep) +{ +#ifdef WITH_DTLS + if(ep && ep->secure && dtls_context) { + dtls_close(dtls_context, ep); + } +#endif /* WITH_DTLS */ +} +/*---------------------------------------------------------------------------*/ +uint8_t * +coap_databuf(void) +{ + return uip_appdata; +} +/*---------------------------------------------------------------------------*/ +uint16_t +coap_datalen() +{ + return uip_datalen(); +} +/*---------------------------------------------------------------------------*/ +void +coap_transport_init(void) +{ + process_start(&coap_engine, NULL); +#ifdef WITH_DTLS + dtls_init(); + dtls_set_log_level(8); +#endif /* WITH_DTLS */ + +} +/*---------------------------------------------------------------------------*/ +#ifdef WITH_DTLS +static void +process_secure_data(void) +{ + PRINTF("receiving secure UDP datagram from ["); + PRINT6ADDR(&UIP_IP_BUF->srcipaddr); + PRINTF("]:%u\n Length: %u\n", uip_ntohs(UIP_UDP_BUF->srcport), + uip_datalen()); + + if(dtls_context) { + dtls_handle_message(dtls_context, (coap_endpoint_t *)get_src_endpoint(1), + uip_appdata, uip_datalen()); + } +} +#endif /* WITH_DTLS */ +/*---------------------------------------------------------------------------*/ +static void +process_data(void) +{ + PRINTF("receiving UDP datagram from ["); + PRINT6ADDR(&UIP_IP_BUF->srcipaddr); + PRINTF("]:%u\n Length: %u\n", uip_ntohs(UIP_UDP_BUF->srcport), + uip_datalen()); + + coap_receive(get_src_endpoint(0), uip_appdata, uip_datalen()); +} +/*---------------------------------------------------------------------------*/ +void +coap_send_message(const coap_endpoint_t *ep, const uint8_t *data, + uint16_t length) +{ + if(ep == NULL) { + PRINTF("failed to send - no endpoint\n"); + return; + } + +#ifdef WITH_DTLS + if(coap_endpoint_is_secure(ep)) { + if(dtls_context) { + dtls_write(dtls_context, (session_t *)ep, (uint8_t *)data, length); + PRINTF("-sent secure UDP datagram (%u)-\n", length); + } + return; + } +#endif /* WITH_DTLS */ + + uip_udp_packet_sendto(udp_conn, data, length, &ep->ipaddr, ep->port); + PRINTF("-sent UDP datagram (%u)-\n", length); +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(coap_engine, ev, data) +{ + PROCESS_BEGIN(); + + /* new connection with remote host */ + udp_conn = udp_new(NULL, 0, NULL); + udp_bind(udp_conn, SERVER_LISTEN_PORT); + PRINTF("Listening on port %u\n", uip_ntohs(udp_conn->lport)); + +#ifdef WITH_DTLS + /* create new context with app-data */ + dtls_conn = udp_new(NULL, 0, NULL); + if(dtls_conn != NULL) { + udp_bind(dtls_conn, SERVER_LISTEN_SECURE_PORT); + PRINTF("DTLS listening on port %u\n", uip_ntohs(dtls_conn->lport)); + dtls_context = dtls_new_context(dtls_conn); + } + if(!dtls_context) { + PRINTF("DTLS: cannot create context\n"); + } else { + dtls_set_handler(dtls_context, &cb); + } +#endif /* WITH_DTLS */ + + while(1) { + PROCESS_YIELD(); + + if(ev == tcpip_event) { + if(uip_newdata()) { +#ifdef WITH_DTLS + if(uip_udp_conn == dtls_conn) { + process_secure_data(); + continue; + } +#endif /* WITH_DTLS */ + process_data(); + } + } + } /* while (1) */ + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ + +/* DTLS */ +#ifdef WITH_DTLS + +/* This is input coming from the DTLS code - e.g. de-crypted input from + the other side - peer */ +static int +input_from_peer(struct dtls_context_t *ctx, + session_t *session, uint8_t *data, size_t len) +{ + size_t i; + dtls_peer_t *peer; + + PRINTF("received DTLS data:"); + for (i = 0; i < len; i++) { + PRINTF("%c", data[i]); + } + PRINTF("\nHex:"); + for (i = 0; i < len; i++) { + PRINTF("%02x", data[i]); + } + PRINTF("\n"); + + peer = dtls_get_peer(ctx, session); + /* If we have a peer then ensure that the endpoint is tagged as secure */ + if(peer) { + session->secure = 1; + } + + coap_receive(session, data, len); + + return 0; +} + +/* This is output from the DTLS code to be sent to peer (encrypted) */ +static int +output_to_peer(struct dtls_context_t *ctx, + session_t *session, uint8_t *data, size_t len) +{ + struct uip_udp_conn *udp_connection = dtls_get_app_data(ctx); + PRINTF("output_to DTLS peer ["); + PRINT6ADDR(&session->ipaddr); + PRINTF("]:%u len:%d\n", session->port,(int)len); + uip_udp_packet_sendto(udp_connection, data, len, + &session->ipaddr, session->port); + return len; +} + +/* This defines the key-store set API since we hookup DTLS here */ +void +coap_set_keystore(const coap_keystore_t *keystore) +{ + dtls_keystore = keystore; +} + +/* This function is the "key store" for tinyDTLS. It is called to + * retrieve a key for the given identity within this particular + * session. */ +static int +get_psk_info(struct dtls_context_t *ctx, + const session_t *session, + dtls_credentials_type_t type, + const unsigned char *id, size_t id_len, + unsigned char *result, size_t result_length) +{ + coap_keystore_psk_entry_t ks; + + if(dtls_keystore == NULL) { + PRINTF("--- No key store available ---\n"); + return 0; + } + + memset(&ks, 0, sizeof(ks)); + PRINTF("---===>>> Getting the Key or ID <<<===---\n"); + switch(type) { + case DTLS_PSK_IDENTITY: + if(id && id_len) { + ks.identity_hint = id; + ks.identity_hint_len = id_len; + PRINTF("got psk_identity_hint: '%.*s'\n", id_len, id); + } + + if(dtls_keystore->coap_get_psk_info) { + /* we know that session is a coap endpoint */ + dtls_keystore->coap_get_psk_info((coap_endpoint_t *)session, &ks); + } + if(ks.identity == NULL || ks.identity_len == 0) { + return 0; + } + + if(result_length < ks.identity_len) { + PRINTF("cannot set psk_identity -- buffer too small\n"); + return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); + } + memcpy(result, ks.identity, ks.identity_len); + return ks.identity_len; + + case DTLS_PSK_KEY: + if(dtls_keystore->coap_get_psk_info) { + ks.identity = id; + ks.identity_len = id_len; + /* we know that session is a coap endpoint */ + dtls_keystore->coap_get_psk_info((coap_endpoint_t *)session, &ks); + } + if(ks.key == NULL || ks.key_len == 0) { + PRINTF("PSK for unknown id requested, exiting\n"); + return dtls_alert_fatal_create(DTLS_ALERT_ILLEGAL_PARAMETER); + } + + if(result_length < ks.key_len) { + PRINTF("cannot set psk -- buffer too small\n"); + return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); + } + memcpy(result, ks.key, ks.key_len); + return ks.key_len; + + default: + PRINTF("unsupported request type: %d\n", type); + } + + return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); +} + + +static dtls_handler_t cb = { + .write = output_to_peer, + .read = input_from_peer, + .event = NULL, +#ifdef DTLS_PSK + .get_psk_info = get_psk_info, +#endif /* DTLS_PSK */ +#ifdef DTLS_ECC + /* .get_ecdsa_key = get_ecdsa_key, */ + /* .verify_ecdsa_key = verify_ecdsa_key */ +#endif /* DTLS_ECC */ +}; + +#endif /* WITH_DTLS */ +/*---------------------------------------------------------------------------*/ diff --git a/os/net/app-layer/coap/coap.c b/os/net/app-layer/coap/coap.c index bcec49cee..35d2c0fcf 100644 --- a/os/net/app-layer/coap/coap.c +++ b/os/net/app-layer/coap/coap.c @@ -37,10 +37,8 @@ */ #include -#include -#include "contiki.h" +#include #include "sys/cc.h" -#include "contiki-net.h" #include "coap.h" #include "coap-transactions.h" @@ -49,22 +47,23 @@ #if DEBUG #include #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]) +#define PRINTS(l,s,f) do { int i; \ + for(i = 0; i < l; i++) printf(f, s[i]); \ + } while(0) +#define PRINTPRE(p,l,s) do { PRINTF(p);PRINTS(l,s,"%c"); } while(0); #else #define PRINTF(...) -#define PRINT6ADDR(addr) -#define PRINTLLADDR(addr) +#define PRINTS(l,s,f) +#define PRINTPRE(p,l,s) #endif /*---------------------------------------------------------------------------*/ /*- Variables ---------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ -static struct uip_udp_conn *udp_conn = NULL; static uint16_t current_mid = 0; -coap_status_t erbium_status_code = NO_ERROR; -char *coap_error_message = ""; +coap_status_t coap_status_code = NO_ERROR; +const char *coap_error_message = ""; /*---------------------------------------------------------------------------*/ /*- Local helper functions --------------------------------------------------*/ /*---------------------------------------------------------------------------*/ @@ -177,8 +176,9 @@ coap_serialize_array_option(unsigned int number, unsigned int current_number, { size_t i = 0; - PRINTF("ARRAY type %u, len %zu, full [%.*s]\n", number, length, - (int)length, array); + PRINTF("ARRAY type %u, len %zu, full [", number, length); + PRINTS(length, array, "%c"); + PRINTF("]\n"); if(split_char != '\0') { int j; @@ -197,9 +197,10 @@ coap_serialize_array_option(unsigned int number, unsigned int current_number, memcpy(&buffer[i], part_start, temp_length); i += temp_length; - PRINTF("OPTION type %u, delta %u, len %zu, part [%.*s]\n", number, - number - current_number, i, (int)temp_length, part_start); - + PRINTF("OPTION type %u, delta %u, len %zu, part [", number, + number - current_number, i); + PRINTS((int)temp_length, part_start, "%c"); + PRINTF("]\n"); ++j; /* skip the splitter */ current_number = number; part_start = array + j; @@ -276,15 +277,10 @@ coap_get_variable(const char *buffer, size_t length, const char *name, /*- Internal API ------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ void -coap_init_connection(uint16_t port) +coap_init_connection(void) { - /* new connection with remote host */ - udp_conn = udp_new(NULL, 0, NULL); - udp_bind(udp_conn, port); - PRINTF("Listening on port %u\n", uip_ntohs(udp_conn->lport)); - /* initialize transaction ID */ - current_mid = random_rand(); + current_mid = rand(); } /*---------------------------------------------------------------------------*/ uint16_t @@ -294,11 +290,9 @@ coap_get_mid() } /*---------------------------------------------------------------------------*/ void -coap_init_message(void *packet, coap_message_type_t type, uint8_t code, - uint16_t mid) +coap_init_message(coap_packet_t *coap_pkt, coap_message_type_t type, + uint8_t code, uint16_t mid) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - /* Important thing */ memset(coap_pkt, 0, sizeof(coap_packet_t)); @@ -308,9 +302,8 @@ coap_init_message(void *packet, coap_message_type_t type, uint8_t code, } /*---------------------------------------------------------------------------*/ size_t -coap_serialize_message(void *packet, uint8_t *buffer) +coap_serialize_message(coap_packet_t *coap_pkt, uint8_t *buffer) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; uint8_t *option; unsigned int current_number = 0; @@ -422,28 +415,9 @@ coap_serialize_message(void *packet, uint8_t *buffer) return (option - buffer) + coap_pkt->payload_len; /* packet length */ } /*---------------------------------------------------------------------------*/ -void -coap_send_message(uip_ipaddr_t *addr, uint16_t port, uint8_t *data, - uint16_t length) -{ - /* configure connection to reply to client */ - uip_ipaddr_copy(&udp_conn->ripaddr, addr); - udp_conn->rport = port; - - uip_udp_packet_send(udp_conn, data, length); - - PRINTF("-sent UDP datagram (%u)-\n", length); - - /* restore server socket to allow data from any node */ - memset(&udp_conn->ripaddr, 0, sizeof(udp_conn->ripaddr)); - udp_conn->rport = 0; -} -/*---------------------------------------------------------------------------*/ coap_status_t -coap_parse_message(void *packet, uint8_t *data, uint16_t data_len) +coap_parse_message(coap_packet_t *coap_pkt, uint8_t *data, uint16_t data_len) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - /* initialize packet */ memset(coap_pkt, 0, sizeof(coap_packet_t)); @@ -493,9 +467,9 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len) coap_pkt->payload = ++current_option; coap_pkt->payload_len = data_len - (coap_pkt->payload - data); - /* also for receiving, the Erbium upper bound is REST_MAX_CHUNK_SIZE */ - if(coap_pkt->payload_len > REST_MAX_CHUNK_SIZE) { - coap_pkt->payload_len = REST_MAX_CHUNK_SIZE; + /* also for receiving, the Erbium upper bound is COAP_MAX_CHUNK_SIZE */ + if(coap_pkt->payload_len > COAP_MAX_CHUNK_SIZE) { + coap_pkt->payload_len = COAP_MAX_CHUNK_SIZE; /* null-terminate payload */ } coap_pkt->payload[coap_pkt->payload_len] = '\0'; @@ -536,7 +510,7 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len) return BAD_REQUEST_4_00; } - option_number += option_delta; + option_number += option_delta; if(option_number > COAP_OPTION_SIZE1) { /* Malformed CoAP - out of bounds */ @@ -547,7 +521,7 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len) PRINTF("OPTION %u (delta %u, len %zu): ", option_number, option_delta, option_length); - SET_OPTION(coap_pkt, option_number); + coap_set_option(coap_pkt, option_number); switch(option_number) { case COAP_OPTION_CONTENT_FORMAT: @@ -595,8 +569,10 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len) coap_pkt->proxy_uri = (char *)current_option; coap_pkt->proxy_uri_len = option_length; #endif - PRINTF("Proxy-Uri NOT IMPLEMENTED [%.*s]\n", (int)coap_pkt->proxy_uri_len, - coap_pkt->proxy_uri); + PRINTPRE("Proxy-Uri NOT IMPLEMENTED [",(int)coap_pkt->proxy_uri_len, + coap_pkt->proxy_uri); + PRINTF("]\n"); + coap_error_message = "This is a constrained server (Contiki)"; return PROXYING_NOT_SUPPORTED_5_05; break; @@ -605,8 +581,9 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len) coap_pkt->proxy_scheme = (char *)current_option; coap_pkt->proxy_scheme_len = option_length; #endif - PRINTF("Proxy-Scheme NOT IMPLEMENTED [%.*s]\n", - (int)coap_pkt->proxy_scheme_len, coap_pkt->proxy_scheme); + PRINTPRE("Proxy-Scheme NOT IMPLEMENTED [", + (int)coap_pkt->proxy_scheme_len, coap_pkt->proxy_scheme); + PRINTF("]\n"); coap_error_message = "This is a constrained server (Contiki)"; return PROXYING_NOT_SUPPORTED_5_05; break; @@ -614,8 +591,9 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len) case COAP_OPTION_URI_HOST: coap_pkt->uri_host = (char *)current_option; coap_pkt->uri_host_len = option_length; - PRINTF("Uri-Host [%.*s]\n", (int)coap_pkt->uri_host_len, - coap_pkt->uri_host); + PRINTPRE("Uri-Host [", (int)coap_pkt->uri_host_len, + coap_pkt->uri_host); + PRINTF("]\n"); break; case COAP_OPTION_URI_PORT: coap_pkt->uri_port = coap_parse_int_option(current_option, @@ -627,15 +605,16 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len) coap_merge_multi_option((char **)&(coap_pkt->uri_path), &(coap_pkt->uri_path_len), current_option, option_length, '/'); - PRINTF("Uri-Path [%.*s]\n", (int)coap_pkt->uri_path_len, coap_pkt->uri_path); + PRINTPRE("Uri-Path [",(int)coap_pkt->uri_path_len, coap_pkt->uri_path); + PRINTF("]\n"); break; case COAP_OPTION_URI_QUERY: /* coap_merge_multi_option() operates in-place on the IPBUF, but final packet field should be const string -> cast to string */ coap_merge_multi_option((char **)&(coap_pkt->uri_query), &(coap_pkt->uri_query_len), current_option, option_length, '&'); - PRINTF("Uri-Query [%.*s]\n", (int)coap_pkt->uri_query_len, - coap_pkt->uri_query); + PRINTPRE("Uri-Query[",(int)coap_pkt->uri_query_len,coap_pkt->uri_query); + PRINTF("]\n"); break; case COAP_OPTION_LOCATION_PATH: @@ -643,16 +622,19 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len) coap_merge_multi_option((char **)&(coap_pkt->location_path), &(coap_pkt->location_path_len), current_option, option_length, '/'); - PRINTF("Location-Path [%.*s]\n", (int)coap_pkt->location_path_len, - coap_pkt->location_path); + + PRINTPRE("Location-Path [",(int)coap_pkt->location_path_len, + coap_pkt->location_path); + PRINTF("]\n"); break; case COAP_OPTION_LOCATION_QUERY: /* coap_merge_multi_option() operates in-place on the IPBUF, but final packet field should be const string -> cast to string */ coap_merge_multi_option((char **)&(coap_pkt->location_query), &(coap_pkt->location_query_len), current_option, option_length, '&'); - PRINTF("Location-Query [%.*s]\n", (int)coap_pkt->location_query_len, - coap_pkt->location_query); + PRINTPRE("Location-Query [",(int)coap_pkt->location_query_len, + coap_pkt->location_query); + PRINTF("]\n"); break; case COAP_OPTION_OBSERVE: @@ -708,24 +690,22 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len) return NO_ERROR; } /*---------------------------------------------------------------------------*/ -/*- REST Engine API ---------------------------------------------------------*/ +/*- CoAP Engine API ---------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ int -coap_get_query_variable(void *packet, const char *name, const char **output) +coap_get_query_variable(coap_packet_t *coap_pkt, + const char *name, const char **output) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(IS_OPTION(coap_pkt, COAP_OPTION_URI_QUERY)) { + if(coap_is_option(coap_pkt, COAP_OPTION_URI_QUERY)) { return coap_get_variable(coap_pkt->uri_query, coap_pkt->uri_query_len, name, output); } return 0; } int -coap_get_post_variable(void *packet, const char *name, const char **output) +coap_get_post_variable(coap_packet_t *coap_pkt, + const char *name, const char **output) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - if(coap_pkt->payload_len) { return coap_get_variable((const char *)coap_pkt->payload, coap_pkt->payload_len, name, output); @@ -734,10 +714,10 @@ coap_get_post_variable(void *packet, const char *name, const char **output) } /*---------------------------------------------------------------------------*/ int -coap_set_status_code(void *packet, unsigned int code) +coap_set_status_code(coap_packet_t *packet, unsigned int code) { if(code <= 0xFF) { - ((coap_packet_t *)packet)->code = (uint8_t)code; + packet->code = (uint8_t)code; return 1; } else { return 0; @@ -745,329 +725,280 @@ coap_set_status_code(void *packet, unsigned int code) } /*---------------------------------------------------------------------------*/ int -coap_set_token(void *packet, const uint8_t *token, size_t token_len) +coap_set_token(coap_packet_t *coap_pkt, const uint8_t *token, size_t token_len) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - coap_pkt->token_len = MIN(COAP_TOKEN_LEN, token_len); memcpy(coap_pkt->token, token, coap_pkt->token_len); return coap_pkt->token_len; } /*---------------------------------------------------------------------------*/ -/*- CoAP REST Implementation API --------------------------------------------*/ +/*- CoAP Implementation API -------------------------------------------------*/ /*---------------------------------------------------------------------------*/ int -coap_get_header_content_format(void *packet, unsigned int *format) +coap_get_header_content_format(coap_packet_t *coap_pkt, unsigned int *format) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(!IS_OPTION(coap_pkt, COAP_OPTION_CONTENT_FORMAT)) { + if(!coap_is_option(coap_pkt, COAP_OPTION_CONTENT_FORMAT)) { return 0; } *format = coap_pkt->content_format; return 1; } int -coap_set_header_content_format(void *packet, unsigned int format) +coap_set_header_content_format(coap_packet_t *coap_pkt, unsigned int format) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - coap_pkt->content_format = format; - SET_OPTION(coap_pkt, COAP_OPTION_CONTENT_FORMAT); + coap_set_option(coap_pkt, COAP_OPTION_CONTENT_FORMAT); return 1; } /*---------------------------------------------------------------------------*/ int -coap_get_header_accept(void *packet, unsigned int *accept) +coap_get_header_accept(coap_packet_t *coap_pkt, unsigned int *accept) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(!IS_OPTION(coap_pkt, COAP_OPTION_ACCEPT)) { + if(!coap_is_option(coap_pkt, COAP_OPTION_ACCEPT)) { return 0; } *accept = coap_pkt->accept; return 1; } int -coap_set_header_accept(void *packet, unsigned int accept) +coap_set_header_accept(coap_packet_t *coap_pkt, unsigned int accept) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - coap_pkt->accept = accept; - SET_OPTION(coap_pkt, COAP_OPTION_ACCEPT); + coap_set_option(coap_pkt, COAP_OPTION_ACCEPT); return 1; } /*---------------------------------------------------------------------------*/ int -coap_get_header_max_age(void *packet, uint32_t *age) +coap_get_header_max_age(coap_packet_t *coap_pkt, uint32_t *age) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(!IS_OPTION(coap_pkt, COAP_OPTION_MAX_AGE)) { + if(!coap_is_option(coap_pkt, COAP_OPTION_MAX_AGE)) { *age = COAP_DEFAULT_MAX_AGE; } else { *age = coap_pkt->max_age; } return 1; } int -coap_set_header_max_age(void *packet, uint32_t age) +coap_set_header_max_age(coap_packet_t *coap_pkt, uint32_t age) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - coap_pkt->max_age = age; - SET_OPTION(coap_pkt, COAP_OPTION_MAX_AGE); + coap_set_option(coap_pkt, COAP_OPTION_MAX_AGE); return 1; } /*---------------------------------------------------------------------------*/ int -coap_get_header_etag(void *packet, const uint8_t **etag) +coap_get_header_etag(coap_packet_t *coap_pkt, const uint8_t **etag) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(!IS_OPTION(coap_pkt, COAP_OPTION_ETAG)) { + if(!coap_is_option(coap_pkt, COAP_OPTION_ETAG)) { return 0; } *etag = coap_pkt->etag; return coap_pkt->etag_len; } int -coap_set_header_etag(void *packet, const uint8_t *etag, size_t etag_len) +coap_set_header_etag(coap_packet_t *coap_pkt, const uint8_t *etag, size_t etag_len) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - coap_pkt->etag_len = MIN(COAP_ETAG_LEN, etag_len); memcpy(coap_pkt->etag, etag, coap_pkt->etag_len); - SET_OPTION(coap_pkt, COAP_OPTION_ETAG); + coap_set_option(coap_pkt, COAP_OPTION_ETAG); return coap_pkt->etag_len; } /*---------------------------------------------------------------------------*/ /*FIXME support multiple ETags */ int -coap_get_header_if_match(void *packet, const uint8_t **etag) +coap_get_header_if_match(coap_packet_t *coap_pkt, const uint8_t **etag) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(!IS_OPTION(coap_pkt, COAP_OPTION_IF_MATCH)) { + if(!coap_is_option(coap_pkt, COAP_OPTION_IF_MATCH)) { return 0; } *etag = coap_pkt->if_match; return coap_pkt->if_match_len; } int -coap_set_header_if_match(void *packet, const uint8_t *etag, size_t etag_len) +coap_set_header_if_match(coap_packet_t *coap_pkt, const uint8_t *etag, size_t etag_len) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - coap_pkt->if_match_len = MIN(COAP_ETAG_LEN, etag_len); memcpy(coap_pkt->if_match, etag, coap_pkt->if_match_len); - SET_OPTION(coap_pkt, COAP_OPTION_IF_MATCH); + coap_set_option(coap_pkt, COAP_OPTION_IF_MATCH); return coap_pkt->if_match_len; } /*---------------------------------------------------------------------------*/ int -coap_get_header_if_none_match(void *packet) +coap_get_header_if_none_match(coap_packet_t *packet) { - return IS_OPTION((coap_packet_t *)packet, - COAP_OPTION_IF_NONE_MATCH) ? 1 : 0; + return coap_is_option(packet, COAP_OPTION_IF_NONE_MATCH) ? 1 : 0; } int -coap_set_header_if_none_match(void *packet) +coap_set_header_if_none_match(coap_packet_t *packet) { - SET_OPTION((coap_packet_t *)packet, COAP_OPTION_IF_NONE_MATCH); + coap_set_option(packet, COAP_OPTION_IF_NONE_MATCH); return 1; } /*---------------------------------------------------------------------------*/ int -coap_get_header_proxy_uri(void *packet, const char **uri) +coap_get_header_proxy_uri(coap_packet_t *coap_pkt, const char **uri) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(!IS_OPTION(coap_pkt, COAP_OPTION_PROXY_URI)) { + if(!coap_is_option(coap_pkt, COAP_OPTION_PROXY_URI)) { return 0; } *uri = coap_pkt->proxy_uri; return coap_pkt->proxy_uri_len; } int -coap_set_header_proxy_uri(void *packet, const char *uri) +coap_set_header_proxy_uri(coap_packet_t *coap_pkt, const char *uri) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - /*TODO Provide alternative that sets Proxy-Scheme and Uri-* options and provide coap-conf define */ + /* TODO Provide alternative that sets Proxy-Scheme and Uri-* options and provide coap-conf define */ coap_pkt->proxy_uri = uri; coap_pkt->proxy_uri_len = strlen(uri); - SET_OPTION(coap_pkt, COAP_OPTION_PROXY_URI); + coap_set_option(coap_pkt, COAP_OPTION_PROXY_URI); return coap_pkt->proxy_uri_len; } /*---------------------------------------------------------------------------*/ int -coap_get_header_uri_host(void *packet, const char **host) +coap_get_header_uri_host(coap_packet_t *coap_pkt, const char **host) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(!IS_OPTION(coap_pkt, COAP_OPTION_URI_HOST)) { + if(!coap_is_option(coap_pkt, COAP_OPTION_URI_HOST)) { return 0; } *host = coap_pkt->uri_host; return coap_pkt->uri_host_len; } int -coap_set_header_uri_host(void *packet, const char *host) +coap_set_header_uri_host(coap_packet_t *coap_pkt, const char *host) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - coap_pkt->uri_host = host; coap_pkt->uri_host_len = strlen(host); - SET_OPTION(coap_pkt, COAP_OPTION_URI_HOST); + coap_set_option(coap_pkt, COAP_OPTION_URI_HOST); return coap_pkt->uri_host_len; } /*---------------------------------------------------------------------------*/ int -coap_get_header_uri_path(void *packet, const char **path) +coap_get_header_uri_path(coap_packet_t *coap_pkt, const char **path) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(!IS_OPTION(coap_pkt, COAP_OPTION_URI_PATH)) { + if(!coap_is_option(coap_pkt, COAP_OPTION_URI_PATH)) { return 0; } *path = coap_pkt->uri_path; return coap_pkt->uri_path_len; } int -coap_set_header_uri_path(void *packet, const char *path) +coap_set_header_uri_path(coap_packet_t *coap_pkt, const char *path) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - while(path[0] == '/') + while(path[0] == '/') { ++path; + } coap_pkt->uri_path = path; coap_pkt->uri_path_len = strlen(path); - SET_OPTION(coap_pkt, COAP_OPTION_URI_PATH); + coap_set_option(coap_pkt, COAP_OPTION_URI_PATH); return coap_pkt->uri_path_len; } /*---------------------------------------------------------------------------*/ int -coap_get_header_uri_query(void *packet, const char **query) +coap_get_header_uri_query(coap_packet_t *coap_pkt, const char **query) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(!IS_OPTION(coap_pkt, COAP_OPTION_URI_QUERY)) { + if(!coap_is_option(coap_pkt, COAP_OPTION_URI_QUERY)) { return 0; } *query = coap_pkt->uri_query; return coap_pkt->uri_query_len; } int -coap_set_header_uri_query(void *packet, const char *query) +coap_set_header_uri_query(coap_packet_t *coap_pkt, const char *query) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - while(query[0] == '?') + while(query[0] == '?') { ++query; + } coap_pkt->uri_query = query; coap_pkt->uri_query_len = strlen(query); - SET_OPTION(coap_pkt, COAP_OPTION_URI_QUERY); + coap_set_option(coap_pkt, COAP_OPTION_URI_QUERY); return coap_pkt->uri_query_len; } /*---------------------------------------------------------------------------*/ int -coap_get_header_location_path(void *packet, const char **path) +coap_get_header_location_path(coap_packet_t *coap_pkt, const char **path) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(!IS_OPTION(coap_pkt, COAP_OPTION_LOCATION_PATH)) { + if(!coap_is_option(coap_pkt, COAP_OPTION_LOCATION_PATH)) { return 0; } *path = coap_pkt->location_path; return coap_pkt->location_path_len; } int -coap_set_header_location_path(void *packet, const char *path) +coap_set_header_location_path(coap_packet_t *coap_pkt, const char *path) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - char *query; - while(path[0] == '/') + while(path[0] == '/') { ++path; + } if((query = strchr(path, '?'))) { - coap_set_header_location_query(packet, query + 1); + coap_set_header_location_query(coap_pkt, query + 1); coap_pkt->location_path_len = query - path; } else { coap_pkt->location_path_len = strlen(path); } coap_pkt->location_path = path; if(coap_pkt->location_path_len > 0) { - SET_OPTION(coap_pkt, COAP_OPTION_LOCATION_PATH); + coap_set_option(coap_pkt, COAP_OPTION_LOCATION_PATH); } return coap_pkt->location_path_len; } /*---------------------------------------------------------------------------*/ int -coap_get_header_location_query(void *packet, const char **query) +coap_get_header_location_query(coap_packet_t *coap_pkt, const char **query) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(!IS_OPTION(coap_pkt, COAP_OPTION_LOCATION_QUERY)) { + if(!coap_is_option(coap_pkt, COAP_OPTION_LOCATION_QUERY)) { return 0; } *query = coap_pkt->location_query; return coap_pkt->location_query_len; } int -coap_set_header_location_query(void *packet, const char *query) +coap_set_header_location_query(coap_packet_t *coap_pkt, const char *query) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - while(query[0] == '?') + while(query[0] == '?') { ++query; + } coap_pkt->location_query = query; coap_pkt->location_query_len = strlen(query); - SET_OPTION(coap_pkt, COAP_OPTION_LOCATION_QUERY); + coap_set_option(coap_pkt, COAP_OPTION_LOCATION_QUERY); return coap_pkt->location_query_len; } /*---------------------------------------------------------------------------*/ int -coap_get_header_observe(void *packet, uint32_t *observe) +coap_get_header_observe(coap_packet_t *coap_pkt, uint32_t *observe) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(!IS_OPTION(coap_pkt, COAP_OPTION_OBSERVE)) { + if(!coap_is_option(coap_pkt, COAP_OPTION_OBSERVE)) { return 0; } *observe = coap_pkt->observe; return 1; } int -coap_set_header_observe(void *packet, uint32_t observe) +coap_set_header_observe(coap_packet_t *coap_pkt, uint32_t observe) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - coap_pkt->observe = observe; - SET_OPTION(coap_pkt, COAP_OPTION_OBSERVE); + coap_set_option(coap_pkt, COAP_OPTION_OBSERVE); return 1; } /*---------------------------------------------------------------------------*/ int -coap_get_header_block2(void *packet, uint32_t *num, uint8_t *more, +coap_get_header_block2(coap_packet_t *coap_pkt, uint32_t *num, uint8_t *more, uint16_t *size, uint32_t *offset) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(!IS_OPTION(coap_pkt, COAP_OPTION_BLOCK2)) { + if(!coap_is_option(coap_pkt, COAP_OPTION_BLOCK2)) { return 0; } /* pointers may be NULL to get only specific block parameters */ @@ -1086,11 +1017,9 @@ coap_get_header_block2(void *packet, uint32_t *num, uint8_t *more, return 1; } int -coap_set_header_block2(void *packet, uint32_t num, uint8_t more, +coap_set_header_block2(coap_packet_t *coap_pkt, uint32_t num, uint8_t more, uint16_t size) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - if(size < 16) { return 0; } @@ -1104,17 +1033,15 @@ coap_set_header_block2(void *packet, uint32_t num, uint8_t more, coap_pkt->block2_more = more ? 1 : 0; coap_pkt->block2_size = size; - SET_OPTION(coap_pkt, COAP_OPTION_BLOCK2); + coap_set_option(coap_pkt, COAP_OPTION_BLOCK2); return 1; } /*---------------------------------------------------------------------------*/ int -coap_get_header_block1(void *packet, uint32_t *num, uint8_t *more, +coap_get_header_block1(coap_packet_t *coap_pkt, uint32_t *num, uint8_t *more, uint16_t *size, uint32_t *offset) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(!IS_OPTION(coap_pkt, COAP_OPTION_BLOCK1)) { + if(!coap_is_option(coap_pkt, COAP_OPTION_BLOCK1)) { return 0; } /* pointers may be NULL to get only specific block parameters */ @@ -1133,11 +1060,9 @@ coap_get_header_block1(void *packet, uint32_t *num, uint8_t *more, return 1; } int -coap_set_header_block1(void *packet, uint32_t num, uint8_t more, +coap_set_header_block1(coap_packet_t *coap_pkt, uint32_t num, uint8_t more, uint16_t size) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - if(size < 16) { return 0; } @@ -1151,57 +1076,47 @@ coap_set_header_block1(void *packet, uint32_t num, uint8_t more, coap_pkt->block1_more = more; coap_pkt->block1_size = size; - SET_OPTION(coap_pkt, COAP_OPTION_BLOCK1); + coap_set_option(coap_pkt, COAP_OPTION_BLOCK1); return 1; } /*---------------------------------------------------------------------------*/ int -coap_get_header_size2(void *packet, uint32_t *size) +coap_get_header_size2(coap_packet_t *coap_pkt, uint32_t *size) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(!IS_OPTION(coap_pkt, COAP_OPTION_SIZE2)) { + if(!coap_is_option(coap_pkt, COAP_OPTION_SIZE2)) { return 0; } *size = coap_pkt->size2; return 1; } int -coap_set_header_size2(void *packet, uint32_t size) +coap_set_header_size2(coap_packet_t *coap_pkt, uint32_t size) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - coap_pkt->size2 = size; - SET_OPTION(coap_pkt, COAP_OPTION_SIZE2); + coap_set_option(coap_pkt, COAP_OPTION_SIZE2); return 1; } /*---------------------------------------------------------------------------*/ int -coap_get_header_size1(void *packet, uint32_t *size) +coap_get_header_size1(coap_packet_t *coap_pkt, uint32_t *size) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(!IS_OPTION(coap_pkt, COAP_OPTION_SIZE1)) { + if(!coap_is_option(coap_pkt, COAP_OPTION_SIZE1)) { return 0; } *size = coap_pkt->size1; return 1; } int -coap_set_header_size1(void *packet, uint32_t size) +coap_set_header_size1(coap_packet_t *coap_pkt, uint32_t size) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - coap_pkt->size1 = size; - SET_OPTION(coap_pkt, COAP_OPTION_SIZE1); + coap_set_option(coap_pkt, COAP_OPTION_SIZE1); return 1; } /*---------------------------------------------------------------------------*/ int -coap_get_payload(void *packet, const uint8_t **payload) +coap_get_payload(coap_packet_t *coap_pkt, const uint8_t **payload) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - if(coap_pkt->payload) { *payload = coap_pkt->payload; return coap_pkt->payload_len; @@ -1211,12 +1126,10 @@ coap_get_payload(void *packet, const uint8_t **payload) } } int -coap_set_payload(void *packet, const void *payload, size_t length) +coap_set_payload(coap_packet_t *coap_pkt, const void *payload, size_t length) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - coap_pkt->payload = (uint8_t *)payload; - coap_pkt->payload_len = MIN(REST_MAX_CHUNK_SIZE, length); + coap_pkt->payload_len = MIN(COAP_MAX_CHUNK_SIZE, length); return coap_pkt->payload_len; } diff --git a/os/net/app-layer/coap/coap.h b/os/net/app-layer/coap/coap.h index 616f67d5c..f93fcf7e9 100644 --- a/os/net/app-layer/coap/coap.h +++ b/os/net/app-layer/coap/coap.h @@ -36,44 +36,29 @@ * Matthias Kovatsch */ -#ifndef ER_COAP_H_ -#define ER_COAP_H_ +#ifndef COAP_H_ +#define COAP_H_ #include /* for size_t */ -#include "contiki-net.h" #include "coap-constants.h" #include "coap-conf.h" +#include "coap-transport.h" -/* sanity check for configured values */ -#define COAP_MAX_PACKET_SIZE (COAP_MAX_HEADER_SIZE + REST_MAX_CHUNK_SIZE) -#if COAP_MAX_PACKET_SIZE > (UIP_BUFSIZE - UIP_LLH_LEN - UIP_IPH_LEN - UIP_UDPH_LEN) -#error "UIP_CONF_BUFFER_SIZE too small for REST_MAX_CHUNK_SIZE" -#endif +#define COAP_MAX_PACKET_SIZE (COAP_MAX_HEADER_SIZE + COAP_MAX_CHUNK_SIZE) -/* use Erbium CoAP for the REST Engine. Must come before include of rest-engine.h. */ -#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 */ +/* COAP_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))))))) +#define COAP_MAX_BLOCK_SIZE (COAP_MAX_CHUNK_SIZE < 32 ? 16 : \ + (COAP_MAX_CHUNK_SIZE < 64 ? 32 : \ + (COAP_MAX_CHUNK_SIZE < 128 ? 64 : \ + (COAP_MAX_CHUNK_SIZE < 256 ? 128 : \ + (COAP_MAX_CHUNK_SIZE < 512 ? 256 : \ + (COAP_MAX_CHUNK_SIZE < 1024 ? 512 : \ + (COAP_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]) -#define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[uip_l2_l3_hdr_len]) - /* bitmap for set options */ -enum { OPTION_MAP_SIZE = sizeof(uint8_t) * 8 }; - -#define SET_OPTION(packet, opt) ((packet)->options[opt / OPTION_MAP_SIZE] |= 1 << (opt % OPTION_MAP_SIZE)) -#define IS_OPTION(packet, opt) ((packet)->options[opt / OPTION_MAP_SIZE] & (1 << (opt % OPTION_MAP_SIZE))) +#define OPTION_MAP_SIZE (sizeof(uint8_t) * 8) /* parsed message struct */ typedef struct { @@ -124,19 +109,38 @@ typedef struct { const char *uri_query; uint8_t if_none_match; + const coap_endpoint_t *src_ep; + uint16_t payload_len; uint8_t *payload; } coap_packet_t; +static inline int +coap_set_option(coap_packet_t *packet, unsigned int opt) +{ + if(opt > COAP_OPTION_SIZE1) { + return 0; + } + packet->options[opt / OPTION_MAP_SIZE] |= 1 << (opt % OPTION_MAP_SIZE); + return 1; +} + +static inline int +coap_is_option(const coap_packet_t *packet, unsigned int opt) +{ + return (opt <= COAP_OPTION_SIZE1) && + (packet->options[opt / OPTION_MAP_SIZE] & (1 << (opt % OPTION_MAP_SIZE))) != 0; +} + /* option format serialization */ #define COAP_SERIALIZE_INT_OPTION(number, field, text) \ - if(IS_OPTION(coap_pkt, number)) { \ - PRINTF(text " [%u]\n", (unsigned int)coap_pkt->field); \ + if(coap_is_option(coap_pkt, number)) { \ + PRINTF(text " [%u]\n", (unsigned int)coap_pkt->field); \ option += coap_serialize_int_option(number, current_number, option, coap_pkt->field); \ current_number = number; \ } #define COAP_SERIALIZE_BYTE_OPTION(number, field, text) \ - if(IS_OPTION(coap_pkt, number)) { \ + if(coap_is_option(coap_pkt, number)) { \ PRINTF(text " %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", (unsigned int)coap_pkt->field##_len, \ coap_pkt->field[0], \ coap_pkt->field[1], \ @@ -151,109 +155,135 @@ typedef struct { current_number = number; \ } #define COAP_SERIALIZE_STRING_OPTION(number, field, splitter, text) \ - if(IS_OPTION(coap_pkt, number)) { \ - PRINTF(text " [%.*s]\n", (int)coap_pkt->field##_len, coap_pkt->field); \ + if(coap_is_option(coap_pkt, number)) { \ + PRINTPRE(text " [", (int)coap_pkt->field##_len, coap_pkt->field); \ + PRINTF("]\n"); \ option += coap_serialize_array_option(number, current_number, option, (uint8_t *)coap_pkt->field, coap_pkt->field##_len, splitter); \ current_number = number; \ } #define COAP_SERIALIZE_BLOCK_OPTION(number, field, text) \ - if(IS_OPTION(coap_pkt, number)) \ + if(coap_is_option(coap_pkt, number)) \ { \ PRINTF(text " [%lu%s (%u B/blk)]\n", (unsigned long)coap_pkt->field##_num, coap_pkt->field##_more ? "+" : "", coap_pkt->field##_size); \ uint32_t block = coap_pkt->field##_num << 4; \ if(coap_pkt->field##_more) { block |= 0x8; } \ block |= 0xF & coap_log_2(coap_pkt->field##_size / 16); \ - PRINTF(text " encoded: 0x%lX\n", (unsigned long)block); \ + PRINTF(text " encoded: 0x%lX\n", (unsigned long)block); \ option += coap_serialize_int_option(number, current_number, option, block); \ current_number = number; \ } /* to store error code and human-readable payload */ -extern coap_status_t erbium_status_code; -extern char *coap_error_message; +extern coap_status_t coap_status_code; +extern const char *coap_error_message; -void coap_init_connection(uint16_t port); +void coap_init_connection(void); uint16_t coap_get_mid(void); -void coap_init_message(void *packet, coap_message_type_t type, uint8_t code, - uint16_t mid); -size_t coap_serialize_message(void *packet, uint8_t *buffer); -void coap_send_message(uip_ipaddr_t *addr, uint16_t port, uint8_t *data, - uint16_t length); -coap_status_t coap_parse_message(void *request, uint8_t *data, +void coap_init_message(coap_packet_t *packet, coap_message_type_t type, + uint8_t code, uint16_t mid); +size_t coap_serialize_message(coap_packet_t *packet, uint8_t *buffer); +coap_status_t coap_parse_message(coap_packet_t *request, uint8_t *data, uint16_t data_len); -int coap_get_query_variable(void *packet, const char *name, +int coap_get_query_variable(coap_packet_t *packet, const char *name, const char **output); -int coap_get_post_variable(void *packet, const char *name, +int coap_get_post_variable(coap_packet_t *packet, const char *name, const char **output); +static inline coap_resource_flags_t +coap_get_method_type(coap_packet_t *packet) +{ + return (coap_resource_flags_t)(1 << (packet->code - 1)); +} + +static inline const coap_endpoint_t * +coap_get_src_endpoint(coap_packet_t *request) +{ + return request->src_ep; +} + +static inline void +coap_set_src_endpoint(coap_packet_t *request, const coap_endpoint_t *ep) +{ + request->src_ep = ep; +} /*---------------------------------------------------------------------------*/ -int coap_set_status_code(void *packet, unsigned int code); +int coap_set_status_code(coap_packet_t *packet, unsigned int code); -int coap_set_token(void *packet, const uint8_t *token, size_t token_len); +int coap_set_token(coap_packet_t *packet, const uint8_t *token, + size_t token_len); -int coap_get_header_content_format(void *packet, unsigned int *format); -int coap_set_header_content_format(void *packet, unsigned int format); +int coap_get_header_content_format(coap_packet_t *packet, unsigned int *format); +int coap_set_header_content_format(coap_packet_t *packet, unsigned int format); -int coap_get_header_accept(void *packet, unsigned int *accept); -int coap_set_header_accept(void *packet, unsigned int accept); +int coap_get_header_accept(coap_packet_t *packet, unsigned int *accept); +int coap_set_header_accept(coap_packet_t *packet, unsigned int accept); -int coap_get_header_max_age(void *packet, uint32_t *age); -int coap_set_header_max_age(void *packet, uint32_t age); +int coap_get_header_max_age(coap_packet_t *packet, uint32_t *age); +int coap_set_header_max_age(coap_packet_t *packet, uint32_t age); -int coap_get_header_etag(void *packet, const uint8_t **etag); -int coap_set_header_etag(void *packet, const uint8_t *etag, size_t etag_len); +int coap_get_header_etag(coap_packet_t *packet, const uint8_t **etag); +int coap_set_header_etag(coap_packet_t *packet, const uint8_t *etag, + size_t etag_len); -int coap_get_header_if_match(void *packet, const uint8_t **etag); -int coap_set_header_if_match(void *packet, const uint8_t *etag, +int coap_get_header_if_match(coap_packet_t *packet, const uint8_t **etag); +int coap_set_header_if_match(coap_packet_t *packet, const uint8_t *etag, size_t etag_len); -int coap_get_header_if_none_match(void *packet); -int coap_set_header_if_none_match(void *packet); +int coap_get_header_if_none_match(coap_packet_t *packet); +int coap_set_header_if_none_match(coap_packet_t *packet); -int coap_get_header_proxy_uri(void *packet, const char **uri); /* in-place string might not be 0-terminated. */ -int coap_set_header_proxy_uri(void *packet, const char *uri); +/* in-place string might not be 0-terminated. */ +int coap_get_header_proxy_uri(coap_packet_t *packet, const char **uri); +int coap_set_header_proxy_uri(coap_packet_t *packet, const char *uri); -int coap_get_header_proxy_scheme(void *packet, const char **scheme); /* in-place string might not be 0-terminated. */ -int coap_set_header_proxy_scheme(void *packet, const char *scheme); +/* in-place string might not be 0-terminated. */ +int coap_get_header_proxy_scheme(coap_packet_t *packet, const char **scheme); +int coap_set_header_proxy_scheme(coap_packet_t *packet, const char *scheme); -int coap_get_header_uri_host(void *packet, const char **host); /* in-place string might not be 0-terminated. */ -int coap_set_header_uri_host(void *packet, const char *host); +/* in-place string might not be 0-terminated. */ +int coap_get_header_uri_host(coap_packet_t *packet, const char **host); +int coap_set_header_uri_host(coap_packet_t *packet, const char *host); -int coap_get_header_uri_path(void *packet, const char **path); /* in-place string might not be 0-terminated. */ -int coap_set_header_uri_path(void *packet, const char *path); +/* in-place string might not be 0-terminated. */ +int coap_get_header_uri_path(coap_packet_t *packet, const char **path); +int coap_set_header_uri_path(coap_packet_t *packet, const char *path); -int coap_get_header_uri_query(void *packet, const char **query); /* in-place string might not be 0-terminated. */ -int coap_set_header_uri_query(void *packet, const char *query); +/* in-place string might not be 0-terminated. */ +int coap_get_header_uri_query(coap_packet_t *packet, const char **query); +int coap_set_header_uri_query(coap_packet_t *packet, const char *query); -int coap_get_header_location_path(void *packet, const char **path); /* in-place string might not be 0-terminated. */ -int coap_set_header_location_path(void *packet, const char *path); /* also splits optional query into Location-Query option. */ +/* in-place string might not be 0-terminated. */ +int coap_get_header_location_path(coap_packet_t *packet, const char **path); +/* also splits optional query into Location-Query option. */ +int coap_set_header_location_path(coap_packet_t *packet, const char *path); -int coap_get_header_location_query(void *packet, const char **query); /* in-place string might not be 0-terminated. */ -int coap_set_header_location_query(void *packet, const char *query); +/* in-place string might not be 0-terminated. */ +int coap_get_header_location_query(coap_packet_t *packet, const char **query); +int coap_set_header_location_query(coap_packet_t *packet, const char *query); -int coap_get_header_observe(void *packet, uint32_t *observe); -int coap_set_header_observe(void *packet, uint32_t observe); +int coap_get_header_observe(coap_packet_t *packet, uint32_t *observe); +int coap_set_header_observe(coap_packet_t *packet, uint32_t observe); -int coap_get_header_block2(void *packet, uint32_t *num, uint8_t *more, +int coap_get_header_block2(coap_packet_t *packet, uint32_t *num, uint8_t *more, uint16_t *size, uint32_t *offset); -int coap_set_header_block2(void *packet, uint32_t num, uint8_t more, +int coap_set_header_block2(coap_packet_t *packet, uint32_t num, uint8_t more, uint16_t size); -int coap_get_header_block1(void *packet, uint32_t *num, uint8_t *more, +int coap_get_header_block1(coap_packet_t *packet, uint32_t *num, uint8_t *more, uint16_t *size, uint32_t *offset); -int coap_set_header_block1(void *packet, uint32_t num, uint8_t more, +int coap_set_header_block1(coap_packet_t *packet, uint32_t num, uint8_t more, uint16_t size); -int coap_get_header_size2(void *packet, uint32_t *size); -int coap_set_header_size2(void *packet, uint32_t size); +int coap_get_header_size2(coap_packet_t *packet, uint32_t *size); +int coap_set_header_size2(coap_packet_t *packet, uint32_t size); -int coap_get_header_size1(void *packet, uint32_t *size); -int coap_set_header_size1(void *packet, uint32_t size); +int coap_get_header_size1(coap_packet_t *packet, uint32_t *size); +int coap_set_header_size1(coap_packet_t *packet, uint32_t size); -int coap_get_payload(void *packet, const uint8_t **payload); -int coap_set_payload(void *packet, const void *payload, size_t length); +int coap_get_payload(coap_packet_t *packet, const uint8_t **payload); +int coap_set_payload(coap_packet_t *packet, const void *payload, size_t length); -#endif /* ER_COAP_H_ */ +#endif /* COAP_H_ */ diff --git a/os/net/app-layer/coap/rest-constants.h b/os/net/app-layer/coap/rest-constants.h deleted file mode 100644 index addc0970b..000000000 --- a/os/net/app-layer/coap/rest-constants.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich - * 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 - * Constants for the REST Engine (Erbium). - * \author - * Matthias Kovatsch - */ - -#ifndef REST_CONSTANTS_H_ -#define REST_CONSTANTS_H_ - -/** - * Generic status codes that are mapped to either HTTP or CoAP codes. - */ -struct rest_implementation_status { - const unsigned int OK; /* CONTENT_2_05, OK_200 */ - const unsigned int CREATED; /* CREATED_2_01, CREATED_201 */ - const unsigned int CHANGED; /* CHANGED_2_04, NO_CONTENT_204 */ - const unsigned int DELETED; /* DELETED_2_02, NO_CONTENT_204 */ - const unsigned int NOT_MODIFIED; /* VALID_2_03, NOT_MODIFIED_304 */ - - const unsigned int BAD_REQUEST; /* BAD_REQUEST_4_00, BAD_REQUEST_400 */ - const unsigned int UNAUTHORIZED; /* UNAUTHORIZED_4_01, UNAUTHORIZED_401 */ - const unsigned int BAD_OPTION; /* BAD_OPTION_4_02, BAD_REQUEST_400 */ - const unsigned int FORBIDDEN; /* FORBIDDEN_4_03, FORBIDDEN_403 */ - const unsigned int NOT_FOUND; /* NOT_FOUND_4_04, NOT_FOUND_404 */ - const unsigned int METHOD_NOT_ALLOWED; /* METHOD_NOT_ALLOWED_4_05, METHOD_NOT_ALLOWED_405 */ - const unsigned int NOT_ACCEPTABLE; /* NOT_ACCEPTABLE_4_06, NOT_ACCEPTABLE_406 */ - const unsigned int REQUEST_ENTITY_TOO_LARGE; /* REQUEST_ENTITY_TOO_LARGE_4_13, REQUEST_ENTITY_TOO_LARGE_413 */ - const unsigned int UNSUPPORTED_MEDIA_TYPE; /* UNSUPPORTED_MEDIA_TYPE_4_15, UNSUPPORTED_MEDIA_TYPE_415 */ - - const unsigned int INTERNAL_SERVER_ERROR; /* INTERNAL_SERVER_ERROR_5_00, INTERNAL_SERVER_ERROR_500 */ - const unsigned int NOT_IMPLEMENTED; /* NOT_IMPLEMENTED_5_01, NOT_IMPLEMENTED_501 */ - const unsigned int BAD_GATEWAY; /* BAD_GATEWAY_5_02, BAD_GATEWAY_502 */ - const unsigned int SERVICE_UNAVAILABLE; /* SERVICE_UNAVAILABLE_5_03, SERVICE_UNAVAILABLE_503 */ - const unsigned int GATEWAY_TIMEOUT; /* GATEWAY_TIMEOUT_5_04, GATEWAY_TIMEOUT_504 */ - const unsigned int PROXYING_NOT_SUPPORTED; /* PROXYING_NOT_SUPPORTED_5_05, INTERNAL_SERVER_ERROR_500 */ -}; - -/** - * List of Content-Formats which are Internet Media Types plus encoding. - * TODO This should be a constant enum taken from CoAP for both CoAP and HTTP. - */ -struct rest_implementation_type { - unsigned int TEXT_PLAIN; - unsigned int TEXT_XML; - unsigned int TEXT_CSV; - unsigned int TEXT_HTML; - unsigned int IMAGE_GIF; - unsigned int IMAGE_JPEG; - unsigned int IMAGE_PNG; - unsigned int IMAGE_TIFF; - unsigned int AUDIO_RAW; - unsigned int VIDEO_RAW; - unsigned int APPLICATION_LINK_FORMAT; - unsigned int APPLICATION_XML; - unsigned int APPLICATION_OCTET_STREAM; - unsigned int APPLICATION_RDF_XML; - unsigned int APPLICATION_SOAP_XML; - unsigned int APPLICATION_ATOM_XML; - unsigned int APPLICATION_XMPP_XML; - unsigned int APPLICATION_EXI; - unsigned int APPLICATION_FASTINFOSET; - unsigned int APPLICATION_SOAP_FASTINFOSET; - unsigned int APPLICATION_JSON; - unsigned int APPLICATION_X_OBIX_BINARY; -}; - -/** - * Resource flags for allowed methods and special functionalities. - */ -typedef enum { - NO_FLAGS = 0, - - /* methods to handle */ - METHOD_GET = (1 << 0), - METHOD_POST = (1 << 1), - METHOD_PUT = (1 << 2), - METHOD_DELETE = (1 << 3), - - /* special flags */ - HAS_SUB_RESOURCES = (1 << 4), - IS_SEPARATE = (1 << 5), - IS_OBSERVABLE = (1 << 6), - IS_PERIODIC = (1 << 7) -} rest_resource_flags_t; - -#endif /* REST_CONSTANTS_H_ */ diff --git a/os/net/app-layer/coap/rest-engine.c b/os/net/app-layer/coap/rest-engine.c deleted file mode 100644 index cec590012..000000000 --- a/os/net/app-layer/coap/rest-engine.c +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich - * 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 - * An abstraction layer for RESTful Web services (Erbium). - * Inspired by RESTful Contiki by Dogan Yazar. - * \author - * Matthias Kovatsch - */ - -#include -#include -#include "contiki.h" -#include "rest-engine.h" - -#define DEBUG 0 -#if DEBUG -#include -#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 - -PROCESS(rest_engine_process, "REST Engine"); -/*---------------------------------------------------------------------------*/ -LIST(restful_services); -LIST(restful_periodic_services); -/*---------------------------------------------------------------------------*/ -/*- REST Engine API ---------------------------------------------------------*/ -/*---------------------------------------------------------------------------*/ -/** - * \brief Initializes and starts the REST Engine process - * - * This function must be called by server processes before any resources are - * registered through rest_activate_resource(). - */ -void -rest_init_engine(void) -{ - /* avoid initializing twice */ - static uint8_t initialized = 0; - - if(initialized) { - PRINTF("REST engine process already running - double initialization?\n"); - return; - } - initialized = 1; - - list_init(restful_services); - - REST.set_service_callback(rest_invoke_restful_service); - - /* Start the RESTful server implementation. */ - REST.init(); - - /*Start REST engine process */ - process_start(&rest_engine_process, NULL); -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Makes a resource available under the given URI path - * \param resource A pointer to a resource implementation - * \param path The URI path string for this resource - * - * The resource implementation must be imported first using the - * extern keyword. The build system takes care of compiling every - * *.c file in the ./resources/ sub-directory (see example Makefile). - */ -void -rest_activate_resource(resource_t *resource, char *path) -{ - resource->url = path; - list_add(restful_services, resource); - - PRINTF("Activating: %s\n", resource->url); - - /* Only add periodic resources with a periodic_handler and a period > 0. */ - if(resource->flags & IS_PERIODIC && resource->periodic->periodic_handler - && resource->periodic->period) { - PRINTF("Periodic resource: %p (%s)\n", resource->periodic, - resource->periodic->resource->url); - list_add(restful_periodic_services, resource->periodic); - if(process_is_running(&rest_engine_process)) { - PRINTF("Periodic: Set timer for /%s to %lu\n", - resource->url, resource->periodic->period); - PROCESS_CONTEXT_BEGIN(&rest_engine_process); - etimer_set(&resource->periodic->periodic_timer, - resource->periodic->period); - PROCESS_CONTEXT_END(&rest_engine_process); - } - } -} -/*---------------------------------------------------------------------------*/ -/*- Internal API ------------------------------------------------------------*/ -/*---------------------------------------------------------------------------*/ -list_t -rest_get_resources(void) -{ - return restful_services; -} -/*---------------------------------------------------------------------------*/ -int -rest_invoke_restful_service(void *request, void *response, uint8_t *buffer, - uint16_t buffer_size, int32_t *offset) -{ - uint8_t found = 0; - uint8_t allowed = 1; - - resource_t *resource = NULL; - const char *url = NULL; - int url_len, res_url_len; - - url_len = REST.get_url(request, &url); - for(resource = (resource_t *)list_head(restful_services); - resource; resource = resource->next) { - - /* if the web service handles that kind of requests and urls matches */ - res_url_len = strlen(resource->url); - if((url_len == res_url_len - || (url_len > res_url_len - && (resource->flags & HAS_SUB_RESOURCES) - && url[res_url_len] == '/')) - && strncmp(resource->url, url, res_url_len) == 0) { - found = 1; - rest_resource_flags_t method = REST.get_method_type(request); - - PRINTF("/%s, method %u, resource->flags %u\n", resource->url, - (uint16_t)method, resource->flags); - - if((method & METHOD_GET) && resource->get_handler != NULL) { - /* call handler function */ - resource->get_handler(request, response, buffer, buffer_size, offset); - } else if((method & METHOD_POST) && resource->post_handler != NULL) { - /* call handler function */ - resource->post_handler(request, response, buffer, buffer_size, - offset); - } else if((method & METHOD_PUT) && resource->put_handler != NULL) { - /* call handler function */ - resource->put_handler(request, response, buffer, buffer_size, offset); - } else if((method & METHOD_DELETE) && resource->delete_handler != NULL) { - /* call handler function */ - resource->delete_handler(request, response, buffer, buffer_size, - offset); - } else { - allowed = 0; - REST.set_response_status(response, REST.status.METHOD_NOT_ALLOWED); - } - break; - } - } - if(!found) { - REST.set_response_status(response, REST.status.NOT_FOUND); - } else if(allowed) { - /* final handler for special flags */ - if(resource->flags & IS_OBSERVABLE) { - REST.subscription_handler(resource, request, response); - } - } - return found & allowed; -} -/*-----------------------------------------------------------------------------------*/ -PROCESS_THREAD(rest_engine_process, ev, data) -{ - PROCESS_BEGIN(); - - /* pause to let REST server finish adding resources. */ - PROCESS_PAUSE(); - - /* initialize the PERIODIC_RESOURCE timers, which will be handled by this process. */ - periodic_resource_t *periodic_resource = NULL; - - for(periodic_resource = - (periodic_resource_t *)list_head(restful_periodic_services); - periodic_resource; periodic_resource = periodic_resource->next) { - if(periodic_resource->periodic_handler && periodic_resource->period) { - PRINTF("Periodic: Set timer for /%s to %lu\n", - periodic_resource->resource->url, periodic_resource->period); - etimer_set(&periodic_resource->periodic_timer, - periodic_resource->period); - } - } - while(1) { - PROCESS_WAIT_EVENT(); - - if(ev == PROCESS_EVENT_TIMER) { - for(periodic_resource = - (periodic_resource_t *)list_head(restful_periodic_services); - periodic_resource; periodic_resource = periodic_resource->next) { - if(periodic_resource->period - && etimer_expired(&periodic_resource->periodic_timer)) { - - PRINTF("Periodic: etimer expired for /%s (period: %lu)\n", - periodic_resource->resource->url, periodic_resource->period); - - /* Call the periodic_handler function, which was checked during adding to list. */ - (periodic_resource->periodic_handler)(); - - etimer_reset(&periodic_resource->periodic_timer); - } - } - } - } - - PROCESS_END(); -} -/*---------------------------------------------------------------------------*/ diff --git a/os/net/app-layer/coap/rest-engine.h b/os/net/app-layer/coap/rest-engine.h deleted file mode 100644 index cf9faa734..000000000 --- a/os/net/app-layer/coap/rest-engine.h +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich - * 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 - * An abstraction layer for RESTful Web services (Erbium). - * Inspired by RESTful Contiki by Dogan Yazar. - * \author - * Matthias Kovatsch - */ - -#ifndef REST_ENGINE_H_ -#define REST_ENGINE_H_ - -#include -#include "contiki.h" -#include "contiki-lib.h" -#include "rest-constants.h" - -/* NOTE: this will be removed - now it is always set to erbium CoAP implementation */ -#define REST coap_rest_implementation - -/* - * The maximum buffer size that is provided for resource responses and must be respected due to the limited IP buffer. - * Larger data must be handled by the resource and will be sent chunk-wise through a TCP stream or CoAP blocks. - */ -#ifndef REST_MAX_CHUNK_SIZE -#define REST_MAX_CHUNK_SIZE 64 -#endif - -struct resource_s; -struct periodic_resource_s; - -/* signatures of handler functions */ -typedef void (*restful_handler)(void *request, void *response, - uint8_t *buffer, uint16_t preferred_size, - int32_t *offset); -typedef void (*restful_final_handler)(struct resource_s *resource, - void *request, void *response); -typedef void (*restful_periodic_handler)(void); -typedef void (*restful_response_handler)(void *data, void *response); -typedef void (*restful_trigger_handler)(void); - -/* signature of the rest-engine service function */ -typedef int (*service_callback_t)(void *request, void *response, - uint8_t *buffer, uint16_t preferred_size, - int32_t *offset); - -/* data structure representing a resource in REST */ -struct resource_s { - struct resource_s *next; /* for LIST, points to next resource defined */ - const char *url; /*handled URL */ - rest_resource_flags_t flags; /* handled RESTful methods */ - const char *attributes; /* link-format attributes */ - restful_handler get_handler; /* handler function */ - restful_handler post_handler; /* handler function */ - restful_handler put_handler; /* handler function */ - restful_handler delete_handler; /* handler function */ - union { - struct periodic_resource_s *periodic; /* special data depending on flags */ - restful_trigger_handler trigger; - restful_trigger_handler resume; - }; -}; -typedef struct resource_s resource_t; - -struct periodic_resource_s { - struct periodic_resource_s *next; /* for LIST, points to next resource defined */ - const resource_t *resource; - uint32_t period; - struct etimer periodic_timer; - const restful_periodic_handler periodic_handler; -}; -typedef struct periodic_resource_s periodic_resource_t; - -/* - * Macro to define a RESTful resource. - * Resources are statically defined for the sake of efficiency and better memory management. - */ -#define RESOURCE(name, attributes, get_handler, post_handler, put_handler, delete_handler) \ - resource_t name = { NULL, NULL, NO_FLAGS, attributes, get_handler, post_handler, put_handler, delete_handler, { NULL } } - -#define PARENT_RESOURCE(name, attributes, get_handler, post_handler, put_handler, delete_handler) \ - resource_t name = { NULL, NULL, HAS_SUB_RESOURCES, attributes, get_handler, post_handler, put_handler, delete_handler, { NULL } } - -#define SEPARATE_RESOURCE(name, attributes, get_handler, post_handler, put_handler, delete_handler, resume_handler) \ - resource_t name = { NULL, NULL, IS_SEPARATE, attributes, get_handler, post_handler, put_handler, delete_handler, { .resume = resume_handler } } - -#define EVENT_RESOURCE(name, attributes, get_handler, post_handler, put_handler, delete_handler, event_handler) \ - resource_t name = { NULL, NULL, IS_OBSERVABLE, attributes, get_handler, post_handler, put_handler, delete_handler, { .trigger = event_handler } } - -/* - * Macro to define a periodic resource. - * The corresponding [name]_periodic_handler() function will be called every period. - * For instance polling a sensor and publishing a changed value to subscribed clients would be done there. - * The subscriber list will be maintained by the final_handler rest_subscription_handler() (see rest-mapping header file). - */ -#define PERIODIC_RESOURCE(name, attributes, get_handler, post_handler, put_handler, delete_handler, period, periodic_handler) \ - periodic_resource_t periodic_##name; \ - resource_t name = { NULL, NULL, IS_OBSERVABLE | IS_PERIODIC, attributes, get_handler, post_handler, put_handler, delete_handler, { .periodic = &periodic_##name } }; \ - periodic_resource_t periodic_##name = { NULL, &name, period, { { 0 } }, periodic_handler }; - -struct rest_implementation { - char *name; - - /** Initialize the REST implementation. */ - void (*init)(void); - - /** Register the RESTful service callback at implementation. */ - void (*set_service_callback)(service_callback_t callback); - - /** Get request URI path. */ - int (*get_url)(void *request, const char **url); - - /** Get the method of a request. */ - rest_resource_flags_t (*get_method_type)(void *request); - - /** Set the status code of a response. */ - int (*set_response_status)(void *response, unsigned int code); - - /** Get the content-type of a request. */ - int (*get_header_content_type)(void *request, - unsigned int *content_format); - - /** Set the Content-Type of a response. */ - int (*set_header_content_type)(void *response, - unsigned int content_format); - - /** Get the Accept types of a request. */ - int (*get_header_accept)(void *request, unsigned int *accept); - - /** Get the Length option of a request. */ - int (*get_header_length)(void *request, uint32_t *size); - - /** Set the Length option of a response. */ - int (*set_header_length)(void *response, uint32_t size); - - /** Get the Max-Age option of a request. */ - int (*get_header_max_age)(void *request, uint32_t *age); - - /** Set the Max-Age option of a response. */ - int (*set_header_max_age)(void *response, uint32_t age); - - /** Set the ETag option of a response. */ - int (*set_header_etag)(void *response, const uint8_t *etag, - size_t length); - - /** Get the If-Match option of a request. */ - int (*get_header_if_match)(void *request, const uint8_t **etag); - - /** Get the If-Match option of a request. */ - int (*get_header_if_none_match)(void *request); - - /** Get the Host option of a request. */ - int (*get_header_host)(void *request, const char **host); - - /** Set the location option of a response. */ - int (*set_header_location)(void *response, const char *location); - - /** Get the payload option of a request. */ - int (*get_request_payload)(void *request, const uint8_t **payload); - - /** Set the payload option of a response. */ - int (*set_response_payload)(void *response, const void *payload, - size_t length); - - /** Get the query string of a request. */ - int (*get_query)(void *request, const char **value); - - /** Get the value of a request query key-value pair. */ - int (*get_query_variable)(void *request, const char *name, - const char **value); - - /** Get the value of a request POST key-value pair. */ - int (*get_post_variable)(void *request, const char *name, - const char **value); - - /** Send the payload to all subscribers of the resource at url. */ - void (*notify_subscribers)(resource_t *resource); - - /** The handler for resource subscriptions. */ - restful_final_handler subscription_handler; - - /* REST status codes. */ - const struct rest_implementation_status status; - - /* REST content-types. */ - const struct rest_implementation_type type; -}; - -/* instance of REST implementation */ -extern const struct rest_implementation REST; - -/* - * To be called by HTTP/COAP server as a callback function when a new service request appears. - * This function dispatches the corresponding RESTful service. - */ -int rest_invoke_restful_service(void *request, void *response, - uint8_t *buffer, uint16_t buffer_size, - int32_t *offset); -/*---------------------------------------------------------------------------*/ -/** - * \brief Initializes REST framework and starts the HTTP or CoAP process. - */ -void rest_init_engine(void); -/*---------------------------------------------------------------------------*/ -/** - * - * \brief Resources wanted to be accessible should be activated with the following code. - * \param resource - * A RESTful resource defined through the RESOURCE macros. - * \param path - * The local URI path where to provide the resource. - */ -void rest_activate_resource(resource_t *resource, char *path); -/*---------------------------------------------------------------------------*/ -/** - * \brief Returns the list of registered RESTful resources. - * \return The resource list. - */ -list_t rest_get_resources(void); -/*---------------------------------------------------------------------------*/ - -#endif /*REST_ENGINE_H_ */ diff --git a/os/net/app-layer/coap/tinydtls-support/dtls-support-conf.h b/os/net/app-layer/coap/tinydtls-support/dtls-support-conf.h new file mode 100644 index 000000000..b1dbacd7d --- /dev/null +++ b/os/net/app-layer/coap/tinydtls-support/dtls-support-conf.h @@ -0,0 +1,27 @@ +#ifndef DTLS_SUPPORT_CONF_H_ +#define DTLS_SUPPORT_CONF_H_ + +#undef HAVE_VPRINTF + +#include "coap-endpoint.h" + +typedef coap_endpoint_t session_t; + +#include "sys/ctimer.h" +#include + +typedef struct { + struct ctimer retransmit_timer; +} dtls_support_context_state_t; + +#define DTLS_SUPPORT_CONF_CONTEXT_STATE dtls_support_context_state_t + +#define DTLS_TICKS_PER_SECOND CLOCK_SECOND + +typedef clock_time_t dtls_tick_t; + +#define WITH_CONTIKI 1 + +#define HAVE_ASSERT_H 1 + +#endif /* DTLS_SUPPORT_CONF_H_ */ diff --git a/os/net/app-layer/coap/tinydtls-support/dtls-support.c b/os/net/app-layer/coap/tinydtls-support/dtls-support.c new file mode 100644 index 000000000..17dceddc9 --- /dev/null +++ b/os/net/app-layer/coap/tinydtls-support/dtls-support.c @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2017, RISE SICS AB. + * 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 copyright holder 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 COPYRIGHT HOLDER 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 + * COPYRIGHT HOLDER 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. + */ + +/** + * \file + * DTLS support for CoAP + * \author + * Niclas Finne + * Joakim Eriksson + */ + +#include "dtls-support.h" +#include "lib/random.h" +#include +#include + +#define DEBUG DEBUG_FULLY +#include "dtls_debug.h" + +static dtls_context_t the_dtls_context; +static dtls_cipher_context_t cipher_context; +static uint8_t lock_context = 0; +/*---------------------------------------------------------------------------*/ +dtls_context_t * +dtls_context_acquire(void) +{ + if(lock_context) { + return NULL; + } + lock_context = 1; + PRINTF("DS: Allocated context\n"); + return &the_dtls_context; +} +/*---------------------------------------------------------------------------*/ +void +dtls_context_release(dtls_context_t *context) +{ + if(context == &the_dtls_context) { + lock_context = 0; + } +} +/*---------------------------------------------------------------------------*/ +dtls_cipher_context_t * +dtls_cipher_context_acquire(void) +{ + return &cipher_context; +} +/*---------------------------------------------------------------------------*/ +void +dtls_cipher_context_release(dtls_cipher_context_t *c) +{ +} +/*---------------------------------------------------------------------------*/ +void +dtls_ticks(dtls_tick_t *t) +{ + *t = clock_time(); +} +/*---------------------------------------------------------------------------*/ +int +dtls_fill_random(uint8_t *buf, size_t len) +{ + int i; + if(buf) { + for(i = 0; i < len; i++) { + buf[i] = random_rand() & 0xff; + } + return 1; + } + return 0; +} +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* message retransmission */ +/*---------------------------------------------------------------------------*/ +static void +dtls_retransmit_callback(void *ptr) +{ + dtls_context_t *ctx; + clock_time_t now; + clock_time_t next; + + ctx = ptr; + now = clock_time(); + /* Just one retransmission per timer scheduling */ + dtls_check_retransmit(ctx, &next, 0); + + /* need to set timer to some value even if no nextpdu is available */ + if(next != 0) { + ctimer_set(&ctx->support.retransmit_timer, + next <= now ? 1 : next - now, + dtls_retransmit_callback, ctx); + } +} +/*---------------------------------------------------------------------------*/ +void +dtls_set_retransmit_timer(dtls_context_t *ctx, unsigned int timeout) +{ + ctimer_set(&ctx->support.retransmit_timer, timeout, + dtls_retransmit_callback, ctx); +} +/*---------------------------------------------------------------------------*/ +void +dtls_session_init(session_t *sess) +{ + memset(sess, 0, sizeof(session_t)); +} +/*---------------------------------------------------------------------------*/ +int +dtls_session_equals(const session_t *a, const session_t *b) +{ + coap_endpoint_t *e1 = (coap_endpoint_t *)a; + coap_endpoint_t *e2 = (coap_endpoint_t *)b; + +#if DEBUG + printf(" **** EP:"); + coap_endpoint_print(e1); + printf(" =?= "); + coap_endpoint_print(e2); + printf(" => %d\n", coap_endpoint_cmp(e1, e2)); +#endif /* DEBUG */ + + return coap_endpoint_cmp(e1, e2); +} +/*---------------------------------------------------------------------------*/ +void * +dtls_session_get_address(const session_t *a) +{ + /* improve this to only contain the addressing info */ + return (void *)a; +} +/*---------------------------------------------------------------------------*/ +int dtls_session_get_address_size(const session_t *a) +{ + /* improve this to only contain the addressing info */ + return sizeof(session_t); +} +/*---------------------------------------------------------------------------*/ +void +dtls_session_print(const session_t *a) +{ + coap_endpoint_print((const coap_endpoint_t *)a); +} +/*---------------------------------------------------------------------------*/ +size_t +dsrv_print_addr(const session_t *addr, char *buf, size_t len) +{ + if(len > 1) { + /* TODO print endpoint */ + buf[0] = '['; + buf[1] = ']'; + return 2; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +extern char *loglevels[]; +static inline size_t +print_timestamp(log_t level) +{ + dtls_tick_t now; + dtls_ticks(&now); + if(level <= DTLS_LOG_DEBUG) { + printf("%s ", loglevels[level]); + } + return printf("%5lu ", (unsigned long)now); +} +/*---------------------------------------------------------------------------*/ +#ifdef HAVE_VPRINTF +void +dsrv_log(log_t level, char *format, ...) +{ + va_list ap; + + if(dtls_get_log_level() < level) { + return; + } + + print_timestamp(level); + + va_start(ap, format); + vprintf(format, ap); + va_end(ap); +} + +#endif /* HAVE_VPRINTF */ +/*---------------------------------------------------------------------------*/ +void +dtls_dsrv_hexdump_log(log_t level, const char *name, const unsigned char *buf, size_t length, int extend) +{ + int n = 0; + + if(dtls_get_log_level() < level) { + return; + } + + print_timestamp(level); + + if(extend) { + printf("%s: (%zu bytes):\n", name, length); + + while(length--) { + if(n % 16 == 0) { + printf("%08X ", n); + } + printf("%02X ", *buf++); + + n++; + if(n % 8 == 0) { + if(n % 16 == 0) { + printf("\n"); + } else { + printf(" "); + } + } + } + } else { + printf("%s: (%zu bytes): ", name, length); + while(length--) { + printf("%02X", *buf++); + } + } + printf("\n"); +} +/*---------------------------------------------------------------------------*/ +void +dtls_support_init(void) +{ + dtls_info("dtls_support_init.\n"); +} +/*---------------------------------------------------------------------------*/ From 49d9ec182d988ea05bdb891e4c7ffacbc2ed1dd4 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Wed, 25 Oct 2017 02:20:05 +0200 Subject: [PATCH 03/51] Imported OMA LWM2M from lwm2m-contiki at https://github.com/sics-iot/lwm2m-contiki --- os/services/lwm2m/Makefile.lwm2m | 1 - os/services/lwm2m/lwm2m-device.c | 218 +- os/services/lwm2m/lwm2m-device.h | 5 + os/services/lwm2m/lwm2m-engine.c | 2293 ++++++++++------- os/services/lwm2m/lwm2m-engine.h | 73 +- os/services/lwm2m/lwm2m-firmware.c | 167 ++ os/services/lwm2m/lwm2m-firmware.h | 45 + os/services/lwm2m/lwm2m-json.c | 201 +- os/services/lwm2m/lwm2m-json.h | 10 + os/services/lwm2m/lwm2m-object.c | 336 --- os/services/lwm2m/lwm2m-object.h | 563 ++-- os/services/lwm2m/lwm2m-plain-text.c | 52 +- os/services/lwm2m/lwm2m-rd-client.c | 729 ++++++ os/services/lwm2m/lwm2m-rd-client.h | 85 + os/services/lwm2m/lwm2m-security.c | 440 +++- os/services/lwm2m/lwm2m-security.h | 73 + os/services/lwm2m/lwm2m-server.c | 257 +- os/services/lwm2m/lwm2m-server.h | 59 + .../{oma-tlv-reader.c => lwm2m-tlv-reader.c} | 41 +- .../{oma-tlv-reader.h => lwm2m-tlv-reader.h} | 8 +- os/services/lwm2m/lwm2m-tlv-writer.c | 175 ++ .../{oma-tlv-writer.h => lwm2m-tlv-writer.h} | 8 +- os/services/lwm2m/{oma-tlv.c => lwm2m-tlv.c} | 104 +- os/services/lwm2m/{oma-tlv.h => lwm2m-tlv.h} | 47 +- os/services/lwm2m/oma-tlv-writer.c | 89 - 25 files changed, 4229 insertions(+), 1850 deletions(-) delete mode 100644 os/services/lwm2m/Makefile.lwm2m create mode 100644 os/services/lwm2m/lwm2m-firmware.c create mode 100644 os/services/lwm2m/lwm2m-firmware.h delete mode 100644 os/services/lwm2m/lwm2m-object.c create mode 100644 os/services/lwm2m/lwm2m-rd-client.c create mode 100644 os/services/lwm2m/lwm2m-rd-client.h create mode 100644 os/services/lwm2m/lwm2m-security.h create mode 100644 os/services/lwm2m/lwm2m-server.h rename os/services/lwm2m/{oma-tlv-reader.c => lwm2m-tlv-reader.c} (76%) rename os/services/lwm2m/{oma-tlv-reader.h => lwm2m-tlv-reader.h} (93%) create mode 100644 os/services/lwm2m/lwm2m-tlv-writer.c rename os/services/lwm2m/{oma-tlv-writer.h => lwm2m-tlv-writer.h} (93%) rename os/services/lwm2m/{oma-tlv.c => lwm2m-tlv.c} (75%) rename os/services/lwm2m/{oma-tlv.h => lwm2m-tlv.h} (67%) delete mode 100644 os/services/lwm2m/oma-tlv-writer.c diff --git a/os/services/lwm2m/Makefile.lwm2m b/os/services/lwm2m/Makefile.lwm2m deleted file mode 100644 index 47c4fe5da..000000000 --- a/os/services/lwm2m/Makefile.lwm2m +++ /dev/null @@ -1 +0,0 @@ -CFLAGS += -DHAVE_OMA_LWM2M=1 diff --git a/os/services/lwm2m/lwm2m-device.c b/os/services/lwm2m/lwm2m-device.c index a911c7c4a..8436f67aa 100644 --- a/os/services/lwm2m/lwm2m-device.c +++ b/os/services/lwm2m/lwm2m-device.c @@ -44,6 +44,7 @@ #include "lwm2m-object.h" #include "lwm2m-device.h" #include "lwm2m-engine.h" +#include #define DEBUG 0 #if DEBUG @@ -53,100 +54,175 @@ #define PRINTF(...) #endif +static const lwm2m_resource_id_t resources[] = + { RO(LWM2M_DEVICE_MANUFACTURER_ID), + RO(LWM2M_DEVICE_MODEL_NUMBER_ID), + RO(LWM2M_DEVICE_SERIAL_NUMBER_ID), + RO(LWM2M_DEVICE_FIRMWARE_VERSION_ID), + RO(LWM2M_DEVICE_AVAILABLE_POWER_SOURCES), /* Multi-resource-instance */ + RO(LWM2M_DEVICE_POWER_SOURCE_VOLTAGE), /* Multi-resource-instance */ + RO(LWM2M_DEVICE_POWER_SOURCE_CURRENT), /* Multi-resource-instance */ + RO(LWM2M_DEVICE_TYPE_ID), + EX(LWM2M_DEVICE_REBOOT_ID), + RW(LWM2M_DEVICE_TIME_ID), + EX(LWM2M_DEVICE_FACTORY_DEFAULT_ID), + }; + +#ifndef LWM2M_DEVICE_MANUFACTURER +#define LWM2M_DEVICE_MANUFACTURER "RISE SICS" +#endif +#ifndef LWM2M_DEVICE_MODEL_NUMBER +#define LWM2M_DEVICE_MODEL_NUMBER "1" +#endif +#ifndef LWM2M_DEVICE_SERIAL_NUMBER +#define LWM2M_DEVICE_SERIAL_NUMBER "1" +#endif +#ifndef LWM2M_DEVICE_FIRMWARE_VERSION +#define LWM2M_DEVICE_FIRMWARE_VERSION CONTIKI_VERSION +#endif +#ifndef LWM2M_DEVICE_TYPE +#define LWM2M_DEVICE_TYPE "Contiki-NG LWM2M" +#endif + +/* All three must be defined */ +#ifndef LWM2M_DEVICE_POWER_AVAILABLE +#define LWM2M_DEVICE_POWER_AVAILABLE {1,5} +#define LWM2M_DEVICE_POWER_VOLTAGE {2500,5000} +#define LWM2M_DEVICE_POWER_CURRENT {500,1000} +#endif + static int32_t time_offset = 0; + +/* Internal battery and USB - just for test...*/ +static uint16_t power_avail[] = LWM2M_DEVICE_POWER_AVAILABLE; +static uint16_t power_voltage[] = LWM2M_DEVICE_POWER_VOLTAGE; +static uint16_t power_current[] = LWM2M_DEVICE_POWER_CURRENT; /*---------------------------------------------------------------------------*/ -static int -read_lwtime(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outsize) +int32_t +lwm2m_device_get_time(void) { - return ctx->writer->write_int(ctx, outbuf, outsize, - time_offset + clock_seconds()); + return coap_timer_seconds() + time_offset; +} +/*---------------------------------------------------------------------------*/ +void +lwm2m_device_set_time(int32_t time) +{ + time_offset = time - coap_timer_seconds(); +} +/*---------------------------------------------------------------------------*/ +static lwm2m_status_t +write_string(lwm2m_context_t *ctx, const char *text) +{ + lwm2m_object_write_string(ctx, text, strlen(text)); + return LWM2M_STATUS_OK; } /*---------------------------------------------------------------------------*/ static int -set_lwtime(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t insize, - uint8_t *outbuf, size_t outsize) +output_multi_i16(lwm2m_context_t *ctx, const uint16_t *data, int count) { - /* assume that this only read one TLV value */ - int32_t lw_time; - size_t len = ctx->reader->read_int(ctx, inbuf, insize, &lw_time); - if(len == 0) { - PRINTF("FAIL: could not read time '%*.s'\n", (int)insize, inbuf); - } else { - PRINTF("Got: time: %*.s => %" PRId32 "\n", (int)insize, inbuf, lw_time); - - time_offset = lw_time - clock_seconds(); - PRINTF("Write time...%" PRId32 " => offset = %" PRId32 "\n", - lw_time, time_offset); + int i; + size_t len; + len = lwm2m_object_write_enter_ri(ctx); + for(i = 0; i < count; i++) { + len += lwm2m_object_write_int_ri(ctx, i, data[i]); } - /* return the number of bytes read */ + len += lwm2m_object_write_exit_ri(ctx); return len; } + /*---------------------------------------------------------------------------*/ -#ifdef PLATFORM_REBOOT -static struct ctimer reboot_timer; -static void -do_the_reboot(void *ptr) -{ - PLATFORM_REBOOT(); -} static int -reboot(lwm2m_context_t *ctx, const uint8_t *arg, size_t argsize, - uint8_t *outbuf, size_t outsize) +lwm2m_dim_callback(lwm2m_object_instance_t *object, uint16_t resource_id) { - PRINTF("Device will reboot!\n"); - ctimer_set(&reboot_timer, CLOCK_SECOND / 2, do_the_reboot, NULL); + switch(resource_id) { + case LWM2M_DEVICE_AVAILABLE_POWER_SOURCES: + case LWM2M_DEVICE_POWER_SOURCE_VOLTAGE: + case LWM2M_DEVICE_POWER_SOURCE_CURRENT: + return sizeof(power_avail) / sizeof(uint16_t); + break; + } + /* zero means that it is no dim parameter to send?? */ return 0; } -#endif /* PLATFORM_REBOOT */ /*---------------------------------------------------------------------------*/ -#ifdef PLATFORM_FACTORY_DEFAULT -static int -factory_reset(lwm2m_context_t *ctx, const uint8_t *arg, size_t arg_size, - uint8_t *outbuf, size_t outsize) +static lwm2m_status_t +lwm2m_callback(lwm2m_object_instance_t *object, lwm2m_context_t *ctx) { - PRINTF("Device will do factory default!\n"); - PLATFORM_FACTORY_DEFAULT(); - return 0; + if(ctx->operation == LWM2M_OP_READ) { + switch(ctx->resource_id) { + case LWM2M_DEVICE_MANUFACTURER_ID: + return write_string(ctx, LWM2M_DEVICE_MANUFACTURER); + case LWM2M_DEVICE_MODEL_NUMBER_ID: + return write_string(ctx, LWM2M_DEVICE_MODEL_NUMBER); + case LWM2M_DEVICE_SERIAL_NUMBER_ID: + return write_string(ctx, LWM2M_DEVICE_SERIAL_NUMBER); + case LWM2M_DEVICE_FIRMWARE_VERSION_ID: + return write_string(ctx, LWM2M_DEVICE_FIRMWARE_VERSION); + case LWM2M_DEVICE_TYPE_ID: + return write_string(ctx, LWM2M_DEVICE_TYPE); + case LWM2M_DEVICE_TIME_ID: + PRINTF("Reading time: %u\n", (unsigned int)lwm2m_device_get_time()); + lwm2m_object_write_int(ctx, lwm2m_device_get_time()); + return LWM2M_STATUS_OK; + case LWM2M_DEVICE_AVAILABLE_POWER_SOURCES: + /* Power Multi-resource case - just use array index as ID */ + output_multi_i16(ctx, power_avail, + sizeof(power_avail)/sizeof(uint16_t)); + return LWM2M_STATUS_OK; + case LWM2M_DEVICE_POWER_SOURCE_VOLTAGE: + output_multi_i16(ctx, power_voltage, + sizeof(power_voltage)/sizeof(uint16_t)); + return LWM2M_STATUS_OK; + case LWM2M_DEVICE_POWER_SOURCE_CURRENT: + output_multi_i16(ctx, power_current, + sizeof(power_current)/sizeof(uint16_t)); + return LWM2M_STATUS_OK; + default: + PRINTF("lwm2m-device: Not found: %u\n", ctx->resource_id); + return LWM2M_STATUS_NOT_FOUND; + } + + } else if(ctx->operation == LWM2M_OP_EXECUTE) { + if(ctx->resource_id == LWM2M_DEVICE_REBOOT_ID) { + /* Do THE REBOOT */ + PRINTF("REBOOT\n"); + return LWM2M_STATUS_OK; + } + + } else if(ctx->operation == LWM2M_OP_WRITE) { + if(ctx->resource_id == LWM2M_DEVICE_TIME_ID) { + int32_t lw_time; + size_t len; + len = lwm2m_object_read_int(ctx, ctx->inbuf->buffer, ctx->inbuf->size, + &lw_time); + if(len == 0) { + PRINTF("FAIL: could not write time\n"); + return LWM2M_STATUS_WRITE_ERROR; + } else { + lwm2m_device_set_time(lw_time); + PRINTF("Write time %lu sec => offset = %ld\n", + (unsigned long)lw_time, (long)time_offset); + return LWM2M_STATUS_OK; + } + } + } + + return LWM2M_STATUS_OPERATION_NOT_ALLOWED; } -#endif /* PLATFORM_FACTORY_DEFAULT */ /*---------------------------------------------------------------------------*/ -LWM2M_RESOURCES(device_resources, -#ifdef LWM2M_DEVICE_MANUFACTURER - LWM2M_RESOURCE_STRING(0, LWM2M_DEVICE_MANUFACTURER), -#endif /* LWM2M_DEVICE_MANUFACTURER */ -#ifdef LWM2M_DEVICE_TYPE - LWM2M_RESOURCE_STRING(17, LWM2M_DEVICE_TYPE), -#endif /* LWM2M_DEVICE_TYPE */ -#ifdef LWM2M_DEVICE_MODEL_NUMBER - LWM2M_RESOURCE_STRING(1, LWM2M_DEVICE_MODEL_NUMBER), -#endif /* LWM2M_DEVICE_MODEL_NUMBER */ -#ifdef LWM2M_DEVICE_SERIAL_NO - LWM2M_RESOURCE_STRING(2, LWM2M_DEVICE_SERIAL_NO), -#endif /* LWM2M_DEVICE_SERIAL_NO */ -#ifdef LWM2M_DEVICE_FIRMWARE_VERSION - LWM2M_RESOURCE_STRING(3, LWM2M_DEVICE_FIRMWARE_VERSION), -#endif /* LWM2M_DEVICE_FIRMWARE_VERSION */ -#ifdef PLATFORM_REBOOT - LWM2M_RESOURCE_CALLBACK(4, { NULL, NULL, reboot }), -#endif /* PLATFORM_REBOOT */ -#ifdef PLATFORM_FACTORY_DEFAULT - LWM2M_RESOURCE_CALLBACK(5, { NULL, NULL, factory_reset }), -#endif /* PLATFORM_FACTORY_DEFAULT */ - /* Current Time */ - LWM2M_RESOURCE_CALLBACK(13, { read_lwtime, set_lwtime, NULL }), - ); -LWM2M_INSTANCES(device_instances, LWM2M_INSTANCE(0, device_resources)); -LWM2M_OBJECT(device, 3, device_instances); +static lwm2m_object_instance_t device = { + .object_id = LWM2M_OBJECT_DEVICE_ID, + .instance_id = 0, + .resource_ids = resources, + .resource_count = sizeof(resources) / sizeof(lwm2m_resource_id_t), + .resource_dim_callback = lwm2m_dim_callback, + .callback = lwm2m_callback, +}; /*---------------------------------------------------------------------------*/ void lwm2m_device_init(void) { - /** - * Register this device and its handlers - the handlers - * automatically sends in the object to handle. - */ - PRINTF("*** Init lwm2m-device\n"); - lwm2m_engine_register_object(&device); + lwm2m_engine_add_object(&device); } /*---------------------------------------------------------------------------*/ /** @} */ diff --git a/os/services/lwm2m/lwm2m-device.h b/os/services/lwm2m/lwm2m-device.h index 4587822d5..2800038c8 100644 --- a/os/services/lwm2m/lwm2m-device.h +++ b/os/services/lwm2m/lwm2m-device.h @@ -53,9 +53,14 @@ #endif /* LWM2M_DEVICE_MODEL_NUMBER */ #ifndef LWM2M_DEVICE_FIRMWARE_VERSION +#ifdef CONTIKI_VERSION_STRING #define LWM2M_DEVICE_FIRMWARE_VERSION CONTIKI_VERSION_STRING +#endif /* CONTIKI_VERSION_STRING */ #endif /* LWM2M_DEVICE_FIRMWARE_VERSION */ +int32_t lwm2m_device_get_time(void); +void lwm2m_device_set_time(int32_t time); + void lwm2m_device_init(void); #endif /* LWM2M_DEVICE_H_ */ diff --git a/os/services/lwm2m/lwm2m-engine.c b/os/services/lwm2m/lwm2m-engine.c index 1e313718f..33783bb4e 100644 --- a/os/services/lwm2m/lwm2m-engine.c +++ b/os/services/lwm2m/lwm2m-engine.c @@ -41,29 +41,38 @@ * Niclas Finne */ -#include "contiki.h" #include "lwm2m-engine.h" #include "lwm2m-object.h" #include "lwm2m-device.h" #include "lwm2m-plain-text.h" #include "lwm2m-json.h" -#include "net/app-layer/coap/rest-engine.h" -#include "net/app-layer/coap/coap-constants.h" -#include "net/app-layer/coap/coap-engine.h" -#include "oma-tlv.h" -#include "oma-tlv-reader.h" -#include "oma-tlv-writer.h" -#include "net/ipv6/uip-ds6.h" +#include "coap-constants.h" +#include "coap-engine.h" +#include "lwm2m-tlv.h" +#include "lwm2m-tlv-reader.h" +#include "lwm2m-tlv-writer.h" +#include "lib/list.h" #include #include #include #if UIP_CONF_IPV6_RPL #include "rpl.h" +#include "net/ipv6/uip-ds6.h" #endif /* UIP_CONF_IPV6_RPL */ -#define DEBUG DEBUG_NONE -#include "net/ipv6/uip-debug.h" +#define DEBUG 0 +#if DEBUG +#define PRINTF(...) printf(__VA_ARGS__) +#define PRINTS(l,s,f) do { int i; \ + for(i = 0; i < l; i++) printf(f, s[i]); \ + } while(0) +#define PRINTPRE(p,l,s) do { PRINTF(p);PRINTS(l,s,"%c"); } while(0); +#else +#define PRINTF(...) +#define PRINTS(l,s,f) +#define PRINTPRE(p,l,s); +#endif #ifndef LWM2M_ENGINE_CLIENT_ENDPOINT_PREFIX #ifdef LWM2M_DEVICE_MODEL_NUMBER @@ -73,341 +82,436 @@ #endif /* LWM2M_DEVICE_MODEL_NUMBER */ #endif /* LWM2M_ENGINE_CLIENT_ENDPOINT_PREFIX */ -#ifdef LWM2M_ENGINE_CONF_MAX_OBJECTS -#define MAX_OBJECTS LWM2M_ENGINE_CONF_MAX_OBJECTS -#else /* LWM2M_ENGINE_CONF_MAX_OBJECTS */ -#define MAX_OBJECTS 10 -#endif /* LWM2M_ENGINE_CONF_MAX_OBJECTS */ +#ifdef LWM2M_ENGINE_CONF_USE_RD_CLIENT +#define USE_RD_CLIENT LWM2M_ENGINE_CONF_USE_RD_CLIENT +#else +#define USE_RD_CLIENT 1 +#endif /* LWM2M_ENGINE_CONF_USE_RD_CLIENT */ -#define REMOTE_PORT UIP_HTONS(COAP_DEFAULT_PORT) -#define BS_REMOTE_PORT UIP_HTONS(5685) +#if USE_RD_CLIENT +#include "lwm2m-rd-client.h" +#endif -static const lwm2m_object_t *objects[MAX_OBJECTS]; -static char endpoint[32]; -static char rd_data[128]; /* allocate some data for the RD */ +/* MACRO for getting out resource ID from resource array ID + flags */ +#define RSC_ID(x) ((uint16_t)(x & 0xffff)) +#define RSC_READABLE(x) ((x & LWM2M_RESOURCE_READ) > 0) +#define RSC_WRITABLE(x) ((x & LWM2M_RESOURCE_WRITE) > 0) -PROCESS(lwm2m_rd_client, "LWM2M Engine"); +/* invalid instance ID - ffff object ID */ +#define NO_INSTANCE 0xffffffff -static uip_ipaddr_t server_ipaddr; -static uint16_t server_port = REMOTE_PORT; -static uip_ipaddr_t bs_server_ipaddr; -static uint16_t bs_server_port = BS_REMOTE_PORT; +/* This is a double-buffer for generating BLOCKs in CoAP - the idea + is that typical LWM2M resources will fit 1 block unless they themselves + handle BLOCK transfer - having a double sized buffer makes it possible + to allow writing more than one block before sending the full block. + The RFC seems to indicate that all blocks execept the last one should + be full. +*/ +static uint8_t d_buf[COAP_MAX_BLOCK_SIZE * 2]; +static lwm2m_buffer_t lwm2m_buf = { + .len = 0, .size = COAP_MAX_BLOCK_SIZE * 2, .buffer = d_buf +}; +static lwm2m_object_instance_t instance_buffer; -static uint8_t use_bootstrap = 0; -static uint8_t has_bootstrap_server_info = 0; -static uint8_t use_registration = 0; -static uint8_t has_registration_server_info = 0; -static uint8_t registered = 0; -static uint8_t bootstrapped = 0; /* bootstrap made... */ +/* obj-id / ... */ +static uint16_t lwm2m_buf_lock[4]; +static uint64_t lwm2m_buf_lock_timeout = 0; -void lwm2m_device_init(void); -void lwm2m_security_init(void); -void lwm2m_server_init(void); +static lwm2m_write_opaque_callback current_opaque_callback; +static int current_opaque_offset = 0; + +static coap_handler_status_t lwm2m_handler_callback(coap_packet_t *request, + coap_packet_t *response, + uint8_t *buffer, + uint16_t buffer_size, + int32_t *offset); +static lwm2m_object_instance_t * +next_object_instance(const lwm2m_context_t *context, lwm2m_object_t *object, lwm2m_object_instance_t *last); + + +COAP_HANDLER(lwm2m_handler, lwm2m_handler_callback); +LIST(object_list); +LIST(generic_object_list); -static const lwm2m_instance_t *get_first_instance_of_object(uint16_t id, lwm2m_context_t *context); -static const lwm2m_instance_t *get_instance(const lwm2m_object_t *object, lwm2m_context_t *context, int depth); -static const lwm2m_resource_t *get_resource(const lwm2m_instance_t *instance, lwm2m_context_t *context); /*---------------------------------------------------------------------------*/ -static void -client_chunk_handler(void *response) +static lwm2m_object_t * +get_object(uint16_t object_id) { -#if (DEBUG) & DEBUG_PRINT - const uint8_t *chunk; - - int len = coap_get_payload(response, &chunk); - - PRINTF("|%.*s\n", len, (char *)chunk); -#endif /* (DEBUG) & DEBUG_PRINT */ -} -/*---------------------------------------------------------------------------*/ -static int -index_of(const uint8_t *data, int offset, int len, uint8_t c) -{ - if(offset < 0) { - return offset; - } - for(; offset < len; offset++) { - if(data[offset] == c) { - return offset; + lwm2m_object_t *object; + for(object = list_head(generic_object_list); + object != NULL; + object = object->next) { + if(object->impl && object->impl->object_id == object_id) { + return object; } } - return -1; + return NULL; } /*---------------------------------------------------------------------------*/ static int -has_network_access(void) +has_non_generic_object(uint16_t object_id) { -#if UIP_CONF_IPV6_RPL - if(rpl_get_any_dag() == NULL) { + lwm2m_object_instance_t *instance; + for(instance = list_head(object_list); + instance != NULL; + instance = instance->next) { + if(instance->object_id == object_id) { + return 1; + } + } + + return 0; +} +/*---------------------------------------------------------------------------*/ +static lwm2m_object_instance_t * +get_instance(uint16_t object_id, uint16_t instance_id, lwm2m_object_t **o) +{ + lwm2m_object_instance_t *instance; + lwm2m_object_t *object; + + if(o) { + *o = NULL; + } + + for(instance = list_head(object_list); + instance != NULL; + instance = instance->next) { + if(instance->object_id == object_id) { + if(instance->instance_id == instance_id || + instance_id == LWM2M_OBJECT_INSTANCE_NONE) { + return instance; + } + } + } + + object = get_object(object_id); + if(object != NULL) { + if(o) { + *o = object; + } + if(instance_id == LWM2M_OBJECT_INSTANCE_NONE) { + return object->impl->get_first(NULL); + } + return object->impl->get_by_id(instance_id, NULL); + } + + return NULL; +} +/*---------------------------------------------------------------------------*/ +static lwm2m_object_instance_t * +get_instance_by_context(const lwm2m_context_t *context, lwm2m_object_t **o) +{ + if(context->level < 2) { + return get_instance(context->object_id, LWM2M_OBJECT_INSTANCE_NONE, o); + } + return get_instance(context->object_id, context->object_instance_id, o); +} +/*---------------------------------------------------------------------------*/ +static lwm2m_status_t +call_instance(lwm2m_object_instance_t *instance, lwm2m_context_t *context) +{ + if(context->level < 3) { + return LWM2M_STATUS_OPERATION_NOT_ALLOWED; + } + + if(instance == NULL) { + /* No instance */ + return LWM2M_STATUS_NOT_FOUND; + } + + if(instance->callback == NULL) { + return LWM2M_STATUS_ERROR; + } + + return instance->callback(instance, context); +} +/*---------------------------------------------------------------------------*/ +/* This is intended to switch out a block2 transfer buffer + * It assumes that ctx containts the double buffer and that the outbuf is to + * be the new buffer in ctx. + */ +static int +double_buffer_flush(lwm2m_buffer_t *ctxbuf, lwm2m_buffer_t *outbuf, int size) +{ + /* Copy the data from the double buffer in ctx to the outbuf and move data */ + /* If the buffer is less than size - we will output all and get remaining down + to zero */ + if(ctxbuf->len < size) { + size = ctxbuf->len; + } + if(ctxbuf->len >= size && outbuf->size >= size) { + PRINTF("Double buffer - copying out %d bytes remaining: %d\n", + size, ctxbuf->len - size); + memcpy(outbuf->buffer, ctxbuf->buffer, size); + memcpy(ctxbuf->buffer, &ctxbuf->buffer[size], + ctxbuf->len - size); + ctxbuf->len -= size; + outbuf->len = size; + return outbuf->len; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +#if DEBUG +static inline const char * +get_method_as_string(coap_resource_flags_t method) +{ + if(method == METHOD_GET) { + return "GET"; + } else if(method == METHOD_POST) { + return "POST"; + } else if(method == METHOD_PUT) { + return "PUT"; + } else if(method == METHOD_DELETE) { + return "DELETE"; + } else { + return "UNKNOWN"; + } +} +#endif /* DEBUG */ +/*--------------------------------------------------------------------------*/ +#if DEBUG +static const char * +get_status_as_string(lwm2m_status_t status) +{ + static char buffer[8]; + switch(status) { + case LWM2M_STATUS_OK: + return "OK"; + case LWM2M_STATUS_ERROR: + return "ERROR"; + case LWM2M_STATUS_WRITE_ERROR: + return "WRITE ERROR"; + case LWM2M_STATUS_READ_ERROR: + return "READ ERROR"; + case LWM2M_STATUS_BAD_REQUEST: + return "BAD REQUEST"; + case LWM2M_STATUS_UNAUTHORIZED: + return "UNAUTHORIZED"; + case LWM2M_STATUS_FORBIDDEN: + return "FORBIDDEN"; + case LWM2M_STATUS_NOT_FOUND: + return "NOT FOUND"; + case LWM2M_STATUS_OPERATION_NOT_ALLOWED: + return "OPERATION NOT ALLOWED"; + case LWM2M_STATUS_NOT_ACCEPTABLE: + return "NOT ACCEPTABLE"; + case LWM2M_STATUS_UNSUPPORTED_CONTENT_FORMAT: + return "UNSUPPORTED CONTENT FORMAT"; + case LWM2M_STATUS_NOT_IMPLEMENTED: + return "NOT IMPLEMENTED"; + case LWM2M_STATUS_SERVICE_UNAVAILABLE: + return "SERVICE UNAVAILABLE"; + default: + snprintf(buffer, sizeof(buffer) - 1, "<%u>", status); + return buffer; + } +} +#endif /* DEBUG */ +/*--------------------------------------------------------------------------*/ +static int +parse_path(const char *path, int path_len, + uint16_t *oid, uint16_t *iid, uint16_t *rid) +{ + int ret; + int pos; + uint16_t val; + char c = 0; + + /* get object id */ + PRINTF("lwm2m: parse PATH: \""); + PRINTS(path_len, path, "%c"); + PRINTF("\"\n"); + + ret = 0; + pos = 0; + do { + val = 0; + /* we should get a value first - consume all numbers */ + while(pos < path_len && (c = path[pos]) >= '0' && c <= '9') { + val = val * 10 + (c - '0'); + pos++; + } + /* Slash will mote thing forward - and the end will be when pos == pl */ + if(c == '/' || pos == path_len) { + /* PRINTF("Setting %u = %u\n", ret, val); */ + if(ret == 0) *oid = val; + if(ret == 1) *iid = val; + if(ret == 2) *rid = val; + ret++; + pos++; + } else { + /* PRINTF("Error: illegal char '%c' at pos:%d\n", c, pos); */ + return -1; + } + } while(pos < path_len); + return ret; +} +/*--------------------------------------------------------------------------*/ +static int +lwm2m_engine_parse_context(const char *path, int path_len, + coap_packet_t *request, coap_packet_t *response, + uint8_t *outbuf, size_t outsize, + lwm2m_context_t *context) +{ + int ret; + if(context == NULL || path == NULL) { return 0; } -#endif /* UIP_CONF_IPV6_RPL */ - return 1; + + ret = parse_path(path, path_len, &context->object_id, + &context->object_instance_id, &context->resource_id); + + if(ret > 0) { + context->level = ret; + } + + return ret; +} + +/*---------------------------------------------------------------------------*/ +void lwm2m_engine_set_opaque_callback(lwm2m_context_t *ctx, lwm2m_write_opaque_callback cb) +{ + /* Here we should set the callback for the opaque that we are currently generating... */ + /* And we should in the future associate the callback with the CoAP message info - MID */ + PRINTF("Setting opaque handler - offset: %d,%d\n", ctx->offset, ctx->outbuf->len); + + current_opaque_offset = 0; + current_opaque_callback = cb; } /*---------------------------------------------------------------------------*/ -void -lwm2m_engine_use_bootstrap_server(int use) +int +lwm2m_engine_set_rd_data(lwm2m_buffer_t *outbuf, int block) { - use_bootstrap = use != 0; - if(use_bootstrap) { - process_poll(&lwm2m_rd_client); - } -} -/*---------------------------------------------------------------------------*/ -void -lwm2m_engine_use_registration_server(int use) -{ - use_registration = use != 0; - if(use_registration) { - process_poll(&lwm2m_rd_client); - } -} -/*---------------------------------------------------------------------------*/ -void -lwm2m_engine_register_with_server(const uip_ipaddr_t *server, uint16_t port) -{ - uip_ipaddr_copy(&server_ipaddr, server); - if(port != 0) { - server_port = port; - } else { - server_port = REMOTE_PORT; - } - has_registration_server_info = 1; - registered = 0; - if(use_registration) { - process_poll(&lwm2m_rd_client); - } -} -/*---------------------------------------------------------------------------*/ -static int -update_registration_server(void) -{ - if(has_registration_server_info) { - return 1; + /* remember things here - need to lock lwm2m buffer also!!! */ + static lwm2m_object_t *object; + static lwm2m_object_instance_t *instance; + int len; + /* pick size from outbuf */ + int maxsize = outbuf->size; + + if(lwm2m_buf_lock[0] != 0 && (lwm2m_buf_lock_timeout > coap_timer_uptime()) && + ((lwm2m_buf_lock[1] != 0xffff) || + (lwm2m_buf_lock[2] != 0xffff))) { + PRINTF("Set-RD: already exporting resource: %d/%d/%d\n", + lwm2m_buf_lock[1], lwm2m_buf_lock[2], lwm2m_buf_lock[3]); + /* fail - what should we return here? */ + return 0; } -#if UIP_CONF_IPV6_RPL - { - rpl_dag_t *dag; + if(block == 0) { + PRINTF("Starting RD genereation\n"); + /* start with simple object instances */ + instance = list_head(object_list); + object = NULL; - /* Use the DAG id as server address if no other has been specified */ - dag = rpl_get_any_dag(); - if(dag != NULL) { - uip_ipaddr_copy(&server_ipaddr, &dag->dag_id); - server_port = REMOTE_PORT; - return 1; - } - } -#endif /* UIP_CONF_IPV6_RPL */ - - return 0; -} -/*---------------------------------------------------------------------------*/ -void -lwm2m_engine_register_with_bootstrap_server(const uip_ipaddr_t *server, - uint16_t port) -{ - uip_ipaddr_copy(&bs_server_ipaddr, server); - if(port != 0) { - bs_server_port = port; - } else { - bs_server_port = BS_REMOTE_PORT; - } - has_bootstrap_server_info = 1; - bootstrapped = 0; - registered = 0; - if(use_bootstrap) { - process_poll(&lwm2m_rd_client); - } -} -/*---------------------------------------------------------------------------*/ -static int -update_bootstrap_server(void) -{ - if(has_bootstrap_server_info) { - return 1; - } - -#if UIP_CONF_IPV6_RPL - { - rpl_dag_t *dag; - - /* Use the DAG id as server address if no other has been specified */ - dag = rpl_get_any_dag(); - if(dag != NULL) { - uip_ipaddr_copy(&bs_server_ipaddr, &dag->dag_id); - bs_server_port = REMOTE_PORT; - return 1; - } - } -#endif /* UIP_CONF_IPV6_RPL */ - - return 0; -} -/*---------------------------------------------------------------------------*/ -PROCESS_THREAD(lwm2m_rd_client, ev, data) -{ - static coap_packet_t request[1]; /* This way the packet can be treated as pointer as usual. */ - static struct etimer et; - - PROCESS_BEGIN(); - - printf("RD Client started with endpoint '%s'\n", endpoint); - - etimer_set(&et, 15 * CLOCK_SECOND); - - while(1) { - PROCESS_YIELD(); - - if(etimer_expired(&et)) { - if(!has_network_access()) { - /* Wait until for a network to join */ - } else if(use_bootstrap && bootstrapped == 0) { - if(update_bootstrap_server()) { - /* prepare request, TID is set by COAP_BLOCKING_REQUEST() */ - coap_init_message(request, COAP_TYPE_CON, COAP_POST, 0); - coap_set_header_uri_path(request, "/bs"); - coap_set_header_uri_query(request, endpoint); - - printf("Registering ID with bootstrap server ["); - uip_debug_ipaddr_print(&bs_server_ipaddr); - printf("]:%u as '%s'\n", uip_ntohs(bs_server_port), endpoint); - - COAP_BLOCKING_REQUEST(&bs_server_ipaddr, bs_server_port, request, - client_chunk_handler); - bootstrapped++; - } - } else if(use_bootstrap && bootstrapped == 1) { - lwm2m_context_t context; - const lwm2m_instance_t *instance = NULL; - const lwm2m_resource_t *rsc; - const uint8_t *first; - int len; - - PRINTF("*** Bootstrap - checking for server info...\n"); - - /* get the security object */ - instance = get_first_instance_of_object(LWM2M_OBJECT_SECURITY_ID, &context); - if(instance != NULL) { - /* get the server URI */ - context.resource_id = LWM2M_SECURITY_SERVER_URI; - rsc = get_resource(instance, &context); - first = lwm2m_object_get_resource_string(rsc, &context); - len = lwm2m_object_get_resource_strlen(rsc, &context); - if(first != NULL && len > 0) { - int start, end; - uip_ipaddr_t addr; - int32_t port; - uint8_t secure = 0; - - PRINTF("**** Found security instance using: %.*s\n", len, first); - /* TODO Should verify it is a URI */ - - /* Check if secure */ - secure = strncmp((const char *)first, "coaps:", 6) == 0; - - /* Only IPv6 supported */ - start = index_of(first, 0, len, '['); - end = index_of(first, start, len, ']'); - if(start > 0 && end > start && - uiplib_ipaddrconv((const char *)&first[start], &addr)) { - if(first[end + 1] == ':' && - lwm2m_plain_text_read_int(first + end + 2, len - end - 2, &port)) { - } else if(secure) { - /** - * Secure CoAP should use a different port but for now - * the same port is used. - */ - port = COAP_DEFAULT_PORT; - } else { - port = COAP_DEFAULT_PORT; - } - PRINTF("Server address "); - PRINT6ADDR(&addr); - PRINTF(" port %" PRId32 "%s\n", port, secure ? " (secure)" : ""); - if(secure) { - printf("Secure CoAP requested but not supported - can not bootstrap\n"); - } else { - lwm2m_engine_register_with_server(&addr, - UIP_HTONS((uint16_t)port)); - bootstrapped++; - } - } else { - printf("** failed to parse URI %.*s\n", len, first); - } - } - } - - if(bootstrapped == 1) { - /* Not ready. Lets retry with the bootstrap server again */ - bootstrapped = 0; - } - - } else if(use_registration && !registered && - update_registration_server()) { - int pos; - int len, i, j; - registered = 1; - - /* prepare request, TID is set by COAP_BLOCKING_REQUEST() */ - coap_init_message(request, COAP_TYPE_CON, COAP_POST, 0); - coap_set_header_uri_path(request, "/rd"); - coap_set_header_uri_query(request, endpoint); - - /* generate the rd data */ - pos = 0; - for(i = 0; i < MAX_OBJECTS; i++) { - if(objects[i] != NULL) { - for(j = 0; j < objects[i]->count; j++) { - if(objects[i]->instances[j].flag & LWM2M_INSTANCE_FLAG_USED) { - len = snprintf(&rd_data[pos], sizeof(rd_data) - pos, - "%s<%d/%d>", pos > 0 ? "," : "", - objects[i]->id, objects[i]->instances[j].id); - if(len > 0 && len < sizeof(rd_data) - pos) { - pos += len; - } - } - } - } - } - - coap_set_payload(request, (uint8_t *)rd_data, pos); - - printf("Registering with ["); - uip_debug_ipaddr_print(&server_ipaddr); - printf("]:%u lwm2m endpoint '%s': '%.*s'\n", uip_ntohs(server_port), - endpoint, pos, rd_data); - COAP_BLOCKING_REQUEST(&server_ipaddr, server_port, request, - client_chunk_handler); + if(instance == NULL) { + /* No simple object instances available */ + object = list_head(generic_object_list); + if(object == NULL) { + /* No objects of any kind available */ + return 0; } - /* for now only register once... registered = 0; */ - etimer_set(&et, 15 * CLOCK_SECOND); + if(object->impl != NULL) { + instance = object->impl->get_first(NULL); + } + } + + lwm2m_buf_lock[0] = 1; /* lock "flag" */ + lwm2m_buf_lock[1] = 0xffff; + lwm2m_buf_lock[2] = 0xffff; + lwm2m_buf_lock[3] = 0xffff; + } else { + /* object and instance was static... */ + } + + lwm2m_buf_lock_timeout = coap_timer_uptime() + 1000; + + PRINTF("Generating RD list:"); + while(instance != NULL || object != NULL) { + int pos = lwm2m_buf.len; + if(instance != NULL) { + len = snprintf((char *) &lwm2m_buf.buffer[pos], + lwm2m_buf.size - pos, (pos > 0 || block > 0) ? "," : "", + instance->object_id, instance->instance_id); + PRINTF((pos > 0 || block > 0) ? "," : "", + instance->object_id, instance->instance_id); + } else if(object->impl != NULL) { + len = snprintf((char *) &lwm2m_buf.buffer[pos], + lwm2m_buf.size - pos, + (pos > 0 || block > 0) ? "," : "", + object->impl->object_id); + PRINTF((pos > 0 || block > 0) ? "," : "", + object->impl->object_id); + } else { + len = 0; + } + lwm2m_buf.len += len; + if(instance != NULL) { + instance = next_object_instance(NULL, object, instance); + } + + if(instance == NULL) { + if(object == NULL) { + /* + * No object and no instance - we are done with simple object instances. + */ + object = list_head(generic_object_list); + } else { + /* + * Object exists but not an instance - instances for this object are + * done - go to next. + */ + object = object->next; + } + + if(object != NULL && object->impl != NULL) { + instance = object->impl->get_first(NULL); + } + + if(instance == NULL && object == NULL && lwm2m_buf.len <= maxsize) { + /* Data generation is done. No more packets are needed after this. */ + break; + } + } + + if(lwm2m_buf.len >= maxsize) { + PRINTF("**** CoAP MAX BLOCK Reached!!! **** SEND\n"); + /* If the produced data is larger than a CoAP block we need to send + this now */ + double_buffer_flush(&lwm2m_buf, outbuf, maxsize); + /* there will be more - keep lock! */ + return 1; } } - PROCESS_END(); + PRINTF("\n"); + double_buffer_flush(&lwm2m_buf, outbuf, maxsize); + /* unlock the buffer */ + lwm2m_buf_lock[0] = 0; + return 0; } /*---------------------------------------------------------------------------*/ void lwm2m_engine_init(void) { -#ifdef LWM2M_ENGINE_CLIENT_ENDPOINT_NAME + list_init(object_list); + list_init(generic_object_list); - snprintf(endpoint, sizeof(endpoint) - 1, - "?ep=" LWM2M_ENGINE_CLIENT_ENDPOINT_NAME); +#ifdef LWM2M_ENGINE_CLIENT_ENDPOINT_NAME + const char *endpoint = LWM2M_ENGINE_CLIENT_ENDPOINT_NAME; #else /* LWM2M_ENGINE_CLIENT_ENDPOINT_NAME */ - + static char endpoint[32]; int len, i; uint8_t state; uip_ipaddr_t *ipaddr; - char client[sizeof(endpoint)]; len = strlen(LWM2M_ENGINE_CLIENT_ENDPOINT_PREFIX); /* ensure that this fits with the hex-nums */ - if(len > sizeof(client) - 13) { - len = sizeof(client) - 13; + if(len > sizeof(endpoint) - 13) { + len = sizeof(endpoint) - 13; } - memcpy(client, LWM2M_ENGINE_CLIENT_ENDPOINT_PREFIX, len); + memcpy(endpoint, LWM2M_ENGINE_CLIENT_ENDPOINT_PREFIX, len); /* pick an IP address that is PREFERRED or TENTATIVE */ ipaddr = NULL; @@ -424,323 +528,24 @@ lwm2m_engine_init(void) for(i = 0; i < 6; i++) { /* assume IPv6 for now */ uint8_t b = ipaddr->u8[10 + i]; - client[len++] = (b >> 4) > 9 ? 'A' - 10 + (b >> 4) : '0' + (b >> 4); - client[len++] = (b & 0xf) > 9 ? 'A' - 10 + (b & 0xf) : '0' + (b & 0xf); + endpoint[len++] = (b >> 4) > 9 ? 'A' - 10 + (b >> 4) : '0' + (b >> 4); + endpoint[len++] = (b & 0xf) > 9 ? 'A' - 10 + (b & 0xf) : '0' + (b & 0xf); } } /* a zero at end of string */ - client[len] = 0; - /* create endpoint */ - snprintf(endpoint, sizeof(endpoint) - 1, "?ep=%s", client); + endpoint[len] = 0; #endif /* LWM2M_ENGINE_CLIENT_ENDPOINT_NAME */ - rest_init_engine(); - process_start(&lwm2m_rd_client, NULL); -} -/*---------------------------------------------------------------------------*/ -void -lwm2m_engine_register_default_objects(void) -{ - lwm2m_security_init(); - lwm2m_server_init(); - lwm2m_device_init(); -} -/*---------------------------------------------------------------------------*/ -static int -parse_next(const char **path, int *path_len, uint16_t *value) -{ - char c; - *value = 0; - /* printf("parse_next: %p %d\n", *path, *path_len); */ - if(*path_len == 0) { - return 0; - } - while(*path_len > 0) { - c = **path; - (*path)++; - *path_len = *path_len - 1; - if(c >= '0' && c <= '9') { - *value = *value * 10 + (c - '0'); - } else if(c == '/') { - return 1; - } else { - /* error */ - return -4; - } - } - return 1; -} -/*---------------------------------------------------------------------------*/ -int -lwm2m_engine_parse_context(const lwm2m_object_t *object, - const char *path, int path_len, - lwm2m_context_t *context) -{ - int ret; - if(context == NULL || object == NULL || path == NULL) { - return 0; - } - memset(context, 0, sizeof(lwm2m_context_t)); - /* get object id */ - ret = 0; - ret += parse_next(&path, &path_len, &context->object_id); - ret += parse_next(&path, &path_len, &context->object_instance_id); - ret += parse_next(&path, &path_len, &context->resource_id); + coap_engine_init(); - /* Set default reader/writer */ - context->reader = &lwm2m_plain_text_reader; - context->writer = &oma_tlv_writer; + /* Register the CoAP handler for lightweight object handling */ + coap_add_handler(&lwm2m_handler); - return ret; -} -/*---------------------------------------------------------------------------*/ -const lwm2m_object_t * -lwm2m_engine_get_object(uint16_t id) -{ - int i; - for(i = 0; i < MAX_OBJECTS; i++) { - if(objects[i] != NULL && objects[i]->id == id) { - return objects[i]; - } - } - return NULL; -} -/*---------------------------------------------------------------------------*/ -int -lwm2m_engine_register_object(const lwm2m_object_t *object) -{ - int i; - int found = 0; - for(i = 0; i < MAX_OBJECTS; i++) { - if(objects[i] == NULL) { - objects[i] = object; - found = 1; - break; - } - } - rest_activate_resource(lwm2m_object_get_coap_resource(object), - (char *)object->path); - return found; -} -/*---------------------------------------------------------------------------*/ -static const lwm2m_instance_t * -get_first_instance_of_object(uint16_t id, lwm2m_context_t *context) -{ - const lwm2m_object_t *object; - int i; - - object = lwm2m_engine_get_object(id); - if(object == NULL) { - /* No object with the specified id found */ - return NULL; - } - - /* Initialize the context */ - memset(context, 0, sizeof(lwm2m_context_t)); - context->object_id = id; - - for(i = 0; i < object->count; i++) { - if(object->instances[i].flag & LWM2M_INSTANCE_FLAG_USED) { - context->object_instance_id = object->instances[i].id; - context->object_instance_index = i; - return &object->instances[i]; - } - } - return NULL; -} -/*---------------------------------------------------------------------------*/ -static const lwm2m_instance_t * -get_instance(const lwm2m_object_t *object, lwm2m_context_t *context, int depth) -{ - int i; - if(depth > 1) { - PRINTF("lwm2m: searching for instance %u\n", context->object_instance_id); - for(i = 0; i < object->count; i++) { - PRINTF(" Instance %d -> %u (used: %d)\n", i, object->instances[i].id, - (object->instances[i].flag & LWM2M_INSTANCE_FLAG_USED) != 0); - if(object->instances[i].id == context->object_instance_id && - object->instances[i].flag & LWM2M_INSTANCE_FLAG_USED) { - context->object_instance_index = i; - return &object->instances[i]; - } - } - } - return NULL; -} -/*---------------------------------------------------------------------------*/ -static const lwm2m_resource_t * -get_resource(const lwm2m_instance_t *instance, lwm2m_context_t *context) -{ - int i; - if(instance != NULL) { - PRINTF("lwm2m: searching for resource %u\n", context->resource_id); - for(i = 0; i < instance->count; i++) { - PRINTF(" Resource %d -> %u\n", i, instance->resources[i].id); - if(instance->resources[i].id == context->resource_id) { - context->resource_index = i; - return &instance->resources[i]; - } - } - } - return NULL; -} -/*---------------------------------------------------------------------------*/ -/** - * @brief Write a list of object instances as a CoRE Link-format list - */ -static int -write_object_instances_link(const lwm2m_object_t *object, - char *buffer, size_t size) -{ - const lwm2m_instance_t *instance; - int len, rdlen, i; - - PRINTF("", object->id); - rdlen = snprintf(buffer, size, "", - object->id); - if(rdlen < 0 || rdlen >= size) { - return -1; - } - - for(i = 0; i < object->count; i++) { - if((object->instances[i].flag & LWM2M_INSTANCE_FLAG_USED) == 0) { - continue; - } - instance = &object->instances[i]; - PRINTF(",", object->id, instance->id); - - len = snprintf(&buffer[rdlen], size - rdlen, - ",<%d/%d>", object->id, instance->id); - rdlen += len; - if(len < 0 || rdlen >= size) { - return -1; - } - } - return rdlen; -} -/*---------------------------------------------------------------------------*/ -static int -write_rd_link_data(const lwm2m_object_t *object, - const lwm2m_instance_t *instance, - char *buffer, size_t size) -{ - const lwm2m_resource_t *resource; - int len, rdlen, i; - - PRINTF("<%d/%d>", object->id, instance->id); - rdlen = snprintf(buffer, size, "<%d/%d>", - object->id, instance->id); - if(rdlen < 0 || rdlen >= size) { - return -1; - } - - for(i = 0; i < instance->count; i++) { - resource = &instance->resources[i]; - PRINTF(",<%d/%d/%d>", object->id, instance->id, resource->id); - - len = snprintf(&buffer[rdlen], size - rdlen, - ",<%d/%d/%d>", object->id, instance->id, resource->id); - rdlen += len; - if(len < 0 || rdlen >= size) { - return -1; - } - } - return rdlen; -} -/*---------------------------------------------------------------------------*/ -static int -write_rd_json_data(const lwm2m_context_t *context, - const lwm2m_object_t *object, - const lwm2m_instance_t *instance, - char *buffer, size_t size) -{ - const lwm2m_resource_t *resource; - const char *s = ""; - int len, rdlen, i; - - PRINTF("{\"e\":["); - rdlen = snprintf(buffer, size, "{\"e\":["); - if(rdlen < 0 || rdlen >= size) { - return -1; - } - - for(i = 0, len = 0; i < instance->count; i++) { - resource = &instance->resources[i]; - len = 0; - if(lwm2m_object_is_resource_string(resource)) { - const uint8_t *value; - uint16_t slen; - value = lwm2m_object_get_resource_string(resource, context); - slen = lwm2m_object_get_resource_strlen(resource, context); - if(value != NULL) { - PRINTF("%s{\"n\":\"%u\",\"sv\":\"%.*s\"}", s, - resource->id, slen, value); - len = snprintf(&buffer[rdlen], size - rdlen, - "%s{\"n\":\"%u\",\"sv\":\"%.*s\"}", s, - resource->id, slen, value); - } - } else if(lwm2m_object_is_resource_int(resource)) { - int32_t value; - if(lwm2m_object_get_resource_int(resource, context, &value)) { - PRINTF("%s{\"n\":\"%u\",\"v\":%" PRId32 "}", s, - resource->id, value); - len = snprintf(&buffer[rdlen], size - rdlen, - "%s{\"n\":\"%u\",\"v\":%" PRId32 "}", s, - resource->id, value); - } - } else if(lwm2m_object_is_resource_floatfix(resource)) { - int32_t value; - if(lwm2m_object_get_resource_floatfix(resource, context, &value)) { - PRINTF("%s{\"n\":\"%u\",\"v\":%" PRId32 "}", s, resource->id, - value / LWM2M_FLOAT32_FRAC); - len = snprintf(&buffer[rdlen], size - rdlen, - "%s{\"n\":\"%u\",\"v\":", s, resource->id); - rdlen += len; - if(len < 0 || rdlen >= size) { - return -1; - } - - len = lwm2m_plain_text_write_float32fix((uint8_t *)&buffer[rdlen], - size - rdlen, - value, LWM2M_FLOAT32_BITS); - if(len == 0) { - return -1; - } - rdlen += len; - - if(rdlen < size) { - buffer[rdlen] = '}'; - } - len = 1; - } - } else if(lwm2m_object_is_resource_boolean(resource)) { - int value; - if(lwm2m_object_get_resource_boolean(resource, context, &value)) { - PRINTF("%s{\"n\":\"%u\",\"bv\":%s}", s, resource->id, - value ? "true" : "false"); - len = snprintf(&buffer[rdlen], size - rdlen, - "%s{\"n\":\"%u\",\"bv\":%s}", s, resource->id, - value ? "true" : "false"); - } - } - rdlen += len; - if(len < 0 || rdlen >= size) { - return -1; - } - if(len > 0) { - s = ","; - } - } - PRINTF("]}\n"); - len = snprintf(&buffer[rdlen], size - rdlen, "]}"); - rdlen += len; - if(len < 0 || rdlen >= size) { - return -1; - } - - return rdlen; +#if USE_RD_CLIENT + lwm2m_rd_client_init(endpoint); +#endif } /*---------------------------------------------------------------------------*/ /** @@ -756,13 +561,15 @@ lwm2m_engine_select_writer(lwm2m_context_t *context, unsigned int accept) { switch(accept) { case LWM2M_TLV: - context->writer = &oma_tlv_writer; + case LWM2M_OLD_TLV: + context->writer = &lwm2m_tlv_writer; break; case LWM2M_TEXT_PLAIN: case TEXT_PLAIN: context->writer = &lwm2m_plain_text_writer; break; case LWM2M_JSON: + case LWM2M_OLD_JSON: case APPLICATION_JSON: context->writer = &lwm2m_json_writer; break; @@ -773,6 +580,7 @@ lwm2m_engine_select_writer(lwm2m_context_t *context, unsigned int accept) accept = LWM2M_TEXT_PLAIN; break; } + context->content_type = accept; return accept; } /*---------------------------------------------------------------------------*/ @@ -787,342 +595,1017 @@ lwm2m_engine_select_reader(lwm2m_context_t *context, unsigned int content_format { switch(content_format) { case LWM2M_TLV: - context->reader = &oma_tlv_reader; + case LWM2M_OLD_TLV: + context->reader = &lwm2m_tlv_reader; + break; + case LWM2M_JSON: + case LWM2M_OLD_JSON: + context->reader = &lwm2m_plain_text_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); + PRINTF("Unknown content type %u, using LWM2M plain text\n", + content_format); context->reader = &lwm2m_plain_text_reader; break; } } + /*---------------------------------------------------------------------------*/ -void -lwm2m_engine_handler(const lwm2m_object_t *object, - void *request, void *response, - uint8_t *buffer, uint16_t preferred_size, - int32_t *offset) +/* Lightweight object instances */ +/*---------------------------------------------------------------------------*/ +static uint32_t last_instance_id = NO_INSTANCE; +static int last_rsc_pos; + +/* Multi read will handle read of JSON / TLV or Discovery (Link Format) */ +static lwm2m_status_t +perform_multi_resource_read_op(lwm2m_object_t *object, + lwm2m_object_instance_t *instance, + lwm2m_context_t *ctx) { - int len; - const char *url; - unsigned int format; - unsigned int accept; - unsigned int content_type; - int depth; - lwm2m_context_t context; - rest_resource_flags_t method; - const lwm2m_instance_t *instance; -#if (DEBUG) & DEBUG_PRINT - const char *method_str; -#endif /* (DEBUG) & DEBUG_PRINT */ + int size = ctx->outbuf->size; + int len = 0; + uint8_t initialized = 0; /* used for commas, etc */ + uint8_t num_read = 0; + lwm2m_buffer_t *outbuf; - method = REST.get_method_type(request); - - len = REST.get_url(request, &url); - if(!REST.get_header_content_type(request, &format)) { - PRINTF("No format given. Assume text plain...\n"); - format = LWM2M_TEXT_PLAIN; - } else if(format == TEXT_PLAIN) { - /* CoAP content format text plain - assume LWM2M text plain */ - format = LWM2M_TEXT_PLAIN; - } - if(!REST.get_header_accept(request, &accept)) { - PRINTF("No Accept header, using same as Content-format...\n"); - accept = format; + if(instance == NULL) { + /* No existing instance */ + return LWM2M_STATUS_NOT_FOUND; } - depth = lwm2m_engine_parse_context(object, url, len, &context); - PRINTF("Context: %u/%u/%u found: %d\n", context.object_id, - context.object_instance_id, context.resource_id, depth); + if(ctx->level < 3 && + (ctx->content_type == LWM2M_TEXT_PLAIN || + ctx->content_type == TEXT_PLAIN || + ctx->content_type == LWM2M_OLD_OPAQUE)) { + return LWM2M_STATUS_OPERATION_NOT_ALLOWED; + } - /* 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); + /* copy out the out-buffer as read will use its own - will be same for disoc when + read is fixed */ + outbuf = ctx->outbuf; -#if (DEBUG) & DEBUG_PRINT - /* for debugging */ - if(method == METHOD_GET) { - method_str = "GET"; - } else if(method == METHOD_POST) { - method_str = "POST"; - } else if(method == METHOD_PUT) { - method_str = "PUT"; - } else if(method == METHOD_DELETE) { - method_str = "DELETE"; + /* Currently we only handle one incoming read request at a time - so we return + BUZY or service unavailable */ + if(lwm2m_buf_lock[0] != 0 && (lwm2m_buf_lock_timeout > coap_timer_uptime()) && + ((lwm2m_buf_lock[1] != ctx->object_id) || + (lwm2m_buf_lock[2] != ctx->object_instance_id) || + (lwm2m_buf_lock[3] != ctx->resource_id))) { + PRINTF("Multi-read: already exporting resource: %d/%d/%d\n", + lwm2m_buf_lock[1], lwm2m_buf_lock[2], lwm2m_buf_lock[3]); + return LWM2M_STATUS_SERVICE_UNAVAILABLE; + } + + PRINTF("MultiRead: %d/%d/%d lv:%d offset:%d\n", + ctx->object_id, ctx->object_instance_id, ctx->resource_id, ctx->level, ctx->offset); + + /* Make use of the double buffer */ + ctx->outbuf = &lwm2m_buf; + + if(ctx->offset == 0) { + /* First GET request - need to setup all buffers and reset things here */ + last_instance_id = + ((uint32_t)instance->object_id << 16) | instance->instance_id; + last_rsc_pos = 0; + /* reset any callback */ + current_opaque_callback = NULL; + /* reset lwm2m_buf_len - so that we can use the double-size buffer */ + lwm2m_buf_lock[0] = 1; /* lock "flag" */ + lwm2m_buf_lock[1] = ctx->object_id; + lwm2m_buf_lock[2] = ctx->object_instance_id; + lwm2m_buf_lock[3] = ctx->resource_id; + lwm2m_buf.len = 0; + /* Here we should print top node */ } else { - method_str = "UNKNOWN"; - } - PRINTF("%s Called Path:%.*s Format:%d ID:%d bsize:%u\n", method_str, len, - url, format, object->id, preferred_size); - if(format == LWM2M_TEXT_PLAIN) { - /* a string */ - const uint8_t *data; - int plen = REST.get_request_payload(request, &data); - if(plen > 0) { - PRINTF("Data: '%.*s'\n", plen, (char *)data); + /* offset > 0 - assume that we are already in a disco or multi get*/ + instance = get_instance(last_instance_id >> 16, last_instance_id & 0xffff, + &object); + + /* we assume that this was initialized */ + initialized = 1; + ctx->writer_flags |= WRITER_OUTPUT_VALUE; + if(instance == NULL) { + ctx->offset = -1; + ctx->outbuf->buffer[0] = ' '; } } -#endif /* (DEBUG) & DEBUG_PRINT */ + lwm2m_buf_lock_timeout = coap_timer_uptime() + 1000; - instance = get_instance(object, &context, depth); + while(instance != NULL) { + /* Do the discovery or read */ + if(instance->resource_ids != NULL && instance->resource_count > 0) { + /* show all the available resources (or read all) */ + while(last_rsc_pos < instance->resource_count) { + PRINTF("READ: %x %x %x lv:%d\n", instance->resource_ids[last_rsc_pos], RSC_ID(instance->resource_ids[last_rsc_pos]), ctx->resource_id, ctx->level); - /* from POST */ - if(depth > 1 && instance == NULL) { - if(method != METHOD_PUT && method != METHOD_POST) { - PRINTF("Error - do not have instance %d\n", context.object_instance_id); - REST.set_response_status(response, NOT_FOUND_4_04); - return; - } else { - const uint8_t *data; - int i, len, plen, pos; - oma_tlv_t tlv; - PRINTF(">>> CREATE ? %d/%d\n", context.object_id, - context.object_instance_id); + /* Check if this is a object read or if it is the correct resource */ + if(ctx->level < 3 || ctx->resource_id == RSC_ID(instance->resource_ids[last_rsc_pos])) { + /* ---------- Discovery operation ------------- */ + /* If this is a discovery all the object, instance, and resource triples should be + generted */ + if(ctx->operation == LWM2M_OP_DISCOVER) { + int dim = 0; + len = snprintf((char *) &ctx->outbuf->buffer[ctx->outbuf->len], + ctx->outbuf->size - ctx->outbuf->len, + (ctx->outbuf->len == 0 && ctx->offset == 0) ? "":",", + instance->object_id, instance->instance_id, + RSC_ID(instance->resource_ids[last_rsc_pos])); + if(instance->resource_dim_callback != NULL && + (dim = instance->resource_dim_callback(instance, + RSC_ID(instance->resource_ids[last_rsc_pos]))) > 0) { + len += snprintf((char *) &ctx->outbuf->buffer[ctx->outbuf->len + len], + ctx->outbuf->size - ctx->outbuf->len - len, ";dim=%d", dim); + } + /* here we have "read" out something */ + num_read++; + ctx->outbuf->len += len; + if(len < 0 || ctx->outbuf->len >= size) { + double_buffer_flush(ctx->outbuf, outbuf, size); - for(i = 0; i < object->count; i++) { - if((object->instances[i].flag & LWM2M_INSTANCE_FLAG_USED) == 0) { - /* allocate this instance */ - object->instances[i].flag |= LWM2M_INSTANCE_FLAG_USED; - object->instances[i].id = context.object_instance_id; - context.object_instance_index = i; - PRINTF("Created instance: %d\n", context.object_instance_id); - REST.set_response_status(response, CREATED_2_01); - instance = &object->instances[i]; - break; - } - } + PRINTF("Copied lwm2m buf - remaining: %d\n", lwm2m_buf.len); + /* switch buffer */ + ctx->outbuf = outbuf; + ctx->writer_flags |= WRITER_HAS_MORE; + ctx->offset += size; + return LWM2M_STATUS_OK; + } + /* ---------- Read operation ------------- */ + } else if(ctx->operation == LWM2M_OP_READ) { + lwm2m_status_t success; + uint8_t lv; - if(instance == NULL) { - /* could for some reason not create the instance */ - REST.set_response_status(response, NOT_ACCEPTABLE_4_06); - return; - } + lv = ctx->level; - plen = REST.get_request_payload(request, &data); - if(plen == 0) { - /* do nothing more */ - return; - } - PRINTF("Payload: "); - for(i = 0; i < plen; i++) { - PRINTF("%02x", data[i]); - } - PRINTF("\n"); + /* Do not allow a read on a non-readable */ + if(lv == 3 && !RSC_READABLE(instance->resource_ids[last_rsc_pos])) { + lwm2m_buf_lock[0] = 0; + return LWM2M_STATUS_OPERATION_NOT_ALLOWED; + } + /* Set the resource ID is ctx->level < 3 */ + if(lv < 3) { + ctx->resource_id = RSC_ID(instance->resource_ids[last_rsc_pos]); + } + if(lv < 2) { + ctx->object_instance_id = instance->instance_id; + } - pos = 0; - do { - len = oma_tlv_read(&tlv, (uint8_t *)&data[pos], plen - pos); - PRINTF("Found TLV type=%u id=%u len=%lu\n", - tlv.type, tlv.id, (unsigned long)tlv.length); - /* here we need to do callbacks or write value */ - if(tlv.type == OMA_TLV_TYPE_RESOURCE) { - context.resource_id = tlv.id; - const lwm2m_resource_t *rsc = get_resource(instance, &context); - if(rsc != NULL) { - /* write the value to the resource */ - if(lwm2m_object_is_resource_string(rsc)) { - PRINTF(" new string value for /%d/%d/%d = %.*s\n", - context.object_id, context.object_instance_id, - context.resource_id, (int)tlv.length, tlv.value); - lwm2m_object_set_resource_string(rsc, &context, - tlv.length, tlv.value); - } else if(lwm2m_object_is_resource_int(rsc)) { - PRINTF(" new int value for /%d/%d/%d = %" PRId32 "\n", - context.object_id, context.object_instance_id, - context.resource_id, oma_tlv_get_int32(&tlv)); - lwm2m_object_set_resource_int(rsc, &context, - oma_tlv_get_int32(&tlv)); - } else if(lwm2m_object_is_resource_floatfix(rsc)) { - int32_t value; - if(oma_tlv_float32_to_fix(&tlv, &value, LWM2M_FLOAT32_BITS)) { - PRINTF(" new float value for /%d/%d/%d = %" PRId32 "\n", - context.object_id, context.object_instance_id, - context.resource_id, value >> LWM2M_FLOAT32_BITS); - lwm2m_object_set_resource_floatfix(rsc, &context, value); - } else { - PRINTF(" new float value for /%d/%d/%d: FAILED\n", - context.object_id, context.object_instance_id, - context.resource_id); + if(RSC_READABLE(instance->resource_ids[last_rsc_pos])) { + ctx->level = 3; + if(!initialized) { + /* Now we need to initialize the object writing for this new object */ + len = ctx->writer->init_write(ctx); + ctx->outbuf->len += len; + PRINTF("INIT WRITE len:%d size:%d\n", len, (int) ctx->outbuf->size); + initialized = 1; } - } else if(lwm2m_object_is_resource_boolean(rsc)) { - PRINTF(" new boolean value for /%d/%d/%d = %" PRId32 "\n", - context.object_id, context.object_instance_id, - context.resource_id, oma_tlv_get_int32(&tlv)); - lwm2m_object_set_resource_boolean(rsc, &context, - oma_tlv_get_int32(&tlv) != 0); + + if(current_opaque_callback == NULL) { + PRINTF("Doing the callback to the resource %d\n", ctx->outbuf->len); + /* No special opaque callback to handle - use regular callback */ + success = instance->callback(instance, ctx); + PRINTF("After the callback to the resource %d: %s\n", + ctx->outbuf->len, get_status_as_string(success)); + + if(success != LWM2M_STATUS_OK) { + /* What to do here? */ + PRINTF("Callback failed: %s\n", get_status_as_string(success)); + if(lv < 3) { + if(success == LWM2M_STATUS_NOT_FOUND) { + /* ok with a not found during a multi read - what more + is ok? */ + } else { + lwm2m_buf_lock[0] = 0; + return success; + } + } else { + lwm2m_buf_lock[0] = 0; + return success; + } + } + } + if(current_opaque_callback != NULL) { + uint32_t old_offset = ctx->offset; + int num_write = COAP_MAX_BLOCK_SIZE - ctx->outbuf->len; + /* Check if the callback did set a opaque callback function - then + we should produce data via that callback until the opaque has fully + been handled */ + ctx->offset = current_opaque_offset; + /* PRINTF("Calling the opaque handler %x\n", ctx->writer_flags); */ + success = current_opaque_callback(instance, ctx, num_write); + if((ctx->writer_flags & WRITER_HAS_MORE) == 0) { + /* This opaque stream is now done! */ + /* PRINTF("Setting opaque callback to null - it is done!\n"); */ + current_opaque_callback = NULL; + } else if(ctx->outbuf->len < COAP_MAX_BLOCK_SIZE) { + lwm2m_buf_lock[0] = 0; + return LWM2M_STATUS_ERROR; + } + current_opaque_offset += num_write; + ctx->offset = old_offset; + /* PRINTF("Setting back offset to: %d\n", ctx->offset); */ + } + + /* here we have "read" out something */ + num_read++; + /* We will need to handle no-success and other things */ + PRINTF("Called %u/%u/%u outlen:%u %s\n", + ctx->object_id, ctx->object_instance_id, ctx->resource_id, + ctx->outbuf->len, get_status_as_string(success)); + + /* we need to handle full buffer, etc here also! */ + ctx->level = lv; + } else { + PRINTF("Resource %u not readable\n", + RSC_ID(instance->resource_ids[last_rsc_pos])); } } } - pos = pos + len; - } while(len > 0 && pos < plen); + if(current_opaque_callback == NULL) { + /* This resource is now done - (only when the opaque is also done) */ + last_rsc_pos++; + } else { + PRINTF("Opaque is set - continue with that.\n"); + } + + if(ctx->outbuf->len >= COAP_MAX_BLOCK_SIZE) { + PRINTF("**** CoAP MAX BLOCK Reached!!! **** SEND\n"); + /* If the produced data is larger than a CoAP block we need to send + this now */ + if(ctx->outbuf->len < 2 * COAP_MAX_BLOCK_SIZE) { + /* We assume that size is equal to COAP_MAX_BLOCK_SIZE here */ + double_buffer_flush(ctx->outbuf, outbuf, size); + + PRINTF("Copied lwm2m buf - remaining: %d\n", lwm2m_buf.len); + /* switch buffer */ + ctx->outbuf = outbuf; + ctx->writer_flags |= WRITER_HAS_MORE; + ctx->offset += size; + /* OK - everything went well... but we have more. - keep the lock here! */ + return LWM2M_STATUS_OK; + } else { + PRINTF("*** ERROR Overflow?\n"); + return LWM2M_STATUS_ERROR; + } + } + } } - return; + instance = next_object_instance(ctx, object, instance); + if(instance != NULL) { + last_instance_id = + ((uint32_t)instance->object_id << 16) | instance->instance_id; + } else { + last_instance_id = NO_INSTANCE; + } + if(ctx->operation == LWM2M_OP_READ) { + PRINTF("END Writer %d ->", ctx->outbuf->len); + len = ctx->writer->end_write(ctx); + ctx->outbuf->len += len; + PRINTF("%d\n", ctx->outbuf->len); + } + + initialized = 0; + last_rsc_pos = 0; } - if(depth == 3) { - const lwm2m_resource_t *resource = get_resource(instance, &context); - size_t content_len = 0; - if(resource == NULL) { - PRINTF("Error - do not have resource %d\n", context.resource_id); - REST.set_response_status(response, NOT_FOUND_4_04); - return; - } - /* HANDLE PUT */ - if(method == METHOD_PUT) { - if(lwm2m_object_is_resource_callback(resource)) { - if(resource->value.callback.write != NULL) { - /* pick a reader ??? */ - if(format == LWM2M_TEXT_PLAIN) { - /* a string */ - const uint8_t *data; - int plen = REST.get_request_payload(request, &data); - context.reader = &lwm2m_plain_text_reader; - PRINTF("PUT Callback with data: '%.*s'\n", plen, data); - /* no specific reader for plain text */ - content_len = resource->value.callback.write(&context, data, plen, - buffer, preferred_size); - PRINTF("content_len:%u\n", (unsigned int)content_len); - REST.set_response_status(response, CHANGED_2_04); - } else { - PRINTF("PUT callback with format %d\n", format); - REST.set_response_status(response, NOT_ACCEPTABLE_4_06); - } - } else { - PRINTF("PUT - no write callback\n"); - REST.set_response_status(response, METHOD_NOT_ALLOWED_4_05); - } - } else { - PRINTF("PUT on non-callback resource!\n"); - REST.set_response_status(response, METHOD_NOT_ALLOWED_4_05); + /* did not read anything even if we should have - on single item */ + if(num_read == 0 && ctx->level == 3) { + lwm2m_buf_lock[0] = 0; + return LWM2M_STATUS_NOT_FOUND; + } + + /* seems like we are done! - flush buffer */ + len = double_buffer_flush(ctx->outbuf, outbuf, size); + ctx->outbuf = outbuf; + ctx->offset += len; + + /* If there is still data in the double-buffer - indicate that so that we get another + callback */ + if(lwm2m_buf.len > 0) { + ctx->writer_flags |= WRITER_HAS_MORE; + } else { + /* OK - everything went well we are done, unlock and return */ + lwm2m_buf_lock[0] = 0; + } + + PRINTF("At END: Copied lwm2m buf %d\n", len); + + return LWM2M_STATUS_OK; +} +/*---------------------------------------------------------------------------*/ +static lwm2m_object_instance_t * +create_instance(lwm2m_context_t *context, lwm2m_object_t *object) +{ + lwm2m_object_instance_t *instance; + if(object == NULL || object->impl == NULL || + object->impl->create_instance == NULL) { + return NULL; + } + + /* NOTE: context->object_instance_id needs to be set before calling */ + instance = object->impl->create_instance(context->object_instance_id, NULL); + if(instance != NULL) { + PRINTF("Created instance: %u/%u\n", context->object_id, context->object_instance_id); + coap_set_status_code(context->response, CREATED_2_01); +#if USE_RD_CLIENT + lwm2m_rd_client_set_update_rd(); +#endif + } + return instance; +} +/*---------------------------------------------------------------------------*/ +#define MODE_NONE 0 +#define MODE_INSTANCE 1 +#define MODE_VALUE 2 +#define MODE_READY 3 + +static lwm2m_object_instance_t * +get_or_create_instance(lwm2m_context_t *ctx, lwm2m_object_t *object, + uint8_t *created) +{ + lwm2m_object_instance_t *instance; + + instance = get_instance_by_context(ctx, NULL); + PRINTF("Instance: %u/%u/%u = %p\n", ctx->object_id, + ctx->object_instance_id, ctx->resource_id, instance); + /* by default we assume that the instance is not created... so we set flag to zero */ + if(created != NULL) { + *created = 0; + } + if(instance == NULL) { + instance = create_instance(ctx, object); + if(instance != NULL) { + /* set created flag to one */ + if(created != NULL) { + *created = 1; } - /* HANDLE GET */ - } else if(method == METHOD_GET) { - if(lwm2m_object_is_resource_string(resource)) { - const uint8_t *value; - value = lwm2m_object_get_resource_string(resource, &context); - if(value != NULL) { - uint16_t len = lwm2m_object_get_resource_strlen(resource, &context); - PRINTF("Get string value: %.*s\n", (int)len, (char *)value); - content_len = context.writer->write_string(&context, buffer, - preferred_size, (const char *)value, len); - } - } else if(lwm2m_object_is_resource_int(resource)) { - int32_t value; - if(lwm2m_object_get_resource_int(resource, &context, &value)) { - content_len = context.writer->write_int(&context, buffer, preferred_size, value); - } - } else if(lwm2m_object_is_resource_floatfix(resource)) { - int32_t value; - if(lwm2m_object_get_resource_floatfix(resource, &context, &value)) { - /* export FLOATFIX */ - PRINTF("Exporting %d-bit fix as float: %" PRId32 "\n", - LWM2M_FLOAT32_BITS, value); - content_len = context.writer->write_float32fix(&context, buffer, - preferred_size, value, LWM2M_FLOAT32_BITS); - } - } else if(lwm2m_object_is_resource_callback(resource)) { - if(resource->value.callback.read != NULL) { - content_len = resource->value.callback.read(&context, - buffer, preferred_size); - } else { - REST.set_response_status(response, METHOD_NOT_ALLOWED_4_05); - return; - } - } - if(content_len > 0) { - REST.set_response_payload(response, buffer, content_len); - REST.set_header_content_type(response, content_type); - } else { - /* failed to produce output - it is an internal error */ - REST.set_response_status(response, INTERNAL_SERVER_ERROR_5_00); - } - /* Handle POST */ - } else if(method == METHOD_POST) { - if(lwm2m_object_is_resource_callback(resource)) { - if(resource->value.callback.exec != NULL) { - const uint8_t *data; - int plen = REST.get_request_payload(request, &data); - PRINTF("Execute Callback with data: '%.*s'\n", plen, data); - content_len = resource->value.callback.exec(&context, - data, plen, - buffer, preferred_size); - REST.set_response_status(response, CHANGED_2_04); - } else { - PRINTF("Execute callback - no exec callback\n"); - REST.set_response_status(response, METHOD_NOT_ALLOWED_4_05); - } - } else { - PRINTF("Resource post but no callback resource\n"); - REST.set_response_status(response, METHOD_NOT_ALLOWED_4_05); - } - } - } else if(depth == 2) { - /* produce an instance response */ - if(method != METHOD_GET) { - REST.set_response_status(response, METHOD_NOT_ALLOWED_4_05); - } else if(instance == NULL) { - REST.set_response_status(response, NOT_FOUND_4_04); - } else { - int rdlen; - if(accept == APPLICATION_LINK_FORMAT) { - rdlen = write_rd_link_data(object, instance, - (char *)buffer, preferred_size); - } else { - rdlen = write_rd_json_data(&context, object, instance, - (char *)buffer, preferred_size); - } - if(rdlen < 0) { - PRINTF("Failed to generate instance response\n"); - REST.set_response_status(response, SERVICE_UNAVAILABLE_5_03); - return; - } - REST.set_response_payload(response, buffer, rdlen); - if(accept == APPLICATION_LINK_FORMAT) { - REST.set_header_content_type(response, REST.type.APPLICATION_LINK_FORMAT); - } else { - REST.set_header_content_type(response, LWM2M_JSON); - } - } - } else if(depth == 1) { - /* produce a list of instances */ - if(method != METHOD_GET) { - REST.set_response_status(response, METHOD_NOT_ALLOWED_4_05); - } else { - int rdlen; - PRINTF("Sending instance list for object %u\n", object->id); - /* TODO: if(accept == APPLICATION_LINK_FORMAT) { */ - rdlen = write_object_instances_link(object, (char *)buffer, preferred_size); - if(rdlen < 0) { - PRINTF("Failed to generate object response\n"); - REST.set_response_status(response, SERVICE_UNAVAILABLE_5_03); - return; - } - REST.set_header_content_type(response, REST.type.APPLICATION_LINK_FORMAT); - REST.set_response_payload(response, buffer, rdlen); } } + return instance; +} +/*---------------------------------------------------------------------------*/ +static int +check_write(lwm2m_object_instance_t *instance, int rid) +{ + int i; + if(instance->resource_ids != NULL && instance->resource_count > 0) { + int count = instance->resource_count; + for(i = 0; i < count; i++) { + if(RSC_ID(instance->resource_ids[i]) == rid && + RSC_WRITABLE(instance->resource_ids[i])) { + /* yes - writable */ + return 1; + } + } + } + return 0; +} +/*---------------------------------------------------------------------------*/ +static lwm2m_status_t +process_tlv_write(lwm2m_context_t *ctx, lwm2m_object_t *object, + int rid, uint8_t *data, int len) +{ + lwm2m_object_instance_t *instance; + uint8_t created = 0; + ctx->inbuf->buffer = data; + ctx->inbuf->pos = 0; + ctx->inbuf->size = len; + ctx->level = 3; + ctx->resource_id = rid; + PRINTF(" Doing callback to %u/%u/%u\n", ctx->object_id, + ctx->object_instance_id, ctx->resource_id); + instance = get_or_create_instance(ctx, object, &created); + if(instance != NULL && instance->callback != NULL) { + if(created || check_write(instance, rid)) { + return instance->callback(instance, ctx); + } else { + return LWM2M_STATUS_OPERATION_NOT_ALLOWED; + } + } + return LWM2M_STATUS_ERROR; +} +/*---------------------------------------------------------------------------*/ +static int last_tlv_id = 0; + +static lwm2m_status_t +perform_multi_resource_write_op(lwm2m_object_t *object, + lwm2m_object_instance_t *instance, + lwm2m_context_t *ctx, int format) +{ + /* Only for JSON and TLV formats */ + uint16_t oid = 0, iid = 0, rid = 0; + uint8_t olv = 0; + uint8_t mode = 0; + uint8_t *inbuf; + int inpos; + size_t insize; + + olv = ctx->level; + inbuf = ctx->inbuf->buffer; + inpos = ctx->inbuf->pos; + insize = ctx->inbuf->size; + + if(format == LWM2M_JSON || format == LWM2M_OLD_JSON) { + struct json_data json; + + while(lwm2m_json_next_token(ctx, &json)) { + int i; + uint8_t created = 0; + PRINTF("JSON: '"); + for(i = 0; i < json.name_len; i++) PRINTF("%c", json.name[i]); + PRINTF("':'"); + for(i = 0; i < json.value_len; i++) PRINTF("%c", json.value[i]); + PRINTF("'\n"); + if(json.name[0] == 'n') { + i = parse_path((const char *) json.value, json.value_len, &oid, &iid, &rid); + if(i > 0) { + if(ctx->level == 1) { + ctx->level = 3; + ctx->object_instance_id = oid; + ctx->resource_id = iid; + + instance = get_or_create_instance(ctx, object, &created); + } + if(instance != NULL && instance->callback != NULL) { + mode |= MODE_INSTANCE; + } else { + /* Failure... */ + return LWM2M_STATUS_ERROR; + } + } + } else { + /* HACK - assume value node - can it be anything else? */ + mode |= MODE_VALUE; + /* update values */ + inbuf = ctx->inbuf->buffer; + inpos = ctx->inbuf->pos; + + ctx->inbuf->buffer = json.value; + ctx->inbuf->pos = 0; + ctx->inbuf->size = json.value_len; + } + + if(mode == MODE_READY) { + /* allow write if just created - otherwise not */ + if(!created && !check_write(instance, ctx->resource_id)) { + return LWM2M_STATUS_OPERATION_NOT_ALLOWED; + } + if(instance->callback(instance, ctx) != LWM2M_STATUS_OK) { + /* TODO what to do here */ + } + mode = MODE_NONE; + ctx->inbuf->buffer = inbuf; + ctx->inbuf->pos = inpos; + ctx->inbuf->size = insize; + ctx->level = olv; + } + } + } else if(format == LWM2M_TLV || format == LWM2M_OLD_TLV) { + size_t len; + lwm2m_tlv_t tlv; + int tlvpos = 0; + lwm2m_status_t status; + + /* For handling blockwise (BLOCK1) write */ + uint32_t num; + uint8_t more; + uint16_t size; + uint32_t offset; + + /* NOTE: this assumes that a BLOCK1 non-first block is not a part of a + small TLV but rather a large opaque - this needs to be fixed in the + future */ + + if(coap_get_header_block1(ctx->request, &num, &more, &size, &offset)) { + PRINTF("CoAP BLOCK1: %d/%d/%d offset:%d\n", num, more, size, offset); + PRINTF("LWM2M CTX->offset= %d\n", ctx->offset); + PRINTF("Last TLV ID:%d final:%d\n", last_tlv_id, + lwm2m_object_is_final_incoming(ctx)); + if(offset > 0) { + status = process_tlv_write(ctx, object, last_tlv_id, + inbuf, size); + return status; + } + } + + while(tlvpos < insize) { + len = lwm2m_tlv_read(&tlv, &inbuf[tlvpos], insize - tlvpos); + PRINTF("Got TLV format First is: type:%d id:%d len:%d (p:%d len:%d/%d)\n", + tlv.type, tlv.id, (int) tlv.length, + (int) tlvpos, (int) len, (int) insize); + if(tlv.type == LWM2M_TLV_TYPE_OBJECT_INSTANCE) { + lwm2m_tlv_t tlv2; + int len2; + int pos = 0; + ctx->object_instance_id = tlv.id; + if(tlv.length == 0) { + /* Create only - no data */ + if((instance = create_instance(ctx, object)) == NULL) { + return LWM2M_STATUS_ERROR; + } + } + while(pos < tlv.length && (len2 = lwm2m_tlv_read(&tlv2, &tlv.value[pos], + tlv.length - pos))) { + PRINTF(" TLV type:%d id:%d len:%d (len:%d/%d)\n", + tlv2.type, tlv2.id, (int) tlv2.length, + (int) len2, (int) insize); + if(tlv2.type == LWM2M_TLV_TYPE_RESOURCE) { + last_tlv_id = tlv2.id; + status = process_tlv_write(ctx, object, tlv2.id, + (uint8_t *)&tlv.value[pos], len2); + if(status != LWM2M_STATUS_OK) { + return status; + } + } + pos += len2; + } + } else if(tlv.type == LWM2M_TLV_TYPE_RESOURCE) { + status = process_tlv_write(ctx, object, tlv.id, &inbuf[tlvpos], len); + if(status != LWM2M_STATUS_OK) { + return status; + } + coap_set_status_code(ctx->response, CHANGED_2_04); + } + tlvpos += len; + } + } else if(format == LWM2M_TEXT_PLAIN || + format == TEXT_PLAIN || + format == LWM2M_OLD_OPAQUE) { + return call_instance(instance, ctx); + + } else { + /* Unsupported format */ + return LWM2M_STATUS_UNSUPPORTED_CONTENT_FORMAT; + } + + /* Here we have a success! */ + return LWM2M_STATUS_OK; +} +/*---------------------------------------------------------------------------*/ +lwm2m_object_instance_t * +lwm2m_engine_get_instance_buffer(void) +{ + return &instance_buffer; +} +/*---------------------------------------------------------------------------*/ +int +lwm2m_engine_has_instance(uint16_t object_id, uint16_t instance_id) +{ + return get_instance(object_id, instance_id, NULL) != NULL; +} +/*---------------------------------------------------------------------------*/ +int +lwm2m_engine_add_object(lwm2m_object_instance_t *object) +{ + lwm2m_object_instance_t *instance; + uint16_t min_id = 0xffff; + uint16_t max_id = 0; + int found = 0; + + if(object == NULL || object->callback == NULL) { + /* Insufficient object configuration */ + PRINTF("lwm2m-engine: failed to register NULL object\n"); + return 0; + } + if(get_object(object->object_id) != NULL) { + /* A generic object with this id has already been registered */ + PRINTF("lwm2m-engine: object with id %u already registered\n", + object->object_id); + return 0; + } + + for(instance = list_head(object_list); + instance != NULL; + instance = instance->next) { + if(object->object_id == instance->object_id) { + if(object->instance_id == instance->instance_id) { + PRINTF("lwm2m-engine: object with id %u/%u already registered\n", + instance->object_id, instance->instance_id); + return 0; + } + + found++; + if(instance->instance_id > max_id) { + max_id = instance->instance_id; + } + if(instance->instance_id < min_id) { + min_id = instance->instance_id; + } + } + } + + if(object->instance_id == LWM2M_OBJECT_INSTANCE_NONE) { + /* No instance id has been assigned yet */ + if(found == 0) { + /* First object with this id */ + object->instance_id = 0; + } else if(min_id > 0) { + object->instance_id = min_id - 1; + } else { + object->instance_id = max_id + 1; + } + } + list_add(object_list, object); +#if USE_RD_CLIENT + lwm2m_rd_client_set_update_rd(); +#endif + return 1; } /*---------------------------------------------------------------------------*/ void -lwm2m_engine_delete_handler(const lwm2m_object_t *object, void *request, - void *response, uint8_t *buffer, - uint16_t preferred_size, int32_t *offset) +lwm2m_engine_remove_object(lwm2m_object_instance_t *object) +{ + list_remove(object_list, object); +#if USE_RD_CLIENT + lwm2m_rd_client_set_update_rd(); +#endif +} +/*---------------------------------------------------------------------------*/ +int +lwm2m_engine_add_generic_object(lwm2m_object_t *object) +{ + if(object == NULL || object->impl == NULL + || object->impl->get_first == NULL + || object->impl->get_next == NULL + || object->impl->get_by_id == NULL) { + PRINTF("lwm2m-engine: failed to register NULL object\n"); + return 0; + } + if(get_object(object->impl->object_id) != NULL) { + /* A generic object with this id has already been registered */ + PRINTF("lwm2m-engine: object with id %u already registered\n", + object->impl->object_id); + return 0; + } + if(has_non_generic_object(object->impl->object_id)) { + /* An object with this id has already been registered */ + PRINTF("lwm2m-engine: object with id %u already registered\n", + object->impl->object_id); + return 0; + } + list_add(generic_object_list, object); + +#if USE_RD_CLIENT + lwm2m_rd_client_set_update_rd(); +#endif + + return 1; +} +/*---------------------------------------------------------------------------*/ +void +lwm2m_engine_remove_generic_object(lwm2m_object_t *object) +{ + list_remove(generic_object_list, object); +#if USE_RD_CLIENT + lwm2m_rd_client_set_update_rd(); +#endif +} +/*---------------------------------------------------------------------------*/ +static lwm2m_object_instance_t * +next_object_instance(const lwm2m_context_t *context, lwm2m_object_t *object, + lwm2m_object_instance_t *last) +{ + if(context != NULL && context->level >= 2) { + /* Only single instance */ + return NULL; + } + + /* There has to be a last to get a next */ + if(last == NULL) { + return NULL; + } + + if(object == NULL) { + for(last = last->next; last != NULL; last = last->next) { + /* if no context is given - this will just give the next object */ + if(context == NULL || last->object_id == context->object_id) { + return last; + } + } + return NULL; + } + return object->impl->get_next(last, NULL); +} +/*---------------------------------------------------------------------------*/ +static coap_handler_status_t +lwm2m_handler_callback(coap_packet_t *request, coap_packet_t *response, + uint8_t *buffer, uint16_t buffer_size, int32_t *offset) { - int len; const char *url; + int url_len; + unsigned int format; + unsigned int accept; + int depth; lwm2m_context_t context; + lwm2m_object_t *object; + lwm2m_object_instance_t *instance; + uint32_t bnum; + uint8_t bmore; + uint16_t bsize; + uint32_t boffset; + lwm2m_status_t success; + lwm2m_buffer_t inbuf; + lwm2m_buffer_t outbuf; - len = REST.get_url(request, &url); - PRINTF("*** DELETE URI:'%.*s' called... - responding with DELETED.\n", - len, url); - len = lwm2m_engine_parse_context(object, url, len, &context); - PRINTF("Context: %u/%u/%u found: %d\n", context.object_id, - context.object_instance_id, context.resource_id, len); + /* Initialize the context */ + memset(&context, 0, sizeof(context)); + memset(&outbuf, 0, sizeof(outbuf)); + memset(&inbuf, 0, sizeof(inbuf)); - REST.set_response_status(response, DELETED_2_02); + context.outbuf = &outbuf; + context.inbuf = &inbuf; + + /* Set CoAP request/response for now */ + context.request = request; + context.response = response; + + /* Set out buffer */ + context.outbuf->buffer = buffer; + context.outbuf->size = buffer_size; + + /* Set input buffer */ + if(offset != NULL) { + context.offset = *offset; + } + context.inbuf->size = coap_get_payload(request, (const uint8_t **) &context.inbuf->buffer); + context.inbuf->pos = 0; + + /* Maybe this should be part of CoAP itself - this seems not to be working + with the leshan server */ +#define LWM2M_CONF_ENTITY_TOO_LARGE_BLOCK1 0 +#if LWM2M_CONF_ENTITY_TOO_LARGE_BLOCK1 + if(coap_is_option(request, COAP_OPTION_BLOCK1)) { + uint16_t bsize; + coap_get_header_block1(request, NULL, NULL, &bsize, NULL); + + PRINTF("Block1 size:%d\n", bsize); + if(bsize > COAP_MAX_BLOCK_SIZE) { + PRINTF("Entity too large...\n"); + coap_set_status_code(response, REQUEST_ENTITY_TOO_LARGE_4_13); + coap_set_header_size1(response, COAP_MAX_BLOCK_SIZE); + return COAP_HANDLER_STATUS_PROCESSED; + } + } +#endif + + /* Set default reader/writer */ + context.reader = &lwm2m_plain_text_reader; + context.writer = &lwm2m_tlv_writer; + + + url_len = coap_get_header_uri_path(request, &url); + + if(url_len == 2 && strncmp("bs", url, 2) == 0) { + PRINTF("BOOTSTRAPPED!!!\n"); + coap_set_status_code(response, CHANGED_2_04); + return COAP_HANDLER_STATUS_PROCESSED; + } + + depth = lwm2m_engine_parse_context(url, url_len, request, response, + buffer, buffer_size, &context); + if(depth < 0) { + /* Not a LWM2M context */ + return COAP_HANDLER_STATUS_CONTINUE; + } + + PRINTF("%s URL:'", get_method_as_string(coap_get_method_type(request))); + PRINTS(url_len, url, "%c"); + PRINTF("' CTX:%u/%u/%u dp:%u bs:%d\n", context.object_id, context.object_instance_id, + context.resource_id, depth, buffer_size); + /* Get format and accept */ + if(!coap_get_header_content_format(request, &format)) { + PRINTF("lwm2m: No format given. Assume text plain...\n"); + format = TEXT_PLAIN; + } else if(format == LWM2M_TEXT_PLAIN) { + /* CoAP content format text plain - assume LWM2M text plain */ + format = TEXT_PLAIN; + } + if(!coap_get_header_accept(request, &accept)) { + if(format == TEXT_PLAIN && depth < 3) { + PRINTF("lwm2m: No Accept header, assume JSON\n"); + accept = LWM2M_JSON; + } else { + PRINTF("lwm2m: No Accept header, using same as content-format: %d\n", + format); + accept = format; + } + } + + /** + * 1 => Object only + * 2 => Object and Instance + * 3 => Object and Instance and Resource + */ + if(depth < 1) { + /* No possible object id found in URL - ignore request unless delete all */ + if(coap_get_method_type(request) == METHOD_DELETE) { + PRINTF("This is a delete all - for bootstrap...\n"); + context.operation = LWM2M_OP_DELETE; + coap_set_status_code(response, DELETED_2_02); + + /* Delete all dynamic objects that can be deleted */ + for(object = list_head(generic_object_list); + object != NULL; + object = object->next) { + if(object->impl != NULL && object->impl->delete_instance != NULL) { + object->impl->delete_instance(LWM2M_OBJECT_INSTANCE_NONE, NULL); + } + } +#if USE_RD_CLIENT + lwm2m_rd_client_set_update_rd(); +#endif + return COAP_HANDLER_STATUS_PROCESSED; + } + return COAP_HANDLER_STATUS_CONTINUE; + } + + instance = get_instance_by_context(&context, &object); + if(instance == NULL + && object != NULL + && coap_get_method_type(request) == METHOD_PUT + && context.level == 2) { + /* ALLOW generic instance if CREATE / WRITE*/ + instance = create_instance(&context, object); + if(instance == NULL) { + PRINTF("lwm2m-engine: failed to create instance %u/%u\n", + context.object_id, context.object_instance_id); + } + } + + /* + * Check if we found either instance or object. Instance means we found an + * existing instance and generic objects means we might create an instance. + */ + if(instance == NULL && object == NULL) { + /* No matching object/instance found - ignore request */ + return COAP_HANDLER_STATUS_CONTINUE; + } + + PRINTF("lwm2m: Context: %u/%u/%u found: %d\n", + context.object_id, + context.object_instance_id, context.resource_id, depth); + + /* + * Select reader and writer based on provided Content type and + * Accept headers. + */ + lwm2m_engine_select_reader(&context, format); + lwm2m_engine_select_writer(&context, accept); + + switch(coap_get_method_type(request)) { + case METHOD_PUT: + /* can also be write atts */ + context.operation = LWM2M_OP_WRITE; + coap_set_status_code(response, CHANGED_2_04); + break; + case METHOD_POST: + if(context.level < 2) { + /* write to a instance */ + context.operation = LWM2M_OP_WRITE; + coap_set_status_code(response, CHANGED_2_04); + } else if(context.level == 3) { + context.operation = LWM2M_OP_EXECUTE; + coap_set_status_code(response, CHANGED_2_04); + } + break; + case METHOD_GET: + if(accept == APPLICATION_LINK_FORMAT) { + context.operation = LWM2M_OP_DISCOVER; + } else { + context.operation = LWM2M_OP_READ; + } + coap_set_status_code(response, CONTENT_2_05); + break; + case METHOD_DELETE: + context.operation = LWM2M_OP_DELETE; + coap_set_status_code(response, DELETED_2_02); + break; + default: + break; + } + +#if DEBUG + /* for debugging */ + PRINTPRE("lwm2m: [", url_len, url); + PRINTF("] %s Format:%d ID:%d bsize:%u offset:%d\n", + get_method_as_string(coap_get_method_type(request)), + format, context.object_id, buffer_size, + offset != NULL ? ((int)*offset) : 0); + if(format == TEXT_PLAIN) { + /* a string */ + const uint8_t *data; + int plen = coap_get_payload(request, &data); + if(plen > 0) { + PRINTF("Data: '"); + PRINTS(plen, data, "%c"); + PRINTF("'\n"); + } + } +#endif /* DEBUG */ + + /* PUT/POST - e.g. write will not send in offset here - Maybe in the future? */ + if((offset != NULL && *offset == 0) && + coap_is_option(request, COAP_OPTION_BLOCK1)) { + coap_get_header_block1(request, &bnum, &bmore, &bsize, &boffset); + context.offset = boffset; + } + + /* This is a discovery operation */ + switch(context.operation) { + case LWM2M_OP_DISCOVER: + /* Assume only one disco at a time... */ + success = perform_multi_resource_read_op(object, instance, &context); + break; + case LWM2M_OP_READ: + success = perform_multi_resource_read_op(object, instance, &context); + break; + case LWM2M_OP_WRITE: + success = perform_multi_resource_write_op(object, instance, &context, format); + break; + case LWM2M_OP_EXECUTE: + success = call_instance(instance, &context); + break; + case LWM2M_OP_DELETE: + if(object != NULL && object->impl != NULL && + object->impl->delete_instance != NULL) { + object->impl->delete_instance(context.object_instance_id, &success); +#if USE_RD_CLIENT + lwm2m_rd_client_set_update_rd(); +#endif + } else { + success = LWM2M_STATUS_OPERATION_NOT_ALLOWED; + } + break; + default: + success = LWM2M_STATUS_OPERATION_NOT_ALLOWED; + break; + } + + if(success == LWM2M_STATUS_OK) { + /* Handle blockwise 1 */ + if(coap_is_option(request, COAP_OPTION_BLOCK1)) { + PRINTF("Setting BLOCK 1 num:%d o2:%d o:%d\n", (int) bnum, (int) boffset, + (int) (offset != NULL ? *offset : 0)); + coap_set_header_block1(response, bnum, 0, bsize); + } + + if(context.outbuf->len > 0) { + PRINTPRE("lwm2m: [", url_len, url); + PRINTF("] replying with %u bytes\n", context.outbuf->len); + coap_set_payload(response, context.outbuf->buffer, context.outbuf->len); + coap_set_header_content_format(response, context.content_type); + + if(offset != NULL) { + PRINTF("Setting new offset: oo %d, no: %d\n", *offset, context.offset); + if(context.writer_flags & WRITER_HAS_MORE) { + *offset = context.offset; + } else { + /* this signals to CoAP that there is no more CoAP packets to expect */ + *offset = -1; + } + } + } else { + PRINTPRE("lwm2m: [", url_len, url); + PRINTF("] no data in reply\n"); + } + } else { + switch(success) { + case LWM2M_STATUS_FORBIDDEN: + coap_set_status_code(response, FORBIDDEN_4_03); + break; + case LWM2M_STATUS_NOT_FOUND: + coap_set_status_code(response, NOT_FOUND_4_04); + break; + case LWM2M_STATUS_OPERATION_NOT_ALLOWED: + coap_set_status_code(response, METHOD_NOT_ALLOWED_4_05); + break; + case LWM2M_STATUS_NOT_ACCEPTABLE: + coap_set_status_code(response, NOT_ACCEPTABLE_4_06); + break; + case LWM2M_STATUS_UNSUPPORTED_CONTENT_FORMAT: + coap_set_status_code(response, UNSUPPORTED_MEDIA_TYPE_4_15); + break; + default: + /* Failed to handle the request */ + coap_set_status_code(response, INTERNAL_SERVER_ERROR_5_00); + break; + } + PRINTPRE("lwm2m: [", url_len, url); + PRINTF("] resource failed: %s\n", get_status_as_string(success)); + } + return COAP_HANDLER_STATUS_PROCESSED; +} +/*---------------------------------------------------------------------------*/ +void lwm2m_notify_object_observers(lwm2m_object_instance_t *obj, + uint16_t resource) +{ + char path[20]; /* 60000/60000/60000 */ + if(obj != NULL) { + snprintf(path, 20, "%d/%d/%d", obj->object_id, obj->instance_id, resource); + coap_notify_observers_sub(NULL, path); + } } /*---------------------------------------------------------------------------*/ /** @} */ diff --git a/os/services/lwm2m/lwm2m-engine.h b/os/services/lwm2m/lwm2m-engine.h index 5512a326d..a819540ce 100644 --- a/os/services/lwm2m/lwm2m-engine.h +++ b/os/services/lwm2m/lwm2m-engine.h @@ -52,31 +52,68 @@ /* LWM2M / CoAP Content-Formats */ typedef enum { LWM2M_TEXT_PLAIN = 1541, - LWM2M_TLV = 1542, - LWM2M_JSON = 1543, - LWM2M_OPAQUE = 1544 + LWM2M_TLV = 11542, + LWM2M_JSON = 11543, + LWM2M_OLD_TLV = 1542, + LWM2M_OLD_JSON = 1543, + LWM2M_OLD_OPAQUE = 1544 } lwm2m_content_format_t; void lwm2m_engine_init(void); -void lwm2m_engine_register_default_objects(void); -void lwm2m_engine_use_bootstrap_server(int use); -void lwm2m_engine_use_registration_server(int use); -void lwm2m_engine_register_with_server(const uip_ipaddr_t *server, uint16_t port); -void lwm2m_engine_register_with_bootstrap_server(const uip_ipaddr_t *server, uint16_t port); -const lwm2m_object_t *lwm2m_engine_get_object(uint16_t id); +int lwm2m_engine_set_rd_data(lwm2m_buffer_t *outbuf, int block); -int lwm2m_engine_register_object(const lwm2m_object_t *object); +typedef lwm2m_status_t +(* lwm2m_object_instance_callback_t)(lwm2m_object_instance_t *object, + lwm2m_context_t *ctx); +typedef int +(* lwm2m_resource_dim_callback_t)(lwm2m_object_instance_t *object, + uint16_t resource_id); -void lwm2m_engine_handler(const lwm2m_object_t *object, - void *request, void *response, - uint8_t *buffer, uint16_t preferred_size, - int32_t *offset); +#define LWM2M_OBJECT_INSTANCE_NONE 0xffff + +struct lwm2m_object_instance { + lwm2m_object_instance_t *next; + uint16_t object_id; + uint16_t instance_id; + /* an array of resource IDs for discovery, etc */ + const lwm2m_resource_id_t *resource_ids; + uint16_t resource_count; + /* the callback for requests */ + lwm2m_object_instance_callback_t callback; + lwm2m_resource_dim_callback_t resource_dim_callback; +}; + +typedef struct { + uint16_t object_id; + lwm2m_object_instance_t *(* create_instance)(uint16_t instance_id, + lwm2m_status_t *status); + int (* delete_instance)(uint16_t instance_id, lwm2m_status_t *status); + lwm2m_object_instance_t *(* get_first)(lwm2m_status_t *status); + lwm2m_object_instance_t *(* get_next)(lwm2m_object_instance_t *instance, + lwm2m_status_t *status); + lwm2m_object_instance_t *(* get_by_id)(uint16_t instance_id, + lwm2m_status_t *status); +} lwm2m_object_impl_t; + +typedef struct lwm2m_object lwm2m_object_t; +struct lwm2m_object { + lwm2m_object_t *next; + const lwm2m_object_impl_t *impl; +}; + +lwm2m_object_instance_t *lwm2m_engine_get_instance_buffer(void); + +int lwm2m_engine_has_instance(uint16_t object_id, uint16_t instance_id); +int lwm2m_engine_add_object(lwm2m_object_instance_t *object); +void lwm2m_engine_remove_object(lwm2m_object_instance_t *object); +int lwm2m_engine_add_generic_object(lwm2m_object_t *object); +void lwm2m_engine_remove_generic_object(lwm2m_object_t *object); +void lwm2m_notify_object_observers(lwm2m_object_instance_t *obj, + uint16_t resource); + +void lwm2m_engine_set_opaque_callback(lwm2m_context_t *ctx, lwm2m_write_opaque_callback cb); -void lwm2m_engine_delete_handler(const lwm2m_object_t *object, - void *request, void *response, - uint8_t *buffer, uint16_t preferred_size, - int32_t *offset); #endif /* LWM2M_ENGINE_H */ /** @} */ diff --git a/os/services/lwm2m/lwm2m-firmware.c b/os/services/lwm2m/lwm2m-firmware.c new file mode 100644 index 000000000..b51fb13ab --- /dev/null +++ b/os/services/lwm2m/lwm2m-firmware.c @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2016, SICS Swedish ICT AB + * 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 copyright holder 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 COPYRIGHT HOLDER 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 + * COPYRIGHT HOLDER 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. + */ + +/** + * \addtogroup + * @{ + * + * Code for firmware object of lwm2m + * + */ + +#include "lwm2m-engine.h" +#include "lwm2m-firmware.h" +#include "coap.h" +#include + +#define DEBUG 0 +#if DEBUG +#include +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif + +#define UPDATE_PACKAGE 0 +#define UPDATE_PACKAGE_URI 1 +#define UPDATE_UPDATE 2 +#define UPDATE_STATE 3 +#define UPDATE_RESULT 5 + +#define STATE_IDLE 1 +#define STATE_DOWNLOADING 2 +#define STATE_DOWNLOADED 3 + +#define RESULT_DEFAULT 0 +#define RESULT_SUCCESS 1 +#define RESULT_NO_STORAGE 2 +#define RESULT_OUT_OF_MEM 3 +#define RESULT_CONNECTION_LOST 4 +#define RESULT_CRC_FAILED 5 +#define RESULT_UNSUPPORTED_FW 6 +#define RESULT_INVALID_URI 7 + + +static uint8_t state = STATE_IDLE; +static uint8_t result = RESULT_DEFAULT; + +static lwm2m_object_instance_t reg_object; + +static const lwm2m_resource_id_t resources[] = + { WO(UPDATE_PACKAGE), + WO(UPDATE_PACKAGE_URI), + RO(UPDATE_STATE), + RO(UPDATE_RESULT), + EX(UPDATE_UPDATE) + }; + +/*---------------------------------------------------------------------------*/ +static lwm2m_status_t +lwm2m_callback(lwm2m_object_instance_t *object, + lwm2m_context_t *ctx) +{ +#if DEBUG + uint32_t num; + uint8_t more; + uint16_t size; + uint32_t offset; +#endif + + PRINTF("Got request at: %d/%d/%d lv:%d\n", ctx->object_id, ctx->object_instance_id, ctx->resource_id, ctx->level); + + if(ctx->level == 1 || ctx->level == 2) { + /* Should not happen - as it will be taken care of by the lwm2m engine itself. */ + return LWM2M_STATUS_ERROR; + } + + if(ctx->operation == LWM2M_OP_READ) { + switch(ctx->resource_id) { + case UPDATE_STATE: + lwm2m_object_write_int(ctx, state); /* 1 means idle */ + return LWM2M_STATUS_OK; + case UPDATE_RESULT: + lwm2m_object_write_int(ctx, result); /* 0 means default */ + return LWM2M_STATUS_OK; + } + } else if(ctx->operation == LWM2M_OP_WRITE) { +#if DEBUG + if(coap_get_header_block1(ctx->request, &num, &more, &size, &offset)) { + PRINTF("CoAP BLOCK1: %d/%d/%d offset:%d\n", num, more, size, offset); + PRINTF("LWM2M CTX->offset= %d\n", ctx->offset); + } +#endif + switch(ctx->resource_id) { + case UPDATE_PACKAGE: + /* The firmware is written */ + PRINTF("Firmware received: %d %d fin:%d\n", ctx->offset, (int) ctx->inbuf->size, + lwm2m_object_is_final_incoming(ctx)); + if(lwm2m_object_is_final_incoming(ctx)) { + state = STATE_DOWNLOADED; + } else { + state = STATE_DOWNLOADING; + } + return LWM2M_STATUS_OK; + case UPDATE_PACKAGE_URI: + /* The firmware URI is written */ + PRINTF("Firmware URI received: %d %d fin:%d\n", ctx->offset, (int) ctx->inbuf->size, + lwm2m_object_is_final_incoming(ctx)); + if(DEBUG) { + int i; + PRINTF("Data: '"); + for(i = 0; i < ctx->inbuf->size; i++) { + PRINTF("%c", ctx->inbuf->buffer[i]); + } + PRINTF("'\n"); + } + return LWM2M_STATUS_OK; + } + } else if(ctx->operation == LWM2M_OP_EXECUTE && ctx->resource_id == UPDATE_UPDATE) { + /* Perform the update operation */ + if(state == STATE_DOWNLOADED) { + return LWM2M_STATUS_OK; + } + /* Failure... */ + } + return LWM2M_STATUS_ERROR; +} + +/*---------------------------------------------------------------------------*/ +void +lwm2m_firmware_init(void) +{ + reg_object.object_id = 5; + reg_object.instance_id = 0; + reg_object.callback = lwm2m_callback; + reg_object.resource_ids = resources; + reg_object.resource_count = sizeof(resources) / sizeof(lwm2m_resource_id_t); + + lwm2m_engine_add_object(®_object); +} +/*---------------------------------------------------------------------------*/ diff --git a/os/services/lwm2m/lwm2m-firmware.h b/os/services/lwm2m/lwm2m-firmware.h new file mode 100644 index 000000000..fb291b635 --- /dev/null +++ b/os/services/lwm2m/lwm2m-firmware.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2016, SICS Swedish ICT AB + * 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 copyright holder 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 COPYRIGHT HOLDER 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 + * COPYRIGHT HOLDER 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. + */ + +/** + * \addtogroup + * @{ + * + * Code for firmware object of lwm2m + * + */ + +#ifndef LWM2M_FIRMWARE_H_ +#define LWM2M_FIRMWARE_H_ + +void lwm2m_firmware_init(void); + +#endif /* LWM2M_FIRMWARE_H_ */ +/** @} */ diff --git a/os/services/lwm2m/lwm2m-json.c b/os/services/lwm2m/lwm2m-json.c index 8924ceb8c..a247fd9b1 100644 --- a/os/services/lwm2m/lwm2m-json.c +++ b/os/services/lwm2m/lwm2m-json.c @@ -38,6 +38,7 @@ * Implementation of the Contiki OMA LWM2M JSON writer * \author * Joakim NohlgÃ¥rd + * Joakim Eriksson added JSON reader parts */ #include "lwm2m-object.h" @@ -54,37 +55,195 @@ #else #define PRINTF(...) #endif +/*---------------------------------------------------------------------------*/ +/* {"e":[{"n":"111/1","v":123},{"n":"111/2","v":42}]} */ + +/* Begin String */ +#define T_NONE 0 +#define T_STRING_B 1 +#define T_STRING 2 +#define T_NAME 4 +#define T_VNUM 5 +#define T_OBJ 6 +#define T_VAL 7 + +/* Simlified JSON style reader for reading in values from a LWM2M JSON + string */ +int lwm2m_json_next_token(lwm2m_context_t *ctx, struct json_data *json) { + int pos = ctx->inbuf->pos; + uint8_t type = T_NONE; + uint8_t vpos_start = 0; + uint8_t vpos_end = 0; + uint8_t cont; + uint8_t wscount = 0; + + json->name_len = 0; + json->value_len = 0; + + cont = 1; + /* We will be either at start, or at a specific position */ + while(pos < ctx->inbuf->size && cont) { + uint8_t c = ctx->inbuf->buffer[pos++]; + switch(c) { + case '{': type = T_OBJ; break; + case '}': + case ',': + if(type == T_VAL || type == T_STRING) { + json->value = &ctx->inbuf->buffer[vpos_start]; + json->value_len = vpos_end - vpos_start - wscount; + type = T_NONE; + cont = 0; + } + wscount = 0; + break; + case '\\': + /* stuffing */ + if(pos < ctx->inbuf->size) { + pos++; + vpos_end = pos; + } + break; + case '"': + if(type == T_STRING_B) { + type = T_STRING; + vpos_end = pos - 1; + wscount = 0; + } else { + type = T_STRING_B; + vpos_start = pos; + } + break; + case ':': + if(type == T_STRING) { + json->name = &ctx->inbuf->buffer[vpos_start]; + json->name_len = vpos_end - vpos_start; + vpos_start = vpos_end = pos; + type = T_VAL; + } else { + /* Could be in string or at illegal pos */ + if(type != T_STRING_B) { + PRINTF("ERROR - illegal ':'\n"); + } + } + break; + /* ignore whitespace */ + case ' ': + case '\n': + case '\t': + if(type != T_STRING_B) { + if(vpos_start == pos - 1) { + vpos_start = pos; + } else { + wscount++; + } + } + default: + vpos_end = pos; + } + } + + if(cont == 0 && pos < ctx->inbuf->size) { + ctx->inbuf->pos = pos; + } + /* OK if cont == 0 othewise we failed */ + return cont == 0 && pos < ctx->inbuf->size; +} /*---------------------------------------------------------------------------*/ static size_t -write_boolean(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, +init_write(lwm2m_context_t *ctx) +{ + int len = snprintf((char *)&ctx->outbuf->buffer[ctx->outbuf->len], + ctx->outbuf->size - ctx->outbuf->len, "{\"bn\":\"/%u/%u/\",\"e\":[", + ctx->object_id, ctx->object_instance_id); + ctx->writer_flags = 0; /* set flags to zero */ + if((len < 0) || (len >= ctx->outbuf->size)) { + return 0; + } + return len; +} +/*---------------------------------------------------------------------------*/ +static size_t +end_write(lwm2m_context_t *ctx) +{ + int len = snprintf((char *)&ctx->outbuf->buffer[ctx->outbuf->len], + ctx->outbuf->size - ctx->outbuf->len, "]}"); + if((len < 0) || (len >= ctx->outbuf->size - ctx->outbuf->len)) { + return 0; + } + return len; +} +/*---------------------------------------------------------------------------*/ +static size_t +enter_sub(lwm2m_context_t *ctx) +{ + /* set some flags in state */ + PRINTF("Enter sub-resource rsc=%d\n", ctx->resource_id); + ctx->writer_flags |= WRITER_RESOURCE_INSTANCE; + return 0; +} +/*---------------------------------------------------------------------------*/ +static size_t +exit_sub(lwm2m_context_t *ctx) +{ + /* clear out state info */ + PRINTF("Exit sub-resource rsc=%d\n", ctx->resource_id); + ctx->writer_flags &= ~WRITER_RESOURCE_INSTANCE; + return 0; +} +/*---------------------------------------------------------------------------*/ +static size_t +write_boolean(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, int value) { - int len = snprintf((char *)outbuf, outlen, "{\"e\":[{\"n\":\"%u\",\"bv\":%s}]}\n", ctx->resource_id, value ? "true" : "false"); + char *sep = (ctx->writer_flags & WRITER_OUTPUT_VALUE) ? "," : ""; + int len; + if(ctx->writer_flags & WRITER_RESOURCE_INSTANCE) { + len = snprintf((char *)outbuf, outlen, "%s{\"n\":\"%u/%u\",\"bv\":%s}", sep, ctx->resource_id, ctx->resource_instance_id, value ? "true" : "false"); + } else { + len = snprintf((char *)outbuf, outlen, "%s{\"n\":\"%u\",\"bv\":%s}", sep, ctx->resource_id, value ? "true" : "false"); + } if((len < 0) || (len >= outlen)) { return 0; } + PRINTF("JSON: Write bool:%s\n", outbuf); + + ctx->writer_flags |= WRITER_OUTPUT_VALUE; return len; } /*---------------------------------------------------------------------------*/ static size_t -write_int(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, +write_int(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, int32_t value) { - int len = snprintf((char *)outbuf, outlen, "{\"e\":[{\"n\":\"%u\",\"v\":%" PRId32 "}]}\n", ctx->resource_id, value); + char *sep = (ctx->writer_flags & WRITER_OUTPUT_VALUE) ? "," : ""; + int len; + if(ctx->writer_flags & WRITER_RESOURCE_INSTANCE) { + len = snprintf((char *)outbuf, outlen, "%s{\"n\":\"%u/%u\",\"v\":%" PRId32 "}", sep, ctx->resource_id, ctx->resource_instance_id, value); + } else { + len = snprintf((char *)outbuf, outlen, "%s{\"n\":\"%u\",\"v\":%" PRId32 "}", sep, ctx->resource_id, value); + } if((len < 0) || (len >= outlen)) { return 0; } + PRINTF("JSON: Write int:%s\n", outbuf); + + ctx->writer_flags |= WRITER_OUTPUT_VALUE; return len; } /*---------------------------------------------------------------------------*/ static size_t -write_float32fix(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, +write_float32fix(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, int32_t value, int bits) { + char *sep = (ctx->writer_flags & WRITER_OUTPUT_VALUE) ? "," : ""; size_t len = 0; int res; - res = snprintf((char *)outbuf, outlen, "{\"e\":[{\"n\":\"%u\",\"v\":", ctx->resource_id); + if(ctx->writer_flags & WRITER_RESOURCE_INSTANCE) { + res = snprintf((char *)outbuf, outlen, "%s{\"n\":\"%u/%u\",\"v\":", sep, ctx->resource_id, ctx->resource_instance_id); + } else { + res = snprintf((char *)outbuf, outlen, "%s{\"n\":\"%u\",\"v\":", sep, ctx->resource_id); + } if(res <= 0 || res >= outlen) { return 0; } @@ -96,23 +255,31 @@ write_float32fix(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, } len += res; outlen -= res; - res = snprintf((char *)&outbuf[len], outlen, "}]}\n"); + res = snprintf((char *)&outbuf[len], outlen, "}"); if((res <= 0) || (res >= outlen)) { return 0; } len += res; + ctx->writer_flags |= WRITER_OUTPUT_VALUE; return len; } /*---------------------------------------------------------------------------*/ static size_t -write_string(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, +write_string(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, const char *value, size_t stringlen) { + char *sep = (ctx->writer_flags & WRITER_OUTPUT_VALUE) ? "," : ""; size_t i; size_t len = 0; int res; - PRINTF("{\"e\":[{\"n\":\"%u\",\"sv\":\"", ctx->resource_id); - res = snprintf((char *)outbuf, outlen, "{\"e\":[{\"n\":\"%u\",\"sv\":\"", ctx->resource_id); + PRINTF("{\"n\":\"%u\",\"sv\":\"", ctx->resource_id); + if(ctx->writer_flags & WRITER_RESOURCE_INSTANCE) { + res = snprintf((char *)outbuf, outlen, "%s{\"n\":\"%u/%u\",\"sv\":\"", sep, + ctx->resource_id, ctx->resource_instance_id); + } else { + res = snprintf((char *)outbuf, outlen, "%s{\"n\":\"%u\",\"sv\":\"", sep, + ctx->resource_id); + } if(res < 0 || res >= outlen) { return 0; } @@ -143,20 +310,30 @@ write_string(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, return 0; } } - PRINTF("\"}]}\n"); - res = snprintf((char *)&outbuf[len], outlen - len, "\"}]}\n"); + PRINTF("\"}\n"); + res = snprintf((char *)&outbuf[len], outlen - len, "\"}"); if((res < 0) || (res >= (outlen - len))) { return 0; } + + PRINTF("JSON: Write string:%s\n", outbuf); + len += res; + ctx->writer_flags |= WRITER_OUTPUT_VALUE; return len; } /*---------------------------------------------------------------------------*/ const lwm2m_writer_t lwm2m_json_writer = { + init_write, + end_write, + enter_sub, + exit_sub, write_int, write_string, write_float32fix, write_boolean }; +/*---------------------------------------------------------------------------*/ + /*---------------------------------------------------------------------------*/ /** @} */ diff --git a/os/services/lwm2m/lwm2m-json.h b/os/services/lwm2m/lwm2m-json.h index bc1a1e32a..0fd9a1a82 100644 --- a/os/services/lwm2m/lwm2m-json.h +++ b/os/services/lwm2m/lwm2m-json.h @@ -45,7 +45,17 @@ #include "lwm2m-object.h" +struct json_data { + uint8_t type; /* S,B,V */ + uint8_t *name; + uint8_t *value; + uint8_t name_len; + uint8_t value_len; +}; + extern const lwm2m_writer_t lwm2m_json_writer; +int lwm2m_json_next_token(lwm2m_context_t *ctx, struct json_data *json); + #endif /* LWM2M_JSON_H_ */ /** @} */ diff --git a/os/services/lwm2m/lwm2m-object.c b/os/services/lwm2m/lwm2m-object.c deleted file mode 100644 index 2f5ddb6ed..000000000 --- a/os/services/lwm2m/lwm2m-object.c +++ /dev/null @@ -1,336 +0,0 @@ -/* - * Copyright (c) 2015, Yanzi Networks AB. - * 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 copyright holder 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 COPYRIGHT HOLDER 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 - * COPYRIGHT HOLDER 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. - */ - -/** - * \addtogroup oma-lwm2m - * @{ - * - */ - -/** - * \file - * Implementation of the Contiki OMA LWM2M object API - * \author - * Joakim Eriksson - * Niclas Finne - */ - -#include "lwm2m-object.h" -#include -/*---------------------------------------------------------------------------*/ -int -lwm2m_object_is_resource_string(const lwm2m_resource_t *resource) -{ - if(resource == NULL) { - return 0; - } - if(resource->type == LWM2M_RESOURCE_TYPE_STR_VALUE || - resource->type == LWM2M_RESOURCE_TYPE_STR_VARIABLE || - resource->type == LWM2M_RESOURCE_TYPE_STR_VARIABLE_ARRAY) { - return 1; - } - return 0; -} -/*---------------------------------------------------------------------------*/ -const uint8_t * -lwm2m_object_get_resource_string(const lwm2m_resource_t *resource, - const lwm2m_context_t *context) -{ - if(resource == NULL || context == NULL) { - return NULL; - } - if(resource->type == LWM2M_RESOURCE_TYPE_STR_VALUE) { - return resource->value.string.value; - } - if(resource->type == LWM2M_RESOURCE_TYPE_STR_VARIABLE) { - return *(resource->value.stringvar.var); - } - if(resource->type == LWM2M_RESOURCE_TYPE_STR_VARIABLE_ARRAY) { - if(context->object_instance_index < resource->value.stringvararr.count) { - return resource->value.stringvararr.var + - resource->value.stringvararr.size * context->object_instance_index; - } - return NULL; - } - /* Not a string */ - return NULL; -} -/*---------------------------------------------------------------------------*/ -uint16_t -lwm2m_object_get_resource_strlen(const lwm2m_resource_t *resource, - const lwm2m_context_t *context) -{ - if(resource == NULL || context == NULL) { - return 0; - } - if(resource->type == LWM2M_RESOURCE_TYPE_STR_VALUE) { - return resource->value.string.len; - } - if(resource->type == LWM2M_RESOURCE_TYPE_STR_VARIABLE) { - return *(resource->value.stringvar.len); - } - if(resource->type == LWM2M_RESOURCE_TYPE_STR_VARIABLE_ARRAY) { - if(context->object_instance_index < resource->value.stringvararr.count) { - return resource->value.stringvararr.len[context->object_instance_index]; - } - return 0; - } - /* Not a string */ - return 0; -} -/*---------------------------------------------------------------------------*/ -int -lwm2m_object_set_resource_string(const lwm2m_resource_t *resource, - const lwm2m_context_t *context, - uint16_t len, const uint8_t *string) -{ - if(resource == NULL || context == NULL) { - return 0; - } - if(resource->type == LWM2M_RESOURCE_TYPE_STR_VARIABLE) { - if(len > resource->value.stringvar.size) { - /* Too large */ - return 0; - } - memcpy(resource->value.stringvar.var, string, len); - *(resource->value.stringvar.len) = len; - return 1; - } - if(resource->type == LWM2M_RESOURCE_TYPE_STR_VARIABLE_ARRAY) { - if(context->object_instance_index < resource->value.stringvararr.count && - len <= resource->value.stringvararr.size) { - memcpy(resource->value.stringvararr.var + - resource->value.stringvararr.size * context->object_instance_index, - string, len); - resource->value.stringvararr.len[context->object_instance_index] = len; - return 1; - } - return 0; - } - /* Not a string variable */ - return 0; -} -/*---------------------------------------------------------------------------*/ -int -lwm2m_object_is_resource_int(const lwm2m_resource_t *resource) -{ - if(resource == NULL) { - return 0; - } - if(resource->type == LWM2M_RESOURCE_TYPE_INT_VALUE || - resource->type == LWM2M_RESOURCE_TYPE_INT_VARIABLE || - resource->type == LWM2M_RESOURCE_TYPE_INT_VARIABLE_ARRAY) { - return 1; - } - return 0; -} -/*---------------------------------------------------------------------------*/ -int -lwm2m_object_get_resource_int(const lwm2m_resource_t *resource, - const lwm2m_context_t *context, - int32_t *value) -{ - if(resource == NULL || context == NULL || value == NULL) { - return 0; - } - if(resource->type == LWM2M_RESOURCE_TYPE_INT_VALUE) { - *value = resource->value.integer.value; - return 1; - } - if(resource->type == LWM2M_RESOURCE_TYPE_INT_VARIABLE) { - *value = *(resource->value.integervar.var); - return 1; - } - if(resource->type == LWM2M_RESOURCE_TYPE_INT_VARIABLE_ARRAY) { - if(context->object_instance_index < resource->value.integervararr.count) { - *value = resource->value.integervararr.var[context->object_instance_index]; - return 1; - } - return 0; - } - /* Not an integer */ - return 0; -} -/*---------------------------------------------------------------------------*/ -int -lwm2m_object_set_resource_int(const lwm2m_resource_t *resource, - const lwm2m_context_t *context, - int32_t value) -{ - if(resource == NULL || context == NULL) { - return 0; - } - if(resource->type == LWM2M_RESOURCE_TYPE_INT_VARIABLE) { - *(resource->value.integervar.var) = value; - return 1; - } - if(resource->type == LWM2M_RESOURCE_TYPE_INT_VARIABLE_ARRAY) { - if(context->object_instance_index < resource->value.integervararr.count) { - resource->value.integervararr.var[context->object_instance_index] = - value; - return 1; - } - return 0; - } - /* Not an integer variable */ - return 0; -} -/*---------------------------------------------------------------------------*/ -int -lwm2m_object_is_resource_floatfix(const lwm2m_resource_t *resource) -{ - if(resource == NULL) { - return 0; - } - if(resource->type == LWM2M_RESOURCE_TYPE_FLOATFIX_VALUE || - resource->type == LWM2M_RESOURCE_TYPE_FLOATFIX_VARIABLE || - resource->type == LWM2M_RESOURCE_TYPE_FLOATFIX_VARIABLE_ARRAY) { - return 1; - } - return 0; -} -/*---------------------------------------------------------------------------*/ -int -lwm2m_object_get_resource_floatfix(const lwm2m_resource_t *resource, - const lwm2m_context_t *context, - int32_t *value) -{ - if(resource == NULL || context == NULL || value == NULL) { - return 0; - } - if(resource->type == LWM2M_RESOURCE_TYPE_FLOATFIX_VALUE) { - *value = resource->value.floatfix.value; - return 1; - } - if(resource->type == LWM2M_RESOURCE_TYPE_FLOATFIX_VARIABLE) { - *value = *(resource->value.floatfixvar.var); - return 1; - } - if(resource->type == LWM2M_RESOURCE_TYPE_FLOATFIX_VARIABLE_ARRAY) { - if(context->object_instance_index < resource->value.floatfixvararr.count) { - *value = resource->value.floatfixvararr.var[context->object_instance_index]; - return 1; - } - return 0; - } - /* Not an float */ - return 0; -} -/*---------------------------------------------------------------------------*/ -int -lwm2m_object_set_resource_floatfix(const lwm2m_resource_t *resource, - const lwm2m_context_t *context, - int32_t value) -{ - if(resource == NULL || context == NULL) { - return 0; - } - if(resource->type == LWM2M_RESOURCE_TYPE_FLOATFIX_VARIABLE) { - *(resource->value.floatfixvar.var) = value; - return 1; - } - if(resource->type == LWM2M_RESOURCE_TYPE_FLOATFIX_VARIABLE_ARRAY) { - if(context->object_instance_index < resource->value.floatfixvararr.count) { - resource->value.floatfixvararr.var[context->object_instance_index] = - value; - return 1; - } - return 0; - } - /* Not an float variable */ - return 0; -} -/*---------------------------------------------------------------------------*/ -int -lwm2m_object_is_resource_boolean(const lwm2m_resource_t *resource) -{ - if(resource == NULL) { - return 0; - } - if(resource->type == LWM2M_RESOURCE_TYPE_BOOLEAN_VALUE || - resource->type == LWM2M_RESOURCE_TYPE_BOOLEAN_VARIABLE || - resource->type == LWM2M_RESOURCE_TYPE_BOOLEAN_VARIABLE_ARRAY) { - return 1; - } - return 0; -} -/*---------------------------------------------------------------------------*/ -int -lwm2m_object_get_resource_boolean(const lwm2m_resource_t *resource, - const lwm2m_context_t *context, - int *value) -{ - if(resource == NULL || context == NULL || value == NULL) { - return 0; - } - if(resource->type == LWM2M_RESOURCE_TYPE_BOOLEAN_VALUE) { - *value = resource->value.boolean.value; - return 1; - } - if(resource->type == LWM2M_RESOURCE_TYPE_BOOLEAN_VARIABLE) { - *value = *(resource->value.booleanvar.var); - return 1; - } - if(resource->type == LWM2M_RESOURCE_TYPE_BOOLEAN_VARIABLE_ARRAY) { - if(context->object_instance_index < resource->value.booleanvararr.count) { - *value = resource->value.booleanvararr.var[context->object_instance_index]; - return 1; - } - return 0; - } - /* Not a boolean */ - return 0; -} -/*---------------------------------------------------------------------------*/ -int -lwm2m_object_set_resource_boolean(const lwm2m_resource_t *resource, - const lwm2m_context_t *context, - int value) -{ - if(resource == NULL || context == NULL) { - return 0; - } - if(resource->type == LWM2M_RESOURCE_TYPE_BOOLEAN_VARIABLE) { - *(resource->value.booleanvar.var) = value; - return 1; - } - if(resource->type == LWM2M_RESOURCE_TYPE_BOOLEAN_VARIABLE_ARRAY) { - if(context->object_instance_index < resource->value.booleanvararr.count) { - resource->value.booleanvararr.var[context->object_instance_index] = - value; - return 1; - } - return 0; - } - /* Not a boolean variable */ - return 0; -} -/*---------------------------------------------------------------------------*/ -/** @} */ diff --git a/os/services/lwm2m/lwm2m-object.h b/os/services/lwm2m/lwm2m-object.h index a5ff53ac4..cd0eb0f5d 100644 --- a/os/services/lwm2m/lwm2m-object.h +++ b/os/services/lwm2m/lwm2m-object.h @@ -51,8 +51,24 @@ #ifndef LWM2M_OBJECT_H_ #define LWM2M_OBJECT_H_ -#include "net/app-layer/coap/rest-engine.h" -#include "net/app-layer/coap/coap-observe.h" +#include "coap.h" +#include "coap-observe.h" + +/* Operation permissions on the resources - read/write/execute */ +#define LWM2M_RESOURCE_READ 0x10000 +#define LWM2M_RESOURCE_WRITE 0x20000 +#define LWM2M_RESOURCE_EXECUTE 0x40000 + +/* The resource id type of lwm2m objects - 16 bits for the ID - the rest + is flags */ +typedef uint32_t lwm2m_resource_id_t; + +/* Defines for the resource definition array */ +#define RO(x) (x | LWM2M_RESOURCE_READ) +#define WO(x) (x | LWM2M_RESOURCE_WRITE) +#define RW(x) (x | LWM2M_RESOURCE_READ | LWM2M_RESOURCE_WRITE) +#define EX(x) (x | LWM2M_RESOURCE_EXECUTE) + #define LWM2M_OBJECT_SECURITY_ID 0 #define LWM2M_OBJECT_SERVER_ID 1 @@ -63,14 +79,36 @@ #define LWM2M_OBJECT_LOCATION_ID 6 #define LWM2M_OBJECT_CONNECTIVITY_STATISTICS_ID 7 -#define LWM2M_SECURITY_SERVER_URI 0 -#define LWM2M_SECURITY_BOOTSTRAP_SERVER 1 -#define LWM2M_SECURITY_MODE 2 -#define LWM2M_SECURITY_CLIENT_PKI 3 -#define LWM2M_SECURITY_SERVER_PKI 4 -#define LWM2M_SECURITY_KEY 5 +#define LWM2M_SECURITY_SERVER_URI_ID 0 +#define LWM2M_SECURITY_BOOTSTRAP_SERVER_ID 1 +#define LWM2M_SECURITY_MODE_ID 2 +#define LWM2M_SECURITY_CLIENT_PKI_ID 3 +#define LWM2M_SECURITY_SERVER_PKI_ID 4 +#define LWM2M_SECURITY_KEY_ID 5 #define LWM2M_SECURITY_SHORT_SERVER_ID 10 +#define LWM2M_SERVER_SHORT_SERVER_ID 0 +#define LWM2M_SERVER_LIFETIME_ID 1 +#define LWM2M_SERVER_BINDING_ID 7 +#define LWM2M_SERVER_REG_UPDATE_TRIGGER_ID 8 + +#define LWM2M_DEVICE_MANUFACTURER_ID 0 +#define LWM2M_DEVICE_MODEL_NUMBER_ID 1 +#define LWM2M_DEVICE_SERIAL_NUMBER_ID 2 +#define LWM2M_DEVICE_FIRMWARE_VERSION_ID 3 +#define LWM2M_DEVICE_REBOOT_ID 4 +#define LWM2M_DEVICE_FACTORY_DEFAULT_ID 5 +#define LWM2M_DEVICE_AVAILABLE_POWER_SOURCES 6 +/* These do have multiple instances */ +#define LWM2M_DEVICE_POWER_SOURCE_VOLTAGE 7 +#define LWM2M_DEVICE_POWER_SOURCE_CURRENT 8 +#define LWM2M_DEVICE_BATTERY_LEVEL 9 + +#define LWM2M_DEVICE_ERROR_CODE 11 +#define LWM2M_DEVICE_TIME_ID 13 +#define LWM2M_DEVICE_TYPE_ID 17 + + /* Pre-shared key mode */ #define LWM2M_SECURITY_MODE_PSK 0 /* Raw Public Key mode */ @@ -80,274 +118,281 @@ /* NoSec mode */ #define LWM2M_SECURITY_MODE_NOSEC 3 -#define LWM2M_OBJECT_STR_HELPER(x) (uint8_t *) #x -#define LWM2M_OBJECT_STR(x) LWM2M_OBJECT_STR_HELPER(x) +typedef enum { + LWM2M_OP_NONE, + LWM2M_OP_READ, + LWM2M_OP_DISCOVER, + LWM2M_OP_WRITE, + LWM2M_OP_WRITE_ATTR, + LWM2M_OP_EXECUTE, + LWM2M_OP_CREATE, + LWM2M_OP_DELETE +} lwm2m_operation_t; -#define LWM2M_OBJECT_PATH_STR_HELPER(x) #x -#define LWM2M_OBJECT_PATH_STR(x) LWM2M_OBJECT_PATH_STR_HELPER(x) +typedef enum { + LWM2M_STATUS_OK, + + /* Internal server error */ + LWM2M_STATUS_ERROR, + /* Error from writer */ + LWM2M_STATUS_WRITE_ERROR, + /* Error from reader */ + LWM2M_STATUS_READ_ERROR, + + LWM2M_STATUS_BAD_REQUEST, + LWM2M_STATUS_UNAUTHORIZED, + LWM2M_STATUS_FORBIDDEN, + LWM2M_STATUS_NOT_FOUND, + LWM2M_STATUS_OPERATION_NOT_ALLOWED, + LWM2M_STATUS_NOT_ACCEPTABLE, + LWM2M_STATUS_UNSUPPORTED_CONTENT_FORMAT, + + LWM2M_STATUS_NOT_IMPLEMENTED, + LWM2M_STATUS_SERVICE_UNAVAILABLE, +} lwm2m_status_t; + +/* remember that we have already output a value - can be between two block's */ +#define WRITER_OUTPUT_VALUE 1 +#define WRITER_RESOURCE_INSTANCE 2 +#define WRITER_HAS_MORE 4 + +typedef struct lwm2m_reader lwm2m_reader_t; +typedef struct lwm2m_writer lwm2m_writer_t; + +typedef struct lwm2m_object_instance lwm2m_object_instance_t; + +typedef struct { + uint16_t len; /* used for current length of the data in the buffer */ + uint16_t pos; /* position in the buffer - typically write position or similar */ + uint16_t size; + uint8_t *buffer; +} lwm2m_buffer_t; -struct lwm2m_reader; -struct lwm2m_writer; /* Data model for OMA LWM2M objects */ typedef struct lwm2m_context { uint16_t object_id; uint16_t object_instance_id; uint16_t resource_id; - uint8_t object_instance_index; - uint8_t resource_index; - /* TODO - add uint16_t resource_instance_id */ + uint16_t resource_instance_id; - const struct lwm2m_reader *reader; - const struct lwm2m_writer *writer; + uint8_t resource_index; + uint8_t resource_instance_index; /* for use when stepping to next sub-resource if having multiple */ + uint8_t level; /* 0/1/2/3 = 3 = resource */ + lwm2m_operation_t operation; + + coap_packet_t *request; + coap_packet_t *response; + + unsigned int content_type; + lwm2m_buffer_t *outbuf; + lwm2m_buffer_t *inbuf; + + uint8_t out_mark_pos_oi; /* mark pos for last object instance */ + uint8_t out_mark_pos_ri; /* mark pos for last resource instance */ + + uint32_t offset; /* If we do blockwise - this needs to change */ + + /* Info on last_instance read/write */ + uint16_t last_instance; + uint16_t last_value_len; + + uint8_t writer_flags; /* flags for reader/writer */ + const lwm2m_reader_t *reader; + const lwm2m_writer_t *writer; } lwm2m_context_t; /* LWM2M format writer for the various formats supported */ -typedef struct lwm2m_writer { - size_t (* write_int)(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, int32_t value); - size_t (* write_string)(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, const char *value, size_t strlen); - size_t (* write_float32fix)(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, int32_t value, int bits); - size_t (* write_boolean)(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, int value); -} lwm2m_writer_t; +struct lwm2m_writer { + size_t (* init_write)(lwm2m_context_t *ctx); + size_t (* end_write)(lwm2m_context_t *ctx); + /* For sub-resources */ + size_t (* enter_resource_instance)(lwm2m_context_t *ctx); + size_t (* exit_resource_instance)(lwm2m_context_t *ctx); + size_t (* write_int)(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, int32_t value); + size_t (* write_string)(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, const char *value, size_t strlen); + size_t (* write_float32fix)(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, int32_t value, int bits); + size_t (* write_boolean)(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, int value); + size_t (* write_opaque_header)(lwm2m_context_t *ctx, size_t total_size); +}; -typedef struct lwm2m_reader { - size_t (* read_int)(const lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int32_t *value); - size_t (* read_string)(const lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, uint8_t *value, size_t strlen); - size_t (* read_float32fix)(const lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int32_t *value, int bits); - size_t (* read_boolean)(const lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int *value); -} lwm2m_reader_t; +struct lwm2m_reader { + size_t (* read_int)(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int32_t *value); + size_t (* read_string)(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, uint8_t *value, size_t strlen); + size_t (* read_float32fix)(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int32_t *value, int bits); + size_t (* read_boolean)(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int *value); +}; -typedef struct lwm2m_value_callback { - int (* read)(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen); - int (* write)(lwm2m_context_t *ctx, - const uint8_t *buffer, size_t len, - uint8_t *outbuf, size_t outlen); - int (* exec)(lwm2m_context_t *ctx, const uint8_t *arg, size_t len, - uint8_t *outbuf, size_t outlen); -} lwm2m_value_callback_t; +typedef lwm2m_status_t +(* lwm2m_write_opaque_callback)(lwm2m_object_instance_t *object, + lwm2m_context_t *ctx, int num_to_write); -#define LWM2M_RESOURCE_TYPE_STR_VALUE 1 -#define LWM2M_RESOURCE_TYPE_STR_VARIABLE 2 -#define LWM2M_RESOURCE_TYPE_STR_VARIABLE_ARRAY 3 -#define LWM2M_RESOURCE_TYPE_INT_VALUE 4 -#define LWM2M_RESOURCE_TYPE_INT_VARIABLE 5 -#define LWM2M_RESOURCE_TYPE_INT_VARIABLE_ARRAY 6 -#define LWM2M_RESOURCE_TYPE_FLOATFIX_VALUE 7 -#define LWM2M_RESOURCE_TYPE_FLOATFIX_VARIABLE 8 -#define LWM2M_RESOURCE_TYPE_FLOATFIX_VARIABLE_ARRAY 9 -#define LWM2M_RESOURCE_TYPE_BOOLEAN_VALUE 10 -#define LWM2M_RESOURCE_TYPE_BOOLEAN_VARIABLE 11 -#define LWM2M_RESOURCE_TYPE_BOOLEAN_VARIABLE_ARRAY 12 -#define LWM2M_RESOURCE_TYPE_CALLBACK 16 -#define LWM2M_RESOURCE_TYPE_INSTANCES 17 - -typedef struct lwm2m_resource { - uint16_t id; - uint8_t type; /* indicate value type and multi-instance resource */ - union { - struct { - uint16_t len; - const uint8_t *value; - } string; - struct { - uint16_t size; - uint16_t *len; - uint8_t **var; - } stringvar; - struct { - uint16_t count; - uint16_t size; - /* string var array with counting entries */ - uint16_t *len; - uint8_t *var; - } stringvararr; - struct { - int32_t value; - } integer; - struct { - int32_t *var; - } integervar; - struct { - /* used for multiple instances (dynamic) NOTE: this is an index into - the instance so having two instances means that there is need for - allocation of two ints here */ - uint16_t count; - int32_t *var; /* used as an array? */ - } integervararr; - struct { - int32_t value; - } floatfix; - struct { - int32_t *var; - } floatfixvar; - struct { - uint16_t count; - int32_t *var; - } floatfixvararr; - struct { - int value; - } boolean; - struct { - int *var; - } booleanvar; - struct { - uint16_t count; - int *var; - } booleanvararr; - lwm2m_value_callback_t callback; - /* lwm2m_resource *resources[]; TO BE ADDED LATER*/ - } value; -} lwm2m_resource_t; - -#define LWM2M_INSTANCE_FLAG_USED 1 - -typedef struct lwm2m_instance { - uint16_t id; - uint16_t count; - uint16_t flag; - const lwm2m_resource_t *resources; -} lwm2m_instance_t; - -typedef struct lwm2m_object { - uint16_t id; - uint16_t count; - const char *path; - resource_t *coap_resource; - lwm2m_instance_t *instances; -} lwm2m_object_t; - -#define LWM2M_RESOURCES(name, ...) \ - static const lwm2m_resource_t name[] = { __VA_ARGS__ } - -#define LWM2M_RESOURCE_STRING(id, s) \ - { id, LWM2M_RESOURCE_TYPE_STR_VALUE, .value.string.len = sizeof(s) - 1, .value.string.value = (uint8_t *) s } - -#define LWM2M_RESOURCE_STRING_VAR(id, s, l, v) \ - { id, LWM2M_RESOURCE_TYPE_STR_VARIABLE, .value.stringvar.size = (s), .value.stringvar.len = (l), .value.stringvar.var = (v) } - -#define LWM2M_RESOURCE_STRING_VAR_ARR(id, c, s, l, v) \ - { id, LWM2M_RESOURCE_TYPE_STR_VARIABLE_ARRAY, .value.stringvararr.count = c, .value.stringvararr.size = s, .value.stringvararr.len = l, .value.stringvararr.var = (uint8_t *) v } - -#define LWM2M_RESOURCE_INTEGER(id, v) \ - { id, LWM2M_RESOURCE_TYPE_INT_VALUE, .value.integer.value = (v) } - -#define LWM2M_RESOURCE_INTEGER_VAR(id, v) \ - { id, LWM2M_RESOURCE_TYPE_INT_VARIABLE, .value.integervar.var = (v) } - -#define LWM2M_RESOURCE_INTEGER_VAR_ARR(id, c, v) \ - { id, LWM2M_RESOURCE_TYPE_INT_VARIABLE_ARRAY, .value.integervararr.count = (c), .value.integervararr.var = (v) } - -#define LWM2M_RESOURCE_FLOATFIX(id, v) \ - { id, LWM2M_RESOURCE_TYPE_FLOATFIX_VALUE, .value.floatfix.value = (v) } - -#define LWM2M_RESOURCE_FLOATFIX_VAR(id, v) \ - { id, LWM2M_RESOURCE_TYPE_FLOATFIX_VARIABLE, .value.floatfixvar.var = (v) } - -#define LWM2M_RESOURCE_FLOATFIX_VAR_ARR(id, c, v) \ - { id, LWM2M_RESOURCE_TYPE_FLOATFIX_VARIABLE_ARRAY, .value.floatfixvararr.count = (c), .value.floatfixvararr.var = (v) } - -#define LWM2M_RESOURCE_BOOLEAN(id, v) \ - { id, LWM2M_RESOURCE_TYPE_BOOLEAN_VALUE, .value.boolean.value = (v) } - -#define LWM2M_RESOURCE_BOOLEAN_VAR(id, v) \ - { id, LWM2M_RESOURCE_TYPE_BOOLEAN_VARIABLE, .value.booleanvar.var = (v) } - -#define LWM2M_RESOURCE_BOOLEAN_VAR_ARR(id, c, v) \ - { id, LWM2M_RESOURCE_TYPE_BOOLEAN_VARIABLE_ARRAY, .value.booleanvararr.count = (c), .value.booleanvararr.var = (v) } - -#define LWM2M_RESOURCE_CALLBACK(id, ...) \ - { id, LWM2M_RESOURCE_TYPE_CALLBACK, .value.callback = __VA_ARGS__ } - -#define LWM2M_INSTANCE(id, resources) \ - { id, sizeof(resources)/sizeof(lwm2m_resource_t), LWM2M_INSTANCE_FLAG_USED, resources } - -#define LWM2M_INSTANCE_UNUSED(id, resources) \ - { id, sizeof(resources)/sizeof(lwm2m_resource_t), 0, resources } - -#define LWM2M_INSTANCES(name, ...) \ - static lwm2m_instance_t name[] = { __VA_ARGS__ } - -#define LWM2M_OBJECT(name, id, instances) \ - static void lwm2m_get_h_##name(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); \ - static void lwm2m_put_h_##name(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); \ - static void lwm2m_post_h_##name(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); \ - static void lwm2m_delete_h_##name(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); \ - static resource_t rest_rsc_##name = { NULL, NULL, HAS_SUB_RESOURCES | IS_OBSERVABLE, NULL, lwm2m_get_h_##name, lwm2m_post_h_##name, lwm2m_put_h_##name, lwm2m_delete_h_##name, { NULL } }; \ - static const lwm2m_object_t name = { id, sizeof(instances)/sizeof(lwm2m_instance_t), LWM2M_OBJECT_PATH_STR(id), &rest_rsc_##name, instances}; \ - static void lwm2m_get_h_##name(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { \ - lwm2m_engine_handler(&name, request, response, buffer, preferred_size, offset); } \ - static void lwm2m_put_h_##name(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { \ - lwm2m_engine_handler(&name, request, response, buffer, preferred_size, offset); } \ - static void lwm2m_post_h_##name(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { \ - lwm2m_engine_handler(&name, request, response, buffer, preferred_size, offset); } \ - static void lwm2m_delete_h_##name(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { \ - lwm2m_engine_delete_handler(&name, request, response, buffer, preferred_size, offset); } - -/* how do we register attributes in the above resource here ??? */ - -int lwm2m_object_is_resource_string(const lwm2m_resource_t *resource); -int lwm2m_object_is_resource_int(const lwm2m_resource_t *resource); -int lwm2m_object_is_resource_floatfix(const lwm2m_resource_t *resource); -int lwm2m_object_is_resource_boolean(const lwm2m_resource_t *resource); - -static inline int -lwm2m_object_is_resource_callback(const lwm2m_resource_t *resource) -{ - return resource != NULL && resource->type == LWM2M_RESOURCE_TYPE_CALLBACK; -} - -const uint8_t * -lwm2m_object_get_resource_string(const lwm2m_resource_t *resource, - const lwm2m_context_t *context); - -uint16_t -lwm2m_object_get_resource_strlen(const lwm2m_resource_t *resource, - const lwm2m_context_t *context); - -int -lwm2m_object_set_resource_string(const lwm2m_resource_t *resource, - const lwm2m_context_t *context, - uint16_t len, const uint8_t *string); - -int -lwm2m_object_get_resource_int(const lwm2m_resource_t *resource, - const lwm2m_context_t *context, - int32_t *value); - -int -lwm2m_object_set_resource_int(const lwm2m_resource_t *resource, - const lwm2m_context_t *context, - int32_t value); - -int -lwm2m_object_get_resource_floatfix(const lwm2m_resource_t *resource, - const lwm2m_context_t *context, - int32_t *value); - -int -lwm2m_object_set_resource_floatfix(const lwm2m_resource_t *resource, - const lwm2m_context_t *context, - int32_t value); - -int -lwm2m_object_get_resource_boolean(const lwm2m_resource_t *resource, - const lwm2m_context_t *context, - int *value); - -int -lwm2m_object_set_resource_boolean(const lwm2m_resource_t *resource, - const lwm2m_context_t *context, - int value); - -static inline resource_t * -lwm2m_object_get_coap_resource(const lwm2m_object_t *object) -{ - return (resource_t *)object->coap_resource; -} +void lwm2m_engine_set_opaque_callback(lwm2m_context_t *ctx, lwm2m_write_opaque_callback cb); static inline void -lwm2m_object_notify_observers(const lwm2m_object_t *object, char *path) +lwm2m_notify_observers(char *path) { - coap_notify_observers_sub(lwm2m_object_get_coap_resource(object), path); + coap_notify_observers_sub(NULL, path); +} + +static inline size_t +lwm2m_object_read_int(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int32_t *value) +{ + return ctx->reader->read_int(ctx, inbuf, len, value); +} + +static inline size_t +lwm2m_object_read_string(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, uint8_t *value, size_t strlen) +{ + return ctx->reader->read_string(ctx, inbuf, len, value, strlen); +} + +static inline size_t +lwm2m_object_read_float32fix(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int32_t *value, int bits) +{ + return ctx->reader->read_float32fix(ctx, inbuf, len, value, bits); +} + +static inline size_t +lwm2m_object_read_boolean(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int *value) +{ + return ctx->reader->read_boolean(ctx, inbuf, len, value); +} + +static inline size_t +lwm2m_object_write_int(lwm2m_context_t *ctx, int32_t value) +{ + size_t s; + s = ctx->writer->write_int(ctx, &ctx->outbuf->buffer[ctx->outbuf->len], + ctx->outbuf->size - ctx->outbuf->len, value); + ctx->outbuf->len += s; + return s; +} + +static inline size_t +lwm2m_object_write_string(lwm2m_context_t *ctx, const char *value, size_t strlen) +{ + size_t s; + s = ctx->writer->write_string(ctx, &ctx->outbuf->buffer[ctx->outbuf->len], + ctx->outbuf->size - ctx->outbuf->len, value, strlen); + ctx->outbuf->len += s; + return s; +} + +static inline size_t +lwm2m_object_write_float32fix(lwm2m_context_t *ctx, int32_t value, int bits) +{ + size_t s; + s = ctx->writer->write_float32fix(ctx, &ctx->outbuf->buffer[ctx->outbuf->len], + ctx->outbuf->size - ctx->outbuf->len, value, bits); + ctx->outbuf->len += s; + return s; +} + +static inline size_t +lwm2m_object_write_boolean(lwm2m_context_t *ctx, int value) +{ + size_t s; + s = ctx->writer->write_boolean(ctx, &ctx->outbuf->buffer[ctx->outbuf->len], + ctx->outbuf->size - ctx->outbuf->len, value); + ctx->outbuf->len += s; + return s; +} + +static inline int +lwm2m_object_write_opaque_stream(lwm2m_context_t *ctx, int size, lwm2m_write_opaque_callback cb) +{ + /* 1. - create a header of either OPAQUE (nothing) or TLV if the format is TLV */ + size_t s; + if(ctx->writer->write_opaque_header != NULL) { + s = ctx->writer->write_opaque_header(ctx, size); + ctx->outbuf->len += s; + } else { + return 0; + } + /* 2. - set the callback so that future data will be grabbed from the callback */ + lwm2m_engine_set_opaque_callback(ctx, cb); + return 1; +} + +/* Resource instance functions (_ri)*/ + +static inline size_t +lwm2m_object_write_enter_ri(lwm2m_context_t *ctx) +{ + if(ctx->writer->enter_resource_instance != NULL) { + size_t s; + s = ctx->writer->enter_resource_instance(ctx); + ctx->outbuf->len += s; + return s; + } + return 0; +} + +static inline size_t +lwm2m_object_write_exit_ri(lwm2m_context_t *ctx) +{ + if(ctx->writer->exit_resource_instance != NULL) { + size_t s; + s = ctx->writer->exit_resource_instance(ctx); + ctx->outbuf->len += s; + return s; + } + return 0; +} + +static inline size_t +lwm2m_object_write_int_ri(lwm2m_context_t *ctx, uint16_t id, int32_t value) +{ + size_t s; + ctx->resource_instance_id = id; + s = ctx->writer->write_int(ctx, &ctx->outbuf->buffer[ctx->outbuf->len], + ctx->outbuf->size - ctx->outbuf->len, value); + ctx->outbuf->len += s; + return s; +} + +static inline size_t +lwm2m_object_write_string_ri(lwm2m_context_t *ctx, uint16_t id, const char *value, size_t strlen) +{ + size_t s; + ctx->resource_instance_id = id; + s = ctx->writer->write_string(ctx, &ctx->outbuf->buffer[ctx->outbuf->len], + ctx->outbuf->size - ctx->outbuf->len, value, strlen); + ctx->outbuf->len += s; + return s; +} + +static inline size_t +lwm2m_object_write_float32fix_ri(lwm2m_context_t *ctx, uint16_t id, int32_t value, int bits) +{ + size_t s; + ctx->resource_instance_id = id; + s = ctx->writer->write_float32fix(ctx, &ctx->outbuf->buffer[ctx->outbuf->len], + ctx->outbuf->size - ctx->outbuf->len, value, bits); + ctx->outbuf->len += s; + return s; +} + +static inline size_t +lwm2m_object_write_boolean_ri(lwm2m_context_t *ctx, uint16_t id, int value) +{ + size_t s; + ctx->resource_instance_id = id; + s = ctx->writer->write_boolean(ctx, &ctx->outbuf->buffer[ctx->outbuf->len], + ctx->outbuf->size - ctx->outbuf->len, value); + ctx->outbuf->len += s; + return s; +} + +static inline int +lwm2m_object_is_final_incoming(lwm2m_context_t *ctx) +{ + uint8_t more; + if(coap_get_header_block1(ctx->request, NULL, &more, NULL, NULL)) { + return !more; + } + /* If we do not know this is final... it might not be... */ + return 0; } #include "lwm2m-engine.h" diff --git a/os/services/lwm2m/lwm2m-plain-text.c b/os/services/lwm2m/lwm2m-plain-text.c index b2bc5dcbe..2bd081c76 100644 --- a/os/services/lwm2m/lwm2m-plain-text.c +++ b/os/services/lwm2m/lwm2m-plain-text.c @@ -54,6 +54,18 @@ #define PRINTF(...) #endif +/*---------------------------------------------------------------------------*/ +static size_t +init_write(lwm2m_context_t *ctx) +{ + return 0; +} +/*---------------------------------------------------------------------------*/ +static size_t +end_write(lwm2m_context_t *ctx) +{ + return 0; +} /*---------------------------------------------------------------------------*/ size_t lwm2m_plain_text_read_int(const uint8_t *inbuf, size_t len, int32_t *value) @@ -118,6 +130,7 @@ lwm2m_plain_text_read_float32fix(const uint8_t *inbuf, size_t len, if(neg) { *value = -*value; } + return i; } /*---------------------------------------------------------------------------*/ @@ -153,7 +166,7 @@ lwm2m_plain_text_write_float32fix(uint8_t *outbuf, size_t outlen, } /*---------------------------------------------------------------------------*/ static size_t -write_boolean(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, +write_boolean(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, int value) { if(outlen > 0) { @@ -168,7 +181,7 @@ write_boolean(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, } /*---------------------------------------------------------------------------*/ static size_t -write_int(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, +write_int(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, int32_t value) { int n = snprintf((char *)outbuf, outlen, "%ld", (long)value); @@ -179,24 +192,30 @@ write_int(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, } /*---------------------------------------------------------------------------*/ static size_t -write_float32fix(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, +write_float32fix(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, int32_t value, int bits) { return lwm2m_plain_text_write_float32fix(outbuf, outlen, value, bits); } /*---------------------------------------------------------------------------*/ static size_t -write_string(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, +write_string(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, const char *value, size_t stringlen) { - int n = snprintf((char *)outbuf, outlen, "%.*s", (int) stringlen, value); - if(n < 0 || n >= outlen) { + int totlen = stringlen; + if(stringlen >= outlen) { return 0; } - return n; + memmove(outbuf, value, totlen); + outbuf[totlen] = 0; + return totlen; } /*---------------------------------------------------------------------------*/ const lwm2m_writer_t lwm2m_plain_text_writer = { + init_write, + end_write, + NULL, /* No support for sub resources here! */ + NULL, write_int, write_string, write_float32fix, @@ -204,14 +223,16 @@ const lwm2m_writer_t lwm2m_plain_text_writer = { }; /*---------------------------------------------------------------------------*/ static size_t -read_int(const lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, +read_int(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int32_t *value) { - return lwm2m_plain_text_read_int(inbuf, len, value); + int size = lwm2m_plain_text_read_int(inbuf, len, value); + ctx->last_value_len = size; + return size; } /*---------------------------------------------------------------------------*/ static size_t -read_string(const lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, +read_string(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, uint8_t *value, size_t stringlen) { if(stringlen <= len) { @@ -220,23 +241,28 @@ read_string(const lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, } memcpy(value, inbuf, len); value[len] = '\0'; + ctx->last_value_len = len; return len; } /*---------------------------------------------------------------------------*/ static size_t -read_float32fix(const lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, +read_float32fix(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int32_t *value, int bits) { - return lwm2m_plain_text_read_float32fix(inbuf, len, value, bits); + int size; + size = lwm2m_plain_text_read_float32fix(inbuf, len, value, bits); + ctx->last_value_len = size; + return size; } /*---------------------------------------------------------------------------*/ static size_t -read_boolean(const lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, +read_boolean(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int *value) { if(len > 0) { if(*inbuf == '1' || *inbuf == '0') { *value = *inbuf == '1' ? 1 : 0; + ctx->last_value_len = 1; return 1; } } diff --git a/os/services/lwm2m/lwm2m-rd-client.c b/os/services/lwm2m/lwm2m-rd-client.c new file mode 100644 index 000000000..4df4217e0 --- /dev/null +++ b/os/services/lwm2m/lwm2m-rd-client.c @@ -0,0 +1,729 @@ +/* + * Copyright (c) 2015, Yanzi Networks AB. + * 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 copyright holder 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 COPYRIGHT HOLDER 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 + * COPYRIGHT HOLDER 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. + */ + +/** + * \addtogroup oma-lwm2m + * @{ + */ + +/** + * \file + * Implementation of the Contiki OMA LWM2M engine + * Registration and bootstrap client + * \author + * Joakim Eriksson + * Niclas Finne + * Joel Hoglund + */ + +#include "lwm2m-engine.h" +#include "lwm2m-object.h" +#include "lwm2m-device.h" +#include "lwm2m-plain-text.h" +#include "lwm2m-json.h" +#include "lwm2m-rd-client.h" +#include "coap.h" +#include "coap-engine.h" +#include "coap-endpoint.h" +#include "coap-callback-api.h" +#include "lwm2m-security.h" +#include +#include +#include + +#if UIP_CONF_IPV6_RPL +#include "rpl.h" +#endif /* UIP_CONF_IPV6_RPL */ + +#define DEBUG 0 +#if DEBUG +#include +#define PRINTF(...) printf(__VA_ARGS__) +#define PRINTS(l,s,f) do { int i; \ + for(i = 0; i < l; i++) printf(f, s[i]); \ + } while(0) +#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]) +#define PRINTEP(ep) coap_endpoint_print(ep) +#else +#define PRINTF(...) +#define PRINTS(l,s,f) +#define PRINT6ADDR(addr) +#define PRINTLLADDR(addr) +#define PRINTEP(ep) +#endif + +#ifndef LWM2M_DEFAULT_CLIENT_LIFETIME +#define LWM2M_DEFAULT_CLIENT_LIFETIME 600 /* sec */ +#endif + +#define REMOTE_PORT UIP_HTONS(COAP_DEFAULT_PORT) +#define BS_REMOTE_PORT UIP_HTONS(5685) + +#define STATE_MACHINE_UPDATE_INTERVAL 500 + +static struct lwm2m_session_info session_info; +static coap_request_state_t rd_request_state; + +static coap_packet_t request[1]; /* This way the packet can be treated as pointer as usual. */ + +/* The states for the RD client state machine */ +/* When node is unregistered it ends up in UNREGISTERED + and this is going to be there until use X or Y kicks it + back into INIT again */ +#define INIT 0 +#define WAIT_NETWORK 1 +#define DO_BOOTSTRAP 3 +#define BOOTSTRAP_SENT 4 +#define BOOTSTRAP_DONE 5 +#define DO_REGISTRATION 6 +#define REGISTRATION_SENT 7 +#define REGISTRATION_DONE 8 +#define UPDATE_SENT 9 +#define DEREGISTER 10 +#define DEREGISTER_SENT 11 +#define DEREGISTER_FAILED 12 +#define DEREGISTERED 13 + +#define FLAG_RD_DATA_DIRTY 0x01 +#define FLAG_RD_DATA_UPDATE_TRIGGERED 0x02 +#define FLAG_RD_DATA_UPDATE_ON_DIRTY 0x10 + +static uint8_t rd_state = 0; +static uint8_t rd_flags = FLAG_RD_DATA_UPDATE_ON_DIRTY; +static uint64_t wait_until_network_check = 0; +static uint64_t last_update; + +static char query_data[64]; /* allocate some data for queries and updates */ +static uint8_t rd_data[128]; /* allocate some data for the RD */ + +static uint32_t rd_block1; +static uint8_t rd_more; +static coap_timer_t rd_timer; +static void (*rd_callback)(coap_request_state_t *state); + +static coap_timer_t block1_timer; + +static void check_periodic_observations(); +static void update_callback(coap_request_state_t *state); + +static int +set_rd_data(coap_packet_t *request) +{ + lwm2m_buffer_t outbuf; + + /* setup the output buffer */ + outbuf.buffer = rd_data; + outbuf.size = sizeof(rd_data); + outbuf.len = 0; + + /* this will also set the request payload */ + rd_more = lwm2m_engine_set_rd_data(&outbuf, 0); + coap_set_payload(request, rd_data, outbuf.len); + + if(rd_more) { + /* set the first block here */ + PRINTF("Setting block1 in request\n"); + coap_set_header_block1(request, 0, 1, sizeof(rd_data)); + } + return outbuf.len; +} +/*---------------------------------------------------------------------------*/ +static void +prepare_update(coap_packet_t *request, int triggered) { + coap_init_message(request, COAP_TYPE_CON, COAP_POST, 0); + coap_set_header_uri_path(request, session_info.assigned_ep); + + snprintf(query_data, sizeof(query_data) - 1, "?lt=%d&b=%s", session_info.lifetime, session_info.binding); + PRINTF("UPDATE:%s %s\n", session_info.assigned_ep, query_data); + coap_set_header_uri_query(request, query_data); + + if((triggered || rd_flags & FLAG_RD_DATA_UPDATE_ON_DIRTY) && (rd_flags & FLAG_RD_DATA_DIRTY)) { + rd_flags &= ~FLAG_RD_DATA_DIRTY; + set_rd_data(request); + rd_callback = update_callback; + } +} +/*---------------------------------------------------------------------------*/ +static int +has_network_access(void) +{ +#if UIP_CONF_IPV6_RPL + if(rpl_get_any_dag() == NULL) { + return 0; + } +#endif /* UIP_CONF_IPV6_RPL */ + return 1; +} +/*---------------------------------------------------------------------------*/ +int +lwm2m_rd_client_is_registered(void) +{ + return rd_state == REGISTRATION_DONE || rd_state == UPDATE_SENT; +} +/*---------------------------------------------------------------------------*/ +void +lwm2m_rd_client_use_bootstrap_server(int use) +{ + session_info.use_bootstrap = use != 0; + if(session_info.use_bootstrap) { + rd_state = INIT; + } +} +/*---------------------------------------------------------------------------*/ +/* will take another argument when we support multiple sessions */ +void +lwm2m_rd_client_set_session_callback(session_callback_t cb) +{ + session_info.callback = cb; +} +/*---------------------------------------------------------------------------*/ +static void +perform_session_callback(int state) +{ + if(session_info.callback != NULL) { + PRINTF("Performing session callback: %d cb:%p\n", + state, session_info.callback); + session_info.callback(&session_info, state); + } +} +/*---------------------------------------------------------------------------*/ +void +lwm2m_rd_client_use_registration_server(int use) +{ + session_info.use_registration = use != 0; + if(session_info.use_registration) { + rd_state = INIT; + } +} +/*---------------------------------------------------------------------------*/ +uint16_t +lwm2m_rd_client_get_lifetime(void) +{ + return session_info.lifetime; +} +/*---------------------------------------------------------------------------*/ +void +lwm2m_rd_client_set_lifetime(uint16_t lifetime) +{ + if(lifetime > 0) { + session_info.lifetime = lifetime; + } else { + session_info.lifetime = LWM2M_DEFAULT_CLIENT_LIFETIME; + } +} +/*---------------------------------------------------------------------------*/ +void +lwm2m_rd_client_set_update_rd(void) +{ + rd_flags |= FLAG_RD_DATA_DIRTY; +} +/*---------------------------------------------------------------------------*/ +void +lwm2m_rd_client_set_automatic_update(int update) +{ + rd_flags = (rd_flags & ~FLAG_RD_DATA_UPDATE_ON_DIRTY) | + (update != 0 ? FLAG_RD_DATA_UPDATE_ON_DIRTY : 0); +} +/*---------------------------------------------------------------------------*/ +void +lwm2m_rd_client_register_with_server(const coap_endpoint_t *server) +{ + coap_endpoint_copy(&session_info.server_ep, server); + session_info.has_registration_server_info = 1; + session_info.registered = 0; + if(session_info.use_registration) { + rd_state = INIT; + } +} +/*---------------------------------------------------------------------------*/ +static int +update_registration_server(void) +{ + if(session_info.has_registration_server_info) { + return 1; + } + +#if UIP_CONF_IPV6_RPL + { + rpl_dag_t *dag; + + /* Use the DAG id as server address if no other has been specified */ + dag = rpl_get_any_dag(); + if(dag != NULL) { + /* create coap-endpoint? */ + /* uip_ipaddr_copy(&server_ipaddr, &dag->dag_id); */ + /* server_port = REMOTE_PORT; */ + return 1; + } + } +#endif /* UIP_CONF_IPV6_RPL */ + + return 0; +} +/*---------------------------------------------------------------------------*/ +void +lwm2m_rd_client_register_with_bootstrap_server(const coap_endpoint_t *server) +{ + coap_endpoint_copy(&session_info.bs_server_ep, server); + session_info.has_bs_server_info = 1; + session_info.bootstrapped = 0; + session_info.registered = 0; + if(session_info.use_bootstrap) { + rd_state = INIT; + } +} +/*---------------------------------------------------------------------------*/ +int +lwm2m_rd_client_deregister(void) +{ + if(lwm2m_rd_client_is_registered()) { + rd_state = DEREGISTER; + return 1; + } + /* Not registered */ + return 0; +} +/*---------------------------------------------------------------------------*/ +void +lwm2m_rd_client_update_triggered(void) +{ + rd_flags |= FLAG_RD_DATA_UPDATE_TRIGGERED; + /* Here we need to do an CoAP timer poll - to get a quick request transmission! */ +} +/*---------------------------------------------------------------------------*/ +static int +update_bootstrap_server(void) +{ + if(session_info.has_bs_server_info) { + return 1; + } + +#if UIP_CONF_IPV6_RPL + { + rpl_dag_t *dag; + + /* Use the DAG id as server address if no other has been specified */ + dag = rpl_get_any_dag(); + if(dag != NULL) { + /* create coap endpoint */ + /* uip_ipaddr_copy(&bs_server_ipaddr, &dag->dag_id); */ + /* bs_server_port = REMOTE_PORT; */ + return 1; + } + } +#endif /* UIP_CONF_IPV6_RPL */ + + return 0; +} +/*---------------------------------------------------------------------------*/ +/* + * A client initiated bootstrap starts with a POST to /bs?ep={session_info.ep}, + * on the bootstrap server. The server should reply with 2.04. + * The server will thereafter do DELETE and or PUT to write new client objects. + * The bootstrap finishes with the server doing POST to /bs on the client. + * + * Page 64 in 07 April 2016 spec. + * + * TODO + */ +static void +bootstrap_callback(coap_request_state_t *state) +{ + PRINTF("Bootstrap callback Response: %d, ", state->response != NULL); + if(state->response) { + if(CHANGED_2_04 == state->response->code) { + PRINTF("Considered done!\n"); + rd_state = BOOTSTRAP_DONE; + return; + } + /* Possible error response codes are 4.00 Bad request & 4.15 Unsupported content format */ + PRINTF("Failed with code %d. Retrying\n", state->response->code); + /* TODO Application callback? */ + rd_state = INIT; + } else if(BOOTSTRAP_SENT == rd_state) { /* this can handle double invocations */ + /* Failure! */ + PRINTF("Bootstrap failed! Retry?"); + rd_state = DO_BOOTSTRAP; + } else { + PRINTF("Ignore\n"); + } +} +/*---------------------------------------------------------------------------*/ +static void +produce_more_rd(void) +{ + lwm2m_buffer_t outbuf; + + PRINTF("GOT Continue!\n"); + + /* setup the output buffer */ + outbuf.buffer = rd_data; + outbuf.size = sizeof(rd_data); + outbuf.len = 0; + + rd_block1++; + + /* this will also set the request payload */ + rd_more = lwm2m_engine_set_rd_data(&outbuf, rd_block1); + coap_set_payload(request, rd_data, outbuf.len); + + PRINTF("Setting block1 in request - block: %d more: %d\n", rd_block1, rd_more); + coap_set_header_block1(request, rd_block1, rd_more, sizeof(rd_data)); + + coap_send_request(&rd_request_state, &session_info.server_ep, request, rd_callback); +} +/*---------------------------------------------------------------------------*/ +static void +block1_rd_callback(coap_timer_t *timer) +{ + produce_more_rd(); +} +/*---------------------------------------------------------------------------*/ +/* + * Page 65-66 in 07 April 2016 spec. + */ +static void +registration_callback(coap_request_state_t *state) +{ + PRINTF("Registration callback. Response: %d, ", state->response != NULL); + if(state->response) { + /* check state and possibly set registration to done */ + /* If we get a continue - we need to call the rd generator one more time */ + if(CONTINUE_2_31 == state->response->code) { + /* We assume that size never change?! */ + coap_get_header_block1(state->response, &rd_block1, NULL, NULL, NULL); + coap_timer_set_callback(&block1_timer, block1_rd_callback); + coap_timer_set(&block1_timer, 1); /* delay 1 ms */ + } else if(CREATED_2_01 == state->response->code) { + if(state->response->location_path_len < LWM2M_RD_CLIENT_ASSIGNED_ENDPOINT_MAX_LEN) { + memcpy(session_info.assigned_ep, state->response->location_path, + state->response->location_path_len); + session_info.assigned_ep[state->response->location_path_len] = 0; + /* if we decide to not pass the lt-argument on registration, we should force an initial "update" to register lifetime with server */ + rd_state = REGISTRATION_DONE; + /* remember the last reg time */ + last_update = coap_timer_uptime(); + PRINTF("Done (assigned EP='%s')!\n", session_info.assigned_ep); + perform_session_callback(LWM2M_RD_CLIENT_REGISTERED); + return; + } + + PRINTF("failed to handle assigned EP: '"); + PRINTS(state->response->location_path_len, + state->response->location_path, "%c"); + PRINTF("'. Re-init network.\n"); + } else { + /* Possible error response codes are 4.00 Bad request & 4.03 Forbidden */ + PRINTF("failed with code %d. Re-init network\n", state->response->code); + } + /* TODO Application callback? */ + rd_state = INIT; + } else if(REGISTRATION_SENT == rd_state) { /* this can handle double invocations */ + /* Failure! */ + PRINTF("Registration failed! Retry?\n"); + rd_state = DO_REGISTRATION; + } else { + PRINTF("Ignore\n"); + } +} +/*---------------------------------------------------------------------------*/ +/* + * Page 65-66 in 07 April 2016 spec. + */ +static void +update_callback(coap_request_state_t *state) +{ + PRINTF("Update callback. Response: %d, ", state->response != NULL); + + if(state->response) { + /* If we get a continue - we need to call the rd generator one more time */ + if(CONTINUE_2_31 == state->response->code) { + /* We assume that size never change?! */ + coap_get_header_block1(state->response, &rd_block1, NULL, NULL, NULL); + coap_timer_set_callback(&block1_timer, block1_rd_callback); + coap_timer_set(&block1_timer, 1); /* delay 1 ms */ + } else if(CHANGED_2_04 == state->response->code) { + PRINTF("Done!\n"); + /* remember the last reg time */ + last_update = coap_timer_uptime(); + rd_state = REGISTRATION_DONE; + rd_flags &= ~FLAG_RD_DATA_UPDATE_TRIGGERED; + return; + } + /* Possible error response codes are 4.00 Bad request & 4.04 Not Found */ + PRINTF("Failed with code %d. Retrying registration\n", state->response->code); + rd_state = DO_REGISTRATION; + } else if(REGISTRATION_SENT == rd_state) { /* this can handle the current double invocation */ + /*Failure! */ + PRINTF("Registration failed! Retry?"); + rd_state = DO_REGISTRATION; + } else if(UPDATE_SENT == rd_state) { + /* Update failed */ + PRINTF("Update failed! Retry?"); + rd_state = DO_REGISTRATION; + } else { + PRINTF("Ignore\n"); + } +} +/*---------------------------------------------------------------------------*/ +static void +deregister_callback(coap_request_state_t *state) +{ + PRINTF("Deregister callback. Response Code: %d\n", + state->response != NULL ? state->response->code : 0); + + if(state->response && (DELETED_2_02 == state->response->code)) { + PRINTF("Deregistration success\n"); + rd_state = DEREGISTERED; + perform_session_callback(LWM2M_RD_CLIENT_DEREGISTERED); + } else { + PRINTF("Deregistration failed\n"); + if(rd_state == DEREGISTER_SENT) { + rd_state = DEREGISTER_FAILED; + perform_session_callback(LWM2M_RD_CLIENT_DEREGISTER_FAILED); + } + } +} +/*---------------------------------------------------------------------------*/ +/* CoAP timer callback */ +static void +periodic_process(coap_timer_t *timer) +{ + uint64_t now; + + /* reschedule the CoAP timer */ + coap_timer_reset(&rd_timer, STATE_MACHINE_UPDATE_INTERVAL); + now = coap_timer_uptime(); + + PRINTF("RD Client - state: %d, ms: %lu\n", rd_state, + (unsigned long)coap_timer_uptime()); + + switch(rd_state) { + case INIT: + PRINTF("RD Client started with endpoint '%s' and client lifetime %d\n", session_info.ep, session_info.lifetime); + rd_state = WAIT_NETWORK; + break; + case WAIT_NETWORK: + if(now > wait_until_network_check) { + /* check each 10 seconds before next check */ + PRINTF("Checking for network... %lu\n", + (unsigned long)wait_until_network_check); + wait_until_network_check = now + 10000; + if(has_network_access()) { + /* Either do bootstrap then registration */ + if(session_info.use_bootstrap) { + rd_state = DO_BOOTSTRAP; + } else { + rd_state = DO_REGISTRATION; + } + } + /* Otherwise wait until for a network to join */ + } + break; + case DO_BOOTSTRAP: + if(session_info.use_bootstrap && session_info.bootstrapped == 0) { + if(update_bootstrap_server()) { + /* prepare request, TID is set by COAP_BLOCKING_REQUEST() */ + coap_init_message(request, COAP_TYPE_CON, COAP_POST, 0); + coap_set_header_uri_path(request, "/bs"); + + snprintf(query_data, sizeof(query_data) - 1, "?ep=%s", session_info.ep); + coap_set_header_uri_query(request, query_data); + PRINTF("Registering ID with bootstrap server ["); + PRINTEP(&session_info.bs_server_ep); + PRINTF("] as '%s'\n", query_data); + + coap_send_request(&rd_request_state, &session_info.bs_server_ep, + request, bootstrap_callback); + + rd_state = BOOTSTRAP_SENT; + } + } + break; + case BOOTSTRAP_SENT: + /* Just wait for bootstrap to be done... */ + break; + case BOOTSTRAP_DONE: + /* check that we should still use bootstrap */ + if(session_info.use_bootstrap) { + lwm2m_security_server_t *security; + PRINTF("*** Bootstrap - checking for server info...\n"); + /* get the security object - ignore bootstrap servers */ + for(security = lwm2m_security_get_first(); + security != NULL; + security = lwm2m_security_get_next(security)) { + if(security->bootstrap == 0) { + break; + } + } + + if(security != NULL) { + /* get the server URI */ + if(security->server_uri_len > 0) { + uint8_t secure = 0; + + PRINTF("**** Found security instance using: "); + PRINTS(security->server_uri_len, security->server_uri, "%c"); + PRINTF(" (len %d) \n", security->server_uri_len); + /* TODO Should verify it is a URI */ + /* Check if secure */ + secure = strncmp((const char *)security->server_uri, + "coaps:", 6) == 0; + + if(!coap_endpoint_parse((const char *)security->server_uri, + security->server_uri_len, + &session_info.server_ep)) { + PRINTF("Failed to parse server URI!\n"); + } else { + PRINTF("Server address:"); + PRINTEP(&session_info.server_ep); + PRINTF("\n"); + if(secure) { + PRINTF("Secure CoAP requested but not supported - can not bootstrap\n"); + } else { + lwm2m_rd_client_register_with_server(&session_info.server_ep); + session_info.bootstrapped++; + } + } + } else { + PRINTF("** failed to parse URI "); + PRINTS(security->server_uri_len, security->server_uri, "%c"); + PRINTF("\n"); + } + } + + /* if we did not register above - then fail this and restart... */ + if(session_info.bootstrapped == 0) { + /* Not ready. Lets retry with the bootstrap server again */ + rd_state = DO_BOOTSTRAP; + } else { + rd_state = DO_REGISTRATION; + } + } + break; + case DO_REGISTRATION: + if(!coap_endpoint_is_connected(&session_info.server_ep)) { + /* Not connected... wait a bit... and retry connection */ + coap_endpoint_connect(&session_info.server_ep); + PRINTF("Wait until connected... \n"); + return; + } + if(session_info.use_registration && !session_info.registered && + update_registration_server()) { + int len; + + /* prepare request, TID was set by COAP_BLOCKING_REQUEST() */ + coap_init_message(request, COAP_TYPE_CON, COAP_POST, 0); + coap_set_header_uri_path(request, "/rd"); + + snprintf(query_data, sizeof(query_data) - 1, "?ep=%s<=%d&b=%s", session_info.ep, session_info.lifetime, session_info.binding); + coap_set_header_uri_query(request, query_data); + + len = set_rd_data(request); + rd_callback = registration_callback; + + PRINTF("Registering with ["); + PRINTEP(&session_info.server_ep); + PRINTF("] lwm2m endpoint '%s': '", query_data); + if(len) { + PRINTS(len, rd_data, "%c"); + } + PRINTF("' More:%d\n", rd_more); + + coap_send_request(&rd_request_state, &session_info.server_ep, + request, registration_callback); + rd_state = REGISTRATION_SENT; + } + break; + case REGISTRATION_SENT: + /* just wait until the callback kicks us to the next state... */ + break; + case REGISTRATION_DONE: + /* All is done! */ + + check_periodic_observations(); /* TODO: manage periodic observations */ + + /* check if it is time for the next update */ + if((rd_flags & FLAG_RD_DATA_UPDATE_TRIGGERED) || + ((uint32_t)session_info.lifetime * 500) <= now - last_update) { + /* triggered or time to send an update to the server, at half-time! sec vs ms */ + prepare_update(request, rd_flags & FLAG_RD_DATA_UPDATE_TRIGGERED); + coap_send_request(&rd_request_state, &session_info.server_ep, request, + update_callback); + rd_state = UPDATE_SENT; + } + break; + + case UPDATE_SENT: + /* just wait until the callback kicks us to the next state... */ + break; + case DEREGISTER: + PRINTF("DEREGISTER %s\n", session_info.assigned_ep); + coap_init_message(request, COAP_TYPE_CON, COAP_DELETE, 0); + coap_set_header_uri_path(request, session_info.assigned_ep); + coap_send_request(&rd_request_state, &session_info.server_ep, request, + deregister_callback); + rd_state = DEREGISTER_SENT; + break; + case DEREGISTER_SENT: + break; + case DEREGISTER_FAILED: + break; + case DEREGISTERED: + break; + + default: + PRINTF("Unhandled state: %d\n", rd_state); + } +} +/*---------------------------------------------------------------------------*/ +void +lwm2m_rd_client_init(const char *ep) +{ + session_info.ep = ep; + /* default binding U = UDP, UQ = UDP Q-mode*/ + session_info.binding = "U"; + if(session_info.lifetime == 0) { + session_info.lifetime = LWM2M_DEFAULT_CLIENT_LIFETIME; + } + rd_state = INIT; + + /* call the RD client periodically */ + coap_timer_set_callback(&rd_timer, periodic_process); + coap_timer_set(&rd_timer, STATE_MACHINE_UPDATE_INTERVAL); +} +/*---------------------------------------------------------------------------*/ +static void +check_periodic_observations(void) +{ +/* TODO */ +} +/*---------------------------------------------------------------------------*/ diff --git a/os/services/lwm2m/lwm2m-rd-client.h b/os/services/lwm2m/lwm2m-rd-client.h new file mode 100644 index 000000000..0707728f9 --- /dev/null +++ b/os/services/lwm2m/lwm2m-rd-client.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2016, SICS Swedish ICT AB. + * 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 copyright holder 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 COPYRIGHT HOLDER 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 + * COPYRIGHT HOLDER 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. + */ + +#ifndef LWM2M_RD_CLIENT_H_ +#define LWM2M_RD_CLIENT_H_ + +#define LWM2M_RD_CLIENT_BOOTSTRAPPED 1 +#define LWM2M_RD_CLIENT_REGISTERED 2 +#define LWM2M_RD_CLIENT_DEREGISTERED 3 +#define LWM2M_RD_CLIENT_DEREGISTER_FAILED 4 +#define LWM2M_RD_CLIENT_DISCONNECTED 5 + +#include "lwm2m-object.h" + +struct lwm2m_session_info; +typedef void (*session_callback_t)(struct lwm2m_session_info *session, int status); + +int lwm2m_rd_client_is_registered(void); +void lwm2m_rd_client_use_bootstrap_server(int use); +void lwm2m_rd_client_use_registration_server(int use); +void lwm2m_rd_client_register_with_server(const coap_endpoint_t *server); +void lwm2m_rd_client_register_with_bootstrap_server(const coap_endpoint_t *server); +uint16_t lwm2m_rd_client_get_lifetime(void); +void lwm2m_rd_client_set_lifetime(uint16_t lifetime); +/* Indicate that something in the object list have changed */ +void lwm2m_rd_client_set_update_rd(void); +/* Control if the object list should be automatically updated at updates of lifetime */ +void lwm2m_rd_client_set_automatic_update(int update); +/* trigger an immediate update */ +void lwm2m_rd_client_update_triggered(void); + +int lwm2m_rd_client_deregister(void); +void lwm2m_rd_client_init(const char *ep); + +void lwm2m_rd_client_set_session_callback(session_callback_t cb); + +#define LWM2M_RD_CLIENT_ASSIGNED_ENDPOINT_MAX_LEN 15 + +/*---------------------------------------------------------------------------*/ +/*- Server session-*Currently single session only*---------------------------*/ +/*---------------------------------------------------------------------------*/ +struct lwm2m_session_info { + const char *ep; + const char *binding; + char assigned_ep[LWM2M_RD_CLIENT_ASSIGNED_ENDPOINT_MAX_LEN]; + uint16_t lifetime; + coap_endpoint_t bs_server_ep; + coap_endpoint_t server_ep; + uint8_t use_bootstrap; + uint8_t has_bs_server_info; + uint8_t use_registration; + uint8_t has_registration_server_info; + uint8_t registered; + uint8_t bootstrapped; /* bootstrap done */ + session_callback_t callback; +}; + +#endif /* LWM2M_RD_CLIENT_H_ */ diff --git a/os/services/lwm2m/lwm2m-security.c b/os/services/lwm2m/lwm2m-security.c index 953279b4d..e7c8a4bde 100644 --- a/os/services/lwm2m/lwm2m-security.c +++ b/os/services/lwm2m/lwm2m-security.c @@ -43,70 +43,426 @@ */ #include +#include #include "lwm2m-object.h" #include "lwm2m-engine.h" +#include "lwm2m-server.h" +#include "lwm2m-security.h" +#include "coap-keystore.h" +#include "lib/list.h" #define DEBUG 0 #if DEBUG #include #define PRINTF(...) printf(__VA_ARGS__) +#define PRINTS(l,s,f) do { int i; \ + for(i = 0; i < l; i++) printf(f, s[i]); \ + } while(0) +#define PRINTPRE(p,l,s) do { PRINTF(p);PRINTS(l,s,"%c"); } while(0); +#define PRINTEP(ep) coap_endpoint_print(ep) #else #define PRINTF(...) +#define PRINTS(l,s,f) +#define PRINTPRE(p,l,s); +#define PRINTEP(ep) #endif -#ifdef LWM2M_CONF_SERVER_MAX_COUNT -#define MAX_COUNT LWM2M_CONF_SERVER_MAX_COUNT -#else -#define MAX_COUNT 2 -#endif +#ifdef LWM2M_SECURITY_CONF_REGISTER_KEY_STORE +#define LWM2M_SECURITY_REGISTER_KEY_STORE LWM2M_SECURITY_CONF_REGISTER_KEY_STORE +#else /* LWM2M_SECURITY_CONF_REGISTER_KEY_STORE */ +#define LWM2M_SECURITY_REGISTER_KEY_STORE 1 +#endif /* LWM2M_SECURITY_CONF_REGISTER_KEY_STORE */ -/* hoping that we do not get more than 64 bytes... */ -#define MAX_SIZE 64 +#define MAX_COUNT LWM2M_SERVER_MAX_COUNT -static int32_t bs_arr[MAX_COUNT]; -static int32_t secmode_arr[MAX_COUNT]; -static int32_t sid_arr[MAX_COUNT]; +static lwm2m_status_t lwm2m_callback(lwm2m_object_instance_t *object, + lwm2m_context_t *ctx); -static char server_uri[MAX_COUNT][MAX_SIZE]; -static uint16_t su_len[MAX_COUNT]; -static char client_id[MAX_COUNT][MAX_SIZE]; -static uint16_t client_id_len[MAX_COUNT]; -static char server_id[MAX_COUNT][MAX_SIZE]; -static uint16_t server_id_len[MAX_COUNT]; -static char psk_key[MAX_COUNT][MAX_SIZE]; -static uint16_t psk_key_len[MAX_COUNT]; -static lwm2m_instance_t security_instances[MAX_COUNT]; +static lwm2m_object_instance_t *get_by_id(uint16_t instance_id, + lwm2m_status_t *status); -LWM2M_RESOURCES(security_resources, - LWM2M_RESOURCE_STRING_VAR_ARR(0, MAX_COUNT, MAX_SIZE, su_len, server_uri), - LWM2M_RESOURCE_INTEGER_VAR_ARR(1, MAX_COUNT, bs_arr), - LWM2M_RESOURCE_INTEGER_VAR_ARR(2, MAX_COUNT, secmode_arr), - LWM2M_RESOURCE_STRING_VAR_ARR(3, MAX_COUNT, MAX_SIZE, client_id_len, client_id), - LWM2M_RESOURCE_STRING_VAR_ARR(4, MAX_COUNT, MAX_SIZE, server_id_len, server_id), - /* TODO This should not be readable! */ - LWM2M_RESOURCE_STRING_VAR_ARR(5, MAX_COUNT, MAX_SIZE, psk_key_len, psk_key), - LWM2M_RESOURCE_INTEGER_VAR_ARR(10, MAX_COUNT, sid_arr) - ); -LWM2M_OBJECT(security, 0, security_instances); +static const lwm2m_resource_id_t resources[] = { + LWM2M_SECURITY_SERVER_URI_ID, LWM2M_SECURITY_BOOTSTRAP_SERVER_ID, + LWM2M_SECURITY_MODE_ID, LWM2M_SECURITY_CLIENT_PKI_ID, + LWM2M_SECURITY_SERVER_PKI_ID, LWM2M_SECURITY_KEY_ID, + LWM2M_SECURITY_SHORT_SERVER_ID +}; + +LIST(instances_list); +static lwm2m_security_server_t instances[MAX_COUNT]; +/*---------------------------------------------------------------------------*/ +static lwm2m_object_instance_t * +create_instance(uint16_t instance_id, lwm2m_status_t *status) +{ + lwm2m_object_instance_t *instance; + int i; + + instance = get_by_id(instance_id, NULL); + if(instance != NULL) { + /* An instance with this id is already registered */ + if(status) { + *status = LWM2M_STATUS_OPERATION_NOT_ALLOWED; + } + return NULL; + } + + for(i = 0; i < MAX_COUNT; i++) { + if(instances[i].instance.instance_id == LWM2M_OBJECT_INSTANCE_NONE) { + memset(&instances[i], 0, sizeof(instances[i])); + instances[i].instance.callback = lwm2m_callback; + instances[i].instance.object_id = LWM2M_OBJECT_SECURITY_ID; + instances[i].instance.instance_id = instance_id; + instances[i].instance.resource_ids = resources; + instances[i].instance.resource_count = + sizeof(resources) / sizeof(lwm2m_resource_id_t); + list_add(instances_list, &instances[i].instance); + + PRINTF("SEC: Create new security instance\n"); + return &instances[i].instance; + } + } + + if(status) { + *status = LWM2M_STATUS_SERVICE_UNAVAILABLE; + } + + return NULL; +} +/*---------------------------------------------------------------------------*/ +static int +delete_instance(uint16_t instance_id, lwm2m_status_t *status) +{ + lwm2m_object_instance_t *instance; + + if(instance_id == LWM2M_OBJECT_INSTANCE_NONE) { + /* Remove all instances */ + while((instance = list_pop(instances_list)) != NULL) { + instance->instance_id = LWM2M_OBJECT_INSTANCE_NONE; + } + return 1; + } + + instance = get_by_id(instance_id, NULL); + if(instance != NULL) { + instance->instance_id = LWM2M_OBJECT_INSTANCE_NONE; + list_remove(instances_list, instance); + return 1; + } + + return 0; +} +/*---------------------------------------------------------------------------*/ +static lwm2m_object_instance_t * +get_first(lwm2m_status_t *status) +{ + return list_head(instances_list); +} +/*---------------------------------------------------------------------------*/ +static lwm2m_object_instance_t * +get_next(lwm2m_object_instance_t *instance, lwm2m_status_t *status) +{ + return instance == NULL ? NULL : instance->next; +} +/*---------------------------------------------------------------------------*/ +static lwm2m_object_instance_t * +get_by_id(uint16_t instance_id, lwm2m_status_t *status) +{ + lwm2m_object_instance_t *instance; + for(instance = list_head(instances_list); + instance != NULL; + instance = instance->next) { + if(instance->instance_id == instance_id) { + return instance; + } + } + return NULL; +} +/*---------------------------------------------------------------------------*/ +static lwm2m_status_t +lwm2m_callback(lwm2m_object_instance_t *object, + lwm2m_context_t *ctx) +{ + /* NOTE: the create operation will only create an instance and should + avoid reading out data */ + int32_t value; + int iv; + lwm2m_security_server_t *security; + security = (lwm2m_security_server_t *) object; + + if(ctx->operation == LWM2M_OP_WRITE) { + /* Handle the writes */ + switch(ctx->resource_id) { + case LWM2M_SECURITY_SERVER_URI_ID: + PRINTF("Writing security URI value: len: %d\n", (int)ctx->inbuf->size); + value = lwm2m_object_read_string(ctx, ctx->inbuf->buffer, ctx->inbuf->size, security->server_uri, URI_SIZE); + /* This is string... */ + security->server_uri_len = ctx->last_value_len; + break; + case LWM2M_SECURITY_BOOTSTRAP_SERVER_ID: + value = lwm2m_object_read_boolean(ctx, ctx->inbuf->buffer, ctx->inbuf->size, &iv); + if(value > 0) { + PRINTF("Set Bootstrap: %d\n", iv); + security->bootstrap = (uint8_t) iv; + } else { + PRINTF("Failed to set bootstrap\n"); + } + break; + case LWM2M_SECURITY_MODE_ID: + { + int32_t v2; + value = lwm2m_object_read_int(ctx, ctx->inbuf->buffer, ctx->inbuf->size, &v2); + PRINTF("Writing security MODE value: %d len: %d\n", v2, + (int)ctx->inbuf->size); + security->security_mode = v2; + } + break; + case LWM2M_SECURITY_CLIENT_PKI_ID: + value = lwm2m_object_read_string(ctx, ctx->inbuf->buffer, ctx->inbuf->size, security->public_key, KEY_SIZE); + security->public_key_len = ctx->last_value_len; + + PRINTF("Writing client PKI: len: %d '", (int)ctx->last_value_len); + PRINTS(ctx->last_value_len, security->public_key, "%c"); + PRINTF("'\n"); + break; + case LWM2M_SECURITY_KEY_ID: + value = lwm2m_object_read_string(ctx, ctx->inbuf->buffer, ctx->inbuf->size, security->secret_key, URI_SIZE); + security->secret_key_len = ctx->last_value_len; + + PRINTF("Writing secret key: len: %d '", (int)ctx->last_value_len); + PRINTS(ctx->last_value_len, security->secret_key, "%c"); + PRINTF("'\n"); + + break; + } + } else if(ctx->operation == LWM2M_OP_READ) { + switch(ctx->resource_id) { + case LWM2M_SECURITY_SERVER_URI_ID: + lwm2m_object_write_string(ctx, (const char *) security->server_uri, + security->server_uri_len); + break; + default: + return LWM2M_STATUS_ERROR; + } + } + return LWM2M_STATUS_OK; +} + +/*---------------------------------------------------------------------------*/ +lwm2m_security_server_t * +lwm2m_security_get_first(void) +{ + return list_head(instances_list); +} +/*---------------------------------------------------------------------------*/ +lwm2m_security_server_t * +lwm2m_security_get_next(lwm2m_security_server_t *last) +{ + return last == NULL ? NULL : (lwm2m_security_server_t *)last->instance.next; +} +/*---------------------------------------------------------------------------*/ +lwm2m_security_server_t * +lwm2m_security_add_server(uint16_t instance_id, + uint16_t server_id, + const uint8_t *server_uri, + uint8_t server_uri_len) +{ + lwm2m_security_server_t *server; + int i; + + if(server_uri_len > URI_SIZE) { + PRINTF("lwm2m-sec: too long server URI\n"); + return NULL; + } + + for(server = lwm2m_security_get_first(); + server != NULL; + server = lwm2m_security_get_next(server)) { + if(server->server_id == server_id) { + if(server->instance.instance_id != instance_id) { + PRINTF("lwm2m-sec: wrong instance id\n"); + return NULL; + } + /* Correct server id and instance id */ + break; + } else if(server->instance.instance_id == instance_id) { + PRINTF("lwm2m-sec: wrong server id\n"); + return NULL; + } + } + + if(server == NULL) { + for(i = 0; i < MAX_COUNT; i++) { + if(instances[i].instance.instance_id == LWM2M_OBJECT_INSTANCE_NONE) { + memset(&instances[i], 0, sizeof(instances[i])); + instances[i].instance.callback = lwm2m_callback; + instances[i].instance.object_id = LWM2M_OBJECT_SECURITY_ID; + instances[i].instance.instance_id = instance_id; + instances[i].instance.resource_ids = resources; + instances[i].instance.resource_count = + sizeof(resources) / sizeof(lwm2m_resource_id_t); + list_add(instances_list, &instances[i].instance); + server = &instances[i]; + } + } + if(server == NULL) { + PRINTF("lwm2m-sec: no space for more servers\n"); + return NULL; + } + } + + memcpy(server->server_uri, server_uri, server_uri_len); + server->server_uri_len = server_uri_len; + + return server; +} +/*---------------------------------------------------------------------------*/ +int +lwm2m_security_set_server_psk(lwm2m_security_server_t *server, + const uint8_t *identity, + uint8_t identity_len, + const uint8_t *key, + uint8_t key_len) +{ + if(server == NULL || identity == NULL || key == NULL) { + return 0; + } + if(identity_len > KEY_SIZE) { + PRINTF("lwm2m-sec: too large identity\n"); + return 0; + } + if(key_len > KEY_SIZE) { + PRINTF("lwm2m-sec: too large identity\n"); + return 0; + } + memcpy(server->public_key, identity, identity_len); + server->public_key_len = identity_len; + memcpy(server->secret_key, key, key_len); + server->secret_key_len = key_len; + + server->security_mode = LWM2M_SECURITY_MODE_PSK; + + return 1; +} +/*---------------------------------------------------------------------------*/ +static const lwm2m_object_impl_t impl = { + .object_id = LWM2M_OBJECT_SECURITY_ID, + .get_first = get_first, + .get_next = get_next, + .get_by_id = get_by_id, + .create_instance = create_instance, + .delete_instance = delete_instance, +}; +static lwm2m_object_t reg_object = { + .impl = &impl, +}; +/*---------------------------------------------------------------------------*/ +#ifdef WITH_DTLS +#if LWM2M_SECURITY_REGISTER_KEY_STORE +static int +get_psk_info(const coap_endpoint_t *address_info, + coap_keystore_psk_entry_t *info) +{ + /* Find matching security object based on address */ + lwm2m_security_server_t *e; + coap_endpoint_t ep; + + if(info == NULL || address_info == NULL) { + return 0; + } + + for(e = lwm2m_security_get_first(); + e != NULL; + e = lwm2m_security_get_next(e)) { + if(e->server_uri_len == 0) { + continue; + } + if(e->security_mode != LWM2M_SECURITY_MODE_PSK) { + /* Only PSK supported for now */ + continue; + } + if(!coap_endpoint_parse((char *)e->server_uri, e->server_uri_len, &ep)) { + /* Failed to parse URI to endpoint */ + PRINTF("lwm2m-sec: failed to parse server URI "); + PRINTS(e->server_uri_len, e->server_uri, "%c"); + PRINTF("\n"); + continue; + } + if(!coap_endpoint_cmp(address_info, &ep)) { + /* Wrong server */ + PRINTF("lwm2m-sec: wrong server "); + PRINTEP(address_info); + PRINTF(" != "); + PRINTEP(&ep); + PRINTF("\n"); + continue; + } + if(info->identity_len > 0 && info->identity != NULL) { + /* Searching for a specific identity */ + if(info->identity_len != e->public_key_len || + memcmp(info->identity, e->public_key, info->identity_len)) { + /* Identity not matching */ + PRINTF("lwm2m-sec: identity not matching\n"); + continue; + } + } + /* Found security information for this server */ + PRINTF("lwm2m-sec: found security match!\n"); + break; + } + + if(e == NULL) { + /* No matching security object found */ + return 0; + } + + if(info->identity == NULL || info->identity_len == 0) { + /* Identity requested */ + info->identity = e->public_key; + info->identity_len = e->public_key_len; + return 1; + } + + if(e->secret_key_len == 0) { + /* No secret key / password */ + return 0; + } + + info->key = e->secret_key; + info->key_len = e->secret_key_len; + return 1; +} +#endif /* LWM2M_SECURITY_REGISTER_KEY_STORE */ +#endif /* WITH_DTLS */ +/*---------------------------------------------------------------------------*/ +#ifdef WITH_DTLS +#if LWM2M_SECURITY_REGISTER_KEY_STORE +static const coap_keystore_t key_store = { + .coap_get_psk_info = get_psk_info +}; +#endif /* LWM2M_SECURITY_REGISTER_KEY_STORE */ +#endif /* WITH_DTLS */ /*---------------------------------------------------------------------------*/ void lwm2m_security_init(void) { - lwm2m_instance_t template = LWM2M_INSTANCE_UNUSED(0, security_resources); int i; - /* Initialize the instances */ - for(i = 0; i < MAX_COUNT; i++) { - security_instances[i] = template; - security_instances[i].id = i; - } - - /** - * Register this device and its handlers - the handlers - * automatically sends in the object to handle. - */ PRINTF("*** Init lwm2m-security\n"); - lwm2m_engine_register_object(&security); + + list_init(instances_list); + + for(i = 0; i < MAX_COUNT; i++) { + instances[i].instance.instance_id = LWM2M_OBJECT_INSTANCE_NONE; + } + if(lwm2m_engine_add_generic_object(®_object)) { + +#ifdef WITH_DTLS +#if LWM2M_SECURITY_REGISTER_KEY_STORE + /* Security object handler added - register keystore */ + coap_set_keystore(&key_store); +#endif /* LWM2M_SECURITY_REGISTER_KEY_STORE */ +#endif /* WITH_DTLS */ + } } /*---------------------------------------------------------------------------*/ /** @} */ diff --git a/os/services/lwm2m/lwm2m-security.h b/os/services/lwm2m/lwm2m-security.h new file mode 100644 index 000000000..7142c4a8e --- /dev/null +++ b/os/services/lwm2m/lwm2m-security.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2017, SICS Swedish ICT + * 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 copyright holder 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 COPYRIGHT HOLDER 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 + * COPYRIGHT HOLDER 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. + */ + +/** + * \addtogroup oma-lwm2m + * @{ + * + */ +#ifndef LWM2M_SECURITY_H +#define LWM2M_SECURITY_H + +#define URI_SIZE 64 +#define KEY_SIZE 32 + +typedef struct { + lwm2m_object_instance_t instance; + uint16_t server_id; + uint8_t bootstrap; + uint8_t security_mode; + uint8_t server_uri[URI_SIZE]; + uint8_t server_uri_len; + uint8_t public_key[KEY_SIZE]; + uint8_t public_key_len; + uint8_t secret_key[KEY_SIZE]; + uint8_t secret_key_len; + uint8_t server_public_key[KEY_SIZE]; + uint8_t server_public_key_len; +} lwm2m_security_server_t; + +lwm2m_security_server_t *lwm2m_security_get_first(void); +lwm2m_security_server_t *lwm2m_security_get_next(lwm2m_security_server_t *last); + +lwm2m_security_server_t *lwm2m_security_add_server(uint16_t instance_id, + uint16_t server_id, + const uint8_t *server_uri, + uint8_t server_uri_len); + +int lwm2m_security_set_server_psk(lwm2m_security_server_t *server, + const uint8_t *identity, + uint8_t identity_len, + const uint8_t *key, + uint8_t key_len); + +void lwm2m_security_init(void); + +#endif /* LWM2M_SECURITY_H */ diff --git a/os/services/lwm2m/lwm2m-server.c b/os/services/lwm2m/lwm2m-server.c index 9de678682..31eb4a32c 100644 --- a/os/services/lwm2m/lwm2m-server.c +++ b/os/services/lwm2m/lwm2m-server.c @@ -43,8 +43,11 @@ */ #include +#include "lib/list.h" #include "lwm2m-object.h" #include "lwm2m-engine.h" +#include "lwm2m-server.h" +#include "lwm2m-rd-client.h" #define DEBUG 0 #if DEBUG @@ -54,40 +57,244 @@ #define PRINTF(...) #endif -#ifdef LWM2M_CONF_SERVER_MAX_COUNT -#define MAX_COUNT LWM2M_CONF_SERVER_MAX_COUNT -#else -#define MAX_COUNT 2 -#endif +#define MAX_COUNT LWM2M_SERVER_MAX_COUNT -static int32_t sid_arr[MAX_COUNT]; -static int32_t lifetime_arr[MAX_COUNT]; -static lwm2m_instance_t server_instances[MAX_COUNT]; +static lwm2m_status_t lwm2m_callback(lwm2m_object_instance_t *object, + lwm2m_context_t *ctx); -LWM2M_RESOURCES(server_resources, - LWM2M_RESOURCE_INTEGER_VAR_ARR(0, MAX_COUNT, sid_arr), - LWM2M_RESOURCE_INTEGER_VAR_ARR(1, MAX_COUNT, lifetime_arr), - ); -LWM2M_OBJECT(server, 1, server_instances); +static lwm2m_object_instance_t *create_instance(uint16_t instance_id, + lwm2m_status_t *status); +static int delete_instance(uint16_t instance_id, lwm2m_status_t *status); +static lwm2m_object_instance_t *get_first(lwm2m_status_t *status); +static lwm2m_object_instance_t *get_next(lwm2m_object_instance_t *instance, + lwm2m_status_t *status); +static lwm2m_object_instance_t *get_by_id(uint16_t instance_id, + lwm2m_status_t *status); + +static const lwm2m_resource_id_t resources[] = { + RO(LWM2M_SERVER_SHORT_SERVER_ID), + RW(LWM2M_SERVER_LIFETIME_ID), + EX(LWM2M_SERVER_REG_UPDATE_TRIGGER_ID) +}; + +static const lwm2m_object_impl_t impl = { + .object_id = LWM2M_OBJECT_SERVER_ID, + .get_first = get_first, + .get_next = get_next, + .get_by_id = get_by_id, + .create_instance = create_instance, + .delete_instance = delete_instance, +}; +static lwm2m_object_t server_object = { + .impl = &impl, +}; + +LIST(server_list); +static lwm2m_server_t server_instances[MAX_COUNT]; +/*---------------------------------------------------------------------------*/ +static lwm2m_object_instance_t * +create_instance(uint16_t instance_id, lwm2m_status_t *status) +{ + lwm2m_object_instance_t *instance; + int i; + + instance = get_by_id(instance_id, NULL); + if(instance != NULL) { + /* An instance with this id is already registered */ + if(status) { + *status = LWM2M_STATUS_OPERATION_NOT_ALLOWED; + } + return NULL; + } + + for(i = 0; i < MAX_COUNT; i++) { + if(server_instances[i].instance.instance_id == LWM2M_OBJECT_INSTANCE_NONE) { + server_instances[i].instance.callback = lwm2m_callback; + server_instances[i].instance.object_id = LWM2M_OBJECT_SERVER_ID; + server_instances[i].instance.instance_id = instance_id; + server_instances[i].instance.resource_ids = resources; + server_instances[i].instance.resource_count = + sizeof(resources) / sizeof(lwm2m_resource_id_t); + server_instances[i].server_id = 0; + server_instances[i].lifetime = 0; + list_add(server_list, &server_instances[i].instance); + + if(status) { + *status = LWM2M_STATUS_OK; + } + + return &server_instances[i].instance; + } + } + + if(status) { + *status = LWM2M_STATUS_SERVICE_UNAVAILABLE; + } + + return NULL; +} +/*---------------------------------------------------------------------------*/ +static int +delete_instance(uint16_t instance_id, lwm2m_status_t *status) +{ + lwm2m_object_instance_t *instance; + + if(status) { + *status = LWM2M_STATUS_OK; + } + + if(instance_id == LWM2M_OBJECT_INSTANCE_NONE) { + /* Remove all instances */ + while((instance = list_pop(server_list)) != NULL) { + instance->instance_id = LWM2M_OBJECT_INSTANCE_NONE; + } + return 1; + } + + instance = get_by_id(instance_id, NULL); + if(instance != NULL) { + instance->instance_id = LWM2M_OBJECT_INSTANCE_NONE; + list_remove(server_list, instance); + return 1; + } + + return 0; +} +/*---------------------------------------------------------------------------*/ +static lwm2m_object_instance_t * +get_first(lwm2m_status_t *status) +{ + if(status) { + *status = LWM2M_STATUS_OK; + } + return list_head(server_list); +} +/*---------------------------------------------------------------------------*/ +static lwm2m_object_instance_t * +get_next(lwm2m_object_instance_t *instance, lwm2m_status_t *status) +{ + if(status) { + *status = LWM2M_STATUS_OK; + } + return instance == NULL ? NULL : instance->next; +} +/*---------------------------------------------------------------------------*/ +static lwm2m_object_instance_t * +get_by_id(uint16_t instance_id, lwm2m_status_t *status) +{ + lwm2m_object_instance_t *instance; + if(status) { + *status = LWM2M_STATUS_OK; + } + for(instance = list_head(server_list); + instance != NULL; + instance = instance->next) { + if(instance->instance_id == instance_id) { + return instance; + } + } + return NULL; +} +/*---------------------------------------------------------------------------*/ +static lwm2m_status_t +lwm2m_callback(lwm2m_object_instance_t *object, + lwm2m_context_t *ctx) +{ + int32_t value; + lwm2m_server_t *server; + server = (lwm2m_server_t *) object; + + if(ctx->operation == LWM2M_OP_WRITE) { + PRINTF("Write to: %d\n", ctx->resource_id); + switch(ctx->resource_id) { + case LWM2M_SERVER_LIFETIME_ID: + lwm2m_object_read_int(ctx, ctx->inbuf->buffer, ctx->inbuf->size, &value); + server->lifetime = value; + break; + } + } else if(ctx->operation == LWM2M_OP_READ) { + switch(ctx->resource_id) { + case LWM2M_SERVER_SHORT_SERVER_ID: + lwm2m_object_write_int(ctx, server->server_id); + break; + case LWM2M_SERVER_LIFETIME_ID: + lwm2m_object_write_int(ctx, server->lifetime); + break; + } + } else if(ctx->operation == LWM2M_OP_EXECUTE) { + switch(ctx->resource_id) { + case LWM2M_SERVER_REG_UPDATE_TRIGGER_ID: + lwm2m_rd_client_update_triggered(); + break; + } + } else { + return LWM2M_STATUS_NOT_IMPLEMENTED; + } + + return LWM2M_STATUS_OK; +} +/*---------------------------------------------------------------------------*/ +lwm2m_server_t * +lwm2m_server_add(uint16_t instance_id, uint16_t server_id, uint32_t lifetime) +{ + lwm2m_server_t *server; + int i; + + for(server = list_head(server_list); + server; + server = (lwm2m_server_t *)server->instance.next) { + if(server->server_id == server_id) { + /* Found a matching server */ + if(server->instance.instance_id != instance_id) { + /* Non-matching instance id */ + PRINTF("lwm2m-server: non-matching instance id for server %u\n", + server_id); + return NULL; + } + server->lifetime = lifetime; + return server; + } else if(server->instance.instance_id == instance_id) { + /* Right instance but wrong server id */ + PRINTF("lwm2m-server: non-matching server id for instance %u\n", + instance_id); + return NULL; + } + } + + for(i = 0; i < MAX_COUNT; i++) { + if(server_instances[i].instance.instance_id == LWM2M_OBJECT_INSTANCE_NONE) { + server_instances[i].instance.callback = lwm2m_callback; + server_instances[i].instance.object_id = LWM2M_OBJECT_SERVER_ID; + server_instances[i].instance.instance_id = instance_id; + server_instances[i].instance.resource_ids = resources; + server_instances[i].instance.resource_count = + sizeof(resources) / sizeof(lwm2m_resource_id_t); + server_instances[i].server_id = server_id; + server_instances[i].lifetime = lifetime; + list_add(server_list, &server_instances[i].instance); + + return &server_instances[i]; + } + } + + PRINTF("lwm2m-server: no space for more servers\n"); + + return NULL; +} /*---------------------------------------------------------------------------*/ void lwm2m_server_init(void) { - lwm2m_instance_t template = LWM2M_INSTANCE_UNUSED(0, server_resources); int i; - /* Initialize the instances */ - for(i = 0; i < MAX_COUNT; i++) { - server_instances[i] = template; - server_instances[i].id = i; - } - - /** - * Register this device and its handlers - the handlers - * automatically sends in the object to handle - */ PRINTF("*** Init lwm2m-server\n"); - lwm2m_engine_register_object(&server); + + list_init(server_list); + + for(i = 0; i < MAX_COUNT; i++) { + server_instances[i].instance.instance_id = LWM2M_OBJECT_INSTANCE_NONE; + } + lwm2m_engine_add_generic_object(&server_object); } /*---------------------------------------------------------------------------*/ /** @} */ diff --git a/os/services/lwm2m/lwm2m-server.h b/os/services/lwm2m/lwm2m-server.h new file mode 100644 index 000000000..9afaf547a --- /dev/null +++ b/os/services/lwm2m/lwm2m-server.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2017, SICS Swedish ICT + * 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 copyright holder 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 COPYRIGHT HOLDER 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 + * COPYRIGHT HOLDER 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. + */ + +/** + * \addtogroup oma-lwm2m + * @{ + * + */ +#ifndef LWM2M_SERVER_H +#define LWM2M_SERVER_H + +#include "contiki.h" + +#ifdef LWM2M_SERVER_CONF_MAX_COUNT +#define LWM2M_SERVER_MAX_COUNT LWM2M_SERVER_CONF_MAX_COUNT +#else +#define LWM2M_SERVER_MAX_COUNT 2 +#endif + +typedef struct { + lwm2m_object_instance_t instance; + uint16_t server_id; + uint32_t lifetime; +} lwm2m_server_t; + +lwm2m_server_t *lwm2m_server_add(uint16_t instance_id, + uint16_t server_id, + uint32_t lifetime); + +void lwm2m_server_init(void); + +#endif /* LWM2M_SERVER_H */ diff --git a/os/services/lwm2m/oma-tlv-reader.c b/os/services/lwm2m/lwm2m-tlv-reader.c similarity index 76% rename from os/services/lwm2m/oma-tlv-reader.c rename to os/services/lwm2m/lwm2m-tlv-reader.c index 58e1dcc54..f1d41d945 100644 --- a/os/services/lwm2m/oma-tlv-reader.c +++ b/os/services/lwm2m/lwm2m-tlv-reader.c @@ -43,30 +43,32 @@ */ #include "lwm2m-object.h" -#include "oma-tlv-reader.h" -#include "oma-tlv.h" +#include "lwm2m-tlv-reader.h" +#include "lwm2m-tlv.h" +#include /*---------------------------------------------------------------------------*/ static size_t -read_int(const lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, +read_int(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int32_t *value) { - oma_tlv_t tlv; + lwm2m_tlv_t tlv; size_t size; - size = oma_tlv_read(&tlv, inbuf, len); + size = lwm2m_tlv_read(&tlv, inbuf, len); if(size > 0) { - *value = oma_tlv_get_int32(&tlv); + *value = lwm2m_tlv_get_int32(&tlv); + ctx->last_value_len = tlv.length; } return size; } /*---------------------------------------------------------------------------*/ static size_t -read_string(const lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, +read_string(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, uint8_t *value, size_t stringlen) { - oma_tlv_t tlv; + lwm2m_tlv_t tlv; size_t size; - size = oma_tlv_read(&tlv, inbuf, len); + size = lwm2m_tlv_read(&tlv, inbuf, len); if(size > 0) { if(stringlen <= tlv.length) { /* The outbuffer can not contain the full string including ending zero */ @@ -74,37 +76,40 @@ read_string(const lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, } memcpy(value, tlv.value, tlv.length); value[tlv.length] = '\0'; + ctx->last_value_len = tlv.length; } return size; } /*---------------------------------------------------------------------------*/ static size_t -read_float32fix(const lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, +read_float32fix(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int32_t *value, int bits) { - oma_tlv_t tlv; + lwm2m_tlv_t tlv; size_t size; - size = oma_tlv_read(&tlv, inbuf, len); + size = lwm2m_tlv_read(&tlv, inbuf, len); if(size > 0) { - oma_tlv_float32_to_fix(&tlv, value, bits); + lwm2m_tlv_float32_to_fix(&tlv, value, bits); + ctx->last_value_len = tlv.length; } return size; } /*---------------------------------------------------------------------------*/ static size_t -read_boolean(const lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, +read_boolean(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int *value) { - oma_tlv_t tlv; + lwm2m_tlv_t tlv; size_t size; - size = oma_tlv_read(&tlv, inbuf, len); + size = lwm2m_tlv_read(&tlv, inbuf, len); if(size > 0) { - *value = oma_tlv_get_int32(&tlv) != 0; + *value = lwm2m_tlv_get_int32(&tlv) != 0; + ctx->last_value_len = tlv.length; } return size; } /*---------------------------------------------------------------------------*/ -const lwm2m_reader_t oma_tlv_reader = { +const lwm2m_reader_t lwm2m_tlv_reader = { read_int, read_string, read_float32fix, diff --git a/os/services/lwm2m/oma-tlv-reader.h b/os/services/lwm2m/lwm2m-tlv-reader.h similarity index 93% rename from os/services/lwm2m/oma-tlv-reader.h rename to os/services/lwm2m/lwm2m-tlv-reader.h index 7e6540c18..5fe610511 100644 --- a/os/services/lwm2m/oma-tlv-reader.h +++ b/os/services/lwm2m/lwm2m-tlv-reader.h @@ -39,12 +39,12 @@ * Niclas Finne */ -#ifndef OMA_TLV_READER_H_ -#define OMA_TLV_READER_H_ +#ifndef LWM2M_TLV_READER_H_ +#define LWM2M_TLV_READER_H_ #include "lwm2m-object.h" -extern const lwm2m_reader_t oma_tlv_reader; +extern const lwm2m_reader_t lwm2m_tlv_reader; -#endif /* OMA_TLV_READER_H_ */ +#endif /* LWM2M_TLV_READER_H_ */ /** @} */ diff --git a/os/services/lwm2m/lwm2m-tlv-writer.c b/os/services/lwm2m/lwm2m-tlv-writer.c new file mode 100644 index 000000000..023fd4700 --- /dev/null +++ b/os/services/lwm2m/lwm2m-tlv-writer.c @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2015, Yanzi Networks AB. + * 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 copyright holder 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 COPYRIGHT HOLDER 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 + * COPYRIGHT HOLDER 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. + */ + +/** + * \addtogroup oma-lwm2m + * @{ + * + */ + +/** + * \file + * Implementation of the Contiki OMA LWM2M TLV writer + * \author + * Joakim Eriksson + * Niclas Finne + */ + +#include "lwm2m-object.h" +#include "lwm2m-tlv.h" + +#define DEBUG 0 +#if DEBUG +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif + +/*---------------------------------------------------------------------------*/ +static size_t +init_write(lwm2m_context_t *ctx) +{ + return 0; +} +/*---------------------------------------------------------------------------*/ +static size_t +end_write(lwm2m_context_t *ctx) +{ + return 0; +} +/*---------------------------------------------------------------------------*/ +static size_t +write_int_tlv(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, + int32_t value) +{ + uint8_t type = ctx->writer_flags & WRITER_RESOURCE_INSTANCE ? + LWM2M_TLV_TYPE_RESOURCE_INSTANCE : LWM2M_TLV_TYPE_RESOURCE; + uint16_t id = ctx->writer_flags & WRITER_RESOURCE_INSTANCE ? + ctx->resource_instance_id : ctx->resource_id; + return lwm2m_tlv_write_int32(type, id, value, outbuf, outlen); +} +/*---------------------------------------------------------------------------*/ +static size_t +write_boolean_tlv(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, + int value) +{ + return write_int_tlv(ctx, outbuf, outlen, value != 0 ? 1 : 0); +} +/*---------------------------------------------------------------------------*/ +static size_t +write_float32fix_tlv(lwm2m_context_t *ctx, uint8_t *outbuf, + size_t outlen, int32_t value, int bits) +{ + uint8_t type = ctx->writer_flags & WRITER_RESOURCE_INSTANCE ? + LWM2M_TLV_TYPE_RESOURCE_INSTANCE : LWM2M_TLV_TYPE_RESOURCE; + uint16_t id = ctx->writer_flags & WRITER_RESOURCE_INSTANCE ? + ctx->resource_instance_id : ctx->resource_id; + return lwm2m_tlv_write_float32(type, id, value, bits, outbuf, outlen); +} +/*---------------------------------------------------------------------------*/ +static size_t +write_string_tlv(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, + const char *value, size_t stringlen) +{ + lwm2m_tlv_t tlv; + tlv.type = ctx->writer_flags & WRITER_RESOURCE_INSTANCE ? + LWM2M_TLV_TYPE_RESOURCE_INSTANCE : LWM2M_TLV_TYPE_RESOURCE; + tlv.value = (uint8_t *) value; + tlv.length = (uint32_t) stringlen; + tlv.id = ctx->resource_id; + return lwm2m_tlv_write(&tlv, outbuf, outlen); +} +/*---------------------------------------------------------------------------*/ +static size_t +write_opaque_header(lwm2m_context_t *ctx, size_t payloadsize) +{ + lwm2m_tlv_t tlv; + tlv.type = LWM2M_TLV_TYPE_RESOURCE; + tlv.value = (uint8_t *) NULL; + tlv.length = (uint32_t) payloadsize; + tlv.id = ctx->resource_id; + return lwm2m_tlv_write(&tlv, &ctx->outbuf->buffer[ctx->outbuf->len], + ctx->outbuf->size - ctx->outbuf->len); +} +/*---------------------------------------------------------------------------*/ +static size_t +enter_sub(lwm2m_context_t *ctx) +{ + /* set some flags in state */ + lwm2m_tlv_t tlv; + int len = 0; + PRINTF("Enter sub-resource rsc=%d mark:%d\n", ctx->resource_id, ctx->outbuf->len); + ctx->writer_flags |= WRITER_RESOURCE_INSTANCE; + tlv.type = LWM2M_TLV_TYPE_MULTI_RESOURCE; + tlv.length = 8; /* create an 8-bit TLV */ + tlv.value = NULL; + tlv.id = ctx->resource_id; + len = lwm2m_tlv_write(&tlv, &ctx->outbuf->buffer[ctx->outbuf->len], + ctx->outbuf->size - ctx->outbuf->len); + /* store position for deciding where to re-write the TLV when we + know the length - NOTE: either this or memmov of buffer later... */ + ctx->out_mark_pos_ri = ctx->outbuf->len; + return len; +} +/*---------------------------------------------------------------------------*/ +static size_t +exit_sub(lwm2m_context_t *ctx) +{ + /* clear out state info */ + int pos = 2; /* this is the lenght pos */ + int len; + ctx->writer_flags &= ~WRITER_RESOURCE_INSTANCE; + + if(ctx->resource_id > 0xff) { + pos++; + } + len = ctx->outbuf->len - ctx->out_mark_pos_ri; + + PRINTF("Exit sub-resource rsc=%d mark:%d len=%d\n", ctx->resource_id, + ctx->out_mark_pos_ri, len); + + /* update the lenght byte... Assume TLV header is pos + 1 bytes. */ + ctx->outbuf->buffer[pos + ctx->out_mark_pos_ri] = len - (pos + 1); + return 0; +} +/*---------------------------------------------------------------------------*/ +const lwm2m_writer_t lwm2m_tlv_writer = { + init_write, + end_write, + enter_sub, + exit_sub, + write_int_tlv, + write_string_tlv, + write_float32fix_tlv, + write_boolean_tlv, + write_opaque_header +}; +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/services/lwm2m/oma-tlv-writer.h b/os/services/lwm2m/lwm2m-tlv-writer.h similarity index 93% rename from os/services/lwm2m/oma-tlv-writer.h rename to os/services/lwm2m/lwm2m-tlv-writer.h index 6ae5edd14..94f3e61bc 100644 --- a/os/services/lwm2m/oma-tlv-writer.h +++ b/os/services/lwm2m/lwm2m-tlv-writer.h @@ -39,12 +39,12 @@ * Niclas Finne */ -#ifndef OMA_TLV_WRITER_H_ -#define OMA_TLV_WRITER_H_ +#ifndef LWM2M_TLV_WRITER_H_ +#define LWM2M_TLV_WRITER_H_ #include "lwm2m-object.h" -extern const lwm2m_writer_t oma_tlv_writer; +extern const lwm2m_writer_t lwm2m_tlv_writer; -#endif /* OMA_TLV_WRITER_H_ */ +#endif /* LWM2M_TLV_WRITER_H_ */ /** @} */ diff --git a/os/services/lwm2m/oma-tlv.c b/os/services/lwm2m/lwm2m-tlv.c similarity index 75% rename from os/services/lwm2m/oma-tlv.c rename to os/services/lwm2m/lwm2m-tlv.c index c07df31cc..5c5bb471e 100644 --- a/os/services/lwm2m/oma-tlv.c +++ b/os/services/lwm2m/lwm2m-tlv.c @@ -44,7 +44,7 @@ #include #include -#include "oma-tlv.h" +#include "lwm2m-tlv.h" #define DEBUG 0 #if DEBUG @@ -56,7 +56,7 @@ /*---------------------------------------------------------------------------*/ static inline uint8_t -get_len_type(const oma_tlv_t *tlv) +get_len_type(const lwm2m_tlv_t *tlv) { if(tlv->length < 8) { return 0; @@ -70,7 +70,7 @@ get_len_type(const oma_tlv_t *tlv) } /*---------------------------------------------------------------------------*/ size_t -oma_tlv_read(oma_tlv_t *tlv, const uint8_t *buffer, size_t len) +lwm2m_tlv_read(lwm2m_tlv_t *tlv, const uint8_t *buffer, size_t len) { uint8_t len_type; uint8_t len_pos = 1; @@ -104,7 +104,7 @@ oma_tlv_read(oma_tlv_t *tlv, const uint8_t *buffer, size_t len) } /*---------------------------------------------------------------------------*/ size_t -oma_tlv_get_size(const oma_tlv_t *tlv) +lwm2m_tlv_get_size(const lwm2m_tlv_t *tlv) { size_t size; /* first hdr + len size */ @@ -117,8 +117,11 @@ oma_tlv_get_size(const oma_tlv_t *tlv) return size; } /*---------------------------------------------------------------------------*/ +/* If the tlv->value is NULL - only the header will be generated - useful for + * large strings or opaque streaming (block transfer) + */ size_t -oma_tlv_write(const oma_tlv_t *tlv, uint8_t *buffer, size_t len) +lwm2m_tlv_write(const lwm2m_tlv_t *tlv, uint8_t *buffer, size_t buffersize) { int pos; uint8_t len_type; @@ -127,8 +130,12 @@ oma_tlv_write(const oma_tlv_t *tlv, uint8_t *buffer, size_t len) len_type = get_len_type(tlv); pos = 1 + len_type; /* ensure that we do not write too much */ - if(len < tlv->length + pos) { - PRINTF("OMA-TLV: Could not write the TLV - buffer overflow.\n"); + if(tlv->value != NULL && buffersize < tlv->length + pos) { + PRINTF("LWM2M-TLV: Could not write the TLV - buffer overflow.\n"); + return 0; + } + + if(buffersize < pos + 2) { return 0; } @@ -156,61 +163,75 @@ oma_tlv_write(const oma_tlv_t *tlv, uint8_t *buffer, size_t len) } /* finally add the value */ - memcpy(&buffer[pos], tlv->value, tlv->length); + if(tlv->value != NULL && tlv->length > 0) { + memcpy(&buffer[pos], tlv->value, tlv->length); + } if(DEBUG) { int i; PRINTF("TLV:"); - for(i = 0; i < pos + tlv->length; i++) { + for(i = 0; i < pos + ((tlv->value != NULL) ? tlv->length : 0); i++) { PRINTF("%02x", buffer[i]); } PRINTF("\n"); } - return pos + tlv->length; + return pos + ((tlv->value != NULL) ? tlv->length : 0); } /*---------------------------------------------------------------------------*/ int32_t -oma_tlv_get_int32(const oma_tlv_t *tlv) +lwm2m_tlv_get_int32(const lwm2m_tlv_t *tlv) { int i; int32_t value = 0; - /* will probably need to handle MSB as a sign bit? */ + for(i = 0; i < tlv->length; i++) { value = (value << 8) | tlv->value[i]; } + + /* Ensure that we set all the bits above what we read in */ + if(tlv->value[0] & 0x80) { + while(i < 4) { + value = value | (0xff << (i * 8)); + i++; + } + } + return value; } /*---------------------------------------------------------------------------*/ size_t -oma_tlv_write_int32(int16_t id, int32_t value, uint8_t *buffer, size_t len) +lwm2m_tlv_write_int32(uint8_t type, int16_t id, int32_t value, uint8_t *buffer, size_t len) { - oma_tlv_t tlv; - size_t tlvlen = 0; + lwm2m_tlv_t tlv; uint8_t buf[4]; int i; + int v; + int last_bit; PRINTF("Exporting int32 %d %ld ", id, (long)value); - buf[3] = value & 0xff; - value = value >> 8; - for(i = 1; value > 0 && i < 4; i++) { + v = value < 0 ? -1 : 0; + i = 0; + do { buf[3 - i] = value & 0xff; + /* check if the last MSB indicates that we need another byte */ + last_bit = (v == 0 && (value & 0x80) > 0) || (v == -1 && (value & 0x80) == 0); value = value >> 8; - } - tlvlen = i; + i++; + } while((value != v || last_bit) && i < 4); /* export INT as TLV */ - PRINTF("len: %zu\n", tlvlen); - tlv.type = OMA_TLV_TYPE_RESOURCE; - tlv.length = tlvlen; - tlv.value = &buf[3 - (tlvlen - 1)]; + PRINTF("len: %d\n", i); + tlv.type = type; + tlv.length = i; + tlv.value = &buf[3 - (i - 1)]; tlv.id = id; - return oma_tlv_write(&tlv, buffer, len); + return lwm2m_tlv_write(&tlv, buffer, len); } /*---------------------------------------------------------------------------*/ /* convert fixpoint 32-bit to a IEEE Float in the byte array*/ size_t -oma_tlv_write_float32(int16_t id, int32_t value, int bits, +lwm2m_tlv_write_float32(uint8_t type, int16_t id, int32_t value, int bits, uint8_t *buffer, size_t len) { int i; @@ -218,7 +239,7 @@ oma_tlv_write_float32(int16_t id, int32_t value, int bits, int32_t val = 0; int32_t v; uint8_t b[4]; - oma_tlv_t tlv; + lwm2m_tlv_t tlv; v = value; if(v < 0) { @@ -243,24 +264,29 @@ oma_tlv_write_float32(int16_t id, int32_t value, int bits, /* convert to the thing we should have */ e = e - bits + 127; + if(value == 0) { + e = 0; + } + /* is this the right byte order? */ b[0] = (value < 0 ? 0x80 : 0) | (e >> 1); b[1] = ((e & 1) << 7) | ((val >> 16) & 0x7f); b[2] = (val >> 8) & 0xff; b[3] = val & 0xff; + PRINTF("B=%02x%02x%02x%02x\n", b[0], b[1], b[2], b[3]); /* construct the TLV */ - tlv.type = OMA_TLV_TYPE_RESOURCE; + tlv.type = type; tlv.length = 4; tlv.value = b; tlv.id = id; - return oma_tlv_write(&tlv, buffer, len); + return lwm2m_tlv_write(&tlv, buffer, len); } /*---------------------------------------------------------------------------*/ /* convert float to fixpoint */ size_t -oma_tlv_float32_to_fix(const oma_tlv_t *tlv, int32_t *value, int bits) +lwm2m_tlv_float32_to_fix(const lwm2m_tlv_t *tlv, int32_t *value, int bits) { /* TLV needs to be 4 bytes */ int e, i; @@ -294,3 +320,21 @@ oma_tlv_float32_to_fix(const oma_tlv_t *tlv, int32_t *value, int bits) } /*---------------------------------------------------------------------------*/ /** @} */ + +#if 0 +int main(int argc, char *argv[]) +{ + lwm2m_tlv_t tlv; + uint8_t data[24]; + /* Make -1 */ + tlv.length = 2; + tlv.value = data; + data[0] = 0x00; + data[1] = 0x80, + + PRINTF("TLV:%d\n", lwm2m_tlv_get_int32(&tlv)); + + PRINTF("Len: %d\n", lwm2m_tlv_write_int32(0, 1, -0x88987f, data, 24)); + +} +#endif diff --git a/os/services/lwm2m/oma-tlv.h b/os/services/lwm2m/lwm2m-tlv.h similarity index 67% rename from os/services/lwm2m/oma-tlv.h rename to os/services/lwm2m/lwm2m-tlv.h index 1bd5fd94a..0cfef25ad 100644 --- a/os/services/lwm2m/oma-tlv.h +++ b/os/services/lwm2m/lwm2m-tlv.h @@ -39,51 +39,52 @@ * Niclas Finne */ -#ifndef OAM_TLV_H_ -#define OAM_TLV_H_ +#ifndef LWM2M_TLV_H_ +#define LWM2M_TLV_H_ -#include "contiki.h" +#include +#include enum { - OMA_TLV_TYPE_OBJECT_INSTANCE = 0, - OMA_TLV_TYPE_RESOURCE_INSTANCE = 1, - OMA_TLV_TYPE_MULTI_RESOURCE = 2, - OMA_TLV_TYPE_RESOURCE = 3 + LWM2M_TLV_TYPE_OBJECT_INSTANCE = 0, + LWM2M_TLV_TYPE_RESOURCE_INSTANCE = 1, + LWM2M_TLV_TYPE_MULTI_RESOURCE = 2, + LWM2M_TLV_TYPE_RESOURCE = 3 }; -typedef uint8_t oma_tlv_type_t; +typedef uint8_t lwm2m_tlv_type_t; typedef enum { - OMA_TLV_LEN_TYPE_NO_LEN = 0, - OMA_TLV_LEN_TYPE_8BIT_LEN = 1, - OMA_TLV_LEN_TYPE_16BIT_LEN = 2, - OMA_TLV_LEN_TYPE_24BIT_LEN = 3 -} oma_tlv_len_type_t; + LWM2M_TLV_LEN_TYPE_NO_LEN = 0, + LWM2M_TLV_LEN_TYPE_8BIT_LEN = 1, + LWM2M_TLV_LEN_TYPE_16BIT_LEN = 2, + LWM2M_TLV_LEN_TYPE_24BIT_LEN = 3 +} lwm2m_tlv_len_type_t; typedef struct { - oma_tlv_type_t type; + lwm2m_tlv_type_t type; uint16_t id; /* can be 8-bit or 16-bit when serialized */ uint32_t length; const uint8_t *value; -} oma_tlv_t; +} lwm2m_tlv_t; -size_t oma_tlv_get_size(const oma_tlv_t *tlv); +size_t lwm2m_tlv_get_size(const lwm2m_tlv_t *tlv); /* read a TLV from the buffer */ -size_t oma_tlv_read(oma_tlv_t *tlv, const uint8_t *buffer, size_t len); +size_t lwm2m_tlv_read(lwm2m_tlv_t *tlv, const uint8_t *buffer, size_t len); /* write a TLV to the buffer */ -size_t oma_tlv_write(const oma_tlv_t *tlv, uint8_t *buffer, size_t len); +size_t lwm2m_tlv_write(const lwm2m_tlv_t *tlv, uint8_t *buffer, size_t len); -int32_t oma_tlv_get_int32(const oma_tlv_t *tlv); +int32_t lwm2m_tlv_get_int32(const lwm2m_tlv_t *tlv); /* write a int as a TLV to the buffer */ -size_t oma_tlv_write_int32(int16_t id, int32_t value, uint8_t *buffer, size_t len); +size_t lwm2m_tlv_write_int32(uint8_t type, int16_t id, int32_t value, uint8_t *buffer, size_t len); /* write a float converted from fixpoint as a TLV to the buffer */ -size_t oma_tlv_write_float32(int16_t id, int32_t value, int bits, uint8_t *buffer, size_t len); +size_t lwm2m_tlv_write_float32(uint8_t type, int16_t id, int32_t value, int bits, uint8_t *buffer, size_t len); /* convert TLV with float32 to fixpoint */ -size_t oma_tlv_float32_to_fix(const oma_tlv_t *tlv, int32_t *value, int bits); +size_t lwm2m_tlv_float32_to_fix(const lwm2m_tlv_t *tlv, int32_t *value, int bits); -#endif /* OAM_TLV_H_ */ +#endif /* LWM2M_TLV_H_ */ /** @} */ diff --git a/os/services/lwm2m/oma-tlv-writer.c b/os/services/lwm2m/oma-tlv-writer.c deleted file mode 100644 index 2f26a69f6..000000000 --- a/os/services/lwm2m/oma-tlv-writer.c +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2015, Yanzi Networks AB. - * 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 copyright holder 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 COPYRIGHT HOLDER 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 - * COPYRIGHT HOLDER 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. - */ - -/** - * \addtogroup oma-lwm2m - * @{ - * - */ - -/** - * \file - * Implementation of the Contiki OMA LWM2M TLV writer - * \author - * Joakim Eriksson - * Niclas Finne - */ - -#include "lwm2m-object.h" -#include "oma-tlv.h" -/*---------------------------------------------------------------------------*/ -static size_t -write_boolean_tlv(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, - int value) -{ - return oma_tlv_write_int32(ctx->resource_id, value != 0 ? 1 : 0, - outbuf, outlen); -} -/*---------------------------------------------------------------------------*/ -static size_t -write_int_tlv(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, - int32_t value) -{ - return oma_tlv_write_int32(ctx->resource_id, value, outbuf, outlen); -} -/*---------------------------------------------------------------------------*/ -static size_t -write_float32fix_tlv(const lwm2m_context_t *ctx, uint8_t *outbuf, - size_t outlen, int32_t value, int bits) -{ - return oma_tlv_write_float32(ctx->resource_id, value, bits, outbuf, outlen); -} -/*---------------------------------------------------------------------------*/ -static size_t -write_string_tlv(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, - const char *value, size_t stringlen) -{ - oma_tlv_t tlv; - tlv.type = OMA_TLV_TYPE_RESOURCE; - tlv.value = (uint8_t *) value; - tlv.length = (uint32_t) stringlen; - tlv.id = ctx->resource_id; - return oma_tlv_write(&tlv, outbuf, outlen); -} -/*---------------------------------------------------------------------------*/ -const lwm2m_writer_t oma_tlv_writer = { - write_int_tlv, - write_string_tlv, - write_float32fix_tlv, - write_boolean_tlv -}; -/*---------------------------------------------------------------------------*/ -/** @} */ From 83446e3f585f96032cacb57c8ca90c770bd286f4 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Wed, 25 Oct 2017 02:27:14 +0200 Subject: [PATCH 04/51] Imported ipso-objects from lwm2m-contiki at https://github.com/sics-iot/lwm2m-contiki --- examples/ipso-objects/example-ipso-objects.c | 155 +++++++++++- examples/ipso-objects/example-server.c | 10 +- examples/ipso-objects/project-conf.h | 9 +- .../ipso-objects/Makefile.ipso-objects | 1 - .../ipso-objects/ipso-blockwise-test.c | 151 +++++++++++ os/services/ipso-objects/ipso-button.c | 110 +++++--- .../ipso-objects/ipso-control-template.c | 204 +++++++++++++++ .../ipso-objects/ipso-control-template.h | 99 ++++++++ os/services/ipso-objects/ipso-leds-control.c | 13 +- os/services/ipso-objects/ipso-light-control.c | 14 +- os/services/ipso-objects/ipso-objects.c | 10 +- .../ipso-objects/ipso-sensor-template.c | 238 ++++++++++++++++++ .../ipso-objects/ipso-sensor-template.h | 83 ++++++ os/services/ipso-objects/ipso-temperature.c | 104 ++------ 14 files changed, 1055 insertions(+), 146 deletions(-) delete mode 100644 os/services/ipso-objects/Makefile.ipso-objects create mode 100644 os/services/ipso-objects/ipso-blockwise-test.c create mode 100644 os/services/ipso-objects/ipso-control-template.c create mode 100644 os/services/ipso-objects/ipso-control-template.h create mode 100644 os/services/ipso-objects/ipso-sensor-template.c create mode 100644 os/services/ipso-objects/ipso-sensor-template.h diff --git a/examples/ipso-objects/example-ipso-objects.c b/examples/ipso-objects/example-ipso-objects.c index 180369076..811ad7732 100644 --- a/examples/ipso-objects/example-ipso-objects.c +++ b/examples/ipso-objects/example-ipso-objects.c @@ -38,7 +38,13 @@ #include "contiki.h" #include "services/lwm2m/lwm2m-engine.h" +#include "services/lwm2m/lwm2m-rd-client.h" +#include "services/lwm2m/lwm2m-device.h" +#include "services/lwm2m/lwm2m-server.h" +#include "services/lwm2m/lwm2m-security.h" #include "services/ipso-objects/ipso-objects.h" +#include "services/ipso-objects/ipso-sensor-template.h" +#include "services/ipso-objects/ipso-control-template.h" #define DEBUG DEBUG_NONE #include "net/ipv6/uip-debug.h" @@ -52,7 +58,101 @@ #endif #ifndef LWM2M_SERVER_ADDRESS -#define LWM2M_SERVER_ADDRESS "fd00::1" +#define LWM2M_SERVER_ADDRESS "coap://[fd00::1]" +#endif + +#if BOARD_SENSORTAG +#include "board-peripherals.h" + +/* Temperature reading */ +static lwm2m_status_t +read_temp_value(const ipso_sensor_t *s, int32_t *value) +{ + *value = 10 * hdc_1000_sensor.value(HDC_1000_SENSOR_TYPE_TEMP); + return LWM2M_STATUS_OK; +} +/* Humitidy reading */ +static lwm2m_status_t +read_hum_value(const ipso_sensor_t *s, int32_t *value) +{ + *value = 10 * hdc_1000_sensor.value(HDC_1000_SENSOR_TYPE_HUMIDITY); + return LWM2M_STATUS_OK; +} +/* Lux reading */ +static lwm2m_status_t +read_lux_value(const ipso_sensor_t *s, int32_t *value) +{ + *value = 10 * opt_3001_sensor.value(0); + return LWM2M_STATUS_OK; +} +/* Barometer reading */ +static lwm2m_status_t +read_bar_value(const ipso_sensor_t *s, int32_t *value) +{ + *value = 10 * bmp_280_sensor.value(BMP_280_SENSOR_TYPE_PRESS); + return LWM2M_STATUS_OK; +} +/* LED control */ +static lwm2m_status_t +leds_set_val(uint8_t value) +{ + if(value > 0) { + leds_on(LEDS_YELLOW); + } else { + leds_off(LEDS_YELLOW); + } + return LWM2M_STATUS_OK; +} +/*---------------------------------------------------------------------------*/ +static ipso_sensor_value_t temp_value; +static ipso_sensor_value_t hum_value; +static ipso_sensor_value_t lux_value; +static ipso_sensor_value_t bar_value; + +static ipso_control_t led_control = { + .reg_object.object_id = 3311, + .reg_object.instance_id = 0, + .set_value = leds_set_val +}; + +static const ipso_sensor_t temp_sensor = { + .object_id = 3303, + .sensor_value = &temp_value, + .max_range = 100000, /* 100 cel milli celcius */ + .min_range = -10000, /* -10 cel milli celcius */ + .get_value_in_millis = read_temp_value, + .unit = "Cel", + .update_interval = 30 +}; + +static const ipso_sensor_t hum_sensor = { + .object_id = 3304, + .sensor_value = &hum_value, + .max_range = 100000, /* 100 % RH */ + .min_range = 0, + .get_value_in_millis = read_hum_value, + .unit = "% RH", + .update_interval = 30 +}; +static const ipso_sensor_t lux_sensor = { + .object_id = 3301, + .sensor_value = &lux_value, + .max_range = 100000, + .min_range = -10000, + .get_value_in_millis = read_lux_value, + .unit = "LUX", + .update_interval = 30 +}; +static const ipso_sensor_t bar_sensor = { + .object_id = 3315, + .sensor_value = &bar_value, + .max_range = 100000, /* 100 cel milli celcius */ + .min_range = -10000, /* -10 cel milli celcius */ + .get_value_in_millis = read_bar_value, + .unit = "hPa", + .update_interval = 30 +}; + #endif PROCESS(example_ipso_objects, "IPSO object example"); @@ -62,39 +162,70 @@ static void setup_lwm2m_servers(void) { #ifdef LWM2M_SERVER_ADDRESS - uip_ipaddr_t addr; - if(uiplib_ipaddrconv(LWM2M_SERVER_ADDRESS, &addr)) { - lwm2m_engine_register_with_bootstrap_server(&addr, 0); - lwm2m_engine_register_with_server(&addr, 0); + coap_endpoint_t server_ep; + if(coap_endpoint_parse(LWM2M_SERVER_ADDRESS, strlen(LWM2M_SERVER_ADDRESS), + &server_ep) != 0) { + lwm2m_rd_client_register_with_bootstrap_server(&server_ep); + lwm2m_rd_client_register_with_server(&server_ep); } #endif /* LWM2M_SERVER_ADDRESS */ - lwm2m_engine_use_bootstrap_server(REGISTER_WITH_LWM2M_BOOTSTRAP_SERVER); - lwm2m_engine_use_registration_server(REGISTER_WITH_LWM2M_SERVER); + lwm2m_rd_client_use_bootstrap_server(REGISTER_WITH_LWM2M_BOOTSTRAP_SERVER); + lwm2m_rd_client_use_registration_server(REGISTER_WITH_LWM2M_SERVER); } /*---------------------------------------------------------------------------*/ PROCESS_THREAD(example_ipso_objects, ev, data) { + static struct etimer periodic; PROCESS_BEGIN(); PROCESS_PAUSE(); - PRINTF("Starting IPSO objects example\n"); - + PRINTF("Starting IPSO objects example%s\n", + REGISTER_WITH_LWM2M_BOOTSTRAP_SERVER ? " (bootstrap)" : ""); /* Initialize the OMA LWM2M engine */ lwm2m_engine_init(); /* Register default LWM2M objects */ - lwm2m_engine_register_default_objects(); + lwm2m_device_init(); + lwm2m_security_init(); + lwm2m_server_init(); - /* Register default IPSO objects */ +#if BOARD_SENSORTAG + ipso_sensor_add(&temp_sensor); + ipso_sensor_add(&hum_sensor); + ipso_sensor_add(&lux_sensor); + ipso_sensor_add(&bar_sensor); + ipso_control_add(&led_control); + ipso_button_init(); + + SENSORS_ACTIVATE(hdc_1000_sensor); + SENSORS_ACTIVATE(opt_3001_sensor); + SENSORS_ACTIVATE(bmp_280_sensor); +#else /* BOARD_SENSORTAG */ + /* Register default IPSO objects - such as button..*/ ipso_objects_init(); +#endif /* BOARD_SENSORTAG */ setup_lwm2m_servers(); + /* Tick loop each 5 seconds */ + etimer_set(&periodic, CLOCK_SECOND * 5); while(1) { PROCESS_WAIT_EVENT(); - } + if(ev == PROCESS_EVENT_TIMER && etimer_expired(&periodic)) { +#if BOARD_SENSORTAG + /* deactive / activate to do a new reading */ + SENSORS_DEACTIVATE(hdc_1000_sensor); + SENSORS_DEACTIVATE(opt_3001_sensor); + SENSORS_DEACTIVATE(bmp_280_sensor); + SENSORS_ACTIVATE(hdc_1000_sensor); + SENSORS_ACTIVATE(opt_3001_sensor); + SENSORS_ACTIVATE(bmp_280_sensor); +#endif /* BOARD_SENSORTAG */ + etimer_reset(&periodic); + } + } PROCESS_END(); } diff --git a/examples/ipso-objects/example-server.c b/examples/ipso-objects/example-server.c index acec7ee25..4da82c9f0 100644 --- a/examples/ipso-objects/example-server.c +++ b/examples/ipso-objects/example-server.c @@ -44,7 +44,7 @@ #include "coap-constants.h" #include "coap-engine.h" #include "lwm2m-engine.h" -#include "oma-tlv.h" +#include "lwm2m-tlv.h" #include "dev/serial-line.h" #include "serial-protocol.h" @@ -187,13 +187,13 @@ client_chunk_handler(void *response) } else { /* otherwise update the current value */ if(format == LWM2M_TLV) { - oma_tlv_t tlv; + lwm2m_tlv_t tlv; /* we can only read int32 for now ? */ - if(oma_tlv_read(&tlv, chunk, len) > 0) { + if(lwm2m_tlv_read(&tlv, chunk, len) > 0) { /* printf("TLV.type=%d len=%d id=%d value[0]=%d\n", */ /* tlv.type, tlv.length, tlv.id, tlv.value[0]); */ - int value = oma_tlv_get_int32(&tlv); + int value = lwm2m_tlv_get_int32(&tlv); snprintf(current_value, sizeof(current_value), "%d", value); } } else { @@ -269,7 +269,7 @@ PROCESS_THREAD(router_process, ev, data) PROCESS_PAUSE(); /* receives all CoAP messages */ - coap_init_engine(); + coap_engine_init(); setup_network(); diff --git a/examples/ipso-objects/project-conf.h b/examples/ipso-objects/project-conf.h index 075cd7444..a7ad8b3ea 100644 --- a/examples/ipso-objects/project-conf.h +++ b/examples/ipso-objects/project-conf.h @@ -30,6 +30,9 @@ #ifndef PROJECT_CONF_H_ #define PROJECT_CONF_H_ +/* No sleep on CC2538 to enable full 32 KiB RAM */ +#define LPM_CONF_ENABLE 0 + #ifdef BOARD_STRING #define LWM2M_DEVICE_MODEL_NUMBER BOARD_STRING #elif defined(CONTIKI_TARGET_WISMOTE) @@ -40,10 +43,14 @@ #define PLATFORM_REBOOT watchdog_reboot #endif +#if BOARD_SENSORTAG +/* Real sensor is present... */ +#else #define IPSO_TEMPERATURE example_ipso_temperature +#endif /* BOARD_SENSORTAG */ /* Increase rpl-border-router IP-buffer when using more than 64. */ -#define REST_MAX_CHUNK_SIZE 64 +#define COAP_MAX_CHUNK_SIZE 64 /* Multiplies with chunk size, be aware of memory constraints. */ #define COAP_MAX_OPEN_TRANSACTIONS 4 diff --git a/os/services/ipso-objects/Makefile.ipso-objects b/os/services/ipso-objects/Makefile.ipso-objects deleted file mode 100644 index 21c56fed0..000000000 --- a/os/services/ipso-objects/Makefile.ipso-objects +++ /dev/null @@ -1 +0,0 @@ -CFLAGS += -DWITH_IPSO=1 diff --git a/os/services/ipso-objects/ipso-blockwise-test.c b/os/services/ipso-objects/ipso-blockwise-test.c new file mode 100644 index 000000000..532642969 --- /dev/null +++ b/os/services/ipso-objects/ipso-blockwise-test.c @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2016, SICS Swedish ICT AB + * 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 copyright holder 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 COPYRIGHT HOLDER 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 + * COPYRIGHT HOLDER 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. + */ + +/** + * \addtogroup ipso-objects + * @{ + * + * Code to test blockwise transfer together with the LWM2M-engine. + * This object tests get with BLOCK2 and put with BLOCK1. + * + */ + +#include "lwm2m-engine.h" +#include "coap.h" +#include + +#define DEBUG 0 +#if DEBUG +#include +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif + +static lwm2m_object_instance_t reg_object; +static char junk[64]; + +static const lwm2m_resource_id_t resources[] = + { + RO(10000), + RO(11000), + RW(11001) + }; + +#define LEN 900 + +static lwm2m_status_t +opaque_callback(lwm2m_object_instance_t *object, + lwm2m_context_t *ctx, int num_to_write) +{ + int i; + PRINTF("opaque-stream callback num_to_write: %d off: %d outlen: %d\n", + num_to_write, ctx->offset, ctx->outbuf->len); + for(i = 0; i < num_to_write; i++) { + ctx->outbuf->buffer[i + ctx->outbuf->len] = '0' + (i & 31); + if(i + ctx->offset == LEN) break; + } + ctx->outbuf->len += i; + if(ctx->offset + i < LEN) { + ctx->writer_flags |= WRITER_HAS_MORE; + } + return LWM2M_STATUS_OK; +} + +/*---------------------------------------------------------------------------*/ +static lwm2m_status_t +lwm2m_callback(lwm2m_object_instance_t *object, + lwm2m_context_t *ctx) +{ + uint32_t num; + uint8_t more; + uint16_t size; + uint32_t offset; + + char *str = "just a string"; + + PRINTF("Got request at: %d/%d/%d lv:%d\n", ctx->object_id, ctx->object_instance_id, ctx->resource_id, ctx->level); + + if(ctx->level == 1) { + /* Should not happen */ + return LWM2M_STATUS_ERROR; + } + if(ctx->level == 2) { + /* This is a get whole object - or write whole object */ + return LWM2M_STATUS_ERROR; + } + + if(ctx->operation == LWM2M_OP_READ) { +#if DEBUG + if(coap_get_header_block2(ctx->request, &num, &more, &size, &offset)) { + PRINTF("CoAP BLOCK2: %d/%d/%d offset:%d\n", num, more, size, offset); + } +#endif + + switch(ctx->resource_id) { + case 10000: + lwm2m_object_write_string(ctx, str, strlen(str)); + break; + case 11000: + case 11001: + PRINTF("Preparing object write\n"); + lwm2m_object_write_opaque_stream(ctx, LEN, opaque_callback); + break; + default: + return LWM2M_STATUS_NOT_FOUND; + } + } else if(ctx->operation == LWM2M_OP_WRITE) { + if(coap_get_header_block1(ctx->request, &num, &more, &size, &offset)) { + PRINTF("CoAP BLOCK1: %d/%d/%d offset:%d\n", num, more, size, offset); + coap_set_header_block1(ctx->response, num, 0, size); + } + } + return LWM2M_STATUS_OK; +} + +void +ipso_blockwise_test_init(void) +{ + int i; + PRINTF("Starting blockwise\n"); + reg_object.object_id = 4711; + reg_object.instance_id = 0; + reg_object.resource_ids = resources; + reg_object.resource_count = + sizeof(resources) / sizeof(lwm2m_resource_id_t); + reg_object.callback = lwm2m_callback; + + for(i = 0; i < sizeof(junk); i++) { + junk[i] = '0' + i; + } + junk[i - 1] = 0; + + lwm2m_engine_add_object(®_object); +} diff --git a/os/services/ipso-objects/ipso-button.c b/os/services/ipso-objects/ipso-button.c index adda46d1e..1f3cb2d9b 100644 --- a/os/services/ipso-objects/ipso-button.c +++ b/os/services/ipso-objects/ipso-button.c @@ -36,6 +36,7 @@ /** * \file * Implementation of OMA LWM2M / IPSO button as a digital input + * NOTE: only works with a Contiki Button Sensor (not for Standalone) * \author * Joakim Eriksson * Niclas Finne @@ -44,7 +45,6 @@ #include "contiki.h" #include "lwm2m-object.h" #include "lwm2m-engine.h" -#include "coap-engine.h" #define DEBUG 0 #if DEBUG @@ -54,20 +54,55 @@ #define PRINTF(...) #endif +#define IPSO_INPUT_STATE 5500 +#define IPSO_INPUT_COUNTER 5501 +#define IPSO_INPUT_POLARITY 5502 +#define IPSO_INPUT_DEBOUNCE 5503 +#define IPSO_INPUT_EDGE_SEL 5504 +#define IPSO_INPUT_CTR_RESET 5505 +#define IPSO_INPUT_SENSOR_TYPE 5751 + #if PLATFORM_HAS_BUTTON #include "dev/button-sensor.h" +#if BOARD_SENSORTAG +#include "sensortag/button-sensor.h" +#define IPSO_BUTTON_SENSOR button_left_sensor +#else +#define IPSO_BUTTON_SENSOR button_sensor +#endif + PROCESS(ipso_button_process, "ipso-button"); #endif /* PLATFORM_HAS_BUTTON */ + +static lwm2m_status_t lwm2m_callback(lwm2m_object_instance_t *object, + lwm2m_context_t *ctx); + static int input_state = 0; static int polarity = 0; static int32_t counter = 0; -static int32_t edge_selection = 3; +static int32_t edge_selection = 3; /* both */ static int32_t debounce_time = 10; + +static const lwm2m_resource_id_t resources[] = { + RO(IPSO_INPUT_STATE), RO(IPSO_INPUT_COUNTER), RW(IPSO_INPUT_POLARITY), + RW(IPSO_INPUT_DEBOUNCE), RW(IPSO_INPUT_EDGE_SEL), EX(IPSO_INPUT_CTR_RESET), + RO(IPSO_INPUT_SENSOR_TYPE) +}; + +/* Only support for one button for now */ +static lwm2m_object_instance_t reg_object = { + .object_id = 3200, + .instance_id = 0, + .resource_ids = resources, + .resource_count = sizeof(resources) / sizeof(lwm2m_resource_id_t), + .callback = lwm2m_callback, +}; + /*---------------------------------------------------------------------------*/ static int -read_state(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outsize) +read_state(void) { int value; if(polarity == 0) { @@ -77,36 +112,53 @@ read_state(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outsize) } PRINTF("Read button state (polarity=%d, state=%d): %d\n", polarity, input_state, value); - return ctx->writer->write_boolean(ctx, outbuf, outsize, value); + return value; } /*---------------------------------------------------------------------------*/ -static int -reset_counter(lwm2m_context_t *ctx, const uint8_t *arg, size_t len, - uint8_t *outbuf, size_t outlen) +/*---------------------------------------------------------------------------*/ +static lwm2m_status_t +lwm2m_callback(lwm2m_object_instance_t *object, + lwm2m_context_t *ctx) { - counter = 0; - return 0; + if(ctx->operation == LWM2M_OP_READ) { + switch(ctx->resource_id) { + case IPSO_INPUT_STATE: + lwm2m_object_write_int(ctx, read_state()); + break; + case IPSO_INPUT_COUNTER: + lwm2m_object_write_int(ctx, counter); + break; + case IPSO_INPUT_POLARITY: + lwm2m_object_write_int(ctx, polarity); + break; + case IPSO_INPUT_DEBOUNCE: + lwm2m_object_write_int(ctx, debounce_time); + break; + case IPSO_INPUT_EDGE_SEL: + lwm2m_object_write_int(ctx, edge_selection); + break; + case IPSO_INPUT_SENSOR_TYPE: + lwm2m_object_write_string(ctx, "button", strlen("button")); + break; + default: + return LWM2M_STATUS_ERROR; + } + } else if(ctx->operation == LWM2M_OP_EXECUTE) { + if(ctx->resource_id == IPSO_INPUT_CTR_RESET) { + counter = 0; + } else { + return LWM2M_STATUS_ERROR; + } + } + return LWM2M_STATUS_OK; } /*---------------------------------------------------------------------------*/ -LWM2M_RESOURCES(button_resources, - LWM2M_RESOURCE_CALLBACK(5500, { read_state, NULL, NULL }), - LWM2M_RESOURCE_INTEGER_VAR(5501, &counter), - LWM2M_RESOURCE_BOOLEAN_VAR(5502, &polarity), - LWM2M_RESOURCE_INTEGER_VAR(5503, &debounce_time), - LWM2M_RESOURCE_INTEGER_VAR(5504, &edge_selection), - LWM2M_RESOURCE_CALLBACK(5505, { NULL, NULL, reset_counter }), - LWM2M_RESOURCE_STRING(5751, "Button") - ); -LWM2M_INSTANCES(button_instances, - LWM2M_INSTANCE(0, button_resources)); -LWM2M_OBJECT(button, 3200, button_instances); -/*---------------------------------------------------------------------------*/ void ipso_button_init(void) { /* register this device and its handlers - the handlers automatically sends in the object to handle */ - lwm2m_engine_register_object(&button); + lwm2m_engine_add_object(®_object); #if PLATFORM_HAS_BUTTON process_start(&ipso_button_process, NULL); @@ -121,19 +173,19 @@ PROCESS_THREAD(ipso_button_process, ev, data) PROCESS_BEGIN(); - SENSORS_ACTIVATE(button_sensor); + SENSORS_ACTIVATE(IPSO_BUTTON_SENSOR); while(1) { PROCESS_WAIT_EVENT(); - if(ev == sensors_event && data == &button_sensor) { + if(ev == sensors_event && data == &IPSO_BUTTON_SENSOR) { if(!input_state) { input_state = 1; counter++; if((edge_selection & 2) != 0) { - lwm2m_object_notify_observers(&button, "/0/5500"); + lwm2m_notify_object_observers(®_object, IPSO_INPUT_STATE); } - lwm2m_object_notify_observers(&button, "/0/5501"); + lwm2m_notify_object_observers(®_object, IPSO_INPUT_COUNTER); time = (debounce_time * CLOCK_SECOND / 1000); if(time < 1) { @@ -144,13 +196,13 @@ PROCESS_THREAD(ipso_button_process, ev, data) } else if(ev == PROCESS_EVENT_TIMER && data == &timer) { if(!input_state) { /* Button is not in pressed state */ - } else if(button_sensor.value(0) != 0) { + } else if(IPSO_BUTTON_SENSOR.value(0) != 0) { /* Button is still pressed */ etimer_reset(&timer); } else { input_state = 0; if((edge_selection & 1) != 0) { - lwm2m_object_notify_observers(&button, "/0/5500"); + lwm2m_notify_object_observers(®_object, IPSO_INPUT_STATE); } } } diff --git a/os/services/ipso-objects/ipso-control-template.c b/os/services/ipso-objects/ipso-control-template.c new file mode 100644 index 000000000..4d0f28d6b --- /dev/null +++ b/os/services/ipso-objects/ipso-control-template.c @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2016, SICS Swedish ICT AB + * 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 copyright holder 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 COPYRIGHT HOLDER 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 + * COPYRIGHT HOLDER 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. + */ + +/** + * \addtogroup ipso-objects + * @{ + * + */ + +/** + * \file + * Implementation of OMA LWM2M / IPSO control template. + * Useful for implementing controllable objects + * \author + * Joakim Eriksson + * Niclas Finne + */ +#include "ipso-control-template.h" +#include "lwm2m-engine.h" +#include "coap-timer.h" +#include +#include +#include + +#define IPSO_ONOFF 5850 +#define IPSO_DIMMER 5851 +#define IPSO_ON_TIME 5852 + +static const lwm2m_resource_id_t resources[] = + { + RW(IPSO_ONOFF), + RW(IPSO_DIMMER), + RW(IPSO_ON_TIME) + }; +/*---------------------------------------------------------------------------*/ +lwm2m_status_t +ipso_control_set_on(ipso_control_t *control, uint8_t onoroff) +{ + uint8_t v; + + if(onoroff) { + v = control->value & 0x7f; + if(v == 0) { + v = 100; + } + } else { + v = 0; + } + + return ipso_control_set_value(control, v); +} +/*---------------------------------------------------------------------------*/ +lwm2m_status_t +ipso_control_set_value(ipso_control_t *control, uint8_t value) +{ + lwm2m_status_t status = LWM2M_STATUS_OK; + int was_on; + + was_on = ipso_control_is_on(control); + + if(value == 0) { + if(was_on) { + /* Turn off */ + status = control->set_value(0); + if(status == LWM2M_STATUS_OK) { + control->value &= 0x7f; + control->on_time += + (coap_timer_uptime() - control->last_on_time) / 1000; + } + } + } else { + /* Restrict value between 0 - 100 */ + if(value > 100) { + value = 100; + } + value |= 0x80; + + if(value != control->value) { + status = control->set_value(value & 0x7f); + if(status == LWM2M_STATUS_OK) { + control->value = value; + if(! was_on) { + control->last_on_time = coap_timer_uptime(); + } + } + } + } + return status; +} +/*---------------------------------------------------------------------------*/ +static lwm2m_status_t +lwm2m_callback(lwm2m_object_instance_t *object, lwm2m_context_t *ctx) +{ + ipso_control_t *control; + int32_t v; + + /* Here we cast to our sensor-template struct */ + control = (ipso_control_t *)object; + + if(ctx->operation == LWM2M_OP_READ) { + switch(ctx->resource_id) { + case IPSO_ONOFF: + v = ipso_control_is_on(control) ? 1 : 0; + break; + case IPSO_DIMMER: + v = ipso_control_get_value(control); + break; + case IPSO_ON_TIME: + v = control->on_time; + if(ipso_control_is_on(control)) { + v += (coap_timer_uptime() - control->last_on_time) / 1000; + } + printf("ON-TIME: %"PRId32" (last on: %"PRIu32"\n", v, control->on_time); + break; + default: + return LWM2M_STATUS_ERROR; + } + lwm2m_object_write_int(ctx, v); + return LWM2M_STATUS_OK; + + } else if(ctx->operation == LWM2M_OP_WRITE) { + switch(ctx->resource_id) { + case IPSO_ONOFF: + if(lwm2m_object_read_int(ctx, ctx->inbuf->buffer, ctx->inbuf->size, &v) == 0) { + return LWM2M_STATUS_ERROR; + } + return ipso_control_set_on(control, v > 0); + case IPSO_DIMMER: + if(lwm2m_object_read_int(ctx, ctx->inbuf->buffer, ctx->inbuf->size, &v) == 0) { + return LWM2M_STATUS_ERROR; + } + if(v < 0) { + v = 0; + } else if(v > 100) { + v = 100; + } + return ipso_control_set_value(control, v & 0xff); + case IPSO_ON_TIME: + if(lwm2m_object_read_int(ctx, ctx->inbuf->buffer, ctx->inbuf->size, &v) == 0) { + return LWM2M_STATUS_ERROR; + } + + if(v == 0) { + control->on_time = 0; + control->last_on_time = coap_timer_uptime(); + return LWM2M_STATUS_OK; + } else { + /* Only allowed to write 0 to reset ontime */ + return LWM2M_STATUS_FORBIDDEN; + } + break; + default: + return LWM2M_STATUS_ERROR; + } + } else { + return LWM2M_STATUS_OPERATION_NOT_ALLOWED; + } +} +/*---------------------------------------------------------------------------*/ +int +ipso_control_add(ipso_control_t *control) +{ + control->reg_object.resource_ids = resources; + control->reg_object.resource_count = + sizeof(resources) / sizeof(lwm2m_resource_id_t); + + control->reg_object.callback = lwm2m_callback; + return lwm2m_engine_add_object(&control->reg_object); +} +/*---------------------------------------------------------------------------*/ +int +ipso_control_remove(ipso_control_t *control) +{ + lwm2m_engine_remove_object(&control->reg_object); + return 1; +} +/*---------------------------------------------------------------------------*/ diff --git a/os/services/ipso-objects/ipso-control-template.h b/os/services/ipso-objects/ipso-control-template.h new file mode 100644 index 000000000..0e71a17a4 --- /dev/null +++ b/os/services/ipso-objects/ipso-control-template.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2016, SICS Swedish ICT AB + * 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 copyright holder 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 COPYRIGHT HOLDER 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 + * COPYRIGHT HOLDER 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. + */ + +/** + * \addtogroup ipso-objects + * @{ + * + */ + +/** + * \file + * Implementation of OMA LWM2M / IPSO sensor template. + * \author + * Joakim Eriksson + * Niclas Finne + */ + +#ifndef IPSO_CONTROL_TEMPLATE_H_ +#define IPSO_CONTROL_TEMPLATE_H_ + +#include "lwm2m-engine.h" + +typedef struct ipso_control ipso_control_t; + +#define IPSO_CONTROL_USE_DIMMER 0x01 + +typedef lwm2m_status_t (*ipso_control_set_value_t)(uint8_t v); + +/* Values of the IPSO control object */ +struct ipso_control { + lwm2m_object_instance_t reg_object; + uint8_t flags; + uint8_t value; /* used to emulate on/off and dim-value */ + uint32_t on_time; /* on-time in seconds */ + uint64_t last_on_time; + ipso_control_set_value_t set_value; +}; + + +int ipso_control_add(ipso_control_t *control); +int ipso_control_remove(ipso_control_t *control); + +static inline uint16_t +ipso_control_get_object_id(const ipso_control_t *control) +{ + return control->reg_object.object_id; +} + +static inline uint16_t +ipso_control_get_instance_id(const ipso_control_t *control) +{ + return control->reg_object.instance_id; +} + +static inline uint8_t +ipso_control_is_on(const ipso_control_t *control) +{ + return (control->value & 0x80) != 0; +} + +static inline uint8_t +ipso_control_get_value(const ipso_control_t *control) +{ + return (control->value & 0x80) != 0 ? (control->value & 0x7f) : 0; +} + +lwm2m_status_t ipso_control_set_on(ipso_control_t *control, uint8_t onoroff); + +lwm2m_status_t ipso_control_set_value(ipso_control_t *control, uint8_t dimm_value); + +#endif /* IPSO_CONTROL_TEMPLATE_H_ */ +/** @} */ diff --git a/os/services/ipso-objects/ipso-leds-control.c b/os/services/ipso-objects/ipso-leds-control.c index 38f150f39..7023d800c 100644 --- a/os/services/ipso-objects/ipso-leds-control.c +++ b/os/services/ipso-objects/ipso-leds-control.c @@ -44,7 +44,6 @@ #include "lwm2m-object.h" #include "lwm2m-engine.h" -#include "coap-engine.h" #include "dev/leds.h" #include @@ -62,6 +61,7 @@ #define LEDS_CONTROL_NUMBER 1 #endif +#if 0 struct led_state { unsigned long last_on_time; uint32_t total_on_time; @@ -79,7 +79,7 @@ read_state(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outsize) if(idx >= LEDS_CONTROL_NUMBER) { return 0; } - return ctx->writer->write_boolean(ctx, outbuf, outsize, + return lwm2m_object_write_boolean(ctx, outbuf, outsize, states[idx].is_on ? 1 : 0); } /*---------------------------------------------------------------------------*/ @@ -95,7 +95,7 @@ write_state(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t insize, return 0; } - len = ctx->reader->read_boolean(ctx, inbuf, insize, &value); + len = lwm2m_object_read_boolean(ctx, inbuf, insize, &value); if(len > 0) { if(value) { if(!states[idx].is_on) { @@ -140,7 +140,7 @@ read_color(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outsize) return 0; } value = get_color(states[idx].led_value); - return ctx->writer->write_string(ctx, outbuf, outsize, + return lwm2m_object_write_string(ctx, outbuf, outsize, value, strlen(value)); } /*---------------------------------------------------------------------------*/ @@ -159,7 +159,7 @@ read_on_time(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outsize) states[idx].total_on_time += now - states[idx].last_on_time; states[idx].last_on_time = now; } - return ctx->writer->write_int(ctx, outbuf, outsize, + return lwm2m_object_write_int(ctx, outbuf, outsize, (int32_t)states[idx].total_on_time); } /*---------------------------------------------------------------------------*/ @@ -175,7 +175,7 @@ write_on_time(lwm2m_context_t *ctx, return 0; } - len = ctx->reader->read_int(ctx, inbuf, insize, &value); + len = lwm2m_object_read_int(ctx, inbuf, insize, &value); if(len > 0 && value == 0) { PRINTF("IPSO leds control - reset On Time\n"); states[idx].total_on_time = 0; @@ -233,4 +233,5 @@ ipso_leds_control_init(void) LEDS_CONTROL_NUMBER); } /*---------------------------------------------------------------------------*/ +#endif /* 0 */ /** @} */ diff --git a/os/services/ipso-objects/ipso-light-control.c b/os/services/ipso-objects/ipso-light-control.c index 02c4b9be2..d8575a0dc 100644 --- a/os/services/ipso-objects/ipso-light-control.c +++ b/os/services/ipso-objects/ipso-light-control.c @@ -46,6 +46,7 @@ #include "lwm2m-object.h" #include "lwm2m-engine.h" +#if 0 #ifdef IPSO_LIGHT_CONTROL extern const struct ipso_objects_actuator IPSO_LIGHT_CONTROL; #endif /* IPSO_LIGHT_CONTROL */ @@ -58,7 +59,7 @@ static uint8_t is_on = 0; static int read_state(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outsize) { - return ctx->writer->write_boolean(ctx, outbuf, outsize, is_on ? 1 : 0); + return lwm2m_object_write_boolean(ctx, outbuf, outsize, is_on ? 1 : 0); } /*---------------------------------------------------------------------------*/ static int @@ -68,7 +69,7 @@ write_state(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t insize, int value; size_t len; - len = ctx->reader->read_boolean(ctx, inbuf, insize, &value); + len = lwm2m_object_read_boolean(ctx, inbuf, insize, &value); if(len > 0) { if(value) { if(!is_on) { @@ -96,7 +97,7 @@ write_state(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t insize, static int read_dim(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outsize) { - return ctx->writer->write_int(ctx, outbuf, outsize, dim_level); + return lwm2m_object_write_int(ctx, outbuf, outsize, dim_level); } /*---------------------------------------------------------------------------*/ static int @@ -106,7 +107,7 @@ write_dim(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t insize, int32_t value; size_t len; - len = ctx->reader->read_int(ctx, inbuf, insize, &value); + len = lwm2m_object_read_int(ctx, inbuf, insize, &value); if(len > 0) { if(value < 0) { value = 0; @@ -147,7 +148,7 @@ read_on_time(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outsize) total_on_time += now - last_on_time; last_on_time = now; } - return ctx->writer->write_int(ctx, outbuf, outsize, (int32_t)total_on_time); + return lwm2m_object_write_int(ctx, outbuf, outsize, (int32_t)total_on_time); } /*---------------------------------------------------------------------------*/ static int @@ -158,7 +159,7 @@ write_on_time(lwm2m_context_t *ctx, int32_t value; size_t len; - len = ctx->reader->read_int(ctx, inbuf, insize, &value); + len = lwm2m_object_read_int(ctx, inbuf, insize, &value); if(len > 0 && value == 0) { total_on_time = 0; if(is_on) { @@ -199,4 +200,5 @@ ipso_light_control_init(void) lwm2m_engine_register_object(&light_control); } /*---------------------------------------------------------------------------*/ +#endif /* 0 */ /** @} */ diff --git a/os/services/ipso-objects/ipso-objects.c b/os/services/ipso-objects/ipso-objects.c index 1e8243f94..e73606621 100644 --- a/os/services/ipso-objects/ipso-objects.c +++ b/os/services/ipso-objects/ipso-objects.c @@ -56,11 +56,11 @@ ipso_objects_init(void) ipso_button_init(); #endif -#ifdef IPSO_LIGHT_CONTROL - ipso_light_control_init(); -#elif PLATFORM_HAS_LEDS - ipso_leds_control_init(); -#endif +/* #ifdef IPSO_LIGHT_CONTROL */ +/* ipso_light_control_init(); */ +/* #elif PLATFORM_HAS_LEDS */ +/* ipso_leds_control_init(); */ +/* #endif */ } /*---------------------------------------------------------------------------*/ /** @} */ diff --git a/os/services/ipso-objects/ipso-sensor-template.c b/os/services/ipso-objects/ipso-sensor-template.c new file mode 100644 index 000000000..02f930c60 --- /dev/null +++ b/os/services/ipso-objects/ipso-sensor-template.c @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2016, SICS Swedish ICT AB + * 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 copyright holder 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 COPYRIGHT HOLDER 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 + * COPYRIGHT HOLDER 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. + */ + +/** + * \addtogroup ipso-objects + * @{ + * + */ + +/** + * \file + * Implementation of OMA LWM2M / IPSO sensor template. + * \author + * Joakim Eriksson + * Niclas Finne + */ +#include "ipso-sensor-template.h" +#include "lwm2m-engine.h" +#include +#include + +#define IPSO_SENSOR_VALUE 5700 +#define IPSO_SENSOR_UNIT 5701 +#define IPSO_SENSOR_MIN_VALUE 5601 +#define IPSO_SENSOR_MAX_VALUE 5602 +#define IPSO_SENSOR_MIN_RANGE 5603 +#define IPSO_SENSOR_MAX_RANGE 5604 + +#define IPSO_SENSOR_RESET_MINMAX 5605 + +static const lwm2m_resource_id_t resources[] = + { + RO(IPSO_SENSOR_VALUE), RO(IPSO_SENSOR_UNIT), + RO(IPSO_SENSOR_MIN_VALUE), RO(IPSO_SENSOR_MAX_VALUE), + RO(IPSO_SENSOR_MIN_RANGE), RO(IPSO_SENSOR_MAX_RANGE), + EX(IPSO_SENSOR_RESET_MINMAX) + }; + +/*---------------------------------------------------------------------------*/ +static void update_last_value(ipso_sensor_value_t *sval, int32_t value, + uint8_t notify); +/*---------------------------------------------------------------------------*/ +static int init = 0; +static coap_timer_t nt; + +/* Currently support max 4 periodic sensors */ +#define MAX_PERIODIC 4 +struct periodic_sensor { + ipso_sensor_value_t *value; + uint16_t ticks_left; +} periodics[MAX_PERIODIC]; + +static void +timer_callback(coap_timer_t *timer) +{ + int i; + coap_timer_reset(timer, 1000); + + for(i = 0; i < MAX_PERIODIC; i++) { + if(periodics[i].value != NULL) { + if(periodics[i].ticks_left > 0) { + periodics[i].ticks_left--; + } else { + int32_t value; + periodics[i].ticks_left = periodics[i].value->sensor->update_interval; + if(periodics[i].value->sensor->get_value_in_millis(periodics[i].value->sensor, &value) == LWM2M_STATUS_OK) { + update_last_value(periodics[i].value, value, 1); + } + } + } + } +} + +static void +add_periodic(const ipso_sensor_t *sensor) +{ + int i; + for(i = 0; i < MAX_PERIODIC; i++) { + if(periodics[i].value == NULL) { + periodics[i].value = sensor->sensor_value; + periodics[i].ticks_left = sensor->update_interval; + return; + } + } +} +/*---------------------------------------------------------------------------*/ +static void +update_last_value(ipso_sensor_value_t *sval, int32_t value, uint8_t notify) +{ + /* No notification if this a regular read that cause the update */ + if(sval->last_value != value && notify) { + lwm2m_notify_object_observers(&sval->reg_object, IPSO_SENSOR_VALUE); + } + sval->last_value = value; + if(sval->min_value > value) { + sval->min_value = value; + lwm2m_notify_object_observers(&sval->reg_object, IPSO_SENSOR_MIN_VALUE); + } + if(sval->max_value < value) { + sval->max_value = value; + lwm2m_notify_object_observers(&sval->reg_object, IPSO_SENSOR_MAX_VALUE); + } +} +/*---------------------------------------------------------------------------*/ +static inline size_t +write_float32fix(lwm2m_context_t *ctx, int32_t value) +{ + int64_t tmp = value; + tmp = (tmp * 1024) / 1000; + return lwm2m_object_write_float32fix(ctx, (int32_t)tmp, 10); +} +/*---------------------------------------------------------------------------*/ +static lwm2m_status_t +lwm2m_callback(lwm2m_object_instance_t *object, + lwm2m_context_t *ctx) +{ + /* Here we cast to our sensor-template struct */ + const ipso_sensor_t *sensor; + ipso_sensor_value_t *value; + value = (ipso_sensor_value_t *) object; + sensor = value->sensor; + + /* Do the stuff */ + if(ctx->level == 1) { + /* Should not happen 3303 */ + return LWM2M_STATUS_ERROR; + } + if(ctx->level == 2) { + /* This is a get whole object - or write whole object 3303/0 */ + return LWM2M_STATUS_ERROR; + } + if(ctx->level == 3) { + /* This is a get request on 3303/0/3700 */ + /* NOW we assume a get.... which might be wrong... */ + if(ctx->operation == LWM2M_OP_READ) { + switch(ctx->resource_id) { + case IPSO_SENSOR_UNIT: + if(sensor->unit != NULL) { + lwm2m_object_write_string(ctx, sensor->unit, strlen(sensor->unit)); + } + break; + case IPSO_SENSOR_MAX_RANGE: + write_float32fix(ctx, sensor->max_range); + break; + case IPSO_SENSOR_MIN_RANGE: + write_float32fix(ctx, sensor->min_range); + break; + case IPSO_SENSOR_MAX_VALUE: + write_float32fix(ctx, value->max_value); + break; + case IPSO_SENSOR_MIN_VALUE: + write_float32fix(ctx, value->min_value); + break; + case IPSO_SENSOR_VALUE: + if(sensor->get_value_in_millis != NULL) { + int32_t v; + if(sensor->get_value_in_millis(sensor, &v) == LWM2M_STATUS_OK) { + update_last_value(value, v, 0); + write_float32fix(ctx, value->last_value); + } + } + break; + default: + return LWM2M_STATUS_ERROR; + } + } else if(ctx->operation == LWM2M_OP_EXECUTE) { + if(ctx->resource_id == IPSO_SENSOR_RESET_MINMAX) { + value->min_value = value->last_value; + value->max_value = value->last_value; + } + } + } + return LWM2M_STATUS_OK; +} +/*---------------------------------------------------------------------------*/ +int +ipso_sensor_add(const ipso_sensor_t *sensor) +{ + if(sensor->update_interval > 0) { + if(init == 0) { + coap_timer_set_callback(&nt, timer_callback); + coap_timer_set(&nt, 1000); + init = 1; + } + add_periodic(sensor); + } + + if(sensor->sensor_value == NULL) { + return 0; + } + sensor->sensor_value->reg_object.object_id = sensor->object_id; + sensor->sensor_value->sensor = sensor; + if(sensor->instance_id == 0) { + sensor->sensor_value->reg_object.instance_id = LWM2M_OBJECT_INSTANCE_NONE; + } else { + sensor->sensor_value->reg_object.instance_id = sensor->instance_id; + } + sensor->sensor_value->reg_object.callback = lwm2m_callback; + sensor->sensor_value->reg_object.resource_ids = resources; + sensor->sensor_value->reg_object.resource_count = + sizeof(resources) / sizeof(lwm2m_resource_id_t); + return lwm2m_engine_add_object(&sensor->sensor_value->reg_object); +} +/*---------------------------------------------------------------------------*/ +int +ipso_sensor_remove(const ipso_sensor_t *sensor) +{ + lwm2m_engine_remove_object(&sensor->sensor_value->reg_object); + return 1; +} +/*---------------------------------------------------------------------------*/ diff --git a/os/services/ipso-objects/ipso-sensor-template.h b/os/services/ipso-objects/ipso-sensor-template.h new file mode 100644 index 000000000..ce13effcb --- /dev/null +++ b/os/services/ipso-objects/ipso-sensor-template.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2016, SICS Swedish ICT AB + * 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 copyright holder 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 COPYRIGHT HOLDER 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 + * COPYRIGHT HOLDER 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. + */ + +/** + * \addtogroup ipso-objects + * @{ + * + */ + +/** + * \file + * Implementation of OMA LWM2M / IPSO sensor template. + * \author + * Joakim Eriksson + * Niclas Finne + */ + +#ifndef IPSO_SENSOR_TEMPLATE_H_ +#define IPSO_SENSOR_TEMPLATE_H_ + +#include "lwm2m-engine.h" + +typedef struct ipso_sensor ipso_sensor_t; + +typedef lwm2m_status_t (*ipso_sensor_get_value_millis_t)(const ipso_sensor_t *sensor, int32_t *v); + +/* Values of the IPSO object */ +typedef struct ipso_sensor_value { + lwm2m_object_instance_t reg_object; + const ipso_sensor_t *sensor; + uint8_t flags; + int32_t last_value; + int32_t min_value; + int32_t max_value; +} ipso_sensor_value_t; + +/* Meta data about an IPSO sensor object */ +struct ipso_sensor { + /* LWM2M object type */ + uint16_t object_id; + uint16_t instance_id; + /* When we read out the value we send in a context to write to */ + ipso_sensor_get_value_millis_t get_value_in_millis; + int32_t min_range; + int32_t max_range; + char *unit; + /* update interval in seconds */ + uint16_t update_interval; + ipso_sensor_value_t *sensor_value; +}; + + +int ipso_sensor_add(const ipso_sensor_t *sensor); +int ipso_sensor_remove(const ipso_sensor_t *sensor); + +#endif /* IPSO_SENSOR_TEMPLATE_H_ */ diff --git a/os/services/ipso-objects/ipso-temperature.c b/os/services/ipso-objects/ipso-temperature.c index 1851245e2..c1b7748e3 100644 --- a/os/services/ipso-objects/ipso-temperature.c +++ b/os/services/ipso-objects/ipso-temperature.c @@ -42,118 +42,60 @@ */ #include +#include "ipso-sensor-template.h" #include "ipso-objects.h" #include "lwm2m-object.h" #include "lwm2m-engine.h" -#include "coap-engine.h" #ifdef IPSO_TEMPERATURE extern const struct ipso_objects_sensor IPSO_TEMPERATURE; #endif /* IPSO_TEMPERATURE */ #ifndef IPSO_TEMPERATURE_MIN -#define IPSO_TEMPERATURE_MIN (-50 * LWM2M_FLOAT32_FRAC) +#define IPSO_TEMPERATURE_MIN -50000 #endif #ifndef IPSO_TEMPERATURE_MAX -#define IPSO_TEMPERATURE_MAX (80 * LWM2M_FLOAT32_FRAC) +#define IPSO_TEMPERATURE_MAX 80000 #endif -static struct ctimer periodic_timer; -static int32_t min_temp; -static int32_t max_temp; -static int read_temp(int32_t *value); +lwm2m_status_t get_temp_value(const ipso_sensor_t *sensor, int32_t *value); + +static ipso_sensor_value_t temp_value; + +static const ipso_sensor_t temp_sensor = { + .object_id = 3303, + .sensor_value = &temp_value, + .max_range = IPSO_TEMPERATURE_MAX, /* milli celcius */ + .min_range = IPSO_TEMPERATURE_MIN, /* milli celcius */ + .get_value_in_millis = get_temp_value, + .unit = "Cel", + .update_interval = 10 +}; + /*---------------------------------------------------------------------------*/ -static int -temp(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outsize) -{ - int32_t value; - if(read_temp(&value)) { - return ctx->writer->write_float32fix(ctx, outbuf, outsize, - value, LWM2M_FLOAT32_BITS); - } - return 0; -} -/*---------------------------------------------------------------------------*/ -LWM2M_RESOURCES(temperature_resources, - /* Temperature (Current) */ - LWM2M_RESOURCE_CALLBACK(5700, { temp, NULL, NULL }), - /* Units */ - LWM2M_RESOURCE_STRING(5701, "Cel"), - /* Min Range Value */ - LWM2M_RESOURCE_FLOATFIX(5603, IPSO_TEMPERATURE_MIN), - /* Max Range Value */ - LWM2M_RESOURCE_FLOATFIX(5604, IPSO_TEMPERATURE_MAX), - /* Min Measured Value */ - LWM2M_RESOURCE_FLOATFIX_VAR(5601, &min_temp), - /* Max Measured Value */ - LWM2M_RESOURCE_FLOATFIX_VAR(5602, &max_temp), - ); -LWM2M_INSTANCES(temperature_instances, - LWM2M_INSTANCE(0, temperature_resources)); -LWM2M_OBJECT(temperature, 3303, temperature_instances); -/*---------------------------------------------------------------------------*/ -static int -read_temp(int32_t *value) +lwm2m_status_t +get_temp_value(const ipso_sensor_t *s, int32_t *value) { #ifdef IPSO_TEMPERATURE - int32_t temp; if(IPSO_TEMPERATURE.read_value == NULL || - IPSO_TEMPERATURE.read_value(&temp) != 0) { - return 0; + IPSO_TEMPERATURE.read_value(value) != 0) { + return LWM2M_STATUS_OK; } - - /* Convert milliCelsius to fix float */ - *value = (temp * LWM2M_FLOAT32_FRAC) / 1000; - - if(*value < min_temp) { - min_temp = *value; - lwm2m_object_notify_observers(&temperature, "/0/5601"); - } - if(*value > max_temp) { - max_temp = *value; - lwm2m_object_notify_observers(&temperature, "/0/5602"); - } - return 1; -#else /* IPSO_TEMPERATURE */ - return 0; #endif /* IPSO_TEMPERATURE */ -} -/*---------------------------------------------------------------------------*/ -static void -handle_periodic_timer(void *ptr) -{ - static int32_t last_value = IPSO_TEMPERATURE_MIN; - int32_t v; - - /* Only notify when the value has changed since last */ - if(read_temp(&v) && v != last_value) { - last_value = v; - lwm2m_object_notify_observers(&temperature, "/0/5700"); - } - ctimer_reset(&periodic_timer); + return LWM2M_STATUS_ERROR; } /*---------------------------------------------------------------------------*/ void ipso_temperature_init(void) { - int32_t v; - min_temp = IPSO_TEMPERATURE_MAX; - max_temp = IPSO_TEMPERATURE_MIN; - #ifdef IPSO_TEMPERATURE if(IPSO_TEMPERATURE.init) { IPSO_TEMPERATURE.init(); } #endif /* IPSO_TEMPERATURE */ - /* register this device and its handlers - the handlers automatically - sends in the object to handle */ - lwm2m_engine_register_object(&temperature); - - /* update temp and min/max + notify any listeners */ - read_temp(&v); - ctimer_set(&periodic_timer, CLOCK_SECOND * 10, handle_periodic_timer, NULL); + ipso_sensor_add(&temp_sensor); } /*---------------------------------------------------------------------------*/ /** @} */ From e7edd147a98b08b4dbb8a3cdfb4fe223edae8916 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Wed, 25 Oct 2017 03:12:54 +0200 Subject: [PATCH 05/51] Imported LWM2M standalone example from lwm2m-contiki at https://github.com/sics-iot/lwm2m-contiki --- examples/lwm2m/standalone/.gitignore | 3 + examples/lwm2m/standalone/Hex2DTLS.java | 141 +++++ examples/lwm2m/standalone/Hex2UDP.java | 139 ++++ examples/lwm2m/standalone/Makefile | 61 ++ examples/lwm2m/standalone/Makefile.contiki | 53 ++ examples/lwm2m/standalone/README.md | 68 ++ examples/lwm2m/standalone/coap-hex/coap-hex.c | 427 +++++++++++++ examples/lwm2m/standalone/coap-hex/coap-hex.h | 51 ++ .../lwm2m/standalone/coap-ipv4/coap-ipv4.c | 597 ++++++++++++++++++ .../lwm2m/standalone/coap-ipv4/coap-ipv4.h | 51 ++ examples/lwm2m/standalone/contiki.h | 60 ++ .../lwm2m/standalone/generic-object-test.c | 193 ++++++ examples/lwm2m/standalone/ipso-control-test.c | 93 +++ examples/lwm2m/standalone/ipso-sensor-temp.c | 119 ++++ examples/lwm2m/standalone/lwm2m-example.c | 200 ++++++ examples/lwm2m/standalone/posix-coap-timer.c | 106 ++++ examples/lwm2m/standalone/posix-main.c | 213 +++++++ examples/lwm2m/standalone/posix-main.h | 55 ++ .../tinydtls-support/dtls-support-conf.h | 57 ++ .../tinydtls-support/dtls-support.c | 302 +++++++++ 20 files changed, 2989 insertions(+) create mode 100644 examples/lwm2m/standalone/.gitignore create mode 100644 examples/lwm2m/standalone/Hex2DTLS.java create mode 100644 examples/lwm2m/standalone/Hex2UDP.java create mode 100644 examples/lwm2m/standalone/Makefile create mode 100644 examples/lwm2m/standalone/Makefile.contiki create mode 100644 examples/lwm2m/standalone/README.md create mode 100644 examples/lwm2m/standalone/coap-hex/coap-hex.c create mode 100644 examples/lwm2m/standalone/coap-hex/coap-hex.h create mode 100644 examples/lwm2m/standalone/coap-ipv4/coap-ipv4.c create mode 100644 examples/lwm2m/standalone/coap-ipv4/coap-ipv4.h create mode 100644 examples/lwm2m/standalone/contiki.h create mode 100644 examples/lwm2m/standalone/generic-object-test.c create mode 100644 examples/lwm2m/standalone/ipso-control-test.c create mode 100644 examples/lwm2m/standalone/ipso-sensor-temp.c create mode 100644 examples/lwm2m/standalone/lwm2m-example.c create mode 100644 examples/lwm2m/standalone/posix-coap-timer.c create mode 100644 examples/lwm2m/standalone/posix-main.c create mode 100644 examples/lwm2m/standalone/posix-main.h create mode 100644 examples/lwm2m/standalone/tinydtls-support/dtls-support-conf.h create mode 100644 examples/lwm2m/standalone/tinydtls-support/dtls-support.c diff --git a/examples/lwm2m/standalone/.gitignore b/examples/lwm2m/standalone/.gitignore new file mode 100644 index 000000000..f1e834bc0 --- /dev/null +++ b/examples/lwm2m/standalone/.gitignore @@ -0,0 +1,3 @@ +*.o +oma-lwm2m-src +lwm2m-example diff --git a/examples/lwm2m/standalone/Hex2DTLS.java b/examples/lwm2m/standalone/Hex2DTLS.java new file mode 100644 index 000000000..8bb381100 --- /dev/null +++ b/examples/lwm2m/standalone/Hex2DTLS.java @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2016, SICS, Swedish ICT AB. + * 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. + */ + +/** + * \file + * A Java IPv4 transport for CoAP + LWM2M + * Converts hex input to DTLS/UDP packets and incoming packets to + * hex out. + * + * Note: This needs the eclipse scandium DTLS implementation to work. + * The example use PSK and the keys according to the code. This needs + * to be configured in Leshan for it to accept the device. + * \author + * Joakim Eriksson + * Niclas Finne + */ +import javax.xml.bind.DatatypeConverter; +import java.net.DatagramSocket; +import java.net.DatagramPacket; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.io.IOException; +import java.util.Arrays; +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.InputStream; +import java.io.PrintStream; + +import org.eclipse.californium.scandium.dtls.pskstore.StaticPskStore; +import org.eclipse.californium.scandium.config.DtlsConnectorConfig; +import org.eclipse.californium.scandium.DTLSConnector; +import org.eclipse.californium.elements.RawData; +import org.eclipse.californium.elements.RawDataChannel; + + +public class Hex2DTLS { + + DTLSConnector dtlsConnector; + InetAddress address; + int port; + + Hex2DTLS(String host, int port) { + try { + DtlsConnectorConfig.Builder builder = new DtlsConnectorConfig.Builder(new InetSocketAddress(0)); + builder.setPskStore(new StaticPskStore("Client_Identity", "secretPSK".getBytes())); + builder.setClientOnly(); + dtlsConnector = new DTLSConnector(builder.build(), null); + dtlsConnector.setRawDataReceiver(new RawDataChannel() { + public void receiveData(final RawData raw) { + receive(raw.getBytes()); + } + }); + dtlsConnector.start(); + + this.address = InetAddress.getByName(host); + this.port = port; + } catch(Exception e) { + e.printStackTrace(); + } + } + + public void send(byte[] data) throws IOException { + RawData rawData = new RawData(data, address, port); + dtlsConnector.send(rawData); + } + + /* Override this to make something more sensible with the data */ + public void receive(byte[] data) { + String s = DatatypeConverter.printHexBinary(data); + System.out.println("COAPHEX:" + s); + } + + /* Loop on std in to get lines of hex to send */ + public static void main(String[] args) throws IOException { + InputStream in = System.in; + final PrintStream out; + System.err.println("Connecting to " + args[0]); + if(args.length > 1) { + Runtime rt = Runtime.getRuntime(); + Process pr = rt.exec(args[1]); + System.err.println("Started " + args[1]); + in = pr.getInputStream(); + out = new PrintStream(pr.getOutputStream()); + } else { + out = System.out; + } + + /* Create a Hex2DTLS that print on this out stream . CoAPs Port*/ + Hex2DTLS udpc = new Hex2DTLS(args[0], 5684) { + public void receive(byte[] data) { + String s = DatatypeConverter.printHexBinary(data); + out.println("COAPHEX:" + s); + out.flush(); + System.err.println("IN: " + s); + } + }; + + BufferedReader buffer = + new BufferedReader(new InputStreamReader(in)); + + /* The read loop */ + while(true) { + String line = buffer.readLine(); + if(line == null) { + /* Connection closed */ + System.err.println("*** stdin closed"); + System.exit(0); + } else if (line.startsWith("COAPHEX:")) { + byte[] data = DatatypeConverter.parseHexBinary(line.substring(8)); + udpc.send(data); + } + System.err.println("OUT:" + line); + } + } +} diff --git a/examples/lwm2m/standalone/Hex2UDP.java b/examples/lwm2m/standalone/Hex2UDP.java new file mode 100644 index 000000000..d084d7d24 --- /dev/null +++ b/examples/lwm2m/standalone/Hex2UDP.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2016, SICS, Swedish ICT AB. + * 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. + */ + +/** + * \file + * A Java IPv4 transport for CoAP + LWM2M + * Converts hex input to UDP packets and incoming packets to hex out. + * \author + * Joakim Eriksson + * Niclas Finne + */ +import javax.xml.bind.DatatypeConverter; +import java.net.DatagramSocket; +import java.net.DatagramPacket; +import java.net.InetAddress; +import java.io.IOException; +import java.util.Arrays; +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.InputStream; +import java.io.PrintStream; + +public class Hex2UDP implements Runnable { + + DatagramSocket serverSocket; + InetAddress address; + int port; + + Hex2UDP(String host, int port) { + try { + serverSocket = new DatagramSocket(); + this.address = InetAddress.getByName(host); + this.port = port; + new Thread(this).start(); + } catch(Exception e) { + /* Do good stuff here... */ + e.printStackTrace(); + } + } + + public void run() { + byte[] receiveData = new byte[1024]; + /* The receive loop */ + while(true) { + DatagramPacket receivePacket = + new DatagramPacket(receiveData, receiveData.length); + try { + /* Receive a packet */ + serverSocket.receive(receivePacket); + } catch (IOException e) { + e.printStackTrace(); + } + byte[] data2 = Arrays.copyOf(receivePacket.getData(), + receivePacket.getLength()); + receive(data2); + } + } + + public void send(byte[] data) throws IOException { + DatagramPacket sendPacket = + new DatagramPacket(data, data.length, address, port); + serverSocket.send(sendPacket); + } + + /* Override this to make something more sensible with the data */ + public void receive(byte[] data) { + String s = DatatypeConverter.printHexBinary(data); + System.out.println("COAPHEX:" + s); + } + + /* Loop on std in to get lines of hex to send */ + public static void main(String[] args) throws IOException { + InputStream in = System.in; + final PrintStream out; + System.err.println("Connecting to " + args[0]); + if(args.length > 2) { + Runtime rt = Runtime.getRuntime(); + Process pr = rt.exec(args[2]); + System.err.println("Started " + args[2]); + in = pr.getInputStream(); + out = new PrintStream(pr.getOutputStream()); + } else { + out = System.out; + } + + /* Create a Hex2UDP that print on this out stream */ + Hex2UDP udpc = new Hex2UDP(args[0], Integer.parseInt(args[1])) { + public void receive(byte[] data) { + String s = DatatypeConverter.printHexBinary(data); + out.println("COAPHEX:" + s); + out.flush(); + System.err.println("IN: " + s); + } + }; + + BufferedReader buffer = + new BufferedReader(new InputStreamReader(in)); + + /* The read loop */ + while(true) { + String line = buffer.readLine(); + if(line == null) { + /* Connection closed */ + System.err.println("*** stdin closed"); + System.exit(0); + } else if (line.startsWith("COAPHEX:")) { + byte[] data = DatatypeConverter.parseHexBinary(line.substring(8)); + udpc.send(data); + } + System.err.println("OUT:" + line); + } + } +} diff --git a/examples/lwm2m/standalone/Makefile b/examples/lwm2m/standalone/Makefile new file mode 100644 index 000000000..03a8fda23 --- /dev/null +++ b/examples/lwm2m/standalone/Makefile @@ -0,0 +1,61 @@ +PROJECT = lwm2m-example + +all: $(PROJECT) + +TARGETCDIR = oma-lwm2m-src +COREDIRS = sys lib +SOURCEDIRS = . +SOURCE_FILES = posix-main.c posix-coap-timer.c ipso-sensor-temp.c \ + ipso-control-test.c generic-object-test.c +APPSDIRS = coap lwm2m ipso-objects + +ifneq ($(MAKE_WITH_DTLS),) + CFLAGS += -DWITH_DTLS=1 + TINYDTLS_DIRS = aes ecc sha2 + APPSDIRS += tinydtls ${addprefix tinydtls/,$(TINYDTLS_DIRS)} + SOURCE_FILES += dtls-support.c + SOURCEDIRS += tinydtls-support +endif + +TARGETCDIRS += ${addprefix $(TARGETCDIR)/,$(COREDIRS) $(APPSDIRS)} +SOURCEDIRS += ${addprefix $(TARGETCDIR)/,. $(APPSDIRS)} + +CFLAGS += -Wall -Werror +CFLAGS += ${addprefix -I,$(SOURCEDIRS)} + +TRANSPORT ?= ipv4 +ifeq ($(TRANSPORT),ipv4) + TRANSPORTDIR = coap-ipv4 + CFLAGS += -DWITH_COAP_IPV4=1 -DCOAP_TRANSPORT_CONF_H=\"coap-ipv4.h\" +else ifeq ($(TRANSPORT),hex) + TRANSPORTDIR = coap-hex + CFLAGS += -DWITH_COAP_HEX=1 -DCOAP_TRANSPORT_CONF_H=\"coap-hex.h\" +else + ${error Unknown CoAP transport: $(TRANSPORT)} +endif + +SOURCEDIRS += $(TRANSPORTDIR) +SOURCE_FILES += ${notdir ${wildcard $(TRANSPORTDIR)/*.c}} + +vpath %.c $(SOURCEDIRS) + +-include Makefile.contiki + +ifndef OBJECT_FILES + SOURCE_FILES += ${wildcard ${addsuffix /*.c,$(TARGETCDIRS)} } + OBJECT_FILES = $(SOURCE_FILES:.c=.o) +endif + +$(PROJECT): $(PROJECT).c $(OBJECT_FILES) + $(CC) $(CFLAGS) -o $@ $(PROJECT).c $(OBJECT_FILES) + +lib: liblwm2m.a + +clean:: + @-rm -f $(OBJECT_FILES) *.o liblwm2m.a $(PROJECT) + +liblwm2m.a: $(OBJECT_FILES) + $(AR) rvs $@ $(OBJECT_FILES) + +%.o: %.c + $(CC) $(CFLAGS) -c $< -o $@ diff --git a/examples/lwm2m/standalone/Makefile.contiki b/examples/lwm2m/standalone/Makefile.contiki new file mode 100644 index 000000000..ecd46311a --- /dev/null +++ b/examples/lwm2m/standalone/Makefile.contiki @@ -0,0 +1,53 @@ +CONTIKI = ../../.. +CP=cp +MKDIR=mkdir + +DTLS_PATH := $(CONTIKI)/os/net/security +CORE_FILES = sys/cc.h sys/cc-gcc.h lib/list.c lib/memb.c +COAP_FILES = ${addprefix coap/,${filter-out coap-blocking-api.% coap-uip.% coap-timer-default.%,${notdir ${wildcard $(CONTIKI)/os/net/app-layer/coap/coap*}}}} +LWM2M_FILES = ${addprefix lwm2m/,${filter-out ,${notdir ${wildcard $(CONTIKI)/os/services/lwm2m/lwm2m-*}}}} +IPSO_FILES = ${addprefix ipso-objects/,${filter-out ipso-leds-control.c ipso-objects.% ipso-temperature.% ipso-light-control.% ipso-button.c,${notdir ${wildcard $(CONTIKI)/os/services/ipso-objects/ipso-*}}}} +TARGET_FILES += ${addprefix $(TARGETCDIR)/,$(CORE_FILES) $(CORE_FILES:.c=.h) \ + $(COAP_FILES) $(LWM2M_FILES) $(IPSO_FILES)} + +ifneq ($(MAKE_WITH_DTLS),) + DTLS_FILES = ${subst $(DTLS_PATH)/,,${wildcard ${addprefix $(DTLS_PATH)/tinydtls/,*.[ch] ${addsuffix /*.[ch],$(TINYDTLS_DIRS)}}}} + TARGET_FILES += ${addprefix $(TARGETCDIR)/,$(DTLS_FILES)} +endif + +SOURCE_FILES += ${filter %.c,$(TARGET_FILES)} +OBJECT_FILES = $(SOURCE_FILES:.c=.o) + +$(TARGETCDIR): + @$(MKDIR) $@ + +$(TARGETCDIRS): $(TARGETCDIR) + @$(MKDIR) $@ + +$(TARGETCDIR)/sys/%: $(CONTIKI)/os/sys/% | $(TARGETCDIRS) + @$(CP) -av $^ $@ + +$(TARGETCDIR)/lib/%: $(CONTIKI)/os/lib/% | $(TARGETCDIRS) + @$(CP) -av $^ $@ + +$(TARGETCDIR)/coap/%: $(CONTIKI)/os/net/app-layer/coap/% | $(TARGETCDIRS) + @$(CP) -av $^ $@ + +$(TARGETCDIR)/lwm2m/%: $(CONTIKI)/os/services/lwm2m/% | $(TARGETCDIRS) + @$(CP) -av $^ $@ + +$(TARGETCDIR)/ipso-objects/%: $(CONTIKI)/os/services/ipso-objects/% | $(TARGETCDIRS) + @$(CP) -av $^ $@ + +$(TARGETCDIR)/tinydtls/%.c: $(DTLS_PATH)/tinydtls/%.c | $(TARGETCDIRS) + @$(CP) -av $^ $@ + +$(TARGETCDIR)/tinydtls/%.h: $(DTLS_PATH)/tinydtls/%.h | $(TARGETCDIRS) + @$(CP) -av $^ $@ + +$(OBJECT_FILES): $(TARGET_FILES) + +copy: $(TARGET_FILES) + +clean:: + @-rm -rf $(TARGETCDIR) diff --git a/examples/lwm2m/standalone/README.md b/examples/lwm2m/standalone/README.md new file mode 100644 index 000000000..2a582645f --- /dev/null +++ b/examples/lwm2m/standalone/README.md @@ -0,0 +1,68 @@ +OMA LWM2M Standalone Example +==================================== + +This is an example of how to make use of the OMA LWM2M and CoAP +implementation from Contiki in a native application. + +The Makefile will copy necessary files from Contiki to the subfolder +```oma-lwm2m-src``` and then compile the example ```lwm2m-example``` +as a native application. By copying only the needed source files, +the example can be used outside the Contiki source tree. + +### Running the OMA LWM2M example + +```bash +cd contiki/examples/oma-lwm2m/standalone +make +./lwm2m-example +``` + +The example application will start a CoAP server listening on +localhost port 5683 with an example OMA LWM2M device object. + + +### Testing the OMA LWM2M example + +The Copper (Cu) Firefox addon can be used to access the LWM2M example. + +1. Start the OMA LWM2M example as described above. + +2. Get the Copper (Cu) CoAP user-agent from +[https://addons.mozilla.org/en-US/firefox/addon/copper-270430](https://addons.mozilla.org/en-US/firefox/addon/copper-270430). + +3. Start Copper and discover resources at coap://127.0.0.1:5683/ + It should find three objects named 0, 1, and 3. + +4. Browse to the device type resource at coap://127.0.0.1:5683/3/0/17 + (object 3, instance 0, resource 17) and then click ```GET```. + As device type the LWM2M example should return the text "lwm2m-example". + +5. Browse to the time resource at coap://127.0.0.1:5683/3/0/13 + Every time you click ```GET```, it should return the number of seconds + since the example application was started. + +### Moving the example outside Contiki + +```bash +cd contiki/examples/oma-lwm2m/standalone +make copy +``` + +Copy the example directory contents to a directory outside Contiki. +Remove the Makefile ```Makefile.contiki``` and the remaining Makefile +will compile the example independent of the Contiki source tree. + + +The Hex Transport can be tested together with DTLS using: + +```bash +make clean +make TRANSPORT=hex MAKE_WITH_DTLS=1 +javac Hex2UDP.java +java Hex2UDP leshan.eclipse.org 5684 ./lwm2m-example +``` + +Note that you need to configure the Leshan server with the correct +key and ID. + +(without DTLS it should be 5683 for CoAP) diff --git a/examples/lwm2m/standalone/coap-hex/coap-hex.c b/examples/lwm2m/standalone/coap-hex/coap-hex.c new file mode 100644 index 000000000..67e887619 --- /dev/null +++ b/examples/lwm2m/standalone/coap-hex/coap-hex.c @@ -0,0 +1,427 @@ +/* + * Copyright (c) 2016, SICS, Swedish ICT AB. + * 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. + */ + +/** + * \file + * A HEX text transport for CoAP + * \author + * Niclas Finne + * Joakim Eriksson + */ + +#include "coap.h" +#include "coap-endpoint.h" +#include "coap-engine.h" +#include +#include +#include + +#define DEBUG 0 +#if DEBUG +#define PRINTF(...) printf(__VA_ARGS__) +#define PRINTEP(ep) coap_endpoint_print(ep) +#else +#define PRINTF(...) +#define PRINTEP(ep) +#endif + +#ifdef WITH_DTLS +#include "tinydtls.h" +#include "dtls.h" +#include "dtls_debug.h" +#endif /* WITH_DTLS */ + +#define BUFSIZE 1280 + +typedef union { + uint32_t u32[(BUFSIZE + 3) / 4]; + uint8_t u8[BUFSIZE]; +} coap_buf_t; + +static coap_endpoint_t last_source; +static coap_buf_t coap_aligned_buf; +static uint16_t coap_buf_len; + +#ifdef WITH_DTLS +#define PSK_DEFAULT_IDENTITY "Client_identity" +#define PSK_DEFAULT_KEY "secretPSK" + +static dtls_handler_t cb; +static dtls_context_t *dtls_context = NULL; + +/* The PSK information for DTLS */ +#define PSK_ID_MAXLEN 256 +#define PSK_MAXLEN 256 +static unsigned char psk_id[PSK_ID_MAXLEN]; +static size_t psk_id_length = 0; +static unsigned char psk_key[PSK_MAXLEN]; +static size_t psk_key_length = 0; +#endif /* WITH_DTLS */ + +/*---------------------------------------------------------------------------*/ +static const coap_endpoint_t * +coap_src_endpoint(void) +{ + return &last_source; +} +/*---------------------------------------------------------------------------*/ +void +coap_endpoint_copy(coap_endpoint_t *destination, const coap_endpoint_t *from) +{ + memcpy(destination, from, sizeof(coap_endpoint_t)); +} +/*---------------------------------------------------------------------------*/ +int +coap_endpoint_cmp(const coap_endpoint_t *e1, const coap_endpoint_t *e2) +{ + return e1->addr == e2->addr; +} +/*---------------------------------------------------------------------------*/ +void +coap_endpoint_print(const coap_endpoint_t *ep) +{ + printf("%u", ep->addr); +} +/*---------------------------------------------------------------------------*/ +int +coap_endpoint_parse(const char *text, size_t size, coap_endpoint_t *ep) +{ + /* Hex based CoAP has no addresses, just writes data to standard out */ + ep->addr = last_source.addr; +#ifdef WITH_DTLS + ep->secure = 1; +#endif /* WITH_DTLS */ + return 1; +} +/*---------------------------------------------------------------------------*/ +uint8_t * +coap_databuf(void) +{ + return coap_aligned_buf.u8; +} +/*---------------------------------------------------------------------------*/ +uint16_t +coap_datalen() +{ + return coap_buf_len; +} +/*---------------------------------------------------------------------------*/ +static int +hextod(char c) +{ + if(c >= '0' && c <= '9') { + return c - '0'; + } + if(c >= 'a' && c <= 'f') { + return c - 'a' + 10; + } + if(c >= 'A' && c <= 'F') { + return c - 'A' + 10; + } + return -1; +} +/*---------------------------------------------------------------------------*/ +static void +stdin_callback(const char *line) +{ + uint8_t *buf; + int i, len, llen, v1, v2; + + if(strncmp("COAPHEX:", line, 8) != 0) { + /* Not a CoAP message */ + return; + } + + line += 8; + llen = strlen(line); + if((llen & 1) != 0) { + /* Odd number of characters - not hex */ + fprintf(stderr, "ERROR: %s\n", line); + return; + } + + buf = coap_databuf(); + for(i = 0, len = 0; i < llen; i += 2, len++) { + v1 = hextod(line[i]); + v2 = hextod(line[i + 1]); + if(v1 < 0 || v2 < 0) { + /* Not hex */ + fprintf(stderr, "ERROR: %s\n", line); + return; + } + buf[len] = (uint8_t)(((v1 << 4) | v2) & 0xff); + } + + PRINTF("RECV from "); + PRINTEP(&last_source); + PRINTF(" %u bytes\n", len); + coap_buf_len = len; + + if(DEBUG) { + int i; + uint8_t *data; + data = coap_databuf(); + printf("Received:"); + for(i = 0; i < len; i++) { + printf("%02x", data[i]); + } + printf("\n"); + } + +#ifdef WITH_DTLS + /* DTLS receive??? */ + last_source.secure = 1; + dtls_handle_message(dtls_context, (coap_endpoint_t *) coap_src_endpoint(), coap_databuf(), coap_datalen()); +#else + coap_receive(coap_src_endpoint(), coap_databuf(), coap_datalen()); +#endif /* WITH_DTLS */ +} +/*---------------------------------------------------------------------------*/ +void +coap_transport_init(void) +{ + select_set_stdin_callback(stdin_callback); + + printf("CoAP listening on standard in\n"); + +#ifdef WITH_DTLS + /* create new contet with app-data - no real app-data... */ + dtls_context = dtls_new_context(&last_source); + if (!dtls_context) { + PRINTF("DTLS: cannot create context\n"); + exit(-1); + } + +#ifdef DTLS_PSK + psk_id_length = strlen(PSK_DEFAULT_IDENTITY); + psk_key_length = strlen(PSK_DEFAULT_KEY); + memcpy(psk_id, PSK_DEFAULT_IDENTITY, psk_id_length); + memcpy(psk_key, PSK_DEFAULT_KEY, psk_key_length); +#endif /* DTLS_PSK */ + PRINTF("Setting DTLS handler\n"); + dtls_set_handler(dtls_context, &cb); +#endif /* WITH_DTLS */ + +} +/*---------------------------------------------------------------------------*/ +void +coap_send_message(const coap_endpoint_t *ep, const uint8_t *data, uint16_t len) +{ + if(!coap_endpoint_is_connected(ep)) { + PRINTF("CoAP endpoint not connected\n"); + return; + } + +#ifdef WITH_DTLS + if(coap_endpoint_is_secure(ep)) { + dtls_write(dtls_context, (session_t *)ep, (uint8_t *)data, len); + return; + } +#endif /* WITH_DTLS */ + + int i; + printf("COAPHEX:"); + for(i = 0; i < len; i++) { + printf("%02x", data[i]); + } + printf("\n"); +} +/*---------------------------------------------------------------------------*/ +int +coap_endpoint_connect(coap_endpoint_t *ep) +{ + if(ep->secure == 0) { + return 1; + } +#ifdef WITH_DTLS + PRINTF("DTLS EP:"); + PRINTEP(ep); + PRINTF(" len:%d\n", ep->size); + + /* setup all address info here... should be done to connect */ + + dtls_connect(dtls_context, ep); +#endif /* WITH_DTLS */ + return 1; +} +/*---------------------------------------------------------------------------*/ +void +coap_endpoint_disconnect(coap_endpoint_t *ep) +{ +#ifdef WITH_DTLS + dtls_close(dtls_context, ep); +#endif /* WITH_DTLS */ +} +/*---------------------------------------------------------------------------*/ +int +coap_endpoint_is_secure(const coap_endpoint_t *ep) +{ + return ep->secure; +} +/*---------------------------------------------------------------------------*/ +int +coap_endpoint_is_connected(const coap_endpoint_t *ep) +{ + if(ep->secure) { +#ifdef WITH_DTLS + dtls_peer_t *peer; + peer = dtls_get_peer(dtls_context, ep); + if(peer != NULL) { + /* only if handshake is done! */ + PRINTF("peer state for "); + PRINTEP(ep); + PRINTF(" is %d %d\n", peer->state, dtls_peer_is_connected(peer)); + return dtls_peer_is_connected(peer); + } else { + PRINTF("Did not find peer "); + PRINTEP(ep); + PRINTF("\n"); + } +#endif /* WITH_DTLS */ + return 0; + } + /* Assume that the UDP socket is already up... */ + return 1; +} + +/* DTLS */ +#ifdef WITH_DTLS + +/* This is input coming from the DTLS code - e.g. de-crypted input from + the other side - peer */ +static int +input_from_peer(struct dtls_context_t *ctx, + session_t *session, uint8_t *data, size_t len) +{ + size_t i; + dtls_peer_t *peer; + + printf("received data:"); + for (i = 0; i < len; i++) + printf("%c", data[i]); + printf("\nHex:"); + for (i = 0; i < len; i++) + printf("%02x", data[i]); + printf("\n"); + + /* Send this into coap-input */ + memmove(coap_databuf(), data, len); + coap_buf_len = len; + + peer = dtls_get_peer(ctx, session); + /* If we have a peer then ensure that the endpoint is tagged as secure */ + if(peer) { + session->secure = 1; + } + + coap_receive(session, coap_databuf(), coap_datalen()); + + return 0; +} + +/* This is output from the DTLS code to be sent to peer (encrypted) */ +static int +output_to_peer(struct dtls_context_t *ctx, + session_t *session, uint8_t *data, size_t len) +{ + int fd = *(int *)dtls_get_app_data(ctx); + printf("output_to_peer len:%d %d (s-size: %d)\n", (int)len, fd, + session->size); + + + int i; + printf("COAPHEX:"); + for(i = 0; i < len; i++) { + printf("%02x", data[i]); + } + printf("\n"); + + return len; +} + + +/* This function is the "key store" for tinyDTLS. It is called to + * retrieve a key for the given identity within this particular + * session. */ +static int +get_psk_info(struct dtls_context_t *ctx, + const session_t *session, + dtls_credentials_type_t type, + const unsigned char *id, size_t id_len, + unsigned char *result, size_t result_length) +{ + PRINTF("---===>>> Getting the Key or ID <<<===---\n"); + switch (type) { + case DTLS_PSK_IDENTITY: + if (id_len) { + dtls_debug("got psk_identity_hint: '%.*s'\n", id_len, id); + } + + if (result_length < psk_id_length) { + dtls_warn("cannot set psk_identity -- buffer too small\n"); + return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); + } + + memcpy(result, psk_id, psk_id_length); + return psk_id_length; + case DTLS_PSK_KEY: + if (id_len != psk_id_length || memcmp(psk_id, id, id_len) != 0) { + dtls_warn("PSK for unknown id requested, exiting\n"); + return dtls_alert_fatal_create(DTLS_ALERT_ILLEGAL_PARAMETER); + } else if (result_length < psk_key_length) { + dtls_warn("cannot set psk -- buffer too small\n"); + return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); + } + + memcpy(result, psk_key, psk_key_length); + return psk_key_length; + default: + dtls_warn("unsupported request type: %d\n", type); + } + + return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); +} + + +static dtls_handler_t cb = { + .write = output_to_peer, + .read = input_from_peer, + .event = NULL, +#ifdef DTLS_PSK + .get_psk_info = get_psk_info, +#endif /* DTLS_PSK */ +#ifdef DTLS_ECC + /* .get_ecdsa_key = get_ecdsa_key, */ + /* .verify_ecdsa_key = verify_ecdsa_key */ +#endif /* DTLS_ECC */ +}; + +#endif /* WITH_DTLS */ + +/*---------------------------------------------------------------------------*/ diff --git a/examples/lwm2m/standalone/coap-hex/coap-hex.h b/examples/lwm2m/standalone/coap-hex/coap-hex.h new file mode 100644 index 000000000..b03b0f3a1 --- /dev/null +++ b/examples/lwm2m/standalone/coap-hex/coap-hex.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2016, SICS, Swedish ICT AB. + * 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. + */ + +/** + * \file + * A HEX text transport for CoAP + * \author + * Niclas Finne + * Joakim Eriksson + */ + +#ifndef COAP_HEX_H_ +#define COAP_HEX_H_ + +#define COAP_ENDPOINT_CUSTOM 1 + +#define LWM2M_SECURITY_CONF_REGISTER_KEY_STORE 0 + +typedef struct { + int addr; /* if we want to switch on something... */ + unsigned int size; + int secure; +} coap_endpoint_t; + +#endif /* COAP_HEX_H_ */ diff --git a/examples/lwm2m/standalone/coap-ipv4/coap-ipv4.c b/examples/lwm2m/standalone/coap-ipv4/coap-ipv4.c new file mode 100644 index 000000000..95659ef6f --- /dev/null +++ b/examples/lwm2m/standalone/coap-ipv4/coap-ipv4.c @@ -0,0 +1,597 @@ +/* + * Copyright (c) 2016, SICS, Swedish ICT AB. + * 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. + */ + +/** + * \file + * A native IPv4 transport for CoAP + * \author + * Niclas Finne + * Joakim Eriksson + */ + +#include "coap.h" +#include "coap-endpoint.h" +#include "coap-engine.h" +#include "coap-keystore.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEBUG 1 +#if DEBUG +#define PRINTF(...) printf(__VA_ARGS__) +#define PRINTEP(ep) coap_endpoint_print(ep) +#else /* DEBUG */ +#define PRINTF(...) +#define PRINTEP(ep) +#endif /* DEBUG */ + +#ifdef WITH_DTLS +#include "tinydtls.h" +#include "dtls.h" +#include "dtls_debug.h" +#endif /* WITH_DTLS */ + +#define BUFSIZE 1280 + +typedef union { + uint32_t u32[(BUFSIZE + 3) / 4]; + uint8_t u8[BUFSIZE]; +} coap_buf_t; + +static int coap_ipv4_fd = -1; + +static coap_endpoint_t last_source; +static coap_buf_t coap_aligned_buf; +static uint16_t coap_buf_len; + +#ifdef WITH_DTLS +static int dtls_ipv4_fd = -1; +static dtls_handler_t cb; +static dtls_context_t *dtls_context = NULL; + +static const coap_keystore_t *dtls_keystore = NULL; +#endif /* WITH_DTLS */ + +/*---------------------------------------------------------------------------*/ +static const coap_endpoint_t * +coap_src_endpoint(void) +{ + return &last_source; +} +/*---------------------------------------------------------------------------*/ +int +coap_endpoint_is_secure(const coap_endpoint_t *ep) +{ + return ep->secure; +} +/*---------------------------------------------------------------------------*/ +int +coap_endpoint_is_connected(const coap_endpoint_t *ep) +{ + if(ep->secure) { +#ifdef WITH_DTLS + dtls_peer_t *peer; + peer = dtls_get_peer(dtls_context, ep); + if(peer != NULL) { + /* only if handshake is done! */ + PRINTF("peer state for "); + PRINTEP(ep); + PRINTF(" is %d %d\n", peer->state, dtls_peer_is_connected(peer)); + return dtls_peer_is_connected(peer); + } else { + PRINTF("Did not find peer "); + PRINTEP(ep); + PRINTF("\n"); + } +#endif /* WITH_DTLS */ + return 0; + } + /* Assume that the UDP socket is already up... */ + return 1; +} +/*---------------------------------------------------------------------------*/ +int +coap_endpoint_connect(coap_endpoint_t *ep) +{ + if(ep->secure == 0) { + return 1; + } +#ifdef WITH_DTLS + PRINTF("DTLS EP:"); + PRINTEP(ep); + PRINTF(" len:%d\n", ep->size); + + /* setup all address info here... should be done to connect */ + if(dtls_context) { + dtls_connect(dtls_context, ep); + return 1; + } +#endif /* WITH_DTLS */ + return 0; +} +/*---------------------------------------------------------------------------*/ +void +coap_endpoint_disconnect(coap_endpoint_t *ep) +{ +#ifdef WITH_DTLS + if(ep && ep->secure && dtls_context) { + dtls_close(dtls_context, ep); + } +#endif /* WITH_DTLS */ +} +/*---------------------------------------------------------------------------*/ +void +coap_endpoint_copy(coap_endpoint_t *destination, const coap_endpoint_t *from) +{ + memcpy(destination, from, sizeof(coap_endpoint_t)); +} +/*---------------------------------------------------------------------------*/ +int +coap_endpoint_cmp(const coap_endpoint_t *e1, const coap_endpoint_t *e2) +{ + /* need to compare only relevant parts of sockaddr */ + switch(e1->addr.sin_family) { + case AF_INET: + return e1->addr.sin_port == e2->addr.sin_port && + e1->secure == e2->secure && + memcmp(&e1->addr.sin_addr, &e2->addr.sin_addr, + sizeof(struct in_addr)) == 0; + default: + return 0; + } +} +/*---------------------------------------------------------------------------*/ +void +coap_endpoint_print(const coap_endpoint_t *ep) +{ + const char *address; + address = inet_ntoa(ep->addr.sin_addr); + if(address != NULL) { + printf("coap%s://%s:%u",ep->secure ? "s":"", + address, ntohs(ep->addr.sin_port)); + } else { + printf("<#N/A>"); + } +} +/*---------------------------------------------------------------------------*/ +int +coap_endpoint_parse(const char *text, size_t size, coap_endpoint_t *ep) +{ + /* text = format coap://host:port/... we assume */ + /* will not work for know - on the TODO */ + /* set server and port */ + char host[32]; + uint16_t port; + int hlen = 0; + int secure; + int offset = 0; + int i; + PRINTF("CoAP-IPv4: Parsing endpoint: %.*s\n", (int)size, text); + if(strncmp("coap://", text, 7) == 0) { + secure = 0; + offset = 7; + PRINTF("COAP found\n"); + } else if(strncmp("coaps://", text, 8) == 0) { + secure = 1; + offset = 8; + PRINTF("COAPS found\n"); + } else { + secure = 0; + } + + for(i = offset; i < size && text[i] != ':' && text[i] != '/' && + hlen < sizeof(host) - 1; i++) { + host[hlen++] = text[i]; + } + host[hlen] = 0; + + port = secure == 0 ? COAP_DEFAULT_PORT : COAP_DEFAULT_SECURE_PORT; + if(text[i] == ':') { + /* Parse IPv4 endpoint port */ + port = atoi(&text[i + 1]); + } + + PRINTF("CoAP-IPv4: endpoint %s:%u\n", host, port); + + ep->addr.sin_family = AF_INET; + ep->addr.sin_port = htons(port); + ep->size = sizeof(ep->addr); + ep->secure = secure; + if(inet_aton(host, &ep->addr.sin_addr) == 0) { + /* Failed to parse the address */ + PRINTF("CoAP-IPv4: Failed to parse endpoint host '%s'\n", host); + return 0; + } + return 1; +} +/*---------------------------------------------------------------------------*/ +uint8_t * +coap_databuf(void) +{ + return coap_aligned_buf.u8; +} +/*---------------------------------------------------------------------------*/ +uint16_t +coap_datalen() +{ + return coap_buf_len; +} +/*---------------------------------------------------------------------------*/ +static int +read_packet_to_coapbuf(int fd) +{ + int len; + + memset(&last_source, 0, sizeof(last_source)); + last_source.size = sizeof(last_source.addr); + len = recvfrom(fd, coap_databuf(), BUFSIZE, 0, + (struct sockaddr *)&last_source.addr, &last_source.size); + if(len == -1) { + if(errno == EAGAIN) { + return 0; + } + err(1, "CoAP-IPv4: recv"); + return 0; + } + + PRINTF("RECV from "); + PRINTEP(&last_source); + PRINTF(" %u bytes\n", len); + coap_buf_len = len; + +#if 0 + if((rand() & 0xffff) < 0x1000) { + printf("*********---- PACKET LOSS ----********\n"); + return 0; + } +#endif + + return 1; +} +/*---------------------------------------------------------------------------*/ +static int +coap_ipv4_set_fd(fd_set *rset, fd_set *wset) +{ + if(coap_ipv4_fd >= 0) { + FD_SET(coap_ipv4_fd, rset); + return 1; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +static void +coap_ipv4_handle_fd(fd_set *rset, fd_set *wset) +{ + + if(coap_ipv4_fd >= 0 && FD_ISSET(coap_ipv4_fd, rset)) { + if(read_packet_to_coapbuf(coap_ipv4_fd)) { +#if DEBUG + int i; + uint8_t *data; + data = coap_databuf(); + PRINTF("Received:"); + for(i = 0; i < coap_buf_len; i++) { + PRINTF("%02x", data[i]); + } + PRINTF("\n"); +#endif /* DEBUG */ + coap_receive(coap_src_endpoint(), coap_databuf(), coap_datalen()); + } + } +} +/*---------------------------------------------------------------------------*/ +static const struct select_callback udp_callback = { + coap_ipv4_set_fd, coap_ipv4_handle_fd +}; +/*---------------------------------------------------------------------------*/ +#ifdef WITH_DTLS +static int +dtls_ipv4_set_fd(fd_set *rset, fd_set *wset) +{ + if(dtls_ipv4_fd >= 0 && dtls_context) { + FD_SET(dtls_ipv4_fd, rset); + return 1; + } + return 0; +} +#endif /* WITH_DTLS */ +/*---------------------------------------------------------------------------*/ +#ifdef WITH_DTLS +static void +dtls_ipv4_handle_fd(fd_set *rset, fd_set *wset) +{ + if(dtls_ipv4_fd >= 0 && FD_ISSET(dtls_ipv4_fd, rset)) { + if(read_packet_to_coapbuf(dtls_ipv4_fd) && dtls_context) { + /* DTLS receive */ + last_source.secure = 1; + dtls_handle_message(dtls_context, &last_source, + coap_databuf(), coap_datalen()); + } + } +} +#endif /* WITH_DTLS */ +/*---------------------------------------------------------------------------*/ +#ifdef WITH_DTLS +static const struct select_callback dtls_callback = { + dtls_ipv4_set_fd, dtls_ipv4_handle_fd +}; +#endif /* WITH_DTLS */ +/*---------------------------------------------------------------------------*/ +void +coap_transport_init(void) +{ + static struct sockaddr_in server; + + coap_ipv4_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if(coap_ipv4_fd == -1) { + fprintf(stderr, "Could not create CoAP UDP socket\n"); + exit(1); + return; + } + + memset((void *)&server, 0, sizeof(server)); + + server.sin_family = AF_INET; + server.sin_port = htons(COAP_SERVER_PORT); + server.sin_addr.s_addr = htonl(INADDR_ANY); + + if(bind(coap_ipv4_fd, (struct sockaddr *)&server, sizeof(server)) == -1) { + PRINTF("Could not bind CoAP UDP port to %u\n", COAP_SERVER_PORT); + exit(1); + } + + printf("CoAP server listening on port %u\n", COAP_SERVER_PORT); + select_set_callback(coap_ipv4_fd, &udp_callback); + +#ifdef WITH_DTLS + dtls_init(); + dtls_set_log_level(8); + + dtls_ipv4_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if(dtls_ipv4_fd == -1) { + fprintf(stderr, "Could not create CoAP DTLS UDP socket\n"); + exit(1); + return; + } + + memset((void *)&server, 0, sizeof(server)); + server.sin_family = AF_INET; + server.sin_port = htons(COAP_DEFAULT_SECURE_PORT); + server.sin_addr.s_addr = htonl(INADDR_ANY); + + if(bind(dtls_ipv4_fd, (struct sockaddr *)&server, sizeof(server)) == -1) { + PRINTF("Could not bind CoAP DTLS UDP port to %u\n", + COAP_DEFAULT_SECURE_PORT); + exit(1); + } + + printf("CoAP DTLS server listening on port %u\n", COAP_DEFAULT_SECURE_PORT); + select_set_callback(dtls_ipv4_fd, &dtls_callback); + + /* create new contet with app-data */ + dtls_context = dtls_new_context(&dtls_ipv4_fd); + if(!dtls_context) { + PRINTF("DTLS: cannot create context\n"); + exit(-1); + } + + dtls_set_handler(dtls_context, &cb); +#endif /* WITH_DTLS */ +} +/*---------------------------------------------------------------------------*/ +void +coap_send_message(const coap_endpoint_t *ep, const uint8_t *data, uint16_t len) +{ + if(!coap_endpoint_is_connected(ep)) { + PRINTF("CoAP endpoint not connected\n"); + return; + } + +#ifdef WITH_DTLS + if(coap_endpoint_is_secure(ep)) { + if(dtls_context) { + dtls_write(dtls_context, (session_t *)ep, (uint8_t *)data, len); + } + return; + } +#endif /* WITH_DTLS */ + + if(coap_ipv4_fd >= 0) { + if(sendto(coap_ipv4_fd, data, len, 0, + (struct sockaddr *)&ep->addr, ep->size) < 1) { + PRINTF("failed to send to "); + PRINTEP(ep); + PRINTF(" %u bytes: %s\n", len, strerror(errno)); + } else { + PRINTF("SENT to "); + PRINTEP(ep); + PRINTF(" %u bytes\n", len); + + if(DEBUG) { + int i; + PRINTF("Sent:"); + for(i = 0; i < len; i++) { + PRINTF("%02x", data[i]); + } + PRINTF("\n"); + } + } + } +} +/*---------------------------------------------------------------------------*/ +/* DTLS */ +#ifdef WITH_DTLS + +/* This is input coming from the DTLS code - e.g. de-crypted input from + the other side - peer */ +static int +input_from_peer(struct dtls_context_t *ctx, + session_t *session, uint8_t *data, size_t len) +{ + size_t i; + dtls_peer_t *peer; + + printf("received data:"); + for (i = 0; i < len; i++) { + printf("%c", data[i]); + } + printf("\nHex:"); + for (i = 0; i < len; i++) { + printf("%02x", data[i]); + } + printf("\n"); + + /* Send this into coap-input */ + memmove(coap_databuf(), data, len); + coap_buf_len = len; + + peer = dtls_get_peer(ctx, session); + /* If we have a peer then ensure that the endpoint is tagged as secure */ + if(peer) { + session->secure = 1; + } + + coap_receive(session, coap_databuf(), coap_datalen()); + + return 0; +} + +/* This is output from the DTLS code to be sent to peer (encrypted) */ +static int +output_to_peer(struct dtls_context_t *ctx, + session_t *session, uint8_t *data, size_t len) +{ + int fd = *(int *)dtls_get_app_data(ctx); + printf("output_to_peer len:%d %d (s-size: %d)\n", (int)len, fd, + session->size); + return sendto(fd, data, len, MSG_DONTWAIT, + (struct sockaddr *)&session->addr, session->size); +} + +/* This defines the key-store set API since we hookup DTLS here */ +void +coap_set_keystore(const coap_keystore_t *keystore) +{ + dtls_keystore = keystore; +} + +/* This function is the "key store" for tinyDTLS. It is called to + * retrieve a key for the given identity within this particular + * session. */ +static int +get_psk_info(struct dtls_context_t *ctx, + const session_t *session, + dtls_credentials_type_t type, + const unsigned char *id, size_t id_len, + unsigned char *result, size_t result_length) +{ + const coap_keystore_t *keystore; + coap_keystore_psk_entry_t ks; + + keystore = dtls_keystore; + if(keystore == NULL) { + PRINTF("--- No key store available ---\n"); + return 0; + } + + memset(&ks, 0, sizeof(ks)); + PRINTF("---===>>> Getting the Key or ID <<<===---\n"); + switch(type) { + case DTLS_PSK_IDENTITY: + if(id && id_len) { + ks.identity_hint = id; + ks.identity_hint_len = id_len; + dtls_debug("got psk_identity_hint: '%.*s'\n", id_len, id); + } + + if(keystore->coap_get_psk_info) { + /* we know that session is a coap endpoint */ + keystore->coap_get_psk_info((coap_endpoint_t *)session, &ks); + } + if(ks.identity == NULL || ks.identity_len == 0) { + return 0; + } + + if(result_length < ks.identity_len) { + PRINTF("cannot set psk_identity -- buffer too small\n"); + return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); + } + memcpy(result, ks.identity, ks.identity_len); + return ks.identity_len; + + case DTLS_PSK_KEY: + if(keystore->coap_get_psk_info) { + ks.identity = id; + ks.identity_len = id_len; + /* we know that session is a coap endpoint */ + keystore->coap_get_psk_info((coap_endpoint_t *)session, &ks); + } + if(ks.key == NULL || ks.key_len == 0) { + PRINTF("PSK for unknown id requested, exiting\n"); + return dtls_alert_fatal_create(DTLS_ALERT_ILLEGAL_PARAMETER); + } + + if(result_length < ks.key_len) { + PRINTF("cannot set psk -- buffer too small\n"); + return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); + } + memcpy(result, ks.key, ks.key_len); + return ks.key_len; + + default: + dtls_warn("unsupported request type: %d\n", type); + } + + return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); +} + +static dtls_handler_t cb = { + .write = output_to_peer, + .read = input_from_peer, + .event = NULL, +#ifdef DTLS_PSK + .get_psk_info = get_psk_info, +#endif /* DTLS_PSK */ +#ifdef DTLS_ECC + /* .get_ecdsa_key = get_ecdsa_key, */ + /* .verify_ecdsa_key = verify_ecdsa_key */ +#endif /* DTLS_ECC */ +}; + +#endif /* WITH_DTLS */ + +/*---------------------------------------------------------------------------*/ diff --git a/examples/lwm2m/standalone/coap-ipv4/coap-ipv4.h b/examples/lwm2m/standalone/coap-ipv4/coap-ipv4.h new file mode 100644 index 000000000..8af2e5fc6 --- /dev/null +++ b/examples/lwm2m/standalone/coap-ipv4/coap-ipv4.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2016, SICS, Swedish ICT AB. + * 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. + */ + +/** + * \file + * A native IPv4 transport for CoAP + * \author + * Niclas Finne + * Joakim Eriksson + */ + +#ifndef COAP_IPV4_H_ +#define COAP_IPV4_H_ + +#include + +#define COAP_ENDPOINT_CUSTOM 1 + +typedef struct { + struct sockaddr_in addr; + unsigned int size; + int secure; +} coap_endpoint_t; + +#endif /* COAP_IPV4_H_ */ diff --git a/examples/lwm2m/standalone/contiki.h b/examples/lwm2m/standalone/contiki.h new file mode 100644 index 000000000..6149da0e3 --- /dev/null +++ b/examples/lwm2m/standalone/contiki.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2016, SICS, Swedish ICT AB. + * 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. + */ + +/** + * \file + * Configuration for Contiki library + * \author + * Niclas Finne + * Joakim Eriksson + */ + +#ifndef CONTIKI_H_ +#define CONTIKI_H_ + +#include + +#include "posix-main.h" + +#define COAP_TIMER_CONF_DRIVER coap_timer_native_driver + +#define LWM2M_ENGINE_CLIENT_ENDPOINT_NAME "lwm2m-ex" +#define LWM2M_DEVICE_MANUFACTURER "SICS, Swedish ICT AB" +#define LWM2M_DEVICE_TYPE "lwm2m-example" +#define LWM2M_DEVICE_MODEL_NUMBER "000" +#define LWM2M_DEVICE_SERIAL_NO "1" +#define LWM2M_DEVICE_FIRMWARE_VERSION "0.1" + +#ifdef COAP_TRANSPORT_CONF_H +#include COAP_TRANSPORT_CONF_H +#endif + +#define COAP_MAX_CHUNK_SIZE 256 + +#endif /* CONTIKI_H_ */ diff --git a/examples/lwm2m/standalone/generic-object-test.c b/examples/lwm2m/standalone/generic-object-test.c new file mode 100644 index 000000000..493238607 --- /dev/null +++ b/examples/lwm2m/standalone/generic-object-test.c @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2017, RISE SICS AB + * 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 copyright holder 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 COPYRIGHT HOLDER 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 + * COPYRIGHT HOLDER 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. + */ + +/** + * \addtogroup lwm2m-objects + * @{ + */ + +/** + * \file + * Implementation of OMA LWM2M / Generic Object Example + * \author + * Joakim Eriksson + * Niclas Finne + */ + +#include +#include "lwm2m-object.h" +#include "lwm2m-engine.h" +#include "coap-engine.h" +#include +#include + +static lwm2m_object_t generic_object; + +#define MAX_SIZE 512 +#define NUMBER_OF_INSTANCES 50 + +#define DEBUG 0 + +#if DEBUG +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) + +#endif + +static const lwm2m_resource_id_t resources[] = + { + RO(10000), + RO(11000), + }; + +/*---------------------------------------------------------------------------*/ +static int read_data(uint8_t *buffer, int instance_id, int start, int len) +{ + int i; + int start_index; + start_index = instance_id; + /* Write len bytes into the buffer from the start-offset */ + for(i = 0; i < len; i++) { + buffer[i] = '0' + ((start_index + i) & 0x3f); + if(i + start >= MAX_SIZE) return i; + } + return i; +} + +static lwm2m_status_t +opaque_callback(lwm2m_object_instance_t *object, + lwm2m_context_t *ctx, int num_to_write) +{ + int len; + PRINTF("opaque-stream callback num_to_write: %d off: %d outlen: %d\n", + num_to_write, ctx->offset, ctx->outbuf->len); + + len = read_data(&ctx->outbuf->buffer[ctx->outbuf->len], + ctx->object_instance_id, + ctx->offset, num_to_write); + + ctx->outbuf->len += len; + + /* Do we need to write more */ + if(ctx->offset + len < MAX_SIZE) { + ctx->writer_flags |= WRITER_HAS_MORE; + } + return LWM2M_STATUS_OK; +} + +/*---------------------------------------------------------------------------*/ +static lwm2m_status_t +lwm2m_callback(lwm2m_object_instance_t *object, + lwm2m_context_t *ctx) +{ + + if(ctx->level <= 2) { + return LWM2M_STATUS_ERROR; + } + + /* Only support for read at the moment */ + if(ctx->operation == LWM2M_OP_READ) { + switch(ctx->resource_id) { + case 10000: + { + char str[30]; + snprintf(str, 30, "hello-%d", (int)ctx->object_instance_id); + lwm2m_object_write_string(ctx, str, strlen(str)); + } + break; + case 11000: + PRINTF("Preparing object write\n"); + lwm2m_object_write_opaque_stream(ctx, MAX_SIZE, opaque_callback); + break; + default: + return LWM2M_STATUS_NOT_FOUND; + } + } + return LWM2M_STATUS_OK; +} +/*---------------------------------------------------------------------------*/ +static void +setup_instance(lwm2m_object_instance_t *instance, uint16_t instance_id) +{ + instance->object_id = generic_object.impl->object_id; + instance->instance_id = instance_id; + instance->callback = lwm2m_callback; + instance->resource_ids = resources; + instance->resource_count = sizeof(resources) / sizeof(lwm2m_resource_id_t); +} +/*---------------------------------------------------------------------------*/ +static lwm2m_object_instance_t * +get_by_id(uint16_t instance_id, lwm2m_status_t *status) +{ + lwm2m_object_instance_t *instance = NULL; + if(status != NULL) { + *status = LWM2M_STATUS_OK; + } + if(instance_id < NUMBER_OF_INSTANCES) { + instance = lwm2m_engine_get_instance_buffer(); + if(instance == NULL) { + return NULL; + } + + /* We are fine - update instance variable */ + setup_instance(instance, instance_id); + } + return instance; +} +/*---------------------------------------------------------------------------*/ +static lwm2m_object_instance_t * +get_first(lwm2m_status_t *status) +{ + return get_by_id(0, status); +} +/*---------------------------------------------------------------------------*/ +static lwm2m_object_instance_t * +get_next(lwm2m_object_instance_t *instance, lwm2m_status_t *status) +{ + return get_by_id(instance->instance_id + 1, status); +} +/*---------------------------------------------------------------------------*/ +static lwm2m_object_impl_t generic_object_impl = { + .object_id = 4712, + .get_first = get_first, + .get_next = get_next, + .get_by_id = get_by_id +}; + +/*---------------------------------------------------------------------------*/ +void +lwm2m_generic_object_test_init(void) +{ + generic_object.impl = &generic_object_impl; + + lwm2m_engine_add_generic_object(&generic_object); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/lwm2m/standalone/ipso-control-test.c b/examples/lwm2m/standalone/ipso-control-test.c new file mode 100644 index 000000000..63e6dc120 --- /dev/null +++ b/examples/lwm2m/standalone/ipso-control-test.c @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2016, SICS Swedish ICT AB + * 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 copyright holder 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 COPYRIGHT HOLDER 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 + * COPYRIGHT HOLDER 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. + */ + +/** + * \addtogroup ipso-objects + * @{ + */ + +/** + * \file + * Implementation of OMA LWM2M / IPSO Generic Sensor + * \author + * Joakim Eriksson + * Niclas Finne + */ + +#include +#include "lwm2m-object.h" +#include "lwm2m-engine.h" +#include "coap-engine.h" +#include "ipso-sensor-template.h" +#include "ipso-control-template.h" +#include +#include + +static lwm2m_status_t set_value(uint8_t value); +static lwm2m_status_t set_light_value(uint8_t value); + +static ipso_control_t test_control = { + .reg_object.object_id = 3306, + .reg_object.instance_id = 0, + .set_value = set_value, +}; + +static ipso_control_t test_control2 = { + .reg_object.object_id = 3311, + .reg_object.instance_id = 0, + .set_value = set_light_value, +}; +/*---------------------------------------------------------------------------*/ +static lwm2m_status_t +set_value(uint8_t value) +{ + /* do something with the value! */ + printf("Value set to: %u before: %u\n", value, + ipso_control_get_value(&test_control)); + return LWM2M_STATUS_OK; +} +/*---------------------------------------------------------------------------*/ +static lwm2m_status_t +set_light_value(uint8_t value) +{ + /* do something with the value! */ + printf("Light value set to: %u before: %u\n", value, + ipso_control_get_value(&test_control2)); + return LWM2M_STATUS_OK; +} +/*---------------------------------------------------------------------------*/ +void +ipso_control_test_init(void) +{ + ipso_control_add(&test_control); + ipso_control_add(&test_control2); +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/examples/lwm2m/standalone/ipso-sensor-temp.c b/examples/lwm2m/standalone/ipso-sensor-temp.c new file mode 100644 index 000000000..010ce7ea2 --- /dev/null +++ b/examples/lwm2m/standalone/ipso-sensor-temp.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2016, SICS Swedish ICT AB + * 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 copyright holder 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 COPYRIGHT HOLDER 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 + * COPYRIGHT HOLDER 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. + */ + +/** + * \addtogroup ipso-objects + * @{ + */ + +/** + * \file + * Implementation of OMA LWM2M / IPSO Generic Sensor + * \author + * Joakim Eriksson + * Niclas Finne + */ + +#include +#include "lwm2m-object.h" +#include "lwm2m-engine.h" +#include "coap-engine.h" +#include "ipso-sensor-template.h" +#include + +uint32_t temp = 19000; +uint32_t hum = 30000; + +ipso_sensor_value_t temp_value; +ipso_sensor_value_t temp_value2; +ipso_sensor_value_t hum_value; + +lwm2m_status_t get_temp_value(const ipso_sensor_t *sensor, int32_t *value); +lwm2m_status_t get_hum_value(const ipso_sensor_t *sensor, int32_t *value); + +static const ipso_sensor_t temp_sensor = { + .object_id = 3303, + .sensor_value = &temp_value, + .max_range = 120000, /* milli celcius */ + .min_range = -30000, /* milli celcius */ + .get_value_in_millis = get_temp_value, + .unit = "Cel", + .update_interval = 10 +}; + +static const ipso_sensor_t temp_sensor2 = { + .object_id = 3303, + .sensor_value = &temp_value2, + .max_range = 120000, /* milli celcius */ + .min_range = -30000, /* milli celcius */ + .get_value_in_millis = get_temp_value, + .unit = "Cel", + .update_interval = 10 +}; + +/*---------------------------------------------------------------------------*/ + +static const ipso_sensor_t hum_sensor = { + .object_id = 3304, + .instance_id = 12, + .sensor_value = &hum_value, + .max_range = 100000, /* milli */ + .min_range = 0, /* milli */ + .get_value_in_millis = get_hum_value, + .unit = "%", + .update_interval = 10 +}; + +/*---------------------------------------------------------------------------*/ + +lwm2m_status_t +get_temp_value(const ipso_sensor_t *sensor, int32_t *value) +{ + *value = temp++; + return LWM2M_STATUS_OK; +} +/*---------------------------------------------------------------------------*/ +lwm2m_status_t +get_hum_value(const ipso_sensor_t *sensor, int32_t *value) +{ + *value = temp++; + return LWM2M_STATUS_OK; +} +/*---------------------------------------------------------------------------*/ + +void +ipso_sensor_temp_init(void) +{ + ipso_sensor_add(&temp_sensor); + ipso_sensor_add(&temp_sensor2); + ipso_sensor_add(&hum_sensor); +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/examples/lwm2m/standalone/lwm2m-example.c b/examples/lwm2m/standalone/lwm2m-example.c new file mode 100644 index 000000000..543539ca5 --- /dev/null +++ b/examples/lwm2m/standalone/lwm2m-example.c @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2016, SICS, Swedish ICT AB. + * 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. + */ + +/** + * \file + * An OMA LWM2M standalone example to demonstrate how to use + * the Contiki OMA LWM2M library from a native application. + * \author + * Niclas Finne + * Joakim Eriksson + */ + +#include "lwm2m-engine.h" +#include "lwm2m-rd-client.h" +#include "lwm2m-firmware.h" +#include "lwm2m-server.h" +#include "lwm2m-security.h" +#include "lwm2m-device.h" +#include "coap.h" +#include "coap-timer.h" +#include +#include +#include +#include + +#define PSK_DEFAULT_IDENTITY "Client_identity" +#define PSK_DEFAULT_KEY "secretPSK" + +#define WITH_TEST_NOTIFICATION 1 + +void ipso_sensor_temp_init(void); +void ipso_control_test_init(void); +void ipso_blockwise_test_init(void); +void lwm2m_generic_object_test_init(void); + +/* set this above zero to get auto deregister */ +static int deregister = -1; + +/*---------------------------------------------------------------------------*/ +#if WITH_TEST_NOTIFICATION +static void +callback(coap_timer_t *timer) +{ + /* Automatic notification on device timer for test!*/ + lwm2m_notify_observers("3/0/13"); + coap_timer_reset(timer, 10000); + if(deregister > 0) { + deregister--; + if(deregister == 0) { + printf("Deregistering.\n"); + lwm2m_rd_client_deregister(); + } + } +} +#endif /* WITH_TEST_NOTIFICATION */ +/*---------------------------------------------------------------------------*/ +static void +session_callback(struct lwm2m_session_info *si, int state) +{ + printf("Got Session Callback!!! %d\n", state); +} +/*---------------------------------------------------------------------------*/ +#ifndef LWM2M_DEFAULT_RD_SERVER +/* Default to leshan.eclipse.org */ +#ifdef WITH_DTLS +#define LWM2M_DEFAULT_RD_SERVER "coaps://5.39.83.206" +#else +#define LWM2M_DEFAULT_RD_SERVER "coap://5.39.83.206" +#endif +#endif /* LWM2M_DEFAULT_RD_SERVER */ +/*---------------------------------------------------------------------------*/ +void +start_application(int argc, char *argv[]) +{ + const char *default_server = LWM2M_DEFAULT_RD_SERVER; + coap_endpoint_t server_ep; + int has_server_ep = 0; + char *name = "abcde"; + + if(argc > 1) { + default_server = argv[1]; + } + if(argc > 2) { + name = argv[2]; + } + + if(default_server != NULL && *default_server != '\0') { + if(coap_endpoint_parse(default_server, strlen(default_server), &server_ep) == 0) { + fprintf(stderr, "failed to parse the server address '%s'\n", default_server); + exit(1); + } + has_server_ep = 1; + } + + /* Example using network timer */ +#if WITH_TEST_NOTIFICATION + { + static coap_timer_t nt; + coap_timer_set_callback(&nt, callback); + coap_timer_set(&nt, 10000); + } +#endif /* WITH_TEST_NOTIFICATION */ + + /* Initialize the OMA LWM2M engine */ + lwm2m_engine_init(); + + ipso_sensor_temp_init(); + ipso_control_test_init(); + ipso_blockwise_test_init(); + lwm2m_generic_object_test_init(); + + /* Register default LWM2M objects */ + + lwm2m_device_init(); + lwm2m_firmware_init(); + lwm2m_security_init(); + lwm2m_server_init(); + + if(has_server_ep) { + /* start RD client */ + printf("Starting RD client to register at "); + coap_endpoint_print(&server_ep); + printf("\n"); + +#ifdef WITH_DTLS +#if defined(PSK_DEFAULT_IDENTITY) && defined(PSK_DEFAULT_KEY) + { + lwm2m_security_server_t *server; + /* Register new server with instance id, server id, lifetime in seconds */ + if(!lwm2m_server_add(0, 1, 600)) { + printf("failed to add server object\n"); + } + + server = lwm2m_security_add_server(0, 1, + (uint8_t *)default_server, + strlen(default_server)); + if(server == NULL) { + printf("failed to add security object\n"); + } else { + if(lwm2m_security_set_server_psk(server, + (uint8_t *)PSK_DEFAULT_IDENTITY, + strlen(PSK_DEFAULT_IDENTITY), + (uint8_t *)PSK_DEFAULT_KEY, + strlen(PSK_DEFAULT_KEY))) { + printf("registered security object for endpoint %s\n", + default_server); + } else { + printf("failed to register security object\n"); + } + } + } +#endif /* defined(PSK_DEFAULT_IDENTITY) && defined(PSK_DEFAULT_KEY) */ +#endif /* WITH_DTLS */ + +#define BOOTSTRAP 0 +#if BOOTSTRAP + lwm2m_rd_client_register_with_bootstrap_server(&server_ep); + lwm2m_rd_client_use_bootstrap_server(1); +#else + lwm2m_rd_client_register_with_server(&server_ep); +#endif + lwm2m_rd_client_use_registration_server(1); + + lwm2m_rd_client_init(name); + + printf("Callback: %p\n", session_callback); + lwm2m_rd_client_set_session_callback(session_callback); + + } else { + fprintf(stderr, "No registration server specified.\n"); + } + printf("COAP MAX PACKET: %d (BLOCK:%d)\n", COAP_MAX_PACKET_SIZE, COAP_MAX_BLOCK_SIZE); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/lwm2m/standalone/posix-coap-timer.c b/examples/lwm2m/standalone/posix-coap-timer.c new file mode 100644 index 000000000..29a0ecca6 --- /dev/null +++ b/examples/lwm2m/standalone/posix-coap-timer.c @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2016, SICS, Swedish ICT AB. + * 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. + */ + +/** + * \file + * Example posix implementation of CoAP timer driver. + * \author + * Niclas Finne + * Joakim Eriksson + */ + +#include "coap-timer.h" +#include + +#define DEBUG 1 +#if DEBUG +#include +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif + +/* The maximal time allowed to move forward between updates */ +#define MAX_TIME_CHANGE_MSEC 360000UL + +static uint64_t uptime_msec = 0; +static uint64_t last_msec; +/*---------------------------------------------------------------------------*/ +static uint64_t +uptime(void) +{ + struct timeval tv; + uint64_t t; + + if(gettimeofday(&tv, NULL)) { + PRINTF("*** failed to retrieve system time\n"); + return last_msec; + } + + t = tv.tv_sec * (uint64_t)1000; + t += tv.tv_usec / (uint64_t)1000; + + if(last_msec == 0) { + /* No update first time */ + } else if(t < last_msec) { + /* System time has moved backwards */ + PRINTF("*** system time has moved backwards %lu msec\n", + (unsigned long)(last_msec - t)); + + } else if(t - last_msec > MAX_TIME_CHANGE_MSEC) { + /* Too large jump forward in system time */ + PRINTF("*** system time has moved forward %lu msec\n", + (unsigned long)(t - last_msec)); + uptime_msec += 1000UL; + } else { + uptime_msec += t - last_msec; + } + + last_msec = t; + + return uptime_msec; +} +/*---------------------------------------------------------------------------*/ +static void +init(void) +{ + uptime(); +} +/*---------------------------------------------------------------------------*/ +static void +update(void) +{ +} +/*---------------------------------------------------------------------------*/ +const coap_timer_driver_t coap_timer_native_driver = { + .init = init, + .uptime = uptime, + .update = update, +}; +/*---------------------------------------------------------------------------*/ diff --git a/examples/lwm2m/standalone/posix-main.c b/examples/lwm2m/standalone/posix-main.c new file mode 100644 index 000000000..a077eb101 --- /dev/null +++ b/examples/lwm2m/standalone/posix-main.c @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2016, SICS, Swedish ICT AB. + * 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. + */ + +/** + * \file + * Simple posix main loop with support functions. + * \author + * Niclas Finne + * Joakim Eriksson + */ + +#include "lwm2m-engine.h" +#include "lwm2m-rd-client.h" +#include "coap-timer.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef SELECT_CONF_MAX +#define SELECT_MAX SELECT_CONF_MAX +#else +#define SELECT_MAX 8 +#endif + +static const struct select_callback *select_callback[SELECT_MAX]; +static int select_max = 0; +static int is_stdin_open = 1; +static void (* stdin_callback)(const char *line); +static char stdin_buffer[2048]; +static uint16_t stdin_count; +/*---------------------------------------------------------------------------*/ +int +select_set_callback(int fd, const struct select_callback *callback) +{ + int i; + if(fd >= 0 && fd < SELECT_MAX) { + /* Check that the callback functions are set */ + if(callback != NULL && + (callback->set_fd == NULL || callback->handle_fd == NULL)) { + callback = NULL; + } + + select_callback[fd] = callback; + + /* Update fd max */ + if(callback != NULL) { + if(fd > select_max) { + select_max = fd; + } + } else { + select_max = 0; + for(i = SELECT_MAX - 1; i > 0; i--) { + if(select_callback[i] != NULL) { + select_max = i; + break; + } + } + } + return 1; + } + fprintf(stderr, "*** failed to set callback for fd %d\n", fd); + return 0; +} +/*---------------------------------------------------------------------------*/ +void +select_set_stdin_callback(void (* line_read)(const char *line)) +{ + stdin_callback = line_read; +} +/*---------------------------------------------------------------------------*/ +static int +stdin_set_fd(fd_set *rset, fd_set *wset) +{ + if(is_stdin_open) { + FD_SET(STDIN_FILENO, rset); + } + return 1; +} +/*---------------------------------------------------------------------------*/ +static void +stdin_handle_fd(fd_set *rset, fd_set *wset) +{ + ssize_t ret; + char c; + if(is_stdin_open && FD_ISSET(STDIN_FILENO, rset)) { + ret = read(STDIN_FILENO, &c, 1); + if(ret > 0) { + if(c == '\r') { + /* Ignore CR */ + } else if(c == '\n' || stdin_count >= sizeof(stdin_buffer) - 1) { + stdin_buffer[stdin_count] = 0; + if(stdin_count > 0 && stdin_callback != NULL) { + stdin_callback(stdin_buffer); + } else { + fprintf(stderr, "STDIN: %s\n", stdin_buffer); + } + stdin_count = 0; + } else { + stdin_buffer[stdin_count++] = (char)c; + } + } else if(ret == 0) { + /* Standard in closed */ + is_stdin_open = 0; + fprintf(stderr, "*** stdin closed\n"); + stdin_count = 0; + if(stdin_callback) { + stdin_buffer[0] = 0; + stdin_callback(stdin_buffer); + } + } else if(errno != EAGAIN) { + err(1, "stdin: read"); + } + } +} +/*---------------------------------------------------------------------------*/ +const static struct select_callback stdin_fd = { + stdin_set_fd, stdin_handle_fd +}; +/*---------------------------------------------------------------------------*/ +int +main(int argc, char *argv[]) +{ + uint64_t next_time; + fd_set fdr, fdw; + int maxfd, retval, i; + struct timeval tv; + + /* Make standard output unbuffered. */ + setvbuf(stdout, (char *)NULL, _IONBF, 0); + + select_set_callback(STDIN_FILENO, &stdin_fd); + + /* Start the application */ + start_application(argc, argv); + + while(1) { + tv.tv_sec = 0; + tv.tv_usec = 250; + + next_time = coap_timer_time_to_next_expiration(); + if(next_time > 0) { + tv.tv_sec = next_time / 1000; + tv.tv_usec = (next_time % 1000) * 1000; + if(tv.tv_usec == 0 && tv.tv_sec == 0) { + /* + * CoAP timer time resolution is milliseconds. Avoid millisecond + * busy loops. + */ + tv.tv_usec = 250; + } + } + + FD_ZERO(&fdr); + FD_ZERO(&fdw); + maxfd = 0; + for(i = 0; i <= select_max; i++) { + if(select_callback[i] != NULL && select_callback[i]->set_fd(&fdr, &fdw)) { + maxfd = i; + } + } + + retval = select(maxfd + 1, &fdr, &fdw, NULL, &tv); + if(retval < 0) { + if(errno != EINTR) { + perror("select"); + } + } else if(retval > 0) { + /* timeout => retval == 0 */ + for(i = 0; i <= maxfd; i++) { + if(select_callback[i] != NULL) { + select_callback[i]->handle_fd(&fdr, &fdw); + } + } + } + + /* Process network timers */ + for(retval = 0; retval < 5 && coap_timer_run(); retval++); + } + + return 0; +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/lwm2m/standalone/posix-main.h b/examples/lwm2m/standalone/posix-main.h new file mode 100644 index 000000000..c220cd9f9 --- /dev/null +++ b/examples/lwm2m/standalone/posix-main.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2016, SICS, Swedish ICT AB. + * 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. + */ + +/** + * \file + * Simple posix main loop with support functions. + * \author + * Niclas Finne + * Joakim Eriksson + */ + +#ifndef POSIX_MAIN_H_ +#define POSIX_MAIN_H_ + +#include +#include + +typedef struct select_callback { + int (* set_fd)(fd_set *fdr, fd_set *fdw); + void (* handle_fd)(fd_set *fdr, fd_set *fdw); +} select_callback_t; + +int select_set_callback(int fd, const select_callback_t *callback); + +void select_set_stdin_callback(void (* line_read)(const char *text)); + +void start_application(int argc, char *argv[]); + +#endif /* POSIX_MAIN_H_ */ diff --git a/examples/lwm2m/standalone/tinydtls-support/dtls-support-conf.h b/examples/lwm2m/standalone/tinydtls-support/dtls-support-conf.h new file mode 100644 index 000000000..25e55b31d --- /dev/null +++ b/examples/lwm2m/standalone/tinydtls-support/dtls-support-conf.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2017, SICS, Swedish ICT AB. + * 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. + */ + +/** + * \file + * tinyDTLS support for LWM2M standalone + * \author + * Niclas Finne + * Joakim Eriksson + */ + +#ifndef DTLS_SUPPORT_CONF_H_ +#define DTLS_SUPPORT_CONF_H_ + +#include "coap-endpoint.h" + +#include "coap-timer.h" + +typedef coap_endpoint_t session_t; + +typedef struct { + coap_timer_t retransmit_timer; +} dtls_support_context_state_t; + +#define DTLS_SUPPORT_CONF_CONTEXT_STATE dtls_support_context_state_t + +#define DTLS_TICKS_PER_SECOND 1000 + +typedef uint64_t dtls_tick_t; + +#endif /* DTLS_SUPPORT_CONF_H_ */ diff --git a/examples/lwm2m/standalone/tinydtls-support/dtls-support.c b/examples/lwm2m/standalone/tinydtls-support/dtls-support.c new file mode 100644 index 000000000..c39962d3f --- /dev/null +++ b/examples/lwm2m/standalone/tinydtls-support/dtls-support.c @@ -0,0 +1,302 @@ +/* + * Copyright (c) 2017, SICS, Swedish ICT AB. + * 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. + */ + +/** + * \file + * Posix support for TinyDTLS + * \author + * Niclas Finne + * Joakim Eriksson + */ + +#include "tinydtls.h" +#include "coap-timer.h" +#include + +#include +#include +#include +#include +#include + +#define DEBUG DEBUG_NONE +#include "dtls_debug.h" + +#if DEBUG +#define PRINTEP(ep) coap_endpoint_print(ep) +#else /* DEBUG */ +#define PRINTEP(ep) +#endif /* DEBUG */ + +extern char *loglevels[]; +/*---------------------------------------------------------------------------*/ +static inline size_t +print_timestamp(char *s, size_t len) +{ +#ifdef HAVE_TIME_H + time_t t; + struct tm *tmp; + t = time(NULL); + tmp = localtime(&t); + return strftime(s, len, "%b %d %H:%M:%S", tmp); +#else /* alternative implementation: just print the timestamp */ + uint64_t t; + t = coap_timer_uptime(); + return snprintf(s, len, "%u.%03u", + (unsigned int)(t / 1000), + (unsigned int)(t % 1000)); +#endif /* HAVE_TIME_H */ +} +/*---------------------------------------------------------------------------*/ +#include +static pthread_mutex_t cipher_context_mutex = PTHREAD_MUTEX_INITIALIZER; +static dtls_cipher_context_t cipher_context; +#define LOCK(P) pthread_mutex_lock(P) +#define UNLOCK(P) pthread_mutex_unlock(P) +/*---------------------------------------------------------------------------*/ +dtls_cipher_context_t * +dtls_cipher_context_acquire(void) +{ + LOCK(&cipher_context_mutex); + return &cipher_context; +} +/*---------------------------------------------------------------------------*/ +void +dtls_cipher_context_release(dtls_cipher_context_t *c) +{ + /* just one single context for now */ + UNLOCK(&cipher_context_mutex); +} +/*---------------------------------------------------------------------------*/ +dtls_context_t * +dtls_context_acquire(void) +{ + return (dtls_context_t *)malloc(sizeof(dtls_context_t)); +} +/*---------------------------------------------------------------------------*/ +void +dtls_context_release(dtls_context_t *context) +{ + free(context); +} +/*---------------------------------------------------------------------------*/ +#ifndef NDEBUG +size_t +dsrv_print_addr(const session_t *addr, char *buf, size_t len) +{ + return 0; +} +#endif /* NDEBUG */ +/*---------------------------------------------------------------------------*/ +#ifdef HAVE_VPRINTF +void +dsrv_log(log_t level, char *format, ...) +{ + static char timebuf[32]; + va_list ap; + FILE *log_fd; + + if(dtls_get_log_level() < level) { + return; + } + + log_fd = level <= DTLS_LOG_CRIT ? stderr : stdout; + + if(print_timestamp(timebuf, sizeof(timebuf))) { + fprintf(log_fd, "%s ", timebuf); + } + + if(level <= DTLS_LOG_DEBUG) { + fprintf(log_fd, "%s ", loglevels[level]); + } + + va_start(ap, format); + vfprintf(log_fd, format, ap); + va_end(ap); + fflush(log_fd); +} +#endif /* HAVE_VPRINTF */ +/*---------------------------------------------------------------------------*/ +void +dtls_dsrv_hexdump_log(log_t level, const char *name, + const unsigned char *buf, size_t length, int extend) +{ + static char timebuf[32]; + FILE *log_fd; + int n = 0; + + if(dtls_get_log_level() < level) { + return; + } + + log_fd = level <= DTLS_LOG_CRIT ? stderr : stdout; + + if(print_timestamp(timebuf, sizeof(timebuf))) { + fprintf(log_fd, "%s ", timebuf); + } + + if(level <= DTLS_LOG_DEBUG) { + fprintf(log_fd, "%s ", loglevels[level]); + } + + if(extend) { + fprintf(log_fd, "%s: (%zu bytes):\n", name, length); + + while(length--) { + if(n % 16 == 0) { + fprintf(log_fd, "%08X ", n); + } + + fprintf(log_fd, "%02X ", *buf++); + + n++; + if(n % 8 == 0) { + if(n % 16 == 0) { + fprintf(log_fd, "\n"); + } else { + fprintf(log_fd, " "); + } + } + } + } else { + fprintf(log_fd, "%s: (%zu bytes): ", name, length); + while(length--) { + fprintf(log_fd, "%02X", *buf++); + } + } + fprintf(log_fd, "\n"); + + fflush(log_fd); +} +/*---------------------------------------------------------------------------*/ +/* --------- time support ----------- */ +void +dtls_ticks(dtls_tick_t *t) +{ + *t = coap_timer_uptime(); +} +/*---------------------------------------------------------------------------*/ +int +dtls_fill_random(uint8_t *buf, size_t len) +{ + FILE *urandom = fopen("/dev/urandom", "r"); + + if(!urandom) { + dtls_emerg("cannot initialize PRNG\n"); + return 0; + } + + if(fread(buf, 1, len, urandom) != len) { + dtls_emerg("cannot initialize PRNG\n"); + fclose(urandom); + return 0; + } + + fclose(urandom); + + return 1; +} +/*---------------------------------------------------------------------------*/ +/* message retransmission */ +/*---------------------------------------------------------------------------*/ +static void +dtls_retransmit_callback(coap_timer_t *timer) +{ + dtls_context_t *ctx; + uint64_t now; + uint64_t next; + + ctx = coap_timer_get_user_data(timer); + now = coap_timer_uptime(); + /* Just one retransmission per timer scheduling */ + dtls_check_retransmit(ctx, &next, 0); + + /* need to set timer to some value even if no nextpdu is available */ + if(next != 0) { + coap_timer_set(timer, next <= now ? 1 : next - now); + } +} +/*---------------------------------------------------------------------------*/ +void +dtls_set_retransmit_timer(dtls_context_t *ctx, unsigned int timeout) +{ + coap_timer_set_callback(&ctx->support.retransmit_timer, + dtls_retransmit_callback); + coap_timer_set_user_data(&ctx->support.retransmit_timer, ctx); + coap_timer_set(&ctx->support.retransmit_timer, timeout); +} +/*---------------------------------------------------------------------------*/ +/* Implementation of session functions */ +void +dtls_session_init(session_t *session) +{ + memset(session, 0, sizeof(session_t)); +} +/*---------------------------------------------------------------------------*/ +int +dtls_session_equals(const session_t *a, const session_t *b) +{ + coap_endpoint_t *e1 = (coap_endpoint_t *)a; + coap_endpoint_t *e2 = (coap_endpoint_t *)b; + + PRINTF(" **** EP:"); + PRINTEP(e1); + PRINTF(" =?= "); + PRINTEP(e2); + PRINTF(" => %d\n", coap_endpoint_cmp(e1, e2)); + + return coap_endpoint_cmp(e1, e2); +} +/*---------------------------------------------------------------------------*/ +void * +dtls_session_get_address(const session_t *a) +{ + /* improve this to only contain the addressing info */ + return (void *)a; +} +/*---------------------------------------------------------------------------*/ +int +dtls_session_get_address_size(const session_t *a) +{ + /* improve this to only contain the addressing info */ + return sizeof(session_t); +} +/*---------------------------------------------------------------------------*/ +void +dtls_session_print(const session_t *a) +{ + coap_endpoint_print((const coap_endpoint_t *)a); +} +/*---------------------------------------------------------------------------*/ +/* The init */ +void +dtls_support_init(void) +{ +} +/*---------------------------------------------------------------------------*/ From 725e426c61ff97a0b2b66983ad713afa0d07a915 Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Thu, 26 Oct 2017 16:45:57 +0200 Subject: [PATCH 06/51] LWM2M: replace space with dash in endpoint name --- os/services/lwm2m/lwm2m-engine.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/os/services/lwm2m/lwm2m-engine.c b/os/services/lwm2m/lwm2m-engine.c index 33783bb4e..c9f85c4bc 100644 --- a/os/services/lwm2m/lwm2m-engine.c +++ b/os/services/lwm2m/lwm2m-engine.c @@ -511,8 +511,14 @@ lwm2m_engine_init(void) if(len > sizeof(endpoint) - 13) { len = sizeof(endpoint) - 13; } - memcpy(endpoint, LWM2M_ENGINE_CLIENT_ENDPOINT_PREFIX, len); + for(i = 0; i < len; i++) { + if(LWM2M_ENGINE_CLIENT_ENDPOINT_PREFIX[i] == ' ') { + endpoint[i] = '-'; + } else { + endpoint[i] = LWM2M_ENGINE_CLIENT_ENDPOINT_PREFIX[i]; + } + } /* pick an IP address that is PREFERRED or TENTATIVE */ ipaddr = NULL; for(i = 0; i < UIP_DS6_ADDR_NB; i++) { From ebb329de5caddecc36191575f6039da3a20b4cb4 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Thu, 26 Oct 2017 19:47:14 +0200 Subject: [PATCH 07/51] CoAP: added make option to specify CoAP DTLS keystore to use by default. The currently available options are: * none - No keystore registered. * simple - Keystore using fixed PSK credentials. * lwm2m - Keystore based on LWM2M security objects If an application wants to provide its own keystore, it selects 'none' and registers its own at startup. --- Makefile.include | 3 ++ examples/lwm2m/standalone/coap-hex/coap-hex.h | 2 - os/net/app-layer/coap/Makefile.coap | 16 ++++++++ os/net/app-layer/coap/coap-keystore-simple.c | 39 ++++++++++--------- os/net/app-layer/coap/coap-keystore-simple.h | 10 ++++- os/net/app-layer/coap/coap-uip.c | 10 +++-- os/services/lwm2m/lwm2m-security.c | 25 +++++------- 7 files changed, 63 insertions(+), 42 deletions(-) diff --git a/Makefile.include b/Makefile.include index 0c6cc679f..5ca9cd5da 100644 --- a/Makefile.include +++ b/Makefile.include @@ -360,6 +360,9 @@ viewconf: @echo "##### \"MAKE_MAC\": ______________________________ $(MAKE_MAC)" @echo "##### \"MAKE_NET\": ______________________________ $(MAKE_NET)" @echo "##### \"MAKE_ROUTING\": __________________________ $(MAKE_ROUTING)" +ifdef MAKE_COAP_DTLS_KEYSTORE + @echo "##### \"MAKE_COAP_DTLS_KEYSTORE\": _______________ $(MAKE_COAP_DTLS_KEYSTORE)" +endif @echo "----------------- C variables: -----------------" $(Q)$(CC) $(CFLAGS) -E $(CONTIKI)/tools/viewconf.c | grep \#\#\#\#\# @echo "------------------------------------------------" diff --git a/examples/lwm2m/standalone/coap-hex/coap-hex.h b/examples/lwm2m/standalone/coap-hex/coap-hex.h index b03b0f3a1..5da72f5b7 100644 --- a/examples/lwm2m/standalone/coap-hex/coap-hex.h +++ b/examples/lwm2m/standalone/coap-hex/coap-hex.h @@ -40,8 +40,6 @@ #define COAP_ENDPOINT_CUSTOM 1 -#define LWM2M_SECURITY_CONF_REGISTER_KEY_STORE 0 - typedef struct { int addr; /* if we want to switch on something... */ unsigned int size; diff --git a/os/net/app-layer/coap/Makefile.coap b/os/net/app-layer/coap/Makefile.coap index 4f1d2cd9f..ddf195221 100644 --- a/os/net/app-layer/coap/Makefile.coap +++ b/os/net/app-layer/coap/Makefile.coap @@ -13,4 +13,20 @@ ifeq ($(MAKE_WITH_DTLS),1) MODULES += os/net/app-layer/coap/tinydtls-support MODULES += $(TINYDTLS_PATH) ${addprefix $(TINYDTLS_PATH)/,aes sha2 ecc} + MAKE_COAP_DTLS_KEYSTORE_NONE := 0 + MAKE_COAP_DTLS_KEYSTORE_SIMPLE := 1 + MAKE_COAP_DTLS_KEYSTORE_LWM2M := 2 + + MAKE_COAP_DTLS_KEYSTORE ?= MAKE_COAP_DTLS_KEYSTORE_LWM2M + + ifeq ($(MAKE_COAP_DTLS_KEYSTORE),MAKE_COAP_DTLS_KEYSTORE_SIMPLE) + CFLAGS += -DCOAP_DTLS_KEYSTORE_CONF_WITH_SIMPLE=1 + else ifeq ($(MAKE_COAP_DTLS_KEYSTORE),MAKE_COAP_DTLS_KEYSTORE_LWM2M) + CFLAGS += -DCOAP_DTLS_KEYSTORE_CONF_WITH_LWM2M=1 + else ifeq ($(MAKE_COAP_DTLS_KEYSTORE),MAKE_COAP_DTLS_KEYSTORE_NONE) + # No C flag needed for no keystore + else + ${error Unsupported CoAP DTLS keystore: $(MAKE_COAP_DTLS_KEYSTORE)} + endif + endif diff --git a/os/net/app-layer/coap/coap-keystore-simple.c b/os/net/app-layer/coap/coap-keystore-simple.c index 1d3ded722..e195f1b33 100644 --- a/os/net/app-layer/coap/coap-keystore-simple.c +++ b/os/net/app-layer/coap/coap-keystore-simple.c @@ -40,16 +40,10 @@ #include "coap-keystore.h" #include -/* #ifndef PSK_DEFAULT_IDENTITY */ -/* #define PSK_DEFAULT_IDENTITY "Client_identity" */ -/* #endif /\* PSK_DEFAULT_IDENTITY *\/ */ - -/* #ifndef PSK_DEFAULT_KEY */ -/* #define PSK_DEFAULT_KEY "secretPSK" */ -/* #endif /\* PSK_DEFAULT_KEY *\/ */ -/*---------------------------------------------------------------------------*/ #ifdef WITH_DTLS -#if defined(PSK_DEFAULT_IDENTITY) && defined(PSK_DEFAULT_KEY) +#ifdef COAP_DTLS_PSK_DEFAULT_IDENTITY +#ifdef COAP_DTLS_PSK_DEFAULT_KEY +/*---------------------------------------------------------------------------*/ static int get_default_psk_info(const coap_endpoint_t *address_info, coap_keystore_psk_entry_t *info) @@ -57,17 +51,18 @@ get_default_psk_info(const coap_endpoint_t *address_info, if(info != NULL) { if(info->identity == NULL || info->identity_len == 0) { /* Identity requested */ - info->identity = (uint8_t *)PSK_DEFAULT_IDENTITY; - info->identity_len = strlen(PSK_DEFAULT_IDENTITY); + info->identity = (uint8_t *)COAP_DTLS_PSK_DEFAULT_IDENTITY; + info->identity_len = strlen(COAP_DTLS_PSK_DEFAULT_IDENTITY); return 1; } - if(info->identity_len != strlen(PSK_DEFAULT_IDENTITY) || - memcmp(info->identity, PSK_DEFAULT_IDENTITY, info->identity_len) != 0) { + if(info->identity_len != strlen(COAP_DTLS_PSK_DEFAULT_IDENTITY) || + memcmp(info->identity, COAP_DTLS_PSK_DEFAULT_IDENTITY, + info->identity_len) != 0) { /* Identity not matching */ return 0; } - info->key = (uint8_t *)PSK_DEFAULT_KEY; - info->key_len = strlen(PSK_DEFAULT_KEY); + info->key = (uint8_t *)COAP_DTLS_PSK_DEFAULT_KEY; + info->key_len = strlen(COAP_DTLS_PSK_DEFAULT_KEY); return 1; } return 0; @@ -75,16 +70,22 @@ get_default_psk_info(const coap_endpoint_t *address_info, static const coap_keystore_t simple_key_store = { .coap_get_psk_info = get_default_psk_info }; -#endif /* defined(PSK_DEFAULT_IDENTITY) && defined(PSK_DEFAULT_KEY) */ +/*---------------------------------------------------------------------------*/ +#endif /* COAP_DTLS_PSK_DEFAULT_KEY */ +#endif /* COAP_DTLS_PSK_DEFAULT_IDENTITY */ #endif /* WITH_DTLS */ /*---------------------------------------------------------------------------*/ void -coap_store_simple_init(void) +coap_keystore_simple_init(void) { #ifdef WITH_DTLS -#if defined(PSK_DEFAULT_IDENTITY) && defined(PSK_DEFAULT_KEY) +#ifdef COAP_DTLS_PSK_DEFAULT_IDENTITY +#ifdef COAP_DTLS_PSK_DEFAULT_KEY + coap_set_keystore(&simple_key_store); -#endif /* defined(PSK_DEFAULT_IDENTITY) && defined(PSK_DEFAULT_KEY) */ + +#endif /* COAP_DTLS_PSK_DEFAULT_KEY */ +#endif /* COAP_DTLS_PSK_DEFAULT_IDENTITY */ #endif /* WITH_DTLS */ } /*---------------------------------------------------------------------------*/ diff --git a/os/net/app-layer/coap/coap-keystore-simple.h b/os/net/app-layer/coap/coap-keystore-simple.h index 7f13853fb..6e76927e5 100644 --- a/os/net/app-layer/coap/coap-keystore-simple.h +++ b/os/net/app-layer/coap/coap-keystore-simple.h @@ -39,6 +39,14 @@ #ifndef COAP_KEYSTORE_SIMPLE_H_ #define COAP_KEYSTORE_SIMPLE_H_ -void coap_keystore_simple(void); +/* + * Registers a simple CoAP DTLS keystore with fixed PSK credentials. + * + * The credentials can be configured in project-conf.h + * + * #define COAP_DTLS_PSK_DEFAULT_IDENTITY "user" + * #define COAP_DTLS_PSK_DEFAULT_KEY "password" + */ +void coap_keystore_simple_init(void); #endif /* COAP_KEYSTORE_SIMPLE_H_ */ diff --git a/os/net/app-layer/coap/coap-uip.c b/os/net/app-layer/coap/coap-uip.c index b6ab6064f..61fdf49f0 100644 --- a/os/net/app-layer/coap/coap-uip.c +++ b/os/net/app-layer/coap/coap-uip.c @@ -46,6 +46,7 @@ #include "coap-transactions.h" #include "coap-constants.h" #include "coap-keystore.h" +#include "coap-keystore-simple.h" #if UIP_CONF_IPV6_RPL @@ -117,9 +118,6 @@ coap_endpoint_copy(coap_endpoint_t *destination, uip_ipaddr_copy(&destination->ipaddr, &from->ipaddr); destination->port = from->port; destination->secure = from->secure; - - PRINTF("EP copy: from sec:%d to sec:%d\n", from->secure, - destination->secure); } /*---------------------------------------------------------------------------*/ int @@ -296,8 +294,12 @@ coap_transport_init(void) #ifdef WITH_DTLS dtls_init(); dtls_set_log_level(8); -#endif /* WITH_DTLS */ +#if COAP_DTLS_KEYSTORE_CONF_WITH_SIMPLE + coap_keystore_simple_init(); +#endif /* COAP_DTLS_KEYSTORE_CONF_WITH_SIMPLE */ + +#endif /* WITH_DTLS */ } /*---------------------------------------------------------------------------*/ #ifdef WITH_DTLS diff --git a/os/services/lwm2m/lwm2m-security.c b/os/services/lwm2m/lwm2m-security.c index e7c8a4bde..b680acdc7 100644 --- a/os/services/lwm2m/lwm2m-security.c +++ b/os/services/lwm2m/lwm2m-security.c @@ -67,12 +67,6 @@ #define PRINTEP(ep) #endif -#ifdef LWM2M_SECURITY_CONF_REGISTER_KEY_STORE -#define LWM2M_SECURITY_REGISTER_KEY_STORE LWM2M_SECURITY_CONF_REGISTER_KEY_STORE -#else /* LWM2M_SECURITY_CONF_REGISTER_KEY_STORE */ -#define LWM2M_SECURITY_REGISTER_KEY_STORE 1 -#endif /* LWM2M_SECURITY_CONF_REGISTER_KEY_STORE */ - #define MAX_COUNT LWM2M_SERVER_MAX_COUNT static lwm2m_status_t lwm2m_callback(lwm2m_object_instance_t *object, @@ -357,7 +351,7 @@ static lwm2m_object_t reg_object = { }; /*---------------------------------------------------------------------------*/ #ifdef WITH_DTLS -#if LWM2M_SECURITY_REGISTER_KEY_STORE +#if COAP_DTLS_KEYSTORE_CONF_WITH_LWM2M static int get_psk_info(const coap_endpoint_t *address_info, coap_keystore_psk_entry_t *info) @@ -431,15 +425,10 @@ get_psk_info(const coap_endpoint_t *address_info, info->key_len = e->secret_key_len; return 1; } -#endif /* LWM2M_SECURITY_REGISTER_KEY_STORE */ -#endif /* WITH_DTLS */ -/*---------------------------------------------------------------------------*/ -#ifdef WITH_DTLS -#if LWM2M_SECURITY_REGISTER_KEY_STORE static const coap_keystore_t key_store = { .coap_get_psk_info = get_psk_info }; -#endif /* LWM2M_SECURITY_REGISTER_KEY_STORE */ +#endif /* COAP_DTLS_KEYSTORE_CONF_WITH_LWM2M */ #endif /* WITH_DTLS */ /*---------------------------------------------------------------------------*/ void @@ -447,7 +436,7 @@ lwm2m_security_init(void) { int i; - PRINTF("*** Init lwm2m-security\n"); + PRINTF("lwm2m-sec: init\n"); list_init(instances_list); @@ -457,11 +446,15 @@ lwm2m_security_init(void) if(lwm2m_engine_add_generic_object(®_object)) { #ifdef WITH_DTLS -#if LWM2M_SECURITY_REGISTER_KEY_STORE +#if COAP_DTLS_KEYSTORE_CONF_WITH_LWM2M /* Security object handler added - register keystore */ coap_set_keystore(&key_store); -#endif /* LWM2M_SECURITY_REGISTER_KEY_STORE */ + PRINTF("lwm2m-sec: registered keystore\n"); +#endif /* COAP_DTLS_KEYSTORE_CONF_WITH_LWM2M */ #endif /* WITH_DTLS */ + + } else { + PRINTF("lwm2m-sec: failed to register\n"); } } /*---------------------------------------------------------------------------*/ From 082f4b920c4da1c859b1d830ce211229bfabac16 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Thu, 26 Oct 2017 23:22:44 +0200 Subject: [PATCH 08/51] ipso-objects: updated IPSO objects sensor/controllers to latest LWM2M API. Added macros to setup IPSO sensor and control template data structs. --- examples/ipso-objects/example-ipso-objects.c | 75 ++++----- examples/lwm2m/standalone/ipso-control-test.c | 35 ++-- examples/lwm2m/standalone/ipso-sensor-temp.c | 68 ++++---- .../ipso-objects/ipso-control-template.c | 13 +- .../ipso-objects/ipso-control-template.h | 9 +- os/services/ipso-objects/ipso-leds-control.c | 153 +++--------------- os/services/ipso-objects/ipso-light-control.c | 153 +++--------------- os/services/ipso-objects/ipso-objects.c | 10 +- .../ipso-objects/ipso-sensor-template.h | 8 + os/services/ipso-objects/ipso-temperature.c | 22 ++- 10 files changed, 150 insertions(+), 396 deletions(-) diff --git a/examples/ipso-objects/example-ipso-objects.c b/examples/ipso-objects/example-ipso-objects.c index 811ad7732..ee4b992e4 100644 --- a/examples/ipso-objects/example-ipso-objects.c +++ b/examples/ipso-objects/example-ipso-objects.c @@ -94,7 +94,7 @@ read_bar_value(const ipso_sensor_t *s, int32_t *value) } /* LED control */ static lwm2m_status_t -leds_set_val(uint8_t value) +leds_set_val(ipso_control_t *control, uint8_t value) { if(value > 0) { leds_on(LEDS_YELLOW); @@ -104,56 +104,37 @@ leds_set_val(uint8_t value) return LWM2M_STATUS_OK; } /*---------------------------------------------------------------------------*/ -static ipso_sensor_value_t temp_value; -static ipso_sensor_value_t hum_value; -static ipso_sensor_value_t lux_value; -static ipso_sensor_value_t bar_value; -static ipso_control_t led_control = { - .reg_object.object_id = 3311, - .reg_object.instance_id = 0, - .set_value = leds_set_val -}; +IPSO_CONTROL(led_control, 3311, 0, leds_set_val); -static const ipso_sensor_t temp_sensor = { - .object_id = 3303, - .sensor_value = &temp_value, - .max_range = 100000, /* 100 cel milli celcius */ - .min_range = -10000, /* -10 cel milli celcius */ - .get_value_in_millis = read_temp_value, - .unit = "Cel", - .update_interval = 30 -}; +IPSO_SENSOR(temp_sensor, 3303, read_temp_value, + .max_range = 100000, /* 100 cel milli celcius */ + .min_range = -10000, /* -10 cel milli celcius */ + .unit = "Cel", + .update_interval = 30 + ); -static const ipso_sensor_t hum_sensor = { - .object_id = 3304, - .sensor_value = &hum_value, - .max_range = 100000, /* 100 % RH */ - .min_range = 0, - .get_value_in_millis = read_hum_value, - .unit = "% RH", - .update_interval = 30 -}; -static const ipso_sensor_t lux_sensor = { - .object_id = 3301, - .sensor_value = &lux_value, - .max_range = 100000, - .min_range = -10000, - .get_value_in_millis = read_lux_value, - .unit = "LUX", - .update_interval = 30 -}; -static const ipso_sensor_t bar_sensor = { - .object_id = 3315, - .sensor_value = &bar_value, - .max_range = 100000, /* 100 cel milli celcius */ - .min_range = -10000, /* -10 cel milli celcius */ - .get_value_in_millis = read_bar_value, - .unit = "hPa", - .update_interval = 30 -}; +IPSO_SENSOR(hum_sensor, 3304, read_hum_value, + .max_range = 100000, /* 100 % RH */ + .min_range = 0, + .unit = "% RH", + .update_interval = 30 + ); -#endif +IPSO_SENSOR(lux_sensor, 3301, read_lux_value, + .max_range = 100000, + .min_range = -10000, + .unit = "LUX", + .update_interval = 30 + ); + +IPSO_SENSOR(bar_sensor, 3315, read_bar_value, + .max_range = 100000, /* 100 cel milli celcius */ + .min_range = -10000, /* -10 cel milli celcius */ + .unit = "hPa", + .update_interval = 30 + ); +#endif /* BOARD_SENSORTAG */ PROCESS(example_ipso_objects, "IPSO object example"); AUTOSTART_PROCESSES(&example_ipso_objects); diff --git a/examples/lwm2m/standalone/ipso-control-test.c b/examples/lwm2m/standalone/ipso-control-test.c index 63e6dc120..394659e74 100644 --- a/examples/lwm2m/standalone/ipso-control-test.c +++ b/examples/lwm2m/standalone/ipso-control-test.c @@ -35,51 +35,44 @@ /** * \file - * Implementation of OMA LWM2M / IPSO Generic Sensor + * Implementation of OMA LWM2M / IPSO Generic Control * \author * Joakim Eriksson * Niclas Finne */ -#include #include "lwm2m-object.h" #include "lwm2m-engine.h" #include "coap-engine.h" -#include "ipso-sensor-template.h" #include "ipso-control-template.h" -#include +#include #include +#include -static lwm2m_status_t set_value(uint8_t value); -static lwm2m_status_t set_light_value(uint8_t value); +static lwm2m_status_t set_value(ipso_control_t *control, uint8_t value); +static lwm2m_status_t set_light_value(ipso_control_t *control, uint8_t value); -static ipso_control_t test_control = { - .reg_object.object_id = 3306, - .reg_object.instance_id = 0, - .set_value = set_value, -}; +/* Name, Object ID, Instance ID, set_value callback */ +IPSO_CONTROL(test_control, 3306, 0, set_value); + +IPSO_CONTROL(light_control, 3311, 0, set_light_value); -static ipso_control_t test_control2 = { - .reg_object.object_id = 3311, - .reg_object.instance_id = 0, - .set_value = set_light_value, -}; /*---------------------------------------------------------------------------*/ static lwm2m_status_t -set_value(uint8_t value) +set_value(ipso_control_t *control, uint8_t value) { /* do something with the value! */ printf("Value set to: %u before: %u\n", value, - ipso_control_get_value(&test_control)); + ipso_control_get_value(control)); return LWM2M_STATUS_OK; } /*---------------------------------------------------------------------------*/ static lwm2m_status_t -set_light_value(uint8_t value) +set_light_value(ipso_control_t *control, uint8_t value) { /* do something with the value! */ printf("Light value set to: %u before: %u\n", value, - ipso_control_get_value(&test_control2)); + ipso_control_get_value(control)); return LWM2M_STATUS_OK; } /*---------------------------------------------------------------------------*/ @@ -87,7 +80,7 @@ void ipso_control_test_init(void) { ipso_control_add(&test_control); - ipso_control_add(&test_control2); + ipso_control_add(&light_control); } /*---------------------------------------------------------------------------*/ /** @} */ diff --git a/examples/lwm2m/standalone/ipso-sensor-temp.c b/examples/lwm2m/standalone/ipso-sensor-temp.c index 010ce7ea2..6cbd0784e 100644 --- a/examples/lwm2m/standalone/ipso-sensor-temp.c +++ b/examples/lwm2m/standalone/ipso-sensor-temp.c @@ -41,73 +41,59 @@ * Niclas Finne */ -#include #include "lwm2m-object.h" #include "lwm2m-engine.h" #include "coap-engine.h" #include "ipso-sensor-template.h" +#include #include -uint32_t temp = 19000; -uint32_t hum = 30000; +static uint32_t temp = 19000; +static uint32_t hum = 30000; -ipso_sensor_value_t temp_value; -ipso_sensor_value_t temp_value2; -ipso_sensor_value_t hum_value; +static lwm2m_status_t get_temp_value(const ipso_sensor_t *sensor, int32_t *value); +static lwm2m_status_t get_hum_value(const ipso_sensor_t *sensor, int32_t *value); -lwm2m_status_t get_temp_value(const ipso_sensor_t *sensor, int32_t *value); -lwm2m_status_t get_hum_value(const ipso_sensor_t *sensor, int32_t *value); +IPSO_SENSOR(temp_sensor, 3303, get_temp_value, + .max_range = 120000, /* milli celcius */ + .min_range = -30000, /* milli celcius */ + .unit = "Cel", + .update_interval = 10 + ); -static const ipso_sensor_t temp_sensor = { - .object_id = 3303, - .sensor_value = &temp_value, - .max_range = 120000, /* milli celcius */ - .min_range = -30000, /* milli celcius */ - .get_value_in_millis = get_temp_value, - .unit = "Cel", - .update_interval = 10 -}; - -static const ipso_sensor_t temp_sensor2 = { - .object_id = 3303, - .sensor_value = &temp_value2, - .max_range = 120000, /* milli celcius */ - .min_range = -30000, /* milli celcius */ - .get_value_in_millis = get_temp_value, - .unit = "Cel", - .update_interval = 10 -}; +IPSO_SENSOR(temp_sensor2, 3303, get_temp_value, + .max_range = 120000, /* milli celcius */ + .min_range = -30000, /* milli celcius */ + .unit = "Cel", + .update_interval = 10 + ); /*---------------------------------------------------------------------------*/ -static const ipso_sensor_t hum_sensor = { - .object_id = 3304, - .instance_id = 12, - .sensor_value = &hum_value, - .max_range = 100000, /* milli */ - .min_range = 0, /* milli */ - .get_value_in_millis = get_hum_value, - .unit = "%", - .update_interval = 10 -}; +IPSO_SENSOR(hum_sensor, 3304, get_hum_value, + .instance_id = 12, + .max_range = 100000, /* milli */ + .min_range = 0, /* milli */ + .unit = "%", + .update_interval = 10 + ); /*---------------------------------------------------------------------------*/ -lwm2m_status_t +static lwm2m_status_t get_temp_value(const ipso_sensor_t *sensor, int32_t *value) { *value = temp++; return LWM2M_STATUS_OK; } /*---------------------------------------------------------------------------*/ -lwm2m_status_t +static lwm2m_status_t get_hum_value(const ipso_sensor_t *sensor, int32_t *value) { - *value = temp++; + *value = hum++; return LWM2M_STATUS_OK; } /*---------------------------------------------------------------------------*/ - void ipso_sensor_temp_init(void) { diff --git a/os/services/ipso-objects/ipso-control-template.c b/os/services/ipso-objects/ipso-control-template.c index 4d0f28d6b..1383bcd78 100644 --- a/os/services/ipso-objects/ipso-control-template.c +++ b/os/services/ipso-objects/ipso-control-template.c @@ -47,7 +47,14 @@ #include "coap-timer.h" #include #include + +#define DEBUG 0 +#if DEBUG #include +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif #define IPSO_ONOFF 5850 #define IPSO_DIMMER 5851 @@ -88,7 +95,7 @@ ipso_control_set_value(ipso_control_t *control, uint8_t value) if(value == 0) { if(was_on) { /* Turn off */ - status = control->set_value(0); + status = control->set_value(control, 0); if(status == LWM2M_STATUS_OK) { control->value &= 0x7f; control->on_time += @@ -103,7 +110,7 @@ ipso_control_set_value(ipso_control_t *control, uint8_t value) value |= 0x80; if(value != control->value) { - status = control->set_value(value & 0x7f); + status = control->set_value(control, value & 0x7f); if(status == LWM2M_STATUS_OK) { control->value = value; if(! was_on) { @@ -137,7 +144,7 @@ lwm2m_callback(lwm2m_object_instance_t *object, lwm2m_context_t *ctx) if(ipso_control_is_on(control)) { v += (coap_timer_uptime() - control->last_on_time) / 1000; } - printf("ON-TIME: %"PRId32" (last on: %"PRIu32"\n", v, control->on_time); + PRINTF("ON-TIME: %"PRId32" (last on: %"PRIu32"\n", v, control->on_time); break; default: return LWM2M_STATUS_ERROR; diff --git a/os/services/ipso-objects/ipso-control-template.h b/os/services/ipso-objects/ipso-control-template.h index 0e71a17a4..dfbd7076b 100644 --- a/os/services/ipso-objects/ipso-control-template.h +++ b/os/services/ipso-objects/ipso-control-template.h @@ -51,7 +51,8 @@ typedef struct ipso_control ipso_control_t; #define IPSO_CONTROL_USE_DIMMER 0x01 -typedef lwm2m_status_t (*ipso_control_set_value_t)(uint8_t v); +typedef lwm2m_status_t (*ipso_control_set_value_t)(ipso_control_t *control, + uint8_t v); /* Values of the IPSO control object */ struct ipso_control { @@ -63,6 +64,12 @@ struct ipso_control { ipso_control_set_value_t set_value; }; +#define IPSO_CONTROL(name, oid, iid, setv) \ + static ipso_control_t name = { \ + .reg_object.object_id = oid, \ + .reg_object.instance_id = iid, \ + .set_value = setv \ + } int ipso_control_add(ipso_control_t *control); int ipso_control_remove(ipso_control_t *control); diff --git a/os/services/ipso-objects/ipso-leds-control.c b/os/services/ipso-objects/ipso-leds-control.c index 7023d800c..74e599c14 100644 --- a/os/services/ipso-objects/ipso-leds-control.c +++ b/os/services/ipso-objects/ipso-leds-control.c @@ -44,6 +44,7 @@ #include "lwm2m-object.h" #include "lwm2m-engine.h" +#include "ipso-control-template.h" #include "dev/leds.h" #include @@ -61,141 +62,32 @@ #define LEDS_CONTROL_NUMBER 1 #endif -#if 0 -struct led_state { - unsigned long last_on_time; - uint32_t total_on_time; - uint8_t is_on; +typedef struct led_state { + ipso_control_t control; uint8_t led_value; -}; +} led_state_t; -static struct led_state states[LEDS_CONTROL_NUMBER]; -static lwm2m_instance_t leds_control_instances[LEDS_CONTROL_NUMBER]; +static led_state_t leds_controls[LEDS_CONTROL_NUMBER]; /*---------------------------------------------------------------------------*/ -static int -read_state(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outsize) +static lwm2m_status_t +set_value(ipso_control_t *control, uint8_t value) { - uint8_t idx = ctx->object_instance_index; - if(idx >= LEDS_CONTROL_NUMBER) { - return 0; - } - return lwm2m_object_write_boolean(ctx, outbuf, outsize, - states[idx].is_on ? 1 : 0); -} -/*---------------------------------------------------------------------------*/ -static int -write_state(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t insize, - uint8_t *outbuf, size_t outsize) -{ - int value; - size_t len; + led_state_t *state; - uint8_t idx = ctx->object_instance_index; - if(idx >= LEDS_CONTROL_NUMBER) { - return 0; - } + state = (led_state_t *)control; - len = lwm2m_object_read_boolean(ctx, inbuf, insize, &value); - if(len > 0) { - if(value) { - if(!states[idx].is_on) { - states[idx].is_on = 1; - states[idx].last_on_time = clock_seconds(); #if PLATFORM_HAS_LEDS - leds_on(states[idx].led_value); -#endif /* PLATFORM_HAS_LEDS */ - } - } else if(states[idx].is_on) { - states[idx].total_on_time += clock_seconds() - states[idx].last_on_time; - states[idx].is_on = 0; -#if PLATFORM_HAS_LEDS - leds_off(states[idx].led_value); -#endif /* PLATFORM_HAS_LEDS */ - } + if(value) { + leds_on(state->led_value); } else { - PRINTF("IPSO leds control - ignored illegal write to on/off\n"); + leds_off(state->led_value); } - return len; -} -/*---------------------------------------------------------------------------*/ -static char * -get_color(int value) { - switch(value) { - case LEDS_GREEN: - return "Green"; - case LEDS_RED: - return "Red"; - case LEDS_BLUE: - return "Blue"; - } - return "None"; -} +#endif /* PLATFORM_HAS_LEDS */ -static int -read_color(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outsize) -{ - char *value; - uint8_t idx = ctx->object_instance_index; - if(idx >= LEDS_CONTROL_NUMBER) { - return 0; - } - value = get_color(states[idx].led_value); - return lwm2m_object_write_string(ctx, outbuf, outsize, - value, strlen(value)); + return LWM2M_STATUS_OK; } /*---------------------------------------------------------------------------*/ static int -read_on_time(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outsize) -{ - unsigned long now; - uint8_t idx = ctx->object_instance_index; - if(idx >= LEDS_CONTROL_NUMBER) { - return 0; - } - - if(states[idx].is_on) { - /* Update the on time */ - now = clock_seconds(); - states[idx].total_on_time += now - states[idx].last_on_time; - states[idx].last_on_time = now; - } - return lwm2m_object_write_int(ctx, outbuf, outsize, - (int32_t)states[idx].total_on_time); -} -/*---------------------------------------------------------------------------*/ -static int -write_on_time(lwm2m_context_t *ctx, - const uint8_t *inbuf, size_t insize, - uint8_t *outbuf, size_t outsize) -{ - int32_t value; - size_t len; - uint8_t idx = ctx->object_instance_index; - if(idx >= LEDS_CONTROL_NUMBER) { - return 0; - } - - len = lwm2m_object_read_int(ctx, inbuf, insize, &value); - if(len > 0 && value == 0) { - PRINTF("IPSO leds control - reset On Time\n"); - states[idx].total_on_time = 0; - if(states[idx].is_on) { - states[idx].last_on_time = clock_seconds(); - } - } else { - PRINTF("IPSO leds control - ignored illegal write to On Time\n"); - } - return len; -} -/*---------------------------------------------------------------------------*/ -LWM2M_RESOURCES(leds_control_resources, - LWM2M_RESOURCE_CALLBACK(5850, { read_state, write_state, NULL }), - LWM2M_RESOURCE_CALLBACK(5706, { read_color, NULL, NULL }), - LWM2M_RESOURCE_CALLBACK(5852, { read_on_time, write_on_time, NULL }) - ); -LWM2M_OBJECT(leds_control, 3311, leds_control_instances); -/*---------------------------------------------------------------------------*/ -static int bit_no(int bit) { int i; @@ -212,26 +104,25 @@ bit_no(int bit) } return 0; } - +/*---------------------------------------------------------------------------*/ void ipso_leds_control_init(void) { - lwm2m_instance_t template = LWM2M_INSTANCE(0, leds_control_resources); + ipso_control_t *c; int i; /* Initialize the instances */ for(i = 0; i < LEDS_CONTROL_NUMBER; i++) { - leds_control_instances[i] = template; - leds_control_instances[i].id = i; - states[i].led_value = bit_no(i); + c = &leds_controls[i].control; + c->reg_object.object_id = 3311; + c->reg_object.instance_id = i; + c->set_value = set_value; + leds_controls[i].led_value = bit_no(i); + ipso_control_add(c); } - /* register this device and its handlers - the handlers automatically - sends in the object to handle */ - lwm2m_engine_register_object(&leds_control); PRINTF("IPSO leds control initialized with %u instances\n", LEDS_CONTROL_NUMBER); } /*---------------------------------------------------------------------------*/ -#endif /* 0 */ /** @} */ diff --git a/os/services/ipso-objects/ipso-light-control.c b/os/services/ipso-objects/ipso-light-control.c index d8575a0dc..97733b629 100644 --- a/os/services/ipso-objects/ipso-light-control.c +++ b/os/services/ipso-objects/ipso-light-control.c @@ -45,139 +45,29 @@ #include "ipso-objects.h" #include "lwm2m-object.h" #include "lwm2m-engine.h" +#include "ipso-control-template.h" -#if 0 #ifdef IPSO_LIGHT_CONTROL extern const struct ipso_objects_actuator IPSO_LIGHT_CONTROL; #endif /* IPSO_LIGHT_CONTROL */ -/*---------------------------------------------------------------------------*/ -static unsigned long last_on_time; -static uint32_t total_on_time; -static int dim_level = 0; -static uint8_t is_on = 0; -/*---------------------------------------------------------------------------*/ -static int -read_state(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outsize) -{ - return lwm2m_object_write_boolean(ctx, outbuf, outsize, is_on ? 1 : 0); -} -/*---------------------------------------------------------------------------*/ -static int -write_state(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t insize, - uint8_t *outbuf, size_t outsize) -{ - int value; - size_t len; - len = lwm2m_object_read_boolean(ctx, inbuf, insize, &value); - if(len > 0) { - if(value) { - if(!is_on) { - is_on = 1; - last_on_time = clock_seconds(); - } - } else { - if(is_on) { - total_on_time += clock_seconds() - last_on_time; - is_on = 0; - } - } +static lwm2m_status_t set_value(ipso_control_t *control, uint8_t value); + +IPSO_CONTROL(light_control, 3311, 0, set_value); +/*---------------------------------------------------------------------------*/ +static lwm2m_status_t +set_value(ipso_control_t *control, uint8_t value) +{ #ifdef IPSO_LIGHT_CONTROL - if(IPSO_LIGHT_CONTROL.set_on) { - IPSO_LIGHT_CONTROL.set_on(value); - } else if(IPSO_LIGHT_CONTROL.set_dim_level) { - dim_level = value ? 100 : 0; - IPSO_LIGHT_CONTROL.set_dim_level(dim_level); - } + if(IPSO_LIGHT_CONTROL.set_dim_level) { + IPSO_LIGHT_CONTROL.set_dim_level(value); + } else if(IPSO_LIGHT_CONTROL.set_on) { + IPSO_LIGHT_CONTROL.set_on(value); + } #endif /* IPSO_LIGHT_CONTROL */ - } - return len; + return LWM2M_STATUS_OK; } /*---------------------------------------------------------------------------*/ -static int -read_dim(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outsize) -{ - return lwm2m_object_write_int(ctx, outbuf, outsize, dim_level); -} -/*---------------------------------------------------------------------------*/ -static int -write_dim(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t insize, - uint8_t *outbuf, size_t outsize) -{ - int32_t value; - size_t len; - - len = lwm2m_object_read_int(ctx, inbuf, insize, &value); - if(len > 0) { - if(value < 0) { - value = 0; - } else if(value > 100) { - value = 100; - } - - dim_level = value; - if(value > 0) { - if(!is_on) { - is_on = 1; - last_on_time = clock_seconds(); - } - } else { - if(is_on) { - total_on_time += clock_seconds() - last_on_time; - is_on = 0; - } - } -#ifdef IPSO_LIGHT_CONTROL - if(IPSO_LIGHT_CONTROL.set_dim_level) { - IPSO_LIGHT_CONTROL.set_dim_level(dim_level); - } else if(IPSO_LIGHT_CONTROL.set_on) { - IPSO_LIGHT_CONTROL.set_on(is_on); - } -#endif /* IPSO_LIGHT_CONTROL */ - } - return len; -} -/*---------------------------------------------------------------------------*/ -static int -read_on_time(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outsize) -{ - unsigned long now; - if(is_on) { - /* Update the on time */ - now = clock_seconds(); - total_on_time += now - last_on_time; - last_on_time = now; - } - return lwm2m_object_write_int(ctx, outbuf, outsize, (int32_t)total_on_time); -} -/*---------------------------------------------------------------------------*/ -static int -write_on_time(lwm2m_context_t *ctx, - const uint8_t *inbuf, size_t insize, - uint8_t *outbuf, size_t outsize) -{ - int32_t value; - size_t len; - - len = lwm2m_object_read_int(ctx, inbuf, insize, &value); - if(len > 0 && value == 0) { - total_on_time = 0; - if(is_on) { - last_on_time = clock_seconds(); - } - } - return len; -} -/*---------------------------------------------------------------------------*/ -LWM2M_RESOURCES(light_control_resources, - LWM2M_RESOURCE_CALLBACK(5850, { read_state, write_state, NULL }), - LWM2M_RESOURCE_CALLBACK(5851, { read_dim, write_dim, NULL }), - LWM2M_RESOURCE_CALLBACK(5852, { read_on_time, write_on_time, NULL }), - ); -LWM2M_INSTANCES(light_control_instances, - LWM2M_INSTANCE(0, light_control_resources)); -LWM2M_OBJECT(light_control, 3311, light_control_instances); -/*---------------------------------------------------------------------------*/ void ipso_light_control_init(void) { @@ -185,20 +75,15 @@ ipso_light_control_init(void) if(IPSO_LIGHT_CONTROL.init) { IPSO_LIGHT_CONTROL.init(); } - if(IPSO_LIGHT_CONTROL.is_on) { - is_on = IPSO_LIGHT_CONTROL.is_on(); - } if(IPSO_LIGHT_CONTROL.get_dim_level) { - dim_level = IPSO_LIGHT_CONTROL.get_dim_level(); - if(dim_level > 0 && IPSO_LIGHT_CONTROL.is_on == NULL) { - is_on = 1; - } + ipso_control_set_value(&light_control, + IPSO_LIGHT_CONTROL.get_dim_level()); + } else if(IPSO_LIGHT_CONTROL.is_on) { + ipso_control_set_on(&light_control, IPSO_LIGHT_CONTROL.is_on()); } #endif /* IPSO_LIGHT_CONTROL */ - last_on_time = clock_seconds(); - lwm2m_engine_register_object(&light_control); + ipso_control_add(&light_control); } /*---------------------------------------------------------------------------*/ -#endif /* 0 */ /** @} */ diff --git a/os/services/ipso-objects/ipso-objects.c b/os/services/ipso-objects/ipso-objects.c index e73606621..1e8243f94 100644 --- a/os/services/ipso-objects/ipso-objects.c +++ b/os/services/ipso-objects/ipso-objects.c @@ -56,11 +56,11 @@ ipso_objects_init(void) ipso_button_init(); #endif -/* #ifdef IPSO_LIGHT_CONTROL */ -/* ipso_light_control_init(); */ -/* #elif PLATFORM_HAS_LEDS */ -/* ipso_leds_control_init(); */ -/* #endif */ +#ifdef IPSO_LIGHT_CONTROL + ipso_light_control_init(); +#elif PLATFORM_HAS_LEDS + ipso_leds_control_init(); +#endif } /*---------------------------------------------------------------------------*/ /** @} */ diff --git a/os/services/ipso-objects/ipso-sensor-template.h b/os/services/ipso-objects/ipso-sensor-template.h index ce13effcb..65213759f 100644 --- a/os/services/ipso-objects/ipso-sensor-template.h +++ b/os/services/ipso-objects/ipso-sensor-template.h @@ -76,6 +76,14 @@ struct ipso_sensor { ipso_sensor_value_t *sensor_value; }; +#define IPSO_SENSOR(name, oid, get_value, ...) \ + static ipso_sensor_value_t name##_value; \ + static const ipso_sensor_t name = { \ + .object_id = oid, \ + .sensor_value = &name##_value, \ + .get_value_in_millis = get_value, \ + __VA_ARGS__ \ + } int ipso_sensor_add(const ipso_sensor_t *sensor); int ipso_sensor_remove(const ipso_sensor_t *sensor); diff --git a/os/services/ipso-objects/ipso-temperature.c b/os/services/ipso-objects/ipso-temperature.c index c1b7748e3..c27d8b6ba 100644 --- a/os/services/ipso-objects/ipso-temperature.c +++ b/os/services/ipso-objects/ipso-temperature.c @@ -59,22 +59,18 @@ extern const struct ipso_objects_sensor IPSO_TEMPERATURE; #define IPSO_TEMPERATURE_MAX 80000 #endif -lwm2m_status_t get_temp_value(const ipso_sensor_t *sensor, int32_t *value); +static lwm2m_status_t get_temp_value(const ipso_sensor_t *sensor, + int32_t *value); -static ipso_sensor_value_t temp_value; - -static const ipso_sensor_t temp_sensor = { - .object_id = 3303, - .sensor_value = &temp_value, - .max_range = IPSO_TEMPERATURE_MAX, /* milli celcius */ - .min_range = IPSO_TEMPERATURE_MIN, /* milli celcius */ - .get_value_in_millis = get_temp_value, - .unit = "Cel", - .update_interval = 10 -}; +IPSO_SENSOR(temp_sensor, 3303, get_temp_value, + .max_range = IPSO_TEMPERATURE_MAX, /* milli celcius */ + .min_range = IPSO_TEMPERATURE_MIN, /* milli celcius */ + .unit = "Cel", + .update_interval = 10 + ); /*---------------------------------------------------------------------------*/ -lwm2m_status_t +static lwm2m_status_t get_temp_value(const ipso_sensor_t *s, int32_t *value) { #ifdef IPSO_TEMPERATURE From 379a3fac2bb5dd26fa07b4ad54e35b3cd50dc3bf Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Thu, 26 Oct 2017 21:38:55 +0200 Subject: [PATCH 09/51] LWM2M fixed doxygen compile issues --- os/net/app-layer/coap/coap-separate.c | 2 +- os/services/ipso-objects/ipso-blockwise-test.c | 1 + os/services/ipso-objects/ipso-control-template.c | 1 + os/services/ipso-objects/ipso-sensor-template.c | 1 + os/services/ipso-objects/ipso-sensor-template.h | 1 + os/services/lwm2m/lwm2m-firmware.c | 3 ++- os/services/lwm2m/lwm2m-firmware.h | 2 +- os/services/lwm2m/lwm2m-rd-client.c | 6 ++++-- os/services/lwm2m/lwm2m-security.h | 3 ++- os/services/lwm2m/lwm2m-server.h | 3 ++- 10 files changed, 16 insertions(+), 7 deletions(-) diff --git a/os/net/app-layer/coap/coap-separate.c b/os/net/app-layer/coap/coap-separate.c index 45793f505..066dc74a7 100644 --- a/os/net/app-layer/coap/coap-separate.c +++ b/os/net/app-layer/coap/coap-separate.c @@ -71,7 +71,7 @@ coap_separate_reject() /*----------------------------------------------------------------------------*/ /** * \brief Initiate a separate response with an empty ACK - * \param request The request to accept + * \param coap_req The request to accept * \param separate_store A pointer to the data structure that will store the * relevant information for the response * diff --git a/os/services/ipso-objects/ipso-blockwise-test.c b/os/services/ipso-objects/ipso-blockwise-test.c index 532642969..3a557de2b 100644 --- a/os/services/ipso-objects/ipso-blockwise-test.c +++ b/os/services/ipso-objects/ipso-blockwise-test.c @@ -149,3 +149,4 @@ ipso_blockwise_test_init(void) lwm2m_engine_add_object(®_object); } +/** @} */ diff --git a/os/services/ipso-objects/ipso-control-template.c b/os/services/ipso-objects/ipso-control-template.c index 1383bcd78..23b53ef06 100644 --- a/os/services/ipso-objects/ipso-control-template.c +++ b/os/services/ipso-objects/ipso-control-template.c @@ -209,3 +209,4 @@ ipso_control_remove(ipso_control_t *control) return 1; } /*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/services/ipso-objects/ipso-sensor-template.c b/os/services/ipso-objects/ipso-sensor-template.c index 02f930c60..bf46ed5ae 100644 --- a/os/services/ipso-objects/ipso-sensor-template.c +++ b/os/services/ipso-objects/ipso-sensor-template.c @@ -236,3 +236,4 @@ ipso_sensor_remove(const ipso_sensor_t *sensor) return 1; } /*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/services/ipso-objects/ipso-sensor-template.h b/os/services/ipso-objects/ipso-sensor-template.h index 65213759f..375dbad7c 100644 --- a/os/services/ipso-objects/ipso-sensor-template.h +++ b/os/services/ipso-objects/ipso-sensor-template.h @@ -89,3 +89,4 @@ int ipso_sensor_add(const ipso_sensor_t *sensor); int ipso_sensor_remove(const ipso_sensor_t *sensor); #endif /* IPSO_SENSOR_TEMPLATE_H_ */ +/** @} */ diff --git a/os/services/lwm2m/lwm2m-firmware.c b/os/services/lwm2m/lwm2m-firmware.c index b51fb13ab..30c1a8229 100644 --- a/os/services/lwm2m/lwm2m-firmware.c +++ b/os/services/lwm2m/lwm2m-firmware.c @@ -29,7 +29,7 @@ */ /** - * \addtogroup + * \addtogroup lwm2m * @{ * * Code for firmware object of lwm2m @@ -165,3 +165,4 @@ lwm2m_firmware_init(void) lwm2m_engine_add_object(®_object); } /*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/services/lwm2m/lwm2m-firmware.h b/os/services/lwm2m/lwm2m-firmware.h index fb291b635..2b83922cd 100644 --- a/os/services/lwm2m/lwm2m-firmware.h +++ b/os/services/lwm2m/lwm2m-firmware.h @@ -29,7 +29,7 @@ */ /** - * \addtogroup + * \addtogroup lwm2m * @{ * * Code for firmware object of lwm2m diff --git a/os/services/lwm2m/lwm2m-rd-client.c b/os/services/lwm2m/lwm2m-rd-client.c index 4df4217e0..25400025e 100644 --- a/os/services/lwm2m/lwm2m-rd-client.c +++ b/os/services/lwm2m/lwm2m-rd-client.c @@ -62,7 +62,7 @@ #include "rpl.h" #endif /* UIP_CONF_IPV6_RPL */ -#define DEBUG 0 +#define DEBUG 1 #if DEBUG #include #define PRINTF(...) printf(__VA_ARGS__) @@ -395,7 +395,8 @@ produce_more_rd(void) rd_more = lwm2m_engine_set_rd_data(&outbuf, rd_block1); coap_set_payload(request, rd_data, outbuf.len); - PRINTF("Setting block1 in request - block: %d more: %d\n", rd_block1, rd_more); + PRINTF("Setting block1 in request - block: %d more: %d\n", + (int) rd_block1, (int) rd_more); coap_set_header_block1(request, rd_block1, rd_more, sizeof(rd_data)); coap_send_request(&rd_request_state, &session_info.server_ep, request, rd_callback); @@ -727,3 +728,4 @@ check_periodic_observations(void) /* TODO */ } /*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/services/lwm2m/lwm2m-security.h b/os/services/lwm2m/lwm2m-security.h index 7142c4a8e..3120388b7 100644 --- a/os/services/lwm2m/lwm2m-security.h +++ b/os/services/lwm2m/lwm2m-security.h @@ -29,7 +29,7 @@ */ /** - * \addtogroup oma-lwm2m + * \addtogroup lwm2m * @{ * */ @@ -71,3 +71,4 @@ int lwm2m_security_set_server_psk(lwm2m_security_server_t *server, void lwm2m_security_init(void); #endif /* LWM2M_SECURITY_H */ +/** @} */ diff --git a/os/services/lwm2m/lwm2m-server.h b/os/services/lwm2m/lwm2m-server.h index 9afaf547a..92968d138 100644 --- a/os/services/lwm2m/lwm2m-server.h +++ b/os/services/lwm2m/lwm2m-server.h @@ -29,7 +29,7 @@ */ /** - * \addtogroup oma-lwm2m + * \addtogroup lwm2m * @{ * */ @@ -57,3 +57,4 @@ lwm2m_server_t *lwm2m_server_add(uint16_t instance_id, void lwm2m_server_init(void); #endif /* LWM2M_SERVER_H */ +/** @} */ From 6fe4026686737806908ead4657f57f5f8517492d Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Fri, 27 Oct 2017 00:20:08 +0200 Subject: [PATCH 10/51] COAP: adapted CoAP examples to new API --- examples/coap/coap-example-client.c | 20 +- examples/coap/coap-example-server.c | 54 +++--- examples/coap/plugtest-server.c | 44 ++--- .../resources-plugtest/res-plugtest-create1.c | 18 +- .../resources-plugtest/res-plugtest-create2.c | 10 +- .../resources-plugtest/res-plugtest-create3.c | 18 +- .../res-plugtest-large-create.c | 26 +-- .../res-plugtest-large-update.c | 39 ++-- .../resources-plugtest/res-plugtest-large.c | 15 +- .../resources-plugtest/res-plugtest-links.c | 10 +- .../res-plugtest-locquery.c | 10 +- .../res-plugtest-longpath.c | 12 +- .../resources-plugtest/res-plugtest-multi.c | 25 +-- .../resources-plugtest/res-plugtest-obs.c | 47 ++--- .../resources-plugtest/res-plugtest-path.c | 15 +- .../resources-plugtest/res-plugtest-query.c | 15 +- .../res-plugtest-separate.c | 12 +- .../resources-plugtest/res-plugtest-test.c | 48 ++--- .../res-plugtest-validate.c | 30 +-- examples/coap/resources/res-b1-sep-b2.c | 9 +- examples/coap/resources/res-battery.c | 29 +-- examples/coap/resources/res-chunks.c | 15 +- examples/coap/resources/res-event.c | 13 +- examples/coap/resources/res-hello.c | 14 +- examples/coap/resources/res-leds.c | 15 +- examples/coap/resources/res-light.c | 39 ++-- examples/coap/resources/res-mirror.c | 39 ++-- examples/coap/resources/res-push.c | 19 +- examples/coap/resources/res-radio.c | 34 ++-- examples/coap/resources/res-separate.c | 11 +- examples/coap/resources/res-sht11.c | 36 ++-- examples/coap/resources/res-sub.c | 19 +- examples/coap/resources/res-temperature.c | 39 ++-- examples/coap/resources/res-toggle.c | 6 +- .../cc26xx/cc26xx-web-demo/cc26xx-web-demo.c | 2 +- .../cc26xx/cc26xx-web-demo/coap-server.c | 116 ++++++------ .../cc26xx-web-demo/resources/res-ble-advd.c | 17 +- .../cc26xx-web-demo/resources/res-device.c | 87 +++++---- .../cc26xx-web-demo/resources/res-leds.c | 11 +- .../cc26xx-web-demo/resources/res-net.c | 70 +++---- .../cc26xx-web-demo/resources/res-sensors.c | 81 ++++---- .../resources/res-toggle-leds.c | 14 +- .../very-sleepy-demo/very-sleepy-demo.c | 78 ++++---- .../jn516x/rpl/coap-dongle-node/dongle-node.c | 20 +- .../jn516x/rpl/coap-dr1175-node/dr1175-node.c | 154 +++++++-------- .../jn516x/rpl/coap-dr1199-node/dr1199-node.c | 179 +++++++++--------- .../tsch/tx-power-verification/node/node.c | 32 ++-- .../rpl-border-router/rpl-border-router.c | 34 ++-- .../tsch/uart1-test-node/uart1-test-node.c | 35 ++-- .../nrf52dk/coap-demo/Makefile | 6 +- .../nrf52dk/coap-demo/coap-client.c | 11 +- .../nrf52dk/coap-demo/coap-server.c | 10 +- .../nrf52dk/coap-demo/resources/res-leds.c | 35 ++-- 53 files changed, 928 insertions(+), 869 deletions(-) diff --git a/examples/coap/coap-example-client.c b/examples/coap/coap-example-client.c index 5ef8f4fce..0e021f2f0 100644 --- a/examples/coap/coap-example-client.c +++ b/examples/coap/coap-example-client.c @@ -42,6 +42,7 @@ #include "contiki.h" #include "contiki-net.h" #include "coap-engine.h" +#include "coap-blocking-api.h" #include "dev/button-sensor.h" #define DEBUG 0 @@ -60,6 +61,8 @@ #define SERVER_NODE(ipaddr) uip_ip6addr(ipaddr, 0xfe80, 0, 0, 0, 0x0212, 0x7402, 0x0002, 0x0202) /* cooja2 */ /* #define SERVER_NODE(ipaddr) uip_ip6addr(ipaddr, 0xbbbb, 0, 0, 0, 0, 0, 0, 0x1) */ +#define SERVER_EP "coap://[fe80::212:7402:0002:0202]" + #define LOCAL_PORT UIP_HTONS(COAP_DEFAULT_PORT + 1) #define REMOTE_PORT UIP_HTONS(COAP_DEFAULT_PORT) @@ -82,7 +85,7 @@ static int uri_switch = 0; /* This function is will be passed to COAP_BLOCKING_REQUEST() to handle responses. */ void -client_chunk_handler(void *response) +client_chunk_handler(coap_packet_t *response) { const uint8_t *chunk; @@ -92,14 +95,18 @@ client_chunk_handler(void *response) } PROCESS_THREAD(er_example_client, ev, data) { + coap_endpoint_t server_ep; PROCESS_BEGIN(); static coap_packet_t request[1]; /* This way the packet can be treated as pointer as usual. */ - SERVER_NODE(&server_ipaddr); + /* SERVER_NODE(&server_ipaddr); */ + + coap_endpoint_parse(SERVER_EP, strlen(SERVER_EP), + &server_ep); /* receives all CoAP messages */ - coap_init_engine(); + coap_engine_init(); etimer_set(&et, TOGGLE_INTERVAL * CLOCK_SECOND); @@ -122,11 +129,10 @@ PROCESS_THREAD(er_example_client, ev, data) coap_set_payload(request, (uint8_t *)msg, sizeof(msg) - 1); - PRINT6ADDR(&server_ipaddr); + coap_endpoint_print(&server_ep); PRINTF(" : %u\n", UIP_HTONS(REMOTE_PORT)); - COAP_BLOCKING_REQUEST(&server_ipaddr, REMOTE_PORT, request, - client_chunk_handler); + COAP_BLOCKING_REQUEST(&server_ep, request, client_chunk_handler); printf("\n--Done--\n"); @@ -145,7 +151,7 @@ PROCESS_THREAD(er_example_client, ev, data) PRINT6ADDR(&server_ipaddr); PRINTF(" : %u\n", UIP_HTONS(REMOTE_PORT)); - COAP_BLOCKING_REQUEST(&server_ipaddr, REMOTE_PORT, request, + COAP_BLOCKING_REQUEST(&server_ep, request, client_chunk_handler); printf("\n--Done--\n"); diff --git a/examples/coap/coap-example-server.c b/examples/coap/coap-example-server.c index 79c25d501..9d7be130a 100644 --- a/examples/coap/coap-example-server.c +++ b/examples/coap/coap-example-server.c @@ -31,7 +31,7 @@ /** * \file - * Erbium (Er) REST Engine example. + * Erbium (Er) CoAP Engine example. * \author * Matthias Kovatsch */ @@ -41,7 +41,7 @@ #include #include "contiki.h" #include "contiki-net.h" -#include "rest-engine.h" +#include "coap-engine.h" #if PLATFORM_HAS_BUTTON #include "dev/button-sensor.h" @@ -63,7 +63,7 @@ * Resources to be activated need to be imported through the extern keyword. * The build system automatically compiles the resources in the corresponding sub-directory. */ -extern resource_t +extern coap_resource_t res_hello, res_mirror, res_chunks, @@ -73,29 +73,29 @@ extern resource_t res_sub, res_b1_sep_b2; #if PLATFORM_HAS_LEDS -extern resource_t res_leds, res_toggle; +extern coap_resource_t res_leds, res_toggle; #endif #if PLATFORM_HAS_LIGHT #include "dev/light-sensor.h" -extern resource_t res_light; +extern coap_resource_t res_light; #endif #if PLATFORM_HAS_BATTERY #include "dev/battery-sensor.h" -extern resource_t res_battery; +extern coap_resource_t res_battery; #endif #if PLATFORM_HAS_TEMPERATURE #include "dev/temperature-sensor.h" -extern resource_t res_temperature; +extern coap_resource_t res_temperature; #endif /* -extern resource_t res_battery; +extern coap_resource_t res_battery; #endif #if PLATFORM_HAS_RADIO -extern resource_t res_radio; +extern coap_resource_t res_radio; #endif #if PLATFORM_HAS_SHT11 #include "dev/sht11/sht11-sensor.h" -extern resource_t res_sht11; +extern coap_resource_t res_sht11; #endif */ @@ -120,46 +120,46 @@ PROCESS_THREAD(er_example_server, ev, data) PRINTF("uIP buffer: %u\n", UIP_BUFSIZE); PRINTF("LL header: %u\n", UIP_LLH_LEN); PRINTF("IP+UDP header: %u\n", UIP_IPUDPH_LEN); - PRINTF("REST max chunk: %u\n", REST_MAX_CHUNK_SIZE); + PRINTF("CoAP max chunk: %u\n", COAP_MAX_CHUNK_SIZE); /* Initialize the REST engine. */ - rest_init_engine(); + coap_engine_init(); /* * Bind the resources to their Uri-Path. * WARNING: Activating twice only means alternate path, not two instances! * All static variables are the same for each URI path. */ - rest_activate_resource(&res_hello, "test/hello"); -/* rest_activate_resource(&res_mirror, "debug/mirror"); */ -/* rest_activate_resource(&res_chunks, "test/chunks"); */ -/* rest_activate_resource(&res_separate, "test/separate"); */ - 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"); */ + coap_activate_resource(&res_hello, "test/hello"); +/* coap_activate_resource(&res_mirror, "debug/mirror"); */ +/* coap_activate_resource(&res_chunks, "test/chunks"); */ +/* coap_activate_resource(&res_separate, "test/separate"); */ + coap_activate_resource(&res_push, "test/push"); +/* coap_activate_resource(&res_event, "sensors/button"); */ +/* coap_activate_resource(&res_sub, "test/sub"); */ +/* coap_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"); +/* coap_activate_resource(&res_leds, "actuators/leds"); */ + coap_activate_resource(&res_toggle, "actuators/toggle"); #endif #if PLATFORM_HAS_LIGHT - rest_activate_resource(&res_light, "sensors/light"); + coap_activate_resource(&res_light, "sensors/light"); SENSORS_ACTIVATE(light_sensor); #endif #if PLATFORM_HAS_BATTERY - rest_activate_resource(&res_battery, "sensors/battery"); + coap_activate_resource(&res_battery, "sensors/battery"); SENSORS_ACTIVATE(battery_sensor); #endif #if PLATFORM_HAS_TEMPERATURE - rest_activate_resource(&res_temperature, "sensors/temperature"); + coap_activate_resource(&res_temperature, "sensors/temperature"); SENSORS_ACTIVATE(temperature_sensor); #endif /* #if PLATFORM_HAS_RADIO - rest_activate_resource(&res_radio, "sensors/radio"); + coap_activate_resource(&res_radio, "sensors/radio"); #endif #if PLATFORM_HAS_SHT11 - rest_activate_resource(&res_sht11, "sensors/sht11"); + coap_activate_resource(&res_sht11, "sensors/sht11"); SENSORS_ACTIVATE(sht11_sensor); #endif */ diff --git a/examples/coap/plugtest-server.c b/examples/coap/plugtest-server.c index c6c0e534f..7ca53bc2d 100644 --- a/examples/coap/plugtest-server.c +++ b/examples/coap/plugtest-server.c @@ -44,7 +44,7 @@ #include "coap.h" #include "coap-transactions.h" #include "coap-separate.h" -#include "rest-engine.h" +#include "coap-engine.h" #include "plugtest.h" /* @@ -52,7 +52,7 @@ * The build system automatically compiles the resources in the corresponding * sub-directory. */ -extern resource_t +extern coap_resource_t res_plugtest_test, res_plugtest_validate, res_plugtest_create1, @@ -95,29 +95,29 @@ PROCESS_THREAD(plugtest_server, ev, data) PRINTF("REST max chunk: %u\n", REST_MAX_CHUNK_SIZE); /* Initialize the REST engine. */ - rest_init_engine(); + coap_engine_init(); /* Activate the application-specific resources. */ - rest_activate_resource(&res_plugtest_test, "test"); - rest_activate_resource(&res_plugtest_validate, "validate"); - rest_activate_resource(&res_plugtest_create1, "create1"); - rest_activate_resource(&res_plugtest_create2, "create2"); - rest_activate_resource(&res_plugtest_create3, "create3"); - rest_activate_resource(&res_plugtest_longpath, "seg1/seg2/seg3"); - rest_activate_resource(&res_plugtest_query, "query"); - rest_activate_resource(&res_plugtest_locquery, "location-query"); - rest_activate_resource(&res_plugtest_multi, "multi-format"); - rest_activate_resource(&res_plugtest_link1, "link1"); - rest_activate_resource(&res_plugtest_link2, "link2"); - rest_activate_resource(&res_plugtest_link3, "link3"); - rest_activate_resource(&res_plugtest_path, "path"); - rest_activate_resource(&res_plugtest_separate, "separate"); - rest_activate_resource(&res_plugtest_large, "large"); - rest_activate_resource(&res_plugtest_large_update, "large-update"); - rest_activate_resource(&res_plugtest_large_create, "large-create"); - rest_activate_resource(&res_plugtest_obs, "obs"); + coap_activate_resource(&res_plugtest_test, "test"); + coap_activate_resource(&res_plugtest_validate, "validate"); + coap_activate_resource(&res_plugtest_create1, "create1"); + coap_activate_resource(&res_plugtest_create2, "create2"); + coap_activate_resource(&res_plugtest_create3, "create3"); + coap_activate_resource(&res_plugtest_longpath, "seg1/seg2/seg3"); + coap_activate_resource(&res_plugtest_query, "query"); + coap_activate_resource(&res_plugtest_locquery, "location-query"); + coap_activate_resource(&res_plugtest_multi, "multi-format"); + coap_activate_resource(&res_plugtest_link1, "link1"); + coap_activate_resource(&res_plugtest_link2, "link2"); + coap_activate_resource(&res_plugtest_link3, "link3"); + coap_activate_resource(&res_plugtest_path, "path"); + coap_activate_resource(&res_plugtest_separate, "separate"); + coap_activate_resource(&res_plugtest_large, "large"); + coap_activate_resource(&res_plugtest_large_update, "large-update"); + coap_activate_resource(&res_plugtest_large_create, "large-create"); + coap_activate_resource(&res_plugtest_obs, "obs"); - rest_activate_resource(&res_mirror, "mirror"); + coap_activate_resource(&res_mirror, "mirror"); /* Define application-specific events here. */ while(1) { diff --git a/examples/coap/resources-plugtest/res-plugtest-create1.c b/examples/coap/resources-plugtest/res-plugtest-create1.c index 4e8c52231..661a3f210 100644 --- a/examples/coap/resources-plugtest/res-plugtest-create1.c +++ b/examples/coap/resources-plugtest/res-plugtest-create1.c @@ -37,12 +37,12 @@ */ #include -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #include "plugtest.h" -static void res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void res_delete_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_put_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_delete_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); RESOURCE(res_plugtest_create1, "title=\"Creates on PUT\"", @@ -54,27 +54,27 @@ RESOURCE(res_plugtest_create1, static uint8_t create1_exists = 0; static void -res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_put_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { PRINTF("/create1 PUT"); if(coap_get_header_if_none_match(request)) { if(!create1_exists) { - REST.set_response_status(response, REST.status.CREATED); + coap_set_status_code(response, CREATED_2_01); create1_exists = 1; } else { - REST.set_response_status(response, PRECONDITION_FAILED_4_12); + coap_set_status_code(response, PRECONDITION_FAILED_4_12); } } else { - REST.set_response_status(response, REST.status.CHANGED); + coap_set_status_code(response, CHANGED_2_04); } } static void -res_delete_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_delete_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { PRINTF("/create1 DELETE "); - REST.set_response_status(response, REST.status.DELETED); + coap_set_status_code(response, DELETED_2_02); create1_exists = 0; } diff --git a/examples/coap/resources-plugtest/res-plugtest-create2.c b/examples/coap/resources-plugtest/res-plugtest-create2.c index 714432ff6..756d9b0fa 100644 --- a/examples/coap/resources-plugtest/res-plugtest-create2.c +++ b/examples/coap/resources-plugtest/res-plugtest-create2.c @@ -37,11 +37,11 @@ */ #include -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #include "plugtest.h" -static void res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_post_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); RESOURCE(res_plugtest_create2, "title=\"Creates on POST\"", @@ -51,10 +51,10 @@ RESOURCE(res_plugtest_create2, NULL); static void -res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_post_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { PRINTF("/create2 "); - REST.set_response_status(response, REST.status.CREATED); - REST.set_header_location(response, "/location1/location2/location3"); + coap_set_status_code(response, CREATED_2_01); + coap_set_header_location_path(response, "/location1/location2/location3"); } diff --git a/examples/coap/resources-plugtest/res-plugtest-create3.c b/examples/coap/resources-plugtest/res-plugtest-create3.c index fe7526eba..9356dd2a6 100644 --- a/examples/coap/resources-plugtest/res-plugtest-create3.c +++ b/examples/coap/resources-plugtest/res-plugtest-create3.c @@ -37,12 +37,12 @@ */ #include -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #include "plugtest.h" -static void res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void res_delete_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_put_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_delete_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); RESOURCE(res_plugtest_create3, "title=\"Default test resource\"", @@ -54,27 +54,27 @@ RESOURCE(res_plugtest_create3, static uint8_t create3_exists = 0; static void -res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_put_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { PRINTF("/create3 PUT "); if(coap_get_header_if_none_match(request)) { if(!create3_exists) { - REST.set_response_status(response, REST.status.CREATED); + coap_set_status_code(response, CREATED_2_01); create3_exists = 1; } else { - REST.set_response_status(response, PRECONDITION_FAILED_4_12); + coap_set_status_code(response, PRECONDITION_FAILED_4_12); } } else { - REST.set_response_status(response, REST.status.CHANGED); + coap_set_status_code(response, CHANGED_2_04); } } static void -res_delete_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_delete_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { PRINTF("/create3 DELETE "); - REST.set_response_status(response, REST.status.DELETED); + coap_set_status_code(response, DELETED_2_02); create3_exists = 0; } diff --git a/examples/coap/resources-plugtest/res-plugtest-large-create.c b/examples/coap/resources-plugtest/res-plugtest-large-create.c index ac1e27a3d..aa7e60ac2 100644 --- a/examples/coap/resources-plugtest/res-plugtest-large-create.c +++ b/examples/coap/resources-plugtest/res-plugtest-large-create.c @@ -37,11 +37,11 @@ */ #include -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #include "plugtest.h" -static void res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_post_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); /* * Large resource that can be created using POST method @@ -54,7 +54,7 @@ RESOURCE(res_plugtest_large_create, NULL); static void -res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_post_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { coap_packet_t *const coap_req = (coap_packet_t *)request; @@ -63,29 +63,29 @@ res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t prefer unsigned int ct = -1; - if(!REST.get_header_content_type(request, &ct)) { - REST.set_response_status(response, REST.status.BAD_REQUEST); + if(!coap_get_header_content_format(request, &ct)) { + coap_set_status_code(response, BAD_REQUEST_4_00); const char *error_msg = "NoContentType"; - REST.set_response_payload(response, error_msg, strlen(error_msg)); + coap_set_payload(response, error_msg, strlen(error_msg)); return; } - if((len = REST.get_request_payload(request, (const uint8_t **)&incoming))) { + if((len = coap_get_payload(request, (const uint8_t **)&incoming))) { if(coap_req->block1_num * coap_req->block1_size + len <= 2048) { - REST.set_response_status(response, REST.status.CREATED); - REST.set_header_location(response, "/nirvana"); + coap_set_status_code(response, CREATED_2_01); + coap_set_header_location_path(response, "/nirvana"); coap_set_header_block1(response, coap_req->block1_num, 0, coap_req->block1_size); } else { - REST.set_response_status(response, REST.status.REQUEST_ENTITY_TOO_LARGE); + coap_set_status_code(response, REQUEST_ENTITY_TOO_LARGE_4_13); const char *error_msg = "2048B max."; - REST.set_response_payload(response, error_msg, strlen(error_msg)); + coap_set_payload(response, error_msg, strlen(error_msg)); return; } } else { - REST.set_response_status(response, REST.status.BAD_REQUEST); + coap_set_status_code(response, BAD_REQUEST_4_00); const char *error_msg = "NoPayload"; - REST.set_response_payload(response, error_msg, strlen(error_msg)); + coap_set_payload(response, error_msg, strlen(error_msg)); return; } } diff --git a/examples/coap/resources-plugtest/res-plugtest-large-update.c b/examples/coap/resources-plugtest/res-plugtest-large-update.c index 8263ccc2a..a8e4b9c5a 100644 --- a/examples/coap/resources-plugtest/res-plugtest-large-update.c +++ b/examples/coap/resources-plugtest/res-plugtest-large-update.c @@ -36,14 +36,15 @@ * Matthias Kovatsch */ +#include #include #include "sys/cc.h" -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #include "plugtest.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_put_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); RESOURCE( res_plugtest_large_update, @@ -58,21 +59,21 @@ static uint8_t large_update_store[MAX_PLUGFEST_BODY] = { 0 }; static unsigned int large_update_ct = APPLICATION_OCTET_STREAM; static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { /* Check the offset for boundaries of the resource data. */ if(*offset >= large_update_size) { - REST.set_response_status(response, REST.status.BAD_OPTION); + coap_set_status_code(response, BAD_OPTION_4_02); /* A block error message should not exceed the minimum block size (16). */ const char *error_msg = "BlockOutOfScope"; - REST.set_response_payload(response, error_msg, strlen(error_msg)); + coap_set_payload(response, error_msg, strlen(error_msg)); return; } - REST.set_response_payload(response, large_update_store + *offset, + coap_set_payload(response, large_update_store + *offset, MIN(large_update_size - *offset, preferred_size)); - REST.set_header_content_type(response, large_update_ct); + coap_set_header_content_format(response, large_update_ct); /* IMPORTANT for chunk-wise resources: Signal chunk awareness to REST engine. */ *offset += preferred_size; @@ -83,7 +84,7 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr } } static void -res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_put_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { coap_packet_t *const coap_req = (coap_packet_t *)request; uint8_t *incoming = NULL; @@ -91,14 +92,14 @@ res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr unsigned int ct = -1; - if(!REST.get_header_content_type(request, &ct)) { - REST.set_response_status(response, REST.status.BAD_REQUEST); + if(!coap_get_header_content_format(request, &ct)) { + coap_set_status_code(response, BAD_REQUEST_4_00); const char *error_msg = "NoContentType"; - REST.set_response_payload(response, error_msg, strlen(error_msg)); + coap_set_payload(response, error_msg, strlen(error_msg)); return; } - if((len = REST.get_request_payload(request, (const uint8_t **)&incoming))) { + if((len = coap_get_payload(request, (const uint8_t **)&incoming))) { if(coap_req->block1_num * coap_req->block1_size + len <= sizeof(large_update_store)) { memcpy( large_update_store + coap_req->block1_num * coap_req->block1_size, @@ -106,13 +107,13 @@ res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr large_update_size = coap_req->block1_num * coap_req->block1_size + len; large_update_ct = ct; - REST.set_response_status(response, REST.status.CHANGED); + coap_set_status_code(response, CHANGED_2_04); coap_set_header_block1(response, coap_req->block1_num, 0, coap_req->block1_size); } else { - REST.set_response_status(response, - REST.status.REQUEST_ENTITY_TOO_LARGE); - REST.set_response_payload( + coap_set_status_code(response, + REQUEST_ENTITY_TOO_LARGE_4_13); + coap_set_payload( response, buffer, snprintf((char *)buffer, MAX_PLUGFEST_PAYLOAD, "%uB max.", @@ -120,9 +121,9 @@ res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr return; } } else { - REST.set_response_status(response, REST.status.BAD_REQUEST); + coap_set_status_code(response, BAD_REQUEST_4_00); const char *error_msg = "NoPayload"; - REST.set_response_payload(response, error_msg, strlen(error_msg)); + coap_set_payload(response, error_msg, strlen(error_msg)); return; } } diff --git a/examples/coap/resources-plugtest/res-plugtest-large.c b/examples/coap/resources-plugtest/res-plugtest-large.c index 8a7372eb8..cb4a53c9a 100644 --- a/examples/coap/resources-plugtest/res-plugtest-large.c +++ b/examples/coap/resources-plugtest/res-plugtest-large.c @@ -36,12 +36,13 @@ * Matthias Kovatsch */ +#include #include -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #include "plugtest.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); RESOURCE(res_plugtest_large, "title=\"Large resource\";rt=\"block\";sz=\"" TO_STRING(CHUNKS_TOTAL) "\"", @@ -51,17 +52,17 @@ RESOURCE(res_plugtest_large, NULL); static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { int32_t strpos = 0; /* Check the offset for boundaries of the resource data. */ if(*offset >= CHUNKS_TOTAL) { - REST.set_response_status(response, REST.status.BAD_OPTION); + coap_set_status_code(response, BAD_OPTION_4_02); /* A block error message should not exceed the minimum block size (16). */ const char *error_msg = "BlockOutOfScope"; - REST.set_response_payload(response, error_msg, strlen(error_msg)); + coap_set_payload(response, error_msg, strlen(error_msg)); return; } @@ -79,8 +80,8 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr if(*offset + (int32_t)strpos > CHUNKS_TOTAL) { strpos = CHUNKS_TOTAL - *offset; } - REST.set_response_payload(response, buffer, strpos); - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + coap_set_payload(response, buffer, strpos); + coap_set_header_content_format(response, TEXT_PLAIN); /* IMPORTANT for chunk-wise resources: Signal chunk awareness to REST engine. */ *offset += strpos; diff --git a/examples/coap/resources-plugtest/res-plugtest-links.c b/examples/coap/resources-plugtest/res-plugtest-links.c index f802d3c56..63344e9a4 100644 --- a/examples/coap/resources-plugtest/res-plugtest-links.c +++ b/examples/coap/resources-plugtest/res-plugtest-links.c @@ -37,11 +37,11 @@ */ #include -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #include "plugtest.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); RESOURCE(res_plugtest_link1, "rt=\"Type1 Type2\";if=\"If1\"", @@ -63,9 +63,9 @@ RESOURCE(res_plugtest_link3, NULL); static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const char *msg = "Dummy link"; - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, msg, strlen(msg)); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, msg, strlen(msg)); } diff --git a/examples/coap/resources-plugtest/res-plugtest-locquery.c b/examples/coap/resources-plugtest/res-plugtest-locquery.c index d75a9a620..8a47aa8c2 100644 --- a/examples/coap/resources-plugtest/res-plugtest-locquery.c +++ b/examples/coap/resources-plugtest/res-plugtest-locquery.c @@ -37,11 +37,11 @@ */ #include -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #include "plugtest.h" -static void res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_post_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); RESOURCE(res_plugtest_locquery, "title=\"Resource accepting query parameters\"", @@ -51,7 +51,7 @@ RESOURCE(res_plugtest_locquery, NULL); static void -res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_post_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { #if DEBUG coap_packet_t *const coap_req = (coap_packet_t *)request; @@ -60,6 +60,6 @@ res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t prefer PRINTF( "/location-query POST (%s %u)\n", coap_req->type == COAP_TYPE_CON ? "CON" : "NON", coap_req->mid); - REST.set_response_status(response, REST.status.CREATED); - REST.set_header_location(response, "?first=1&second=2"); + coap_set_status_code(response, CREATED_2_01); + coap_set_header_location_query(response, "?first=1&second=2"); } diff --git a/examples/coap/resources-plugtest/res-plugtest-longpath.c b/examples/coap/resources-plugtest/res-plugtest-longpath.c index 5a26d4db9..fb18f84bb 100644 --- a/examples/coap/resources-plugtest/res-plugtest-longpath.c +++ b/examples/coap/resources-plugtest/res-plugtest-longpath.c @@ -36,12 +36,14 @@ * Matthias Kovatsch */ + +#include #include -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #include "plugtest.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); RESOURCE(res_plugtest_longpath, "title=\"Long path resource\"", @@ -51,14 +53,14 @@ RESOURCE(res_plugtest_longpath, NULL); static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { coap_packet_t *const coap_req = (coap_packet_t *)request; PRINTF("/seg1/seg2/seg3 GET "); /* Code 2.05 CONTENT is default. */ - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload( + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload( response, buffer, snprintf((char *)buffer, MAX_PLUGFEST_PAYLOAD, diff --git a/examples/coap/resources-plugtest/res-plugtest-multi.c b/examples/coap/resources-plugtest/res-plugtest-multi.c index c6592b397..3e23d7ecc 100644 --- a/examples/coap/resources-plugtest/res-plugtest-multi.c +++ b/examples/coap/resources-plugtest/res-plugtest-multi.c @@ -36,12 +36,13 @@ * Matthias Kovatsch */ +#include #include -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #include "plugtest.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); RESOURCE(res_plugtest_multi, "title=\"Resource providing text/plain and application/xml\";ct=\"0 41\"", @@ -51,27 +52,27 @@ RESOURCE(res_plugtest_multi, NULL); static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { coap_packet_t *const coap_req = (coap_packet_t *)request; unsigned int accept = -1; - REST.get_header_accept(request, &accept); + coap_get_header_accept(request, &accept); PRINTF("/multi-format GET (%s %u) ", coap_req->type == COAP_TYPE_CON ? "CON" : "NON", coap_req->mid); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload( + if(accept == -1 || accept == TEXT_PLAIN) { + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload( response, buffer, snprintf((char *)buffer, MAX_PLUGFEST_PAYLOAD, "Type: %u\nCode: %u\nMID: %u%s", coap_req->type, coap_req->code, coap_req->mid, accept != -1 ? "\nAccept: 0" : "")); PRINTF("PLAIN\n"); - } else if(accept == REST.type.APPLICATION_XML) { - REST.set_header_content_type(response, REST.type.APPLICATION_XML); - REST.set_response_payload( + } else if(accept == APPLICATION_XML) { + coap_set_header_content_format(response, APPLICATION_XML); + coap_set_payload( response, buffer, snprintf((char *)buffer, MAX_PLUGFEST_PAYLOAD, @@ -79,9 +80,9 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr coap_req->type, coap_req->code, coap_req->mid, accept)); PRINTF("XML\n"); } else { - REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); + coap_set_status_code(response, NOT_ACCEPTABLE_4_06); const char *msg = "Supporting content-types text/plain and application/xml"; - REST.set_response_payload(response, msg, strlen(msg)); + coap_set_payload(response, msg, strlen(msg)); PRINTF("ERROR\n"); } } diff --git a/examples/coap/resources-plugtest/res-plugtest-obs.c b/examples/coap/resources-plugtest/res-plugtest-obs.c index 74d61d894..9c4e30672 100644 --- a/examples/coap/resources-plugtest/res-plugtest-obs.c +++ b/examples/coap/resources-plugtest/res-plugtest-obs.c @@ -36,15 +36,16 @@ * Matthias Kovatsch */ +#include #include -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #include "coap-observe.h" #include "plugtest.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void res_delete_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_put_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_delete_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); static void res_periodic_handler(void); PERIODIC_RESOURCE(res_plugtest_obs, @@ -67,35 +68,35 @@ static void obs_purge_list() { PRINTF("### SERVER ACTION ### Purging obs list"); - coap_remove_observer_by_uri(NULL, 0, res_plugtest_obs.url); + coap_remove_observer_by_uri(NULL, res_plugtest_obs.url); } static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { /* Keep server log clean from ticking events */ if(request != NULL) { PRINTF("/obs GET\n"); } - REST.set_header_content_type(response, obs_format); - REST.set_header_max_age(response, 5); + coap_set_header_content_format(response, obs_format); + coap_set_header_max_age(response, 5); if(obs_content_len) { - REST.set_header_content_type(response, obs_format); - REST.set_response_payload(response, obs_content, obs_content_len); + coap_set_header_content_format(response, obs_format); + coap_set_payload(response, obs_content, obs_content_len); } else { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, obs_content, + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, obs_content, snprintf(obs_content, MAX_PLUGFEST_PAYLOAD, "TICK %lu", (unsigned long) obs_counter)); } - /* A post_handler that handles subscriptions will be called for periodic resources by the REST framework. */ + /* A post_handler that handles subscriptions will be called for periodic resources by the CoAP framework. */ } static void -res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_put_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { uint8_t *incoming = NULL; unsigned int ct = -1; - REST.get_header_content_type(request, &ct); + coap_get_header_content_format(request, &ct); PRINTF("/obs PUT\n"); @@ -103,26 +104,26 @@ res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr obs_status = 1; obs_format = ct; } else { - obs_content_len = REST.get_request_payload(request, + obs_content_len = coap_get_payload(request, (const uint8_t **)&incoming); memcpy(obs_content, incoming, obs_content_len); res_periodic_handler(); } - REST.set_response_status(response, REST.status.CHANGED); + coap_set_status_code(response, CHANGED_2_04); } static void -res_delete_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_delete_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { PRINTF("/obs DELETE\n"); obs_status = 2; - REST.set_response_status(response, REST.status.DELETED); + coap_set_status_code(response, DELETED_2_02); } /* * Additionally, a handler function named [resource name]_handler must be implemented for each PERIODIC_RESOURCE. - * It will be called by the REST manager process with the defined period. + * It will be called by the CoAP manager process with the defined period. */ static void res_periodic_handler() @@ -134,7 +135,7 @@ res_periodic_handler() if(obs_status == 1) { /* Notify the registered observers with the given message type, observe option, and payload. */ - REST.notify_subscribers(&res_plugtest_obs); + coap_notify_observers(&res_plugtest_obs); PRINTF("######### sending 5.00\n"); @@ -142,7 +143,7 @@ res_periodic_handler() } else if(obs_status == 2) { /* Notify the registered observers with the given message type, observe option, and payload. */ - REST.notify_subscribers(&res_plugtest_obs); + coap_notify_observers(&res_plugtest_obs); obs_purge_list(); @@ -150,6 +151,6 @@ res_periodic_handler() obs_content_len = 0; } else { /* Notify the registered observers with the given message type, observe option, and payload. */ - REST.notify_subscribers(&res_plugtest_obs); + coap_notify_observers(&res_plugtest_obs); } obs_status = 0; } diff --git a/examples/coap/resources-plugtest/res-plugtest-path.c b/examples/coap/resources-plugtest/res-plugtest-path.c index 03eb362bb..2f3ad7d94 100644 --- a/examples/coap/resources-plugtest/res-plugtest-path.c +++ b/examples/coap/resources-plugtest/res-plugtest-path.c @@ -36,12 +36,13 @@ * Matthias Kovatsch */ +#include #include -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #include "plugtest.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); PARENT_RESOURCE(res_plugtest_path, "title=\"Path test resource\";ct=\"40\"", @@ -51,22 +52,22 @@ PARENT_RESOURCE(res_plugtest_path, NULL); static void -res_get_handler(void *request, void *response, uint8_t *buffer, +res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const char *uri_path = NULL; - int len = REST.get_url(request, &uri_path); + int len = coap_get_header_uri_path(request, &uri_path); int base_len = strlen(res_plugtest_path.url); if(len == base_len) { - REST.set_header_content_type(response, REST.type.APPLICATION_LINK_FORMAT); + coap_set_header_content_format(response, APPLICATION_LINK_FORMAT); snprintf((char *)buffer, MAX_PLUGFEST_PAYLOAD, ",,"); } else { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + coap_set_header_content_format(response, TEXT_PLAIN); snprintf((char *)buffer, MAX_PLUGFEST_PAYLOAD, "/%.*s", len, uri_path); } - REST.set_response_payload(response, buffer, strlen((char *)buffer)); + coap_set_payload(response, buffer, strlen((char *)buffer)); } diff --git a/examples/coap/resources-plugtest/res-plugtest-query.c b/examples/coap/resources-plugtest/res-plugtest-query.c index 6ffbccbbb..249db6998 100644 --- a/examples/coap/resources-plugtest/res-plugtest-query.c +++ b/examples/coap/resources-plugtest/res-plugtest-query.c @@ -36,12 +36,13 @@ * Matthias Kovatsch */ +#include #include -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #include "plugtest.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); RESOURCE(res_plugtest_query, "title=\"Resource accepting query parameters\"", @@ -51,7 +52,7 @@ RESOURCE(res_plugtest_query, NULL); static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { coap_packet_t *const coap_req = (coap_packet_t *)request; int len = 0; @@ -60,13 +61,13 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr PRINTF( "/query GET (%s %u)\n", coap_req->type == COAP_TYPE_CON ? "CON" : "NON", coap_req->mid); - if((len = REST.get_query(request, &query))) { + if((len = coap_get_header_uri_query(request, &query))) { PRINTF("Query: %.*s\n", len, query); /* Code 2.05 CONTENT is default. */ } - REST.set_header_content_type(response, - REST.type.TEXT_PLAIN); - REST.set_response_payload( + coap_set_header_content_format(response, + TEXT_PLAIN); + coap_set_payload( response, buffer, snprintf((char *)buffer, MAX_PLUGFEST_PAYLOAD, diff --git a/examples/coap/resources-plugtest/res-plugtest-separate.c b/examples/coap/resources-plugtest/res-plugtest-separate.c index b45841ec1..3cbe7a896 100644 --- a/examples/coap/resources-plugtest/res-plugtest-separate.c +++ b/examples/coap/resources-plugtest/res-plugtest-separate.c @@ -36,14 +36,15 @@ * Matthias Kovatsch */ +#include #include -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #include "coap-transactions.h" #include "coap-separate.h" #include "plugtest.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); static void res_resume_handler(void); PERIODIC_RESOURCE(res_plugtest_separate, @@ -67,7 +68,7 @@ static uint8_t separate_active = 0; static application_separate_store_t separate_store[1]; void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { coap_packet_t *const coap_req = (coap_packet_t *)request; @@ -97,8 +98,7 @@ res_resume_handler() PRINTF("/separate "); coap_transaction_t *transaction = NULL; if((transaction = coap_new_transaction(separate_store->request_metadata.mid, - &separate_store->request_metadata.addr, - separate_store->request_metadata.port))) { + &separate_store->request_metadata.endpoint))) { PRINTF( "RESPONSE (%s %u)\n", separate_store->request_metadata.type == COAP_TYPE_CON ? "CON" : "NON", separate_store->request_metadata.mid); @@ -107,7 +107,7 @@ res_resume_handler() /* Restore the request information for the response. */ coap_separate_resume(response, &separate_store->request_metadata, CONTENT_2_05); - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + coap_set_header_content_format(response, TEXT_PLAIN); coap_set_payload(response, separate_store->buffer, strlen(separate_store->buffer)); diff --git a/examples/coap/resources-plugtest/res-plugtest-test.c b/examples/coap/resources-plugtest/res-plugtest-test.c index 4af32b9ba..7146726c1 100644 --- a/examples/coap/resources-plugtest/res-plugtest-test.c +++ b/examples/coap/resources-plugtest/res-plugtest-test.c @@ -36,15 +36,17 @@ * Matthias Kovatsch */ +#include #include -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #include "plugtest.h" +#include "random.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void res_delete_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_post_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_put_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_delete_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); RESOURCE(res_plugtest_test, "title=\"Default test resource\"", res_get_handler, res_post_handler, res_put_handler, res_delete_handler); @@ -69,7 +71,7 @@ test_update_etag() PRINTF("### SERVER ACTION ### Changed ETag %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", test_etag_len, test_etag[0], test_etag[1], test_etag[2], test_etag[3], test_etag[4], test_etag[5], test_etag[6], test_etag[7]); } static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { coap_packet_t *const coap_req = (coap_packet_t *)request; @@ -82,34 +84,34 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr && len == test_etag_len && memcmp(test_etag, bytes, len) == 0) { PRINTF("validate "); - REST.set_response_status(response, REST.status.NOT_MODIFIED); - REST.set_header_etag(response, test_etag, test_etag_len); + coap_set_status_code(response, VALID_2_03); + coap_set_header_etag(response, test_etag, test_etag_len); test_change = 1; PRINTF("### SERVER ACTION ### Resource will change\n"); } else { /* Code 2.05 CONTENT is default. */ - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_header_etag(response, test_etag, test_etag_len); - REST.set_header_max_age(response, 30); - REST.set_response_payload( + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_header_etag(response, test_etag, test_etag_len); + coap_set_header_max_age(response, 30); + coap_set_payload( response, buffer, snprintf((char *)buffer, MAX_PLUGFEST_PAYLOAD, "Type: %u\nCode: %u\nMID: %u", coap_req->type, coap_req->code, coap_req->mid)); } } static void -res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_post_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { #if DEBUG coap_packet_t *const coap_req = (coap_packet_t *)request; PRINTF("/test POST (%s %u)\n", coap_req->type == COAP_TYPE_CON ? "CON" : "NON", coap_req->mid); #endif - REST.set_response_status(response, REST.status.CREATED); - REST.set_header_location(response, "/location1/location2/location3"); + coap_set_status_code(response, CREATED_2_01); + coap_set_header_location_path(response, "/location1/location2/location3"); } static void -res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_put_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { #if DEBUG coap_packet_t *const coap_req = (coap_packet_t *)request; @@ -118,12 +120,12 @@ res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr if(coap_get_header_if_none_match(request)) { if(test_none_match_okay) { - REST.set_response_status(response, REST.status.CREATED); + coap_set_status_code(response, CREATED_2_01); test_none_match_okay = 0; PRINTF("### SERVER ACTION ### If-None-Match will FAIL\n"); } else { - REST.set_response_status(response, PRECONDITION_FAILED_4_12); + coap_set_status_code(response, PRECONDITION_FAILED_4_12); test_none_match_okay = 1; PRINTF("### SERVER ACTION ### If-None-Match will SUCCEED\n"); @@ -133,9 +135,9 @@ res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr && memcmp(test_etag, bytes, len) == 0)) || len == 0) { test_update_etag(); - REST.set_header_etag(response, test_etag, test_etag_len); + coap_set_header_etag(response, test_etag, test_etag_len); - REST.set_response_status(response, REST.status.CHANGED); + coap_set_status_code(response, CHANGED_2_04); if(len > 0) { test_change = 1; @@ -148,15 +150,15 @@ res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7], test_etag[0], test_etag[1], test_etag[2], test_etag[3], test_etag[4], test_etag[5], test_etag[6], test_etag[7]); - REST.set_response_status(response, PRECONDITION_FAILED_4_12); + coap_set_status_code(response, PRECONDITION_FAILED_4_12); } } static void -res_delete_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_delete_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { #if DEBUG coap_packet_t *const coap_req = (coap_packet_t *)request; PRINTF("/test DELETE (%s %u)\n", coap_req->type == COAP_TYPE_CON ? "CON" : "NON", coap_req->mid); #endif - REST.set_response_status(response, REST.status.DELETED); + coap_set_status_code(response, DELETED_2_02); } diff --git a/examples/coap/resources-plugtest/res-plugtest-validate.c b/examples/coap/resources-plugtest/res-plugtest-validate.c index ab7b6cfca..45c7ebc06 100644 --- a/examples/coap/resources-plugtest/res-plugtest-validate.c +++ b/examples/coap/resources-plugtest/res-plugtest-validate.c @@ -36,13 +36,15 @@ * Matthias Kovatsch */ +#include #include -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #include "plugtest.h" +#include "random.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_put_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); RESOURCE(res_plugtest_validate, "title=\"Validation test resource\"", @@ -72,7 +74,7 @@ validate_update_etag() validate_etag_len, validate_etag[0], validate_etag[1], validate_etag[2], validate_etag[3], validate_etag[4], validate_etag[5], validate_etag[6], validate_etag[7]); } static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { coap_packet_t *const coap_req = (coap_packet_t *)request; @@ -85,17 +87,17 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr if((len = coap_get_header_etag(request, &bytes)) > 0 && len == validate_etag_len && memcmp(validate_etag, bytes, len) == 0) { PRINTF("validate "); - REST.set_response_status(response, REST.status.NOT_MODIFIED); - REST.set_header_etag(response, validate_etag, validate_etag_len); + coap_set_status_code(response, VALID_2_03); + coap_set_header_etag(response, validate_etag, validate_etag_len); validate_change = 1; PRINTF("### SERVER ACTION ### Resouce will change\n"); } else { /* Code 2.05 CONTENT is default. */ - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_header_etag(response, validate_etag, validate_etag_len); - REST.set_header_max_age(response, 30); - REST.set_response_payload( + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_header_etag(response, validate_etag, validate_etag_len); + coap_set_header_max_age(response, 30); + coap_set_payload( response, buffer, snprintf((char *)buffer, MAX_PLUGFEST_PAYLOAD, @@ -104,7 +106,7 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr } } static void -res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_put_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { #if DEBUG coap_packet_t *const coap_req = (coap_packet_t *)request; @@ -118,9 +120,9 @@ res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr && memcmp(validate_etag, bytes, len) == 0)) || len == 0) { validate_update_etag(); - REST.set_header_etag(response, validate_etag, validate_etag_len); + coap_set_header_etag(response, validate_etag, validate_etag_len); - REST.set_response_status(response, REST.status.CHANGED); + coap_set_status_code(response, CHANGED_2_04); if(len > 0) { validate_change = 1; @@ -134,6 +136,6 @@ res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7], validate_etag[0], validate_etag[1], validate_etag[2], validate_etag[3], validate_etag[4], validate_etag[5], validate_etag[6], validate_etag[7]); - REST.set_response_status(response, PRECONDITION_FAILED_4_12); + coap_set_status_code(response, PRECONDITION_FAILED_4_12); } } diff --git a/examples/coap/resources/res-b1-sep-b2.c b/examples/coap/resources/res-b1-sep-b2.c index 26b6b8606..a295549a7 100644 --- a/examples/coap/resources/res-b1-sep-b2.c +++ b/examples/coap/resources/res-b1-sep-b2.c @@ -36,13 +36,14 @@ * Lars Schmertmann */ +#include #include -#include "rest-engine.h" +#include "coap-engine.h" #include "coap-block1.h" #include "coap-separate.h" #include "coap-transactions.h" -static void res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_post_handler(coap_packet_t *request, coap_packet_t *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 @@ -52,7 +53,7 @@ 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) +res_post_handler(coap_packet_t *request, coap_packet_t *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) { @@ -75,7 +76,7 @@ res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t prefer /* Send first block */ coap_transaction_t *transaction = NULL; - if((transaction = coap_new_transaction(request_metadata.mid, &request_metadata.addr, request_metadata.port))) { + if((transaction = coap_new_transaction(request_metadata.mid, &request_metadata.endpoint))) { coap_packet_t resp[1]; /* This way the packet can be treated as pointer as usual. */ /* Restore the request information for the response. */ diff --git a/examples/coap/resources/res-battery.c b/examples/coap/resources/res-battery.c index b82523594..4d86d05dc 100644 --- a/examples/coap/resources/res-battery.c +++ b/examples/coap/resources/res-battery.c @@ -41,10 +41,11 @@ #if PLATFORM_HAS_BATTERY #include -#include "rest-engine.h" +#include +#include "coap-engine.h" #include "dev/battery-sensor.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); /* A simple getter example. Returns the reading from light sensor with a simple etag */ RESOURCE(res_battery, @@ -55,27 +56,27 @@ RESOURCE(res_battery, NULL); static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { int battery = battery_sensor.value(0); unsigned int accept = -1; - REST.get_header_accept(request, &accept); + coap_get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%d", battery); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_set_header_content_format(response, TEXT_PLAIN); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "%d", battery); - REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_JSON) { - REST.set_header_content_type(response, REST.type.APPLICATION_JSON); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{'battery':%d}", battery); + coap_set_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_JSON) { + coap_set_header_content_format(response, APPLICATION_JSON); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "{'battery':%d}", battery); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); + coap_set_payload(response, buffer, strlen((char *)buffer)); } else { - REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); + coap_set_status_code(response, NOT_ACCEPTABLE_4_06); const char *msg = "Supporting content-types text/plain and application/json"; - REST.set_response_payload(response, msg, strlen(msg)); + coap_set_payload(response, msg, strlen(msg)); } } #endif /* PLATFORM_HAS_BATTERY */ diff --git a/examples/coap/resources/res-chunks.c b/examples/coap/resources/res-chunks.c index 13de706c8..bc2d31226 100644 --- a/examples/coap/resources/res-chunks.c +++ b/examples/coap/resources/res-chunks.c @@ -36,13 +36,14 @@ * Matthias Kovatsch */ +#include #include -#include "rest-engine.h" +#include "coap-engine.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); /* - * For data larger than REST_MAX_CHUNK_SIZE (e.g., when stored in flash) resources must be aware of the buffer limitation + * For data larger than COAP_MAX_CHUNK_SIZE (e.g., when stored in flash) resources must be aware of the buffer limitation * and split their responses by themselves. To transfer the complete resource through a TCP stream or CoAP's blockwise transfer, * the byte offset where to continue is provided to the handler as int32_t pointer. * These chunk-wise resources must set the offset value to its new position or -1 of the end is reached. @@ -58,17 +59,17 @@ RESOURCE(res_chunks, #define CHUNKS_TOTAL 2050 static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { int32_t strpos = 0; /* Check the offset for boundaries of the resource data. */ if(*offset >= CHUNKS_TOTAL) { - REST.set_response_status(response, REST.status.BAD_OPTION); + coap_set_status_code(response, BAD_OPTION_4_02); /* A block error message should not exceed the minimum block size (16). */ const char *error_msg = "BlockOutOfScope"; - REST.set_response_payload(response, error_msg, strlen(error_msg)); + coap_set_payload(response, error_msg, strlen(error_msg)); return; } @@ -85,7 +86,7 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr if(*offset + (int32_t)strpos > CHUNKS_TOTAL) { strpos = CHUNKS_TOTAL - *offset; } - REST.set_response_payload(response, buffer, strpos); + coap_set_payload(response, buffer, strpos); /* IMPORTANT for chunk-wise resources: Signal chunk awareness to REST engine. */ *offset += strpos; diff --git a/examples/coap/resources/res-event.c b/examples/coap/resources/res-event.c index 35ff1f8eb..709405d4d 100644 --- a/examples/coap/resources/res-event.c +++ b/examples/coap/resources/res-event.c @@ -36,8 +36,9 @@ * Matthias Kovatsch */ +#include #include -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #define DEBUG 0 @@ -52,7 +53,7 @@ #define PRINTLLADDR(addr) #endif -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); static void res_event_handler(void); /* @@ -74,10 +75,10 @@ EVENT_RESOURCE(res_event, static int32_t event_counter = 0; static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, buffer, snprintf((char *)buffer, preferred_size, "EVENT %lu", (unsigned long) event_counter)); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, buffer, snprintf((char *)buffer, preferred_size, "EVENT %lu", (unsigned long) event_counter)); /* A post_handler that handles subscriptions/observing will be called for periodic resources by the framework. */ } @@ -96,6 +97,6 @@ res_event_handler(void) PRINTF("TICK %u for /%s\n", event_counter, res_event.url); /* Notify the registered observers which will trigger the res_get_handler to create the response. */ - REST.notify_subscribers(&res_event); + coap_notify_observers(&res_event); } } diff --git a/examples/coap/resources/res-hello.c b/examples/coap/resources/res-hello.c index 9208f8b74..ac0852ee1 100644 --- a/examples/coap/resources/res-hello.c +++ b/examples/coap/resources/res-hello.c @@ -38,9 +38,9 @@ #include #include -#include "rest-engine.h" +#include "coap-engine.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); /* * A handler function named [resource name]_handler must be implemented for each RESOURCE. @@ -56,7 +56,7 @@ RESOURCE(res_hello, NULL); static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const char *len = NULL; /* Some data that has the length up to REST_MAX_CHUNK_SIZE. For more, see the chunk resource. */ @@ -64,7 +64,7 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr int length = 12; /* |<-------->| */ /* The query string can be retrieved by rest_get_query() or parsed for its key-value pairs. */ - if(REST.get_query_variable(request, "len", &len)) { + if(coap_get_query_variable(request, "len", &len)) { length = atoi(len); if(length < 0) { length = 0; @@ -75,7 +75,7 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr memcpy(buffer, message, length); } else { memcpy(buffer, message, length); - } REST.set_header_content_type(response, REST.type.TEXT_PLAIN); /* text/plain is the default, hence this option could be omitted. */ - REST.set_header_etag(response, (uint8_t *)&length, 1); - REST.set_response_payload(response, buffer, length); + } coap_set_header_content_format(response, TEXT_PLAIN); /* text/plain is the default, hence this option could be omitted. */ + coap_set_header_etag(response, (uint8_t *)&length, 1); + coap_set_payload(response, buffer, length); } diff --git a/examples/coap/resources/res-leds.c b/examples/coap/resources/res-leds.c index 5fbcf6c77..9203a5c99 100644 --- a/examples/coap/resources/res-leds.c +++ b/examples/coap/resources/res-leds.c @@ -39,9 +39,8 @@ #include "contiki.h" #if PLATFORM_HAS_LEDS - #include -#include "rest-engine.h" +#include "coap-engine.h" #include "dev/leds.h" #define DEBUG 0 @@ -56,9 +55,9 @@ #define PRINTLLADDR(addr) #endif -static void res_post_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_post_put_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -/*A simple actuator example, depending on the color query parameter and post variable mode, corresponding led is activated or deactivated*/ +/* A simple actuator example, depending on the color query parameter and post variable mode, corresponding led is activated or deactivated */ RESOURCE(res_leds, "title=\"LEDs: ?color=r|g|b, POST/PUT mode=on|off\";rt=\"Control\"", NULL, @@ -67,7 +66,7 @@ RESOURCE(res_leds, NULL); static void -res_post_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_post_put_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { size_t len = 0; const char *color = NULL; @@ -75,7 +74,7 @@ res_post_put_handler(void *request, void *response, uint8_t *buffer, uint16_t pr uint8_t led = 0; int success = 1; - if((len = REST.get_query_variable(request, "color", &color))) { + if((len = coap_get_query_variable(request, "color", &color))) { PRINTF("color %.*s\n", len, color); if(strncmp(color, "r", len) == 0) { @@ -89,7 +88,7 @@ res_post_put_handler(void *request, void *response, uint8_t *buffer, uint16_t pr } } else { success = 0; - } if(success && (len = REST.get_post_variable(request, "mode", &mode))) { + } if(success && (len = coap_get_post_variable(request, "mode", &mode))) { PRINTF("mode %s\n", mode); if(strncmp(mode, "on", len) == 0) { @@ -102,7 +101,7 @@ res_post_put_handler(void *request, void *response, uint8_t *buffer, uint16_t pr } else { success = 0; } if(!success) { - REST.set_response_status(response, REST.status.BAD_REQUEST); + coap_set_status_code(response, BAD_REQUEST_4_00); } } #endif /* PLATFORM_HAS_LEDS */ diff --git a/examples/coap/resources/res-light.c b/examples/coap/resources/res-light.c index 226d814bb..cf55e0302 100644 --- a/examples/coap/resources/res-light.c +++ b/examples/coap/resources/res-light.c @@ -40,11 +40,12 @@ #if PLATFORM_HAS_LIGHT +#include #include -#include "rest-engine.h" -#include "dev/light-sensor.h" +#include "coap-engine.h" +//#include "dev/light-sensor.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); /* A simple getter example. Returns the reading from light sensor with a simple etag */ RESOURCE(res_light, @@ -55,33 +56,33 @@ RESOURCE(res_light, NULL); static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { uint16_t light_photosynthetic = light_sensor.value(LIGHT_SENSOR_PHOTOSYNTHETIC); uint16_t light_solar = light_sensor.value(LIGHT_SENSOR_TOTAL_SOLAR); unsigned int accept = -1; - REST.get_header_accept(request, &accept); + coap_get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%u;%u", light_photosynthetic, light_solar); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_set_header_content_format(response, TEXT_PLAIN); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "%u;%u", light_photosynthetic, light_solar); - REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_XML) { - REST.set_header_content_type(response, REST.type.APPLICATION_XML); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "", light_photosynthetic, light_solar); + coap_set_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_XML) { + coap_set_header_content_format(response, APPLICATION_XML); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "", light_photosynthetic, light_solar); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_JSON) { - REST.set_header_content_type(response, REST.type.APPLICATION_JSON); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{'light':{'photosynthetic':%u,'solar':%u}}", light_photosynthetic, light_solar); + coap_set_payload(response, buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_JSON) { + coap_set_header_content_format(response, APPLICATION_JSON); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "{'light':{'photosynthetic':%u,'solar':%u}}", light_photosynthetic, light_solar); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); + coap_set_payload(response, buffer, strlen((char *)buffer)); } else { - REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); + coap_set_status_code(response, NOT_ACCEPTABLE_4_06); const char *msg = "Supporting content-types text/plain, application/xml, and application/json"; - REST.set_response_payload(response, msg, strlen(msg)); + coap_set_payload(response, msg, strlen(msg)); } } #endif /* PLATFORM_HAS_LIGHT */ diff --git a/examples/coap/resources/res-mirror.c b/examples/coap/resources/res-mirror.c index 15b7c3b80..b4a15b7de 100644 --- a/examples/coap/resources/res-mirror.c +++ b/examples/coap/resources/res-mirror.c @@ -36,8 +36,9 @@ * Matthias Kovatsch */ +#include #include -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #define DEBUG 0 @@ -52,7 +53,7 @@ #define PRINTLLADDR(addr) #endif -static void res_any_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_any_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); /* This resource mirrors the incoming request. It shows how to access the options and how to set them for the response. */ RESOURCE(res_mirror, @@ -63,7 +64,7 @@ RESOURCE(res_mirror, res_any_handler); static void -res_any_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_any_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { /* The ETag and Token is copied to the header. */ uint8_t opaque[] = { 0x0A, 0xBC, 0xDE }; @@ -89,28 +90,28 @@ res_any_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr /* snprintf() counts the terminating '\0' to the size parameter. * The additional byte is taken care of by allocating REST_MAX_CHUNK_SIZE+1 bytes in the REST framework. * Add +1 to fill the complete buffer, as the payload does not need a terminating '\0'. */ - if(REST.get_header_content_type(request, &content_format)) { + if(coap_get_header_content_format(request, &content_format)) { strpos += snprintf((char *)buffer, REST_MAX_CHUNK_SIZE + 1, "CF %u\n", content_format); } - if(strpos <= REST_MAX_CHUNK_SIZE && (len = REST.get_header_accept(request, &content_format))) { + if(strpos <= REST_MAX_CHUNK_SIZE && (len = coap_get_header_accept(request, &content_format))) { strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "Ac %u\n", content_format); /* Some getters such as for ETag or Location are omitted, as these options should not appear in a request. * Max-Age might appear in HTTP requests or used for special purposes in CoAP. */ } - if(strpos <= REST_MAX_CHUNK_SIZE && REST.get_header_max_age(request, &longint)) { + if(strpos <= REST_MAX_CHUNK_SIZE && coap_get_header_max_age(request, &longint)) { strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "MA %lu\n", (unsigned long) longint); /* For HTTP this is the Length option, for CoAP it is the Size option. */ } - if(strpos <= REST_MAX_CHUNK_SIZE && REST.get_header_length(request, &longint)) { + if(strpos <= REST_MAX_CHUNK_SIZE && coap_get_header_size1(request, &longint)) { strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "SZ %lu\n", (unsigned long) longint); } - if(strpos <= REST_MAX_CHUNK_SIZE && (len = REST.get_header_host(request, &str))) { + if(strpos <= REST_MAX_CHUNK_SIZE && (len = coap_get_header_uri_host(request, &str))) { strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "UH %.*s\n", len, str); } - if(strpos <= REST_MAX_CHUNK_SIZE && (len = REST.get_url(request, &str))) { + if(strpos <= REST_MAX_CHUNK_SIZE && (len = coap_get_header_uri_path(request, &str))) { strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "UP %.*s\n", len, str); } - if(strpos <= REST_MAX_CHUNK_SIZE && (len = REST.get_query(request, &str))) { + if(strpos <= REST_MAX_CHUNK_SIZE && (len = coap_get_header_uri_query(request, &str))) { strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "UQ %.*s\n", len, str); /* Undefined request options for debugging: actions not required for normal RESTful Web service. */ } @@ -132,10 +133,10 @@ res_any_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "\n"); } - if(strpos <= REST_MAX_CHUNK_SIZE && IS_OPTION(coap_pkt, COAP_OPTION_OBSERVE)) { + if(strpos <= REST_MAX_CHUNK_SIZE && coap_is_option(coap_pkt, COAP_OPTION_OBSERVE)) { strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "Ob %lu\n", (unsigned long) coap_pkt->observe); } - if(strpos <= REST_MAX_CHUNK_SIZE && IS_OPTION(coap_pkt, COAP_OPTION_ETAG)) { + if(strpos <= REST_MAX_CHUNK_SIZE && coap_is_option(coap_pkt, COAP_OPTION_ETAG)) { strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "ET 0x"); int index = 0; for(index = 0; index < coap_pkt->etag_len; ++index) { @@ -149,22 +150,22 @@ res_any_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr if(strpos <= REST_MAX_CHUNK_SIZE && coap_get_header_block1(request, &block_num, &block_more, &block_size, NULL)) { strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "B1 %lu%s (%u)\n", (unsigned long) block_num, block_more ? "+" : "", block_size); } - if(strpos <= REST_MAX_CHUNK_SIZE && (len = REST.get_request_payload(request, &bytes))) { + if(strpos <= REST_MAX_CHUNK_SIZE && (len = coap_get_payload(request, &bytes))) { strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "%.*s", len, bytes); } if(strpos >= REST_MAX_CHUNK_SIZE) { buffer[REST_MAX_CHUNK_SIZE - 1] = 0xBB; /* '»' to indicate truncation */ } - REST.set_response_payload(response, buffer, strpos); + coap_set_payload(response, buffer, strpos); PRINTF("/mirror options received: %s\n", buffer); /* Set dummy header options for response. Like getters, some setters are not implemented for HTTP and have no effect. */ - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_header_max_age(response, 17); /* For HTTP, browsers will not re-request the page for 17 seconds. */ - REST.set_header_etag(response, opaque, 2); - REST.set_header_location(response, location); /* Initial slash is omitted by framework */ - REST.set_header_length(response, strpos); /* For HTTP, browsers will not re-request the page for 10 seconds. CoAP action depends on the client. */ + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_header_max_age(response, 17); /* For HTTP, browsers will not re-request the page for 17 seconds. */ + coap_set_header_etag(response, opaque, 2); + coap_set_header_location_path(response, location); /* Initial slash is omitted by framework */ + coap_set_header_size1(response, strpos); /* For HTTP, browsers will not re-request the page for 10 s. CoAP action depends on the client. */ /* CoAP-specific example: actions not required for normal RESTful Web service. */ coap_set_header_uri_host(response, "tiki"); diff --git a/examples/coap/resources/res-push.c b/examples/coap/resources/res-push.c index 120e2ffef..824d23ee5 100644 --- a/examples/coap/resources/res-push.c +++ b/examples/coap/resources/res-push.c @@ -36,11 +36,12 @@ * Matthias Kovatsch */ +#include #include -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); static void res_periodic_handler(void); PERIODIC_RESOURCE(res_push, @@ -58,18 +59,18 @@ PERIODIC_RESOURCE(res_push, static int32_t event_counter = 0; static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { /* * For minimal complexity, request query and options should be ignored for GET on observable resources. - * Otherwise the requests must be stored with the observer list and passed by REST.notify_subscribers(). + * Otherwise the requests must be stored with the observer list and passed by coap_notify_subscribers(). * This would be a TODO in the corresponding files in contiki/apps/erbium/! */ - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_header_max_age(response, res_push.periodic->period / CLOCK_SECOND); - REST.set_response_payload(response, buffer, snprintf((char *)buffer, preferred_size, "VERY LONG EVENT %lu", (unsigned long) event_counter)); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_header_max_age(response, res_push.periodic->period / CLOCK_SECOND); + coap_set_payload(response, buffer, snprintf((char *)buffer, preferred_size, "VERY LONG EVENT %lu", (unsigned long) event_counter)); - /* The REST.subscription_handler() will be called for observable resources by the REST framework. */ + /* The coap_subscription_handler() will be called for observable resources by the REST framework. */ } /* * Additionally, a handler function named [resource name]_handler must be implemented for each PERIODIC_RESOURCE. @@ -84,6 +85,6 @@ res_periodic_handler() /* Usually a condition is defined under with subscribers are notified, e.g., large enough delta in sensor reading. */ if(1) { /* Notify the registered observers which will trigger the res_get_handler to create the response. */ - REST.notify_subscribers(&res_push); + coap_notify_observers(&res_push); } } diff --git a/examples/coap/resources/res-radio.c b/examples/coap/resources/res-radio.c index b33bf703a..95f311274 100644 --- a/examples/coap/resources/res-radio.c +++ b/examples/coap/resources/res-radio.c @@ -39,12 +39,12 @@ #include "contiki.h" #if PLATFORM_HAS_RADIO - +#include #include -#include "rest-engine.h" +#include "coap-engine.h" #include "net/netstack.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); /* A simple getter example. Returns the reading of the rssi/lqi from radio sensor */ RESOURCE(res_radio, @@ -55,7 +55,7 @@ RESOURCE(res_radio, NULL); static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { size_t len = 0; const char *p = NULL; @@ -64,9 +64,9 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr int success = 0; unsigned int accept = -1; - REST.get_header_accept(request, &accept); + coap_get_header_accept(request, &accept); - if((len = REST.get_query_variable(request, "p", &p))) { + if((len = coap_get_query_variable(request, "p", &p))) { if(strncmp(p, "rssi", len) == 0) { if(NETSTACK_RADIO.get_value(RADIO_PARAM_RSSI, &value) == RADIO_RESULT_OK) { @@ -77,23 +77,23 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr } if(success) { - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%d", rssi); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_set_header_content_format(response, TEXT_PLAIN); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "%d", rssi); - REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_JSON) { - REST.set_header_content_type(response, REST.type.APPLICATION_JSON); + coap_set_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_JSON) { + coap_set_header_content_format(response, APPLICATION_JSON); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{'rssi':%d}", rssi); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "{'rssi':%d}", rssi); + coap_set_payload(response, buffer, strlen((char *)buffer)); } else { - REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); + coap_set_status_code(response, NOT_ACCEPTABLE_4_06); const char *msg = "Supporting content-types text/plain and application/json"; - REST.set_response_payload(response, msg, strlen(msg)); + coap_set_payload(response, msg, strlen(msg)); } } else { - REST.set_response_status(response, REST.status.BAD_REQUEST); + coap_set_status_code(response, BAD_REQUEST_4_00); } } #endif /* PLATFORM_HAS_RADIO */ diff --git a/examples/coap/resources/res-separate.c b/examples/coap/resources/res-separate.c index fb402d2b9..639cd8c25 100644 --- a/examples/coap/resources/res-separate.c +++ b/examples/coap/resources/res-separate.c @@ -37,11 +37,12 @@ */ #include -#include "rest-engine.h" +#include +#include "coap-engine.h" #include "coap-separate.h" #include "coap-transactions.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); static void res_resume_handler(void); SEPARATE_RESOURCE(res_separate, @@ -68,7 +69,7 @@ static uint8_t separate_active = 0; static application_separate_store_t separate_store[COAP_MAX_OPEN_SEPARATE]; static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { /* * Example allows only one open separate response. @@ -96,11 +97,11 @@ res_resume_handler() { if(separate_active) { coap_transaction_t *transaction = NULL; - if((transaction = coap_new_transaction(separate_store->request_metadata.mid, &separate_store->request_metadata.addr, separate_store->request_metadata.port))) { + if((transaction = coap_new_transaction(separate_store->request_metadata.mid, &separate_store->request_metadata.endpoint))) { coap_packet_t response[1]; /* This way the packet can be treated as pointer as usual. */ /* Restore the request information for the response. */ - coap_separate_resume(response, &separate_store->request_metadata, REST.status.OK); + coap_separate_resume(response, &separate_store->request_metadata, CONTENT_2_05); coap_set_payload(response, separate_store->buffer, strlen(separate_store->buffer)); diff --git a/examples/coap/resources/res-sht11.c b/examples/coap/resources/res-sht11.c index 56ed86c01..cecb5d0da 100644 --- a/examples/coap/resources/res-sht11.c +++ b/examples/coap/resources/res-sht11.c @@ -44,10 +44,10 @@ #if PLATFORM_HAS_SHT11 #include -#include "rest-engine.h" +#include "coap-engine.h" #include "dev/sht11/sht11-sensor.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); /* Get Method Example. Returns the reading from temperature and humidity sensors. */ RESOURCE(res_sht11, @@ -58,7 +58,7 @@ RESOURCE(res_sht11, NULL); static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { /* Temperature in Celsius (t in 14 bits resolution at 3 Volts) * T = -39.60 + 0.01*t @@ -70,27 +70,27 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr uint16_t rh = sht11_sensor.value(SHT11_SENSOR_HUMIDITY); unsigned int accept = -1; - REST.get_header_accept(request, &accept); + coap_get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%u;%u", temperature, rh); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_set_header_content_format(response, TEXT_PLAIN); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "%u;%u", temperature, rh); - REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_XML) { - REST.set_header_content_type(response, REST.type.APPLICATION_XML); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "", temperature, rh); + coap_set_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_XML) { + coap_set_header_content_format(response, APPLICATION_XML); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "", temperature, rh); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_JSON) { - REST.set_header_content_type(response, REST.type.APPLICATION_JSON); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{'Sht11':{'Temperature':%u,'Humidity':%u}}", temperature, rh); + coap_set_payload(response, buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_JSON) { + coap_set_header_content_format(response, APPLICATION_JSON); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "{'Sht11':{'Temperature':%u,'Humidity':%u}}", temperature, rh); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); + coap_set_payload(response, buffer, strlen((char *)buffer)); } else { - REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); + coap_set_status_code(response, NOT_ACCEPTABLE_4_06); const char *msg = "Supporting content-types text/plain, application/xml, and application/json"; - REST.set_response_payload(response, msg, strlen(msg)); + coap_set_payload(response, msg, strlen(msg)); } } #endif /* PLATFORM_HAS_SHT11 */ diff --git a/examples/coap/resources/res-sub.c b/examples/coap/resources/res-sub.c index 1d6f17aeb..2a2abcbcf 100644 --- a/examples/coap/resources/res-sub.c +++ b/examples/coap/resources/res-sub.c @@ -36,14 +36,15 @@ * Matthias Kovatsch */ +#include #include -#include "rest-engine.h" +#include "coap-engine.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); /* * Example for a resource that also handles all its sub-resources. - * Use REST.get_url() to multiplex the handling of the request depending on the Uri-Path. + * Use coap_get_url() to multiplex the handling of the request depending on the Uri-Path. */ PARENT_RESOURCE(res_sub, "title=\"Sub-resource demo\"", @@ -53,17 +54,17 @@ PARENT_RESOURCE(res_sub, NULL); static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + coap_set_header_content_format(response, TEXT_PLAIN); const char *uri_path = NULL; - int len = REST.get_url(request, &uri_path); + int len = coap_get_header_uri_path(request, &uri_path); int base_len = strlen(res_sub.url); if(len == base_len) { - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "Request any sub-resource of /%s", res_sub.url); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "Request any sub-resource of /%s", res_sub.url); } else { - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, ".%.*s", len - base_len, uri_path + base_len); - } REST.set_response_payload(response, buffer, strlen((char *)buffer)); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, ".%.*s", len - base_len, uri_path + base_len); + } coap_set_payload(response, buffer, strlen((char *)buffer)); } diff --git a/examples/coap/resources/res-temperature.c b/examples/coap/resources/res-temperature.c index c8bce8ba8..918fb31ad 100644 --- a/examples/coap/resources/res-temperature.c +++ b/examples/coap/resources/res-temperature.c @@ -44,11 +44,12 @@ #include #include +#include #include -#include "rest-engine.h" +#include "coap-engine.h" #include "dev/temperature-sensor.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); static void res_periodic_handler(void); #define MAX_AGE 60 @@ -69,43 +70,43 @@ PERIODIC_RESOURCE(res_temperature, res_periodic_handler); static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { /* * For minimal complexity, request query and options should be ignored for GET on observable resources. - * Otherwise the requests must be stored with the observer list and passed by REST.notify_subscribers(). + * Otherwise the requests must be stored with the observer list and passed by coap_notify_observers(). * This would be a TODO in the corresponding files in contiki/apps/erbium/! */ int temperature = temperature_sensor.value(0); unsigned int accept = -1; - REST.get_header_accept(request, &accept); + coap_get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%d", temperature); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_set_header_content_format(response, TEXT_PLAIN); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "%d", temperature); - REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_JSON) { - REST.set_header_content_type(response, REST.type.APPLICATION_JSON); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{'temperature':%d}", temperature); + coap_set_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_JSON) { + coap_set_header_content_format(response, APPLICATION_JSON); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "{'temperature':%d}", temperature); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); + coap_set_payload(response, buffer, strlen((char *)buffer)); } else { - REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); + coap_set_status_code(response, NOT_ACCEPTABLE_4_06); const char *msg = "Supporting content-types text/plain and application/json"; - REST.set_response_payload(response, msg, strlen(msg)); + coap_set_payload(response, msg, strlen(msg)); } - REST.set_header_max_age(response, MAX_AGE); + coap_set_header_max_age(response, MAX_AGE); - /* The REST.subscription_handler() will be called for observable resources by the REST framework. */ + /* The coap_subscription_handler() will be called for observable resources by the coap_framework. */ } /* * Additionally, a handler function named [resource name]_handler must be implemented for each PERIODIC_RESOURCE. - * It will be called by the REST manager process with the defined period. + * It will be called by the coap_manager process with the defined period. */ static void res_periodic_handler() @@ -119,7 +120,7 @@ res_periodic_handler() interval_counter = 0; temperature_old = temperature; /* Notify the registered observers which will trigger the res_get_handler to create the response. */ - REST.notify_subscribers(&res_temperature); + coap_notify_observers(&res_temperature); } } #endif /* PLATFORM_HAS_TEMPERATURE */ diff --git a/examples/coap/resources/res-toggle.c b/examples/coap/resources/res-toggle.c index d8a773306..81f558732 100644 --- a/examples/coap/resources/res-toggle.c +++ b/examples/coap/resources/res-toggle.c @@ -42,10 +42,10 @@ #include #include "contiki.h" -#include "rest-engine.h" +#include "coap-engine.h" #include "dev/leds.h" -static void res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_post_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); /* A simple actuator example. Toggles the red led */ RESOURCE(res_toggle, @@ -56,7 +56,7 @@ RESOURCE(res_toggle, NULL); static void -res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_post_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { leds_toggle(LEDS_RED); } diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/cc26xx-web-demo.c b/examples/platform-specific/cc26xx/cc26xx-web-demo/cc26xx-web-demo.c index 3b62f1154..ebbe66c29 100644 --- a/examples/platform-specific/cc26xx/cc26xx-web-demo/cc26xx-web-demo.c +++ b/examples/platform-specific/cc26xx/cc26xx-web-demo/cc26xx-web-demo.c @@ -39,7 +39,7 @@ /*---------------------------------------------------------------------------*/ #include "contiki.h" #include "contiki-net.h" -#include "rest-engine.h" +#include "coap-engine.h" #include "board-peripherals.h" #include "lib/sensors.h" #include "lib/list.h" diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/coap-server.c b/examples/platform-specific/cc26xx/cc26xx-web-demo/coap-server.c index 8897eb23f..54289f102 100644 --- a/examples/platform-specific/cc26xx/cc26xx-web-demo/coap-server.c +++ b/examples/platform-specific/cc26xx/cc26xx-web-demo/coap-server.c @@ -37,7 +37,7 @@ /*---------------------------------------------------------------------------*/ #include "contiki.h" #include "contiki-net.h" -#include "rest-engine.h" +#include "coap-engine.h" #include "board-peripherals.h" #include "rf-core/rf-ble.h" #include "cc26xx-web-demo.h" @@ -47,48 +47,48 @@ #include /*---------------------------------------------------------------------------*/ /* Common resources */ -extern resource_t res_leds; +extern coap_resource_t res_leds; -extern resource_t res_batmon_temp; -extern resource_t res_batmon_volt; +extern coap_resource_t res_batmon_temp; +extern coap_resource_t res_batmon_volt; -extern resource_t res_device_sw; -extern resource_t res_device_hw; -extern resource_t res_device_uptime; -extern resource_t res_device_cfg_reset; +extern coap_resource_t res_device_sw; +extern coap_resource_t res_device_hw; +extern coap_resource_t res_device_uptime; +extern coap_resource_t res_device_cfg_reset; -extern resource_t res_parent_rssi; -extern resource_t res_parent_ip; +extern coap_resource_t res_parent_rssi; +extern coap_resource_t res_parent_ip; #if RF_BLE_ENABLED -extern resource_t res_ble_advd; +extern coap_resource_t res_ble_advd; #endif -extern resource_t res_toggle_red; -extern resource_t res_toggle_green; +extern coap_resource_t res_toggle_red; +extern coap_resource_t res_toggle_green; /* Board-specific resources */ #if BOARD_SENSORTAG -extern resource_t res_bmp280_temp; -extern resource_t res_bmp280_press; -extern resource_t res_tmp007_amb; -extern resource_t res_tmp007_obj; -extern resource_t res_hdc1000_temp; -extern resource_t res_hdc1000_hum; -extern resource_t res_opt3001_light; -extern resource_t res_mpu_acc_x; -extern resource_t res_mpu_acc_y; -extern resource_t res_mpu_acc_z; -extern resource_t res_mpu_gyro_x; -extern resource_t res_mpu_gyro_y; -extern resource_t res_mpu_gyro_z; +extern coap_resource_t res_bmp280_temp; +extern coap_resource_t res_bmp280_press; +extern coap_resource_t res_tmp007_amb; +extern coap_resource_t res_tmp007_obj; +extern coap_resource_t res_hdc1000_temp; +extern coap_resource_t res_hdc1000_hum; +extern coap_resource_t res_opt3001_light; +extern coap_resource_t res_mpu_acc_x; +extern coap_resource_t res_mpu_acc_y; +extern coap_resource_t res_mpu_acc_z; +extern coap_resource_t res_mpu_gyro_x; +extern coap_resource_t res_mpu_gyro_y; +extern coap_resource_t res_mpu_gyro_z; #else -extern resource_t res_toggle_orange; -extern resource_t res_toggle_yellow; +extern coap_resource_t res_toggle_orange; +extern coap_resource_t res_toggle_yellow; #endif #if CC26XX_WEB_DEMO_ADC_DEMO -extern resource_t res_adc_dio23; +extern coap_resource_t res_adc_dio23; #endif /*---------------------------------------------------------------------------*/ const char *coap_server_not_found_msg = "Resource not found"; @@ -101,27 +101,27 @@ static void start_board_resources(void) { - rest_activate_resource(&res_toggle_green, "lt/g"); - rest_activate_resource(&res_toggle_red, "lt/r"); - rest_activate_resource(&res_leds, "lt"); + coap_activate_resource(&res_toggle_green, "lt/g"); + coap_activate_resource(&res_toggle_red, "lt/r"); + coap_activate_resource(&res_leds, "lt"); #if BOARD_SENSORTAG - rest_activate_resource(&res_bmp280_temp, "sen/bar/temp"); - rest_activate_resource(&res_bmp280_press, "sen/bar/pres"); - rest_activate_resource(&res_tmp007_amb, "sen/tmp/amb"); - rest_activate_resource(&res_tmp007_obj, "sen/tmp/obj"); - rest_activate_resource(&res_hdc1000_temp, "sen/hdc/t"); - rest_activate_resource(&res_hdc1000_hum, "sen/hdc/h"); - rest_activate_resource(&res_opt3001_light, "sen/opt/light"); - rest_activate_resource(&res_mpu_acc_x, "sen/mpu/acc/x"); - rest_activate_resource(&res_mpu_acc_y, "sen/mpu/acc/y"); - rest_activate_resource(&res_mpu_acc_z, "sen/mpu/acc/z"); - rest_activate_resource(&res_mpu_gyro_x, "sen/mpu/gyro/x"); - rest_activate_resource(&res_mpu_gyro_y, "sen/mpu/gyro/y"); - rest_activate_resource(&res_mpu_gyro_z, "sen/mpu/gyro/z"); + coap_activate_resource(&res_bmp280_temp, "sen/bar/temp"); + coap_activate_resource(&res_bmp280_press, "sen/bar/pres"); + coap_activate_resource(&res_tmp007_amb, "sen/tmp/amb"); + coap_activate_resource(&res_tmp007_obj, "sen/tmp/obj"); + coap_activate_resource(&res_hdc1000_temp, "sen/hdc/t"); + coap_activate_resource(&res_hdc1000_hum, "sen/hdc/h"); + coap_activate_resource(&res_opt3001_light, "sen/opt/light"); + coap_activate_resource(&res_mpu_acc_x, "sen/mpu/acc/x"); + coap_activate_resource(&res_mpu_acc_y, "sen/mpu/acc/y"); + coap_activate_resource(&res_mpu_acc_z, "sen/mpu/acc/z"); + coap_activate_resource(&res_mpu_gyro_x, "sen/mpu/gyro/x"); + coap_activate_resource(&res_mpu_gyro_y, "sen/mpu/gyro/y"); + coap_activate_resource(&res_mpu_gyro_z, "sen/mpu/gyro/z"); #elif BOARD_SMARTRF06EB - rest_activate_resource(&res_toggle_yellow, "lt/y"); - rest_activate_resource(&res_toggle_orange, "lt/o"); + coap_activate_resource(&res_toggle_yellow, "lt/y"); + coap_activate_resource(&res_toggle_orange, "lt/o"); #endif } /*---------------------------------------------------------------------------*/ @@ -134,25 +134,25 @@ PROCESS_THREAD(coap_server_process, ev, data) printf("CC26XX CoAP Server\n"); /* Initialize the REST engine. */ - rest_init_engine(); + coap_engine_init(); - rest_activate_resource(&res_batmon_temp, "sen/batmon/temp"); - rest_activate_resource(&res_batmon_volt, "sen/batmon/voltage"); + coap_activate_resource(&res_batmon_temp, "sen/batmon/temp"); + coap_activate_resource(&res_batmon_volt, "sen/batmon/voltage"); #if CC26XX_WEB_DEMO_ADC_DEMO - rest_activate_resource(&res_adc_dio23, "sen/adc/dio23"); + coap_activate_resource(&res_adc_dio23, "sen/adc/dio23"); #endif - rest_activate_resource(&res_device_hw, "dev/mdl/hw"); - rest_activate_resource(&res_device_sw, "dev/mdl/sw"); - rest_activate_resource(&res_device_uptime, "dev/uptime"); - rest_activate_resource(&res_device_cfg_reset, "dev/cfg_reset"); + coap_activate_resource(&res_device_hw, "dev/mdl/hw"); + coap_activate_resource(&res_device_sw, "dev/mdl/sw"); + coap_activate_resource(&res_device_uptime, "dev/uptime"); + coap_activate_resource(&res_device_cfg_reset, "dev/cfg_reset"); - rest_activate_resource(&res_parent_rssi, "net/parent/RSSI"); - rest_activate_resource(&res_parent_ip, "net/parent/IPv6"); + coap_activate_resource(&res_parent_rssi, "net/parent/RSSI"); + coap_activate_resource(&res_parent_ip, "net/parent/IPv6"); #if RF_BLE_ENABLED - rest_activate_resource(&res_ble_advd, "dev/ble_advd"); + coap_activate_resource(&res_ble_advd, "dev/ble_advd"); #endif start_board_resources(); diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-ble-advd.c b/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-ble-advd.c index 2dccd1b75..99b0866fe 100644 --- a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-ble-advd.c +++ b/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-ble-advd.c @@ -36,7 +36,7 @@ */ /*---------------------------------------------------------------------------*/ #include "contiki.h" -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #include "rf-core/rf-ble.h" @@ -49,7 +49,8 @@ const char *forbidden_payload = "Name to advertise unspecified.\n" "Use name= in the request"; /*---------------------------------------------------------------------------*/ static void -res_ble_post_put_handler(void *request, void *response, uint8_t *buffer, +res_ble_post_put_handler(coap_packet_t *request, coap_packet_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { size_t len = 0; @@ -60,7 +61,7 @@ res_ble_post_put_handler(void *request, void *response, uint8_t *buffer, memset(name, 0, BLE_NAME_BUF_LEN); - len = REST.get_post_variable(request, "name", &text); + len = coap_get_post_variable(request, "name", &text); if(len > 0 && len < BLE_NAME_BUF_LEN) { memcpy(name, text, len); @@ -68,7 +69,7 @@ res_ble_post_put_handler(void *request, void *response, uint8_t *buffer, success = 1; } - len = REST.get_post_variable(request, "interval", &text); + len = coap_get_post_variable(request, "interval", &text); rv = atoi(text); @@ -77,15 +78,15 @@ res_ble_post_put_handler(void *request, void *response, uint8_t *buffer, success = 1; } - len = REST.get_post_variable(request, "mode", &text); + len = coap_get_post_variable(request, "mode", &text); if(len) { if(strncmp(text, "on", len) == 0) { if(rf_ble_beacond_start()) { success = 1; } else { - REST.set_response_status(response, REST.status.FORBIDDEN); - REST.set_response_payload(response, forbidden_payload, + coap_set_status_code(response, FORBIDDEN_4_03); + coap_set_payload(response, forbidden_payload, strlen(forbidden_payload)); return; } @@ -98,7 +99,7 @@ res_ble_post_put_handler(void *request, void *response, uint8_t *buffer, } if(!success) { - REST.set_response_status(response, REST.status.BAD_REQUEST); + coap_set_status_code(response, BAD_REQUEST_4_00); } } /*---------------------------------------------------------------------------*/ diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-device.c b/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-device.c index a52557ffe..6f0fe8bbb 100644 --- a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-device.c +++ b/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-device.c @@ -37,7 +37,7 @@ */ /*---------------------------------------------------------------------------*/ #include "contiki.h" -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #include "sys/clock.h" #include "coap-server.h" @@ -46,6 +46,7 @@ #include "ti-lib.h" #include +#include /*---------------------------------------------------------------------------*/ static uint16_t detect_chip(void) @@ -74,106 +75,110 @@ detect_chip(void) } /*---------------------------------------------------------------------------*/ static void -res_get_handler_hw(void *request, void *response, uint8_t *buffer, +res_get_handler_hw(coap_packet_t *request, coap_packet_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; uint16_t chip = detect_chip(); - REST.get_header_accept(request, &accept); + coap_get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_set_header_content_format(response, TEXT_PLAIN); snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%s on CC%u", BOARD_STRING, chip); - REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_JSON) { - REST.set_header_content_type(response, REST.type.APPLICATION_JSON); + coap_set_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_JSON) { + coap_set_header_content_format(response, APPLICATION_JSON); snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{\"HW Ver\":\"%s on CC%u\"}", BOARD_STRING, chip); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_XML) { - REST.set_header_content_type(response, REST.type.APPLICATION_XML); + coap_set_payload(response, buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_XML) { + coap_set_header_content_format(response, APPLICATION_XML); snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "", BOARD_STRING, chip); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); + coap_set_payload(response, buffer, strlen((char *)buffer)); } else { - REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); - REST.set_response_payload(response, coap_server_supported_msg, + coap_set_status_code(response, NOT_ACCEPTABLE_4_06); + coap_set_payload(response, coap_server_supported_msg, strlen(coap_server_supported_msg)); } } /*---------------------------------------------------------------------------*/ static void -res_get_handler_sw(void *request, void *response, uint8_t *buffer, +res_get_handler_sw(coap_packet_t *request, coap_packet_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; - REST.get_header_accept(request, &accept); + coap_get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_set_header_content_format(response, TEXT_PLAIN); snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%s", CONTIKI_VERSION_STRING); - REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_JSON) { - REST.set_header_content_type(response, REST.type.APPLICATION_JSON); + coap_set_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_JSON) { + coap_set_header_content_format(response, APPLICATION_JSON); snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{\"SW Ver\":\"%s\"}", CONTIKI_VERSION_STRING); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_XML) { - REST.set_header_content_type(response, REST.type.APPLICATION_XML); + coap_set_payload(response, buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_XML) { + coap_set_header_content_format(response, APPLICATION_XML); snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "", CONTIKI_VERSION_STRING); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); + coap_set_payload(response, buffer, strlen((char *)buffer)); } else { - REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); - REST.set_response_payload(response, coap_server_supported_msg, + coap_set_status_code(response, NOT_ACCEPTABLE_4_06); + coap_set_payload(response, coap_server_supported_msg, strlen(coap_server_supported_msg)); } } /*---------------------------------------------------------------------------*/ static void -res_get_handler_uptime(void *request, void *response, uint8_t *buffer, +res_get_handler_uptime(coap_packet_t *request, coap_packet_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; - REST.get_header_accept(request, &accept); + coap_get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_set_header_content_format(response, TEXT_PLAIN); snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%lu", clock_seconds()); - REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_JSON) { - REST.set_header_content_type(response, REST.type.APPLICATION_JSON); + coap_set_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_JSON) { + coap_set_header_content_format(response, APPLICATION_JSON); snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{\"uptime\":%lu}", clock_seconds()); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_XML) { - REST.set_header_content_type(response, REST.type.APPLICATION_XML); + coap_set_payload(response, buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_XML) { + coap_set_header_content_format(response, APPLICATION_XML); snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "", clock_seconds()); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); + coap_set_payload(response, buffer, strlen((char *)buffer)); } else { - REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); - REST.set_response_payload(response, coap_server_supported_msg, + coap_set_status_code(response, NOT_ACCEPTABLE_4_06); + coap_set_payload(response, coap_server_supported_msg, strlen(coap_server_supported_msg)); } } /*---------------------------------------------------------------------------*/ static void -res_post_handler_cfg_reset(void *request, void *response, uint8_t *buffer, +res_post_handler_cfg_reset(coap_packet_t *request, coap_packet_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { cc26xx_web_demo_restore_defaults(); diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-leds.c b/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-leds.c index 85ce353b5..c3c2d1ca4 100644 --- a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-leds.c +++ b/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-leds.c @@ -40,13 +40,14 @@ */ /*---------------------------------------------------------------------------*/ #include "contiki.h" -#include "rest-engine.h" +#include "coap-engine.h" #include "dev/leds.h" #include /*---------------------------------------------------------------------------*/ static void -res_post_put_handler(void *request, void *response, uint8_t *buffer, +res_post_put_handler(coap_packet_t *request, coap_packet_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { size_t len = 0; @@ -55,7 +56,7 @@ res_post_put_handler(void *request, void *response, uint8_t *buffer, uint8_t led = 0; int success = 1; - if((len = REST.get_query_variable(request, "color", &color))) { + if((len = coap_get_query_variable(request, "color", &color))) { if(strncmp(color, "r", len) == 0) { led = LEDS_RED; } else if(strncmp(color, "g", len) == 0) { @@ -73,7 +74,7 @@ res_post_put_handler(void *request, void *response, uint8_t *buffer, success = 0; } - if(success && (len = REST.get_post_variable(request, "mode", &mode))) { + if(success && (len = coap_get_post_variable(request, "mode", &mode))) { if(strncmp(mode, "on", len) == 0) { leds_on(led); } else if(strncmp(mode, "off", len) == 0) { @@ -86,7 +87,7 @@ res_post_put_handler(void *request, void *response, uint8_t *buffer, } if(!success) { - REST.set_response_status(response, REST.status.BAD_REQUEST); + coap_set_status_code(response, BAD_REQUEST_4_00); } } /*---------------------------------------------------------------------------*/ diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-net.c b/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-net.c index 86346a999..35c4d50a8 100644 --- a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-net.c +++ b/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-net.c @@ -37,82 +37,86 @@ */ /*---------------------------------------------------------------------------*/ #include "contiki.h" -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" +#include "net/ipv6/uip-ds6.h" #include "coap-server.h" #include "cc26xx-web-demo.h" #include "ti-lib.h" #include +#include /*---------------------------------------------------------------------------*/ extern int def_rt_rssi; /*---------------------------------------------------------------------------*/ static void -res_get_handler_parent_rssi(void *request, void *response, uint8_t *buffer, +res_get_handler_parent_rssi(coap_packet_t *request, coap_packet_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; - REST.get_header_accept(request, &accept); + coap_get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%d", def_rt_rssi); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_set_header_content_format(response, TEXT_PLAIN); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "%d", def_rt_rssi); - REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_JSON) { - REST.set_header_content_type(response, REST.type.APPLICATION_JSON); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{\"Parent RSSI\":\"%d\"}", + coap_set_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_JSON) { + coap_set_header_content_format(response, APPLICATION_JSON); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "{\"Parent RSSI\":\"%d\"}", def_rt_rssi); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_XML) { - REST.set_header_content_type(response, REST.type.APPLICATION_XML); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, + coap_set_payload(response, buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_XML) { + coap_set_header_content_format(response, APPLICATION_XML); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "", def_rt_rssi); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); + coap_set_payload(response, buffer, strlen((char *)buffer)); } else { - REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); - REST.set_response_payload(response, coap_server_supported_msg, + coap_set_status_code(response, NOT_ACCEPTABLE_4_06); + coap_set_payload(response, coap_server_supported_msg, strlen(coap_server_supported_msg)); } } /*---------------------------------------------------------------------------*/ static void -res_get_handler_pref_parent(void *request, void *response, uint8_t *buffer, +res_get_handler_pref_parent(coap_packet_t *request, coap_packet_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; char def_rt_str[64]; - REST.get_header_accept(request, &accept); + coap_get_header_accept(request, &accept); memset(def_rt_str, 0, sizeof(def_rt_str)); cc26xx_web_demo_ipaddr_sprintf(def_rt_str, sizeof(def_rt_str), uip_ds6_defrt_choose()); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%s", def_rt_str); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_set_header_content_format(response, TEXT_PLAIN); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "%s", def_rt_str); - REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_JSON) { - REST.set_header_content_type(response, REST.type.APPLICATION_JSON); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{\"Parent\":\"%s\"}", + coap_set_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_JSON) { + coap_set_header_content_format(response, APPLICATION_JSON); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "{\"Parent\":\"%s\"}", def_rt_str); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_XML) { - REST.set_header_content_type(response, REST.type.APPLICATION_XML); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, + coap_set_payload(response, buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_XML) { + coap_set_header_content_format(response, APPLICATION_XML); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "", def_rt_str); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); + coap_set_payload(response, buffer, strlen((char *)buffer)); } else { - REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); - REST.set_response_payload(response, coap_server_supported_msg, + coap_set_status_code(response, NOT_ACCEPTABLE_4_06); + coap_set_payload(response, coap_server_supported_msg, strlen(coap_server_supported_msg)); } } diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-sensors.c b/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-sensors.c index b5fe9adb9..ba161a397 100644 --- a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-sensors.c +++ b/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-sensors.c @@ -37,7 +37,7 @@ */ /*---------------------------------------------------------------------------*/ #include "contiki.h" -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #include "cc26xx-web-demo.h" #include "coap-server.h" @@ -51,7 +51,8 @@ * called by all handlers and populates the CoAP response */ static void -res_get_handler_all(int sens_type, void *request, void *response, +res_get_handler_all(int sens_type, coap_packet_t *request, + coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; @@ -60,43 +61,44 @@ res_get_handler_all(int sens_type, void *request, void *response, reading = cc26xx_web_demo_sensor_lookup(sens_type); if(reading == NULL) { - REST.set_response_status(response, REST.status.NOT_FOUND); - REST.set_response_payload(response, coap_server_not_found_msg, + coap_set_status_code(response, NOT_FOUND_4_04); + coap_set_payload(response, coap_server_not_found_msg, strlen(coap_server_not_found_msg)); return; } - REST.get_header_accept(request, &accept); + coap_get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_set_header_content_format(response, TEXT_PLAIN); snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%s", reading->converted); - REST.set_response_payload(response, (uint8_t *)buffer, + coap_set_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_JSON) { - REST.set_header_content_type(response, REST.type.APPLICATION_JSON); + } else if(accept == APPLICATION_JSON) { + coap_set_header_content_format(response, APPLICATION_JSON); snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{\"%s\":%s}", reading->descr, reading->converted); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_XML) { - REST.set_header_content_type(response, REST.type.APPLICATION_XML); + coap_set_payload(response, buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_XML) { + coap_set_header_content_format(response, APPLICATION_XML); snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "<%s val=\"%s\" unit=\"%s\"/>", reading->xml_element, reading->converted, reading->units); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); + coap_set_payload(response, buffer, strlen((char *)buffer)); } else { - REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); - REST.set_response_payload(response, coap_server_supported_msg, + coap_set_status_code(response, NOT_ACCEPTABLE_4_06); + coap_set_payload(response, coap_server_supported_msg, strlen(coap_server_supported_msg)); } } /*---------------------------------------------------------------------------*/ /* BatMon resources and handler: Temperature, Voltage */ static void -res_get_handler_batmon_temp(void *request, void *response, uint8_t *buffer, +res_get_handler_batmon_temp(coap_packet_t *request, coap_packet_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_BATMON_TEMP, request, response, @@ -104,7 +106,8 @@ res_get_handler_batmon_temp(void *request, void *response, uint8_t *buffer, } /*---------------------------------------------------------------------------*/ static void -res_get_handler_batmon_volt(void *request, void *response, uint8_t *buffer, +res_get_handler_batmon_volt(coap_packet_t *request, coap_packet_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_BATMON_VOLT, request, response, @@ -120,7 +123,8 @@ RESOURCE(res_batmon_volt, "title=\"Battery Voltage\";rt=\"mV\"", #if CC26XX_WEB_DEMO_ADC_DEMO /*---------------------------------------------------------------------------*/ static void -res_get_handler_adc_dio23(void *request, void *response, uint8_t *buffer, +res_get_handler_adc_dio23(coap_packet_t *request, coap_packet_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_ADC_DIO23, request, response, @@ -136,7 +140,8 @@ RESOURCE(res_adc_dio23, "title=\"ADC DIO23\";rt=\"mV\"", /*---------------------------------------------------------------------------*/ /* MPU resources and handler: Accelerometer and Gyro */ static void -res_get_handler_mpu_acc_x(void *request, void *response, uint8_t *buffer, +res_get_handler_mpu_acc_x(coap_packet_t *request, coap_packet_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_MPU_ACC_X, request, response, @@ -144,7 +149,8 @@ res_get_handler_mpu_acc_x(void *request, void *response, uint8_t *buffer, } /*---------------------------------------------------------------------------*/ static void -res_get_handler_mpu_acc_y(void *request, void *response, uint8_t *buffer, +res_get_handler_mpu_acc_y(coap_packet_t *request, coap_packet_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_MPU_ACC_Y, request, response, @@ -152,7 +158,8 @@ res_get_handler_mpu_acc_y(void *request, void *response, uint8_t *buffer, } /*---------------------------------------------------------------------------*/ static void -res_get_handler_mpu_acc_z(void *request, void *response, uint8_t *buffer, +res_get_handler_mpu_acc_z(coap_packet_t *request, coap_packet_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_MPU_ACC_Z, request, response, @@ -160,7 +167,8 @@ res_get_handler_mpu_acc_z(void *request, void *response, uint8_t *buffer, } /*---------------------------------------------------------------------------*/ static void -res_get_handler_mpu_gyro_x(void *request, void *response, uint8_t *buffer, +res_get_handler_mpu_gyro_x(coap_packet_t *request, coap_packet_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_MPU_GYRO_X, request, response, @@ -168,7 +176,8 @@ res_get_handler_mpu_gyro_x(void *request, void *response, uint8_t *buffer, } /*---------------------------------------------------------------------------*/ static void -res_get_handler_mpu_gyro_y(void *request, void *response, uint8_t *buffer, +res_get_handler_mpu_gyro_y(coap_packet_t *request, coap_packet_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_MPU_GYRO_Y, request, response, @@ -176,7 +185,8 @@ res_get_handler_mpu_gyro_y(void *request, void *response, uint8_t *buffer, } /*---------------------------------------------------------------------------*/ static void -res_get_handler_mpu_gyro_z(void *request, void *response, uint8_t *buffer, +res_get_handler_mpu_gyro_z(coap_packet_t *request, coap_packet_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_MPU_GYRO_Z, request, response, @@ -199,7 +209,8 @@ RESOURCE(res_mpu_gyro_z, "title=\"Gyro Z\";rt=\"deg/sec\"", /*---------------------------------------------------------------------------*/ /* TMP sensor resources and handlers: Object, Ambient */ static void -res_get_handler_obj_temp(void *request, void *response, uint8_t *buffer, +res_get_handler_obj_temp(coap_packet_t *request, coap_packet_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_TMP_OBJECT, request, response, @@ -207,7 +218,8 @@ res_get_handler_obj_temp(void *request, void *response, uint8_t *buffer, } /*---------------------------------------------------------------------------*/ static void -res_get_handler_amb_temp(void *request, void *response, uint8_t *buffer, +res_get_handler_amb_temp(coap_packet_t *request, coap_packet_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_TMP_AMBIENT, request, response, @@ -222,7 +234,8 @@ RESOURCE(res_tmp007_amb, "title=\"Temperature (Ambient)\";rt=\"C\"", /*---------------------------------------------------------------------------*/ /* BMP sensor resources: Temperature, Pressure */ static void -res_get_handler_bmp_temp(void *request, void *response, uint8_t *buffer, +res_get_handler_bmp_temp(coap_packet_t *request, coap_packet_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_BMP_TEMP, request, response, @@ -230,7 +243,8 @@ res_get_handler_bmp_temp(void *request, void *response, uint8_t *buffer, } /*---------------------------------------------------------------------------*/ static void -res_get_handler_bmp_press(void *request, void *response, uint8_t *buffer, +res_get_handler_bmp_press(coap_packet_t *request, coap_packet_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_BMP_PRES, request, response, @@ -246,7 +260,8 @@ RESOURCE(res_bmp280_press, /*---------------------------------------------------------------------------*/ /* HDC1000 sensor resources and handler: Temperature, Pressure */ static void -res_get_handler_hdc_temp(void *request, void *response, uint8_t *buffer, +res_get_handler_hdc_temp(coap_packet_t *request, coap_packet_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_HDC_TEMP, request, response, @@ -254,7 +269,8 @@ res_get_handler_hdc_temp(void *request, void *response, uint8_t *buffer, } /*---------------------------------------------------------------------------*/ static void -res_get_handler_hdc_humidity(void *request, void *response, uint8_t *buffer, +res_get_handler_hdc_humidity(coap_packet_t *request, coap_packet_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_HDC_HUMIDITY, request, response, @@ -269,7 +285,8 @@ RESOURCE(res_hdc1000_hum, "title=\"Humidity\";rt=\"%RH\"", /*---------------------------------------------------------------------------*/ /* Illuminance resources and handler */ static void -res_get_handler_opt(void *request, void *response, uint8_t *buffer, +res_get_handler_opt(coap_packet_t *request, coap_packet_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_OPT_LIGHT, request, response, diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-toggle-leds.c b/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-toggle-leds.c index 2fb424a03..5e45bed48 100644 --- a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-toggle-leds.c +++ b/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-toggle-leds.c @@ -42,20 +42,22 @@ */ /*---------------------------------------------------------------------------*/ #include "contiki.h" -#include "rest-engine.h" +#include "coap-engine.h" #include "dev/leds.h" #include /*---------------------------------------------------------------------------*/ static void -res_post_handler_red(void *request, void *response, uint8_t *buffer, +res_post_handler_red(coap_packet_t *request, coap_packet_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { leds_toggle(LEDS_RED); } /*---------------------------------------------------------------------------*/ static void -res_post_handler_green(void *request, void *response, uint8_t *buffer, +res_post_handler_green(coap_packet_t *request, coap_packet_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { leds_toggle(LEDS_GREEN); @@ -81,14 +83,16 @@ RESOURCE(res_toggle_green, #if BOARD_SMARTRF06EB /*---------------------------------------------------------------------------*/ static void -res_post_handler_yellow(void *request, void *response, uint8_t *buffer, +res_post_handler_yellow(coap_packet_t *request, coap_packet_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { leds_toggle(LEDS_YELLOW); } /*---------------------------------------------------------------------------*/ static void -res_post_handler_orange(void *request, void *response, uint8_t *buffer, +res_post_handler_orange(coap_packet_t *request, coap_packet_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { leds_toggle(LEDS_ORANGE); diff --git a/examples/platform-specific/cc26xx/very-sleepy-demo/very-sleepy-demo.c b/examples/platform-specific/cc26xx/very-sleepy-demo/very-sleepy-demo.c index e56ee93e6..0c035839f 100644 --- a/examples/platform-specific/cc26xx/very-sleepy-demo/very-sleepy-demo.c +++ b/examples/platform-specific/cc26xx/very-sleepy-demo/very-sleepy-demo.c @@ -44,7 +44,7 @@ #if UIP_CONF_IPV6_RPL_LITE == 0 #include "rpl-private.h" #endif /* UIP_CONF_IPV6_RPL_LITE == 0 */ -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #include "ti-lib.h" @@ -104,38 +104,38 @@ PROCESS(very_sleepy_demo_process, "CC13xx/CC26xx very sleepy process"); AUTOSTART_PROCESSES(&very_sleepy_demo_process); /*---------------------------------------------------------------------------*/ static void -readings_get_handler(void *request, void *response, uint8_t *buffer, - uint16_t preferred_size, int32_t *offset) +readings_get_handler(coap_packet_t *request, coap_packet_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; int temp; int voltage; if(request != NULL) { - REST.get_header_accept(request, &accept); + coap_get_header_accept(request, &accept); } temp = batmon_sensor.value(BATMON_SENSOR_TYPE_TEMP); voltage = batmon_sensor.value(BATMON_SENSOR_TYPE_VOLT); - if(accept == -1 || accept == REST.type.APPLICATION_JSON) { - REST.set_header_content_type(response, REST.type.APPLICATION_JSON); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, + if(accept == -1 || accept == APPLICATION_JSON) { + coap_set_header_content_format(response, APPLICATION_JSON); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "{\"temp\":{\"v\":%d,\"u\":\"C\"}," "\"voltage\":{\"v\":%d,\"u\":\"mV\"}}", temp, (voltage * 125) >> 5); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); - } else if(accept == REST.type.TEXT_PLAIN) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "Temp=%dC, Voltage=%dmV", + coap_set_payload(response, buffer, strlen((char *)buffer)); + } else if(accept == TEXT_PLAIN) { + coap_set_header_content_format(response, TEXT_PLAIN); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "Temp=%dC, Voltage=%dmV", temp, (voltage * 125) >> 5); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); + coap_set_payload(response, buffer, strlen((char *)buffer)); } else { - REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); - REST.set_response_payload(response, not_supported_msg, + coap_set_status_code(response, NOT_ACCEPTABLE_4_06); + coap_set_payload(response, not_supported_msg, strlen(not_supported_msg)); } } @@ -144,39 +144,39 @@ RESOURCE(readings_resource, "title=\"Sensor Readings\";obs", readings_get_handler, NULL, NULL, NULL); /*---------------------------------------------------------------------------*/ static void -conf_get_handler(void *request, void *response, uint8_t *buffer, - uint16_t preferred_size, int32_t *offset) +conf_get_handler(coap_packet_t *request, coap_packet_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; if(request != NULL) { - REST.get_header_accept(request, &accept); + coap_get_header_accept(request, &accept); } - if(accept == -1 || accept == REST.type.APPLICATION_JSON) { - REST.set_header_content_type(response, REST.type.APPLICATION_JSON); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, + if(accept == -1 || accept == APPLICATION_JSON) { + coap_set_header_content_format(response, APPLICATION_JSON); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "{\"config\":{\"mode\":%u,\"duration\":%lu,\"interval\":%lu}}", config.mode, config.duration, config.interval); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); - } else if(accept == REST.type.TEXT_PLAIN) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, + coap_set_payload(response, buffer, strlen((char *)buffer)); + } else if(accept == TEXT_PLAIN) { + coap_set_header_content_format(response, TEXT_PLAIN); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "Mode=%u, Duration=%lusecs, Interval=%lusecs", config.mode, config.duration, config.interval); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); + coap_set_payload(response, buffer, strlen((char *)buffer)); } else { - REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); - REST.set_response_payload(response, not_supported_msg, + coap_set_status_code(response, NOT_ACCEPTABLE_4_06); + coap_set_payload(response, not_supported_msg, strlen(not_supported_msg)); } } /*---------------------------------------------------------------------------*/ static void -conf_post_handler(void *request, void *response, uint8_t *buffer, - uint16_t preferred_size, int32_t *offset) +conf_post_handler(coap_packet_t *request, coap_packet_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const char *ptr = NULL; char tmp_buf[16]; @@ -186,7 +186,7 @@ conf_post_handler(void *request, void *response, uint8_t *buffer, uint8_t post_status = POST_STATUS_NONE; int rv; - rv = REST.get_post_variable(request, "mode", &ptr); + rv = coap_get_post_variable(request, "mode", &ptr); if(rv && rv < 16) { memset(tmp_buf, 0, sizeof(tmp_buf)); memcpy(tmp_buf, ptr, rv); @@ -203,7 +203,7 @@ conf_post_handler(void *request, void *response, uint8_t *buffer, } } - rv = REST.get_post_variable(request, "duration", &ptr); + rv = coap_get_post_variable(request, "duration", &ptr); if(rv && rv < 16) { memset(tmp_buf, 0, sizeof(tmp_buf)); memcpy(tmp_buf, ptr, rv); @@ -217,7 +217,7 @@ conf_post_handler(void *request, void *response, uint8_t *buffer, } } - rv = REST.get_post_variable(request, "interval", &ptr); + rv = coap_get_post_variable(request, "interval", &ptr); if(rv && rv < 16) { memset(tmp_buf, 0, sizeof(tmp_buf)); memcpy(tmp_buf, ptr, rv); @@ -232,13 +232,13 @@ conf_post_handler(void *request, void *response, uint8_t *buffer, if((post_status & POST_STATUS_BAD) == POST_STATUS_BAD || post_status == POST_STATUS_NONE) { - REST.set_response_status(response, REST.status.BAD_REQUEST); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, + coap_set_status_code(response, BAD_REQUEST_4_00); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "mode=0|1&duration=[%u,%u]&interval=[%u,%u]", NORMAL_OP_DURATION_MIN, NORMAL_OP_DURATION_MAX, PERIODIC_INTERVAL_MIN, PERIODIC_INTERVAL_MAX); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); + coap_set_payload(response, buffer, strlen((char *)buffer)); return; } @@ -345,11 +345,11 @@ PROCESS_THREAD(very_sleepy_demo_process, ev, data) event_new_config = process_alloc_event(); - rest_init_engine(); + coap_engine_init(); readings_resource.flags += IS_OBSERVABLE; - rest_activate_resource(&readings_resource, "sen/readings"); - rest_activate_resource(&very_sleepy_conf, "very_sleepy_config"); + coap_activate_resource(&readings_resource, "sen/readings"); + coap_activate_resource(&very_sleepy_conf, "very_sleepy_config"); printf("Very Sleepy Demo Process\n"); @@ -390,7 +390,7 @@ PROCESS_THREAD(very_sleepy_demo_process, ev, data) * send notifications to observers as required. */ if(state == STATE_NOTIFY_OBSERVERS) { - REST.notify_subscribers(&readings_resource); + coap_notify_observers(&readings_resource); state = STATE_NORMAL; } diff --git a/examples/platform-specific/jn516x/rpl/coap-dongle-node/dongle-node.c b/examples/platform-specific/jn516x/rpl/coap-dongle-node/dongle-node.c index 1e3ab0842..5f113feef 100644 --- a/examples/platform-specific/jn516x/rpl/coap-dongle-node/dongle-node.c +++ b/examples/platform-specific/jn516x/rpl/coap-dongle-node/dongle-node.c @@ -35,15 +35,15 @@ #include "net/ipv6/uip.h" #include "net/ipv6/uip-ds6.h" #include "tools/rpl-tools.h" -#include "rest-engine.h" +#include "coap-engine.h" #include "sys/ctimer.h" #include #include "dev/leds.h" static void ct_callback(void *ptr); -static void put_post_led_toggle_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void put_post_led_toggle_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static char content[REST_MAX_CHUNK_SIZE]; +static char content[COAP_MAX_CHUNK_SIZE]; static int content_len = 0; static struct ctimer ct; @@ -77,7 +77,7 @@ RESOURCE(resource_led_toggle, put_post_led_toggle_handler, NULL); static void -put_post_led_toggle_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +put_post_led_toggle_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { static int led_state = 0; unsigned int accept = -1; @@ -110,10 +110,10 @@ put_post_led_toggle_handler(void *request, void *response, uint8_t *buffer, uint break; } /* Return message */ - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } } /*---------------------------------------------------------------------------*/ @@ -137,8 +137,8 @@ PROCESS_THREAD(start_app, ev, data) rpl_tools_init(NULL); } printf("Starting RPL node\n"); - rest_init_engine(); - rest_activate_resource(&resource_led_toggle, "Dongle/LED-toggle"); + coap_engine_init(); + coap_activate_resource(&resource_led_toggle, "Dongle/LED-toggle"); PROCESS_END(); } diff --git a/examples/platform-specific/jn516x/rpl/coap-dr1175-node/dr1175-node.c b/examples/platform-specific/jn516x/rpl/coap-dr1175-node/dr1175-node.c index 2cd40c283..6a86837ac 100644 --- a/examples/platform-specific/jn516x/rpl/coap-dr1175-node/dr1175-node.c +++ b/examples/platform-specific/jn516x/rpl/coap-dr1175-node/dr1175-node.c @@ -36,7 +36,7 @@ #include "net/ipv6/uip.h" #include "net/ipv6/uip-ds6.h" #include "tools/rpl-tools.h" -#include "rest-engine.h" +#include "coap-engine.h" #include "light-sensor.h" #include "ht-sensor.h" #include "dev/leds.h" @@ -46,19 +46,19 @@ #include static void event_sensors_dr1175_handler(void); -static void get_sensors_dr1175_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_light_sensor_value_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_light_sensor_unit_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_temperature_value_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_temperature_unit_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_humidity_value_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_humidity_unit_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void put_post_white_led_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void put_post_rgb_led_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void put_post_led_d3_1174_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void put_post_led_d6_1174_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_sensors_dr1175_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_light_sensor_value_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_light_sensor_unit_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_temperature_value_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_temperature_unit_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_humidity_value_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_humidity_unit_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void put_post_white_led_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void put_post_rgb_led_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void put_post_led_d3_1174_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void put_post_led_d6_1174_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static char content[REST_MAX_CHUNK_SIZE]; +static char content[COAP_MAX_CHUNK_SIZE]; static int content_len = 0; #define CONTENT_PRINTF(...) { if(content_len < sizeof(content)) { content_len += snprintf(content + content_len, sizeof(content) - content_len, __VA_ARGS__); } } @@ -90,26 +90,26 @@ EVENT_RESOURCE(resource_sensors_dr1175, /* name */ NULL, /* DELETE handler */ event_sensors_dr1175_handler); /* event handler */ static void -get_sensors_dr1175_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_sensors_dr1175_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.APPLICATION_JSON) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == APPLICATION_JSON) { content_len = 0; CONTENT_PRINTF("{\"DR1175\":["); CONTENT_PRINTF("{\"Humidity\":\"%d\"},", ht_sensor.value(HT_SENSOR_HUM)); CONTENT_PRINTF("{\"Light\":\"%d\"},", light_sensor.value(0)); CONTENT_PRINTF("{\"Temp\":\"%d\"}", ht_sensor.value(HT_SENSOR_TEMP)); CONTENT_PRINTF("]}"); - REST.set_header_content_type(response, REST.type.APPLICATION_JSON); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, APPLICATION_JSON); + coap_set_payload(response, (uint8_t *)content, content_len); } } static void event_sensors_dr1175_handler() { /* Registered observers are notified and will trigger the GET handler to create the response. */ - REST.notify_subscribers(&resource_sensors_dr1175); + coap_notify_observers(&resource_sensors_dr1175); } /*****************************************************/ /* Resource and handler to obtain light sensor value */ @@ -121,15 +121,15 @@ RESOURCE(resource_light_sensor_value, NULL, NULL); static void -get_light_sensor_value_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_light_sensor_value_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { content_len = 0; CONTENT_PRINTF("%d", light_sensor.value(0)); - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } } /***************************************************/ @@ -142,15 +142,15 @@ RESOURCE(resource_light_sensor_unit, NULL, NULL); static void -get_light_sensor_unit_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_light_sensor_unit_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { content_len = 0; CONTENT_PRINTF("Lux"); - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } } /***********************************************************/ @@ -163,15 +163,15 @@ RESOURCE(resource_temperature_value, NULL, NULL); static void -get_temperature_value_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_temperature_value_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { content_len = 0; CONTENT_PRINTF("%d", ht_sensor.value(HT_SENSOR_TEMP)); - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } } /*********************************************************/ @@ -184,15 +184,15 @@ RESOURCE(resource_temperature_unit, NULL, NULL); static void -get_temperature_unit_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_temperature_unit_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { content_len = 0; CONTENT_PRINTF("degrees C"); - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } } /********************************************************/ @@ -205,15 +205,15 @@ RESOURCE(resource_humidity_value, NULL, NULL); static void -get_humidity_value_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_humidity_value_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { content_len = 0; CONTENT_PRINTF("%d", ht_sensor.value(HT_SENSOR_HUM)); - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } } /******************************************************/ @@ -226,15 +226,15 @@ RESOURCE(resource_humidity_unit, NULL, NULL); static void -get_humidity_unit_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_humidity_unit_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { content_len = 0; CONTENT_PRINTF("relative %%"); - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } } /***************************************************/ @@ -247,15 +247,15 @@ RESOURCE(resource_white_led, put_post_white_led_handler, NULL); static void -put_post_white_led_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +put_post_white_led_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *request_content = NULL; int level; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.get_request_payload(request, &request_content); + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_get_payload(request, &request_content); level = atoi((const char *)request_content); CLIP(level, 255) leds_set_level(level, LEDS_WHITE); @@ -271,7 +271,7 @@ RESOURCE(resource_rgb_led, put_post_rgb_led_handler, NULL); static void -put_post_rgb_led_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +put_post_rgb_led_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *request_content = NULL; char *pch; @@ -279,9 +279,9 @@ put_post_rgb_led_handler(void *request, void *response, uint8_t *buffer, uint16_ int index = 0; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.get_request_payload(request, &request_content); + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_get_payload(request, &request_content); pch = strtok((char *)request_content, " "); while((pch != NULL) && (index != sizeof(RGB) / sizeof(int))) { /* Convert token to int */ @@ -306,13 +306,13 @@ RESOURCE(resource_led_d3_1174, put_post_led_d3_1174_handler, NULL); static void -put_post_led_d3_1174_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +put_post_led_d3_1174_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *request_content; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.get_request_payload(request, &request_content); + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_get_payload(request, &request_content); SET_LED(LEDS_GP0); } } @@ -326,13 +326,13 @@ RESOURCE(resource_led_d6_1174, put_post_led_d6_1174_handler, NULL); static void -put_post_led_d6_1174_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +put_post_led_d6_1174_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *request_content; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.get_request_payload(request, &request_content); + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_get_payload(request, &request_content); SET_LED(LEDS_GP1); } } @@ -357,18 +357,18 @@ PROCESS_THREAD(start_app, ev, data) rpl_tools_init(NULL); } printf("Starting RPL node\n"); - rest_init_engine(); - rest_activate_resource(&resource_light_sensor_value, "DR1175/LightSensor/Value"); - rest_activate_resource(&resource_light_sensor_unit, "DR1175/LightSensor/Unit"); - rest_activate_resource(&resource_temperature_unit, "DR1175/Temperature/Unit"); - rest_activate_resource(&resource_temperature_value, "DR1175/Temperature/Value"); - rest_activate_resource(&resource_humidity_unit, "DR1175/Humidity/Unit"); - rest_activate_resource(&resource_humidity_value, "DR1175/Humidity/Value"); - rest_activate_resource(&resource_white_led, "DR1175/WhiteLED"); - rest_activate_resource(&resource_rgb_led, "DR1175/ColorLED/RGBValue"); - rest_activate_resource(&resource_led_d3_1174, "DR1175/LED/D3On1174"); - rest_activate_resource(&resource_led_d6_1174, "DR1175/LED/D6On1174"); - rest_activate_resource(&resource_sensors_dr1175, "DR1175/AllSensors"); + coap_engine_init(); + coap_activate_resource(&resource_light_sensor_value, "DR1175/LightSensor/Value"); + coap_activate_resource(&resource_light_sensor_unit, "DR1175/LightSensor/Unit"); + coap_activate_resource(&resource_temperature_unit, "DR1175/Temperature/Unit"); + coap_activate_resource(&resource_temperature_value, "DR1175/Temperature/Value"); + coap_activate_resource(&resource_humidity_unit, "DR1175/Humidity/Unit"); + coap_activate_resource(&resource_humidity_value, "DR1175/Humidity/Value"); + coap_activate_resource(&resource_white_led, "DR1175/WhiteLED"); + coap_activate_resource(&resource_rgb_led, "DR1175/ColorLED/RGBValue"); + coap_activate_resource(&resource_led_d3_1174, "DR1175/LED/D3On1174"); + coap_activate_resource(&resource_led_d6_1174, "DR1175/LED/D6On1174"); + coap_activate_resource(&resource_sensors_dr1175, "DR1175/AllSensors"); /* Level of LEDS=0, so no light after start-up */ leds_on(LEDS_WHITE | LEDS_RED | LEDS_GREEN | LEDS_BLUE); diff --git a/examples/platform-specific/jn516x/rpl/coap-dr1199-node/dr1199-node.c b/examples/platform-specific/jn516x/rpl/coap-dr1199-node/dr1199-node.c index 0309538ec..d1677e6b9 100644 --- a/examples/platform-specific/jn516x/rpl/coap-dr1199-node/dr1199-node.c +++ b/examples/platform-specific/jn516x/rpl/coap-dr1199-node/dr1199-node.c @@ -35,30 +35,30 @@ #include "net/ipv6/uip.h" #include "net/ipv6/uip-ds6.h" #include "tools/rpl-tools.h" -#include "rest-engine.h" +#include "coap-engine.h" #include "dev/leds.h" #include "button-sensor.h" #include "pot-sensor.h" #include #include -static char content[REST_MAX_CHUNK_SIZE]; +static char content[COAP_MAX_CHUNK_SIZE]; static int content_len = 0; static void event_sensors_dr1199_handler(); -static void get_sensors_dr1199_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_switch_sw1_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_switch_sw2_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_switch_sw3_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_switch_sw4_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_switch_dio8_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_pot_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void put_post_led_d1_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void put_post_led_d2_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void put_post_led_d3_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void put_post_led_d3_1174_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void put_post_led_d6_1174_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void put_post_led_all_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_sensors_dr1199_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_switch_sw1_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_switch_sw2_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_switch_sw3_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_switch_sw4_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_switch_dio8_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_pot_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void put_post_led_d1_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void put_post_led_d2_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void put_post_led_d3_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void put_post_led_d3_1174_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void put_post_led_d6_1174_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void put_post_led_all_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); #define CONTENT_PRINTF(...) { if(content_len < sizeof(content)) { content_len += snprintf(content + content_len, sizeof(content) - content_len, __VA_ARGS__); } } @@ -93,25 +93,25 @@ EVENT_RESOURCE(resource_sensors_dr1199, /* name */ NULL, /* DELETE handler */ event_sensors_dr1199_handler); /* event handler */ static void -get_sensors_dr1199_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_sensors_dr1199_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.APPLICATION_JSON) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == APPLICATION_JSON) { content_len = 0; CONTENT_PRINTF("{\"DR1199\":["); CONTENT_PRINTF("{\"Switch\":\"0x%X\"},", button_sensor.value(0)); CONTENT_PRINTF("{\"Pot\":\"%d\"}", pot_sensor.value(0)); CONTENT_PRINTF("]}"); - REST.set_header_content_type(response, REST.type.APPLICATION_JSON); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, APPLICATION_JSON); + coap_set_payload(response, (uint8_t *)content, content_len); } } static void event_sensors_dr1199_handler() { /* Registered observers are notified and will trigger the GET handler to create the response. */ - REST.notify_subscribers(&resource_sensors_dr1199); + coap_notify_observers(&resource_sensors_dr1199); } /***********************************************/ /* Resource and handler to obtain switch value */ @@ -123,15 +123,15 @@ RESOURCE(resource_switch_sw1, NULL, NULL); static void -get_switch_sw1_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_switch_sw1_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { content_len = 0; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { PARSE_SWITCH(1) - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } } RESOURCE(resource_switch_sw2, @@ -141,15 +141,15 @@ RESOURCE(resource_switch_sw2, NULL, NULL); static void -get_switch_sw2_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_switch_sw2_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { content_len = 0; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { PARSE_SWITCH(2) - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } } RESOURCE(resource_switch_sw3, @@ -159,15 +159,15 @@ RESOURCE(resource_switch_sw3, NULL, NULL); static void -get_switch_sw3_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_switch_sw3_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { content_len = 0; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { PARSE_SWITCH(3) - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } } RESOURCE(resource_switch_sw4, @@ -177,15 +177,15 @@ RESOURCE(resource_switch_sw4, NULL, NULL); static void -get_switch_sw4_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_switch_sw4_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { content_len = 0; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { PARSE_SWITCH(4) - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } } RESOURCE(resource_switch_dio8, @@ -195,15 +195,15 @@ RESOURCE(resource_switch_dio8, NULL, NULL); static void -get_switch_dio8_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_switch_dio8_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { content_len = 0; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { PARSE_SWITCH(0) - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } } /*******************************************************/ @@ -216,15 +216,15 @@ RESOURCE(resource_pot, NULL, NULL); static void -get_pot_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_pot_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { content_len = 0; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { CONTENT_PRINTF("%d", pot_sensor.value(0)); - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } } /************************************/ @@ -237,13 +237,13 @@ RESOURCE(resource_led_d1, put_post_led_d1_handler, NULL); static void -put_post_led_d1_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +put_post_led_d1_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *request_content; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.get_request_payload(request, &request_content); + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_get_payload(request, &request_content); SET_LED(LEDS_GREEN) } } @@ -254,13 +254,13 @@ RESOURCE(resource_led_d2, put_post_led_d2_handler, NULL); static void -put_post_led_d2_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +put_post_led_d2_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *request_content; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.get_request_payload(request, &request_content); + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_get_payload(request, &request_content); SET_LED(LEDS_BLUE) } } @@ -271,13 +271,13 @@ RESOURCE(resource_led_d3, put_post_led_d3_handler, NULL); static void -put_post_led_d3_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +put_post_led_d3_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *request_content; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.get_request_payload(request, &request_content); + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_get_payload(request, &request_content); SET_LED(LEDS_RED) } } @@ -288,13 +288,13 @@ RESOURCE(resource_led_d3_1174, put_post_led_d3_1174_handler, NULL); static void -put_post_led_d3_1174_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +put_post_led_d3_1174_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *request_content; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.get_request_payload(request, &request_content); + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_get_payload(request, &request_content); SET_LED(LEDS_GP0); } } @@ -305,13 +305,13 @@ RESOURCE(resource_led_d6_1174, put_post_led_d6_1174_handler, NULL); static void -put_post_led_d6_1174_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +put_post_led_d6_1174_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *request_content; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.get_request_payload(request, &request_content); + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_get_payload(request, &request_content); SET_LED(LEDS_GP1); } } @@ -322,13 +322,13 @@ RESOURCE(resource_led_all, put_post_led_all_handler, NULL); static void -put_post_led_all_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +put_post_led_all_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *request_content; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.get_request_payload(request, &request_content); + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_get_payload(request, &request_content); if(atoi((const char *)request_content) != 0) { leds_on(LEDS_ALL); } else { @@ -358,20 +358,20 @@ PROCESS_THREAD(start_app, ev, data) rpl_tools_init(NULL); } printf("Starting RPL node\n"); - rest_init_engine(); - rest_activate_resource(&resource_switch_sw1, "DR1199/Switch/SW1"); - rest_activate_resource(&resource_switch_sw2, "DR1199/Switch/SW2"); - rest_activate_resource(&resource_switch_sw3, "DR1199/Switch/SW3"); - rest_activate_resource(&resource_switch_sw4, "DR1199/Switch/SW4"); - rest_activate_resource(&resource_switch_dio8, "DR1199/Switch/DIO8"); - rest_activate_resource(&resource_pot, "DR1199/Potentiometer"); - rest_activate_resource(&resource_led_d1, "DR1199/LED/D1"); - rest_activate_resource(&resource_led_d2, "DR1199/LED/D2"); - rest_activate_resource(&resource_led_d3, "DR1199/LED/D3"); - rest_activate_resource(&resource_led_d3_1174, "DR1199/LED/D3On1174"); - rest_activate_resource(&resource_led_d6_1174, "DR1199/LED/D6On1174"); - rest_activate_resource(&resource_led_all, "DR1199/LED/All"); - rest_activate_resource(&resource_sensors_dr1199, "DR1199/AllSensors"); + coap_engine_init(); + coap_activate_resource(&resource_switch_sw1, "DR1199/Switch/SW1"); + coap_activate_resource(&resource_switch_sw2, "DR1199/Switch/SW2"); + coap_activate_resource(&resource_switch_sw3, "DR1199/Switch/SW3"); + coap_activate_resource(&resource_switch_sw4, "DR1199/Switch/SW4"); + coap_activate_resource(&resource_switch_dio8, "DR1199/Switch/DIO8"); + coap_activate_resource(&resource_pot, "DR1199/Potentiometer"); + coap_activate_resource(&resource_led_d1, "DR1199/LED/D1"); + coap_activate_resource(&resource_led_d2, "DR1199/LED/D2"); + coap_activate_resource(&resource_led_d3, "DR1199/LED/D3"); + coap_activate_resource(&resource_led_d3_1174, "DR1199/LED/D3On1174"); + coap_activate_resource(&resource_led_d6_1174, "DR1199/LED/D6On1174"); + coap_activate_resource(&resource_led_all, "DR1199/LED/All"); + coap_activate_resource(&resource_sensors_dr1199, "DR1199/AllSensors"); /* If sensor process generates an event, call event_handler of resource. This will make this resource observable by the client */ while(1) { @@ -382,4 +382,3 @@ PROCESS_THREAD(start_app, ev, data) PROCESS_END(); } - diff --git a/examples/platform-specific/jn516x/tsch/tx-power-verification/node/node.c b/examples/platform-specific/jn516x/tsch/tx-power-verification/node/node.c index 115649535..df3197525 100644 --- a/examples/platform-specific/jn516x/tsch/tx-power-verification/node/node.c +++ b/examples/platform-specific/jn516x/tsch/tx-power-verification/node/node.c @@ -37,15 +37,15 @@ #include "net/ipv6/uip.h" #include "net/linkaddr.h" #include "rpl-tools.h" -#include "rest-engine.h" +#include "coap-engine.h" #include #include #include -static void set_tx_power_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_tx_power_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void set_tx_power_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_tx_power_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static char content[REST_MAX_CHUNK_SIZE]; +static char content[COAP_MAX_CHUNK_SIZE]; static int content_len = 0; #define CONTENT_PRINTF(...) { if(content_len < sizeof(content)) content_len += snprintf(content+content_len, sizeof(content)-content_len, __VA_ARGS__); } @@ -63,15 +63,15 @@ RESOURCE(resource_set_tx_power, set_tx_power_handler, NULL); static void -set_tx_power_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +set_tx_power_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *request_content = NULL; int tx_level; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.get_request_payload(request, &request_content); + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_get_payload(request, &request_content); tx_level = atoi((const char *)request_content); NETSTACK_RADIO.set_value(RADIO_PARAM_TXPOWER, tx_level); } @@ -84,17 +84,17 @@ RESOURCE(resource_get_tx_power, NULL, NULL); static void -get_tx_power_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_tx_power_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { int tx_level; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { content_len = 0; NETSTACK_RADIO.get_value(RADIO_PARAM_TXPOWER, &tx_level); CONTENT_PRINTF("%d", tx_level); - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } } /*---------------------------------------------------------------------------*/ @@ -113,9 +113,9 @@ PROCESS_THREAD(start_app, ev, data) } printf("Starting RPL node\n"); - rest_init_engine(); - rest_activate_resource(&resource_set_tx_power, "Set-TX-Power"); - rest_activate_resource(&resource_get_tx_power, "Get-TX-Power"); + coap_engine_init(); + coap_activate_resource(&resource_set_tx_power, "Set-TX-Power"); + coap_activate_resource(&resource_get_tx_power, "Get-TX-Power"); PROCESS_END(); } diff --git a/examples/platform-specific/jn516x/tsch/tx-power-verification/rpl-border-router/rpl-border-router.c b/examples/platform-specific/jn516x/tsch/tx-power-verification/rpl-border-router/rpl-border-router.c index e15a77989..76e0a72ec 100644 --- a/examples/platform-specific/jn516x/tsch/tx-power-verification/rpl-border-router/rpl-border-router.c +++ b/examples/platform-specific/jn516x/tsch/tx-power-verification/rpl-border-router/rpl-border-router.c @@ -42,7 +42,7 @@ #include "net/mac/tsch/tsch-schedule.h" #include "net/netstack.h" #include "dev/slip.h" -#include "rest-engine.h" +#include "coap-engine.h" #include "rpl-tools.h" #include @@ -56,10 +56,10 @@ static uip_ipaddr_t prefix; static uint8_t prefix_set; -static void get_rssi_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_last_rssi_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_rssi_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_last_rssi_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static char content[REST_MAX_CHUNK_SIZE]; +static char content[COAP_MAX_CHUNK_SIZE]; static int content_len = 0; #define CONTENT_PRINTF(...) { if(content_len < sizeof(content)) content_len += snprintf(content+content_len, sizeof(content)-content_len, __VA_ARGS__); } @@ -74,17 +74,17 @@ RESOURCE(resource_get_rssi, NULL, NULL); static void -get_rssi_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_rssi_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { int rssi_level; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { content_len = 0; NETSTACK_RADIO.get_value(RADIO_PARAM_RSSI, &rssi_level); CONTENT_PRINTF("%d", rssi_level); - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } } @@ -95,17 +95,17 @@ RESOURCE(resource_get_last_rssi, NULL, NULL); static void -get_last_rssi_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_last_rssi_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { int last_rssi_level; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { content_len = 0; NETSTACK_RADIO.get_value(RADIO_PARAM_LAST_RSSI, &last_rssi_level); CONTENT_PRINTF("%d", last_rssi_level); - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } } @@ -159,9 +159,9 @@ PROCESS_THREAD(border_router_process, ev, data) rpl_tools_init(&prefix); - rest_init_engine(); - rest_activate_resource(&resource_get_rssi, "Get-RSSI"); - rest_activate_resource(&resource_get_last_rssi, "Get-Last-RSSI"); + coap_engine_init(); + coap_activate_resource(&resource_get_rssi, "Get-RSSI"); + coap_activate_resource(&resource_get_last_rssi, "Get-Last-RSSI"); PROCESS_END(); diff --git a/examples/platform-specific/jn516x/tsch/uart1-test-node/uart1-test-node.c b/examples/platform-specific/jn516x/tsch/uart1-test-node/uart1-test-node.c index 244672d48..b5003e452 100644 --- a/examples/platform-specific/jn516x/tsch/uart1-test-node/uart1-test-node.c +++ b/examples/platform-specific/jn516x/tsch/uart1-test-node/uart1-test-node.c @@ -36,22 +36,22 @@ #include "net/ipv6/uip.h" #include "net/linkaddr.h" #include "rpl-tools.h" -#include "rest-engine.h" +#include "coap-engine.h" #include "sys/ctimer.h" #include "dev/uart-driver.h" #include "uart1.h" #include -static void get_coap_rx_uart1_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_coap_rx_uart1_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); static void event_coap_rx_uart1_handler(void); -static void put_post_tx_uart1_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void put_post_tx_uart1_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); static void string2uart1(uint8_t *c); static int handleRxChar(uint8_t c); static int get_ringbuf(uint8_t *c); static int put_ringbuf(uint8_t c); /* COAP helpers */ -static char content[REST_MAX_CHUNK_SIZE]; +static char content[COAP_MAX_CHUNK_SIZE]; static int content_len = 0; #define CONTENT_PRINTF(...) { if(content_len < sizeof(content)) content_len += snprintf(content+content_len, sizeof(content)-content_len, __VA_ARGS__); } @@ -85,15 +85,15 @@ EVENT_RESOURCE(resource_coap_rx_uart1, /* name */ NULL, /* DELETE handler */ event_coap_rx_uart1_handler); /* event handler */ static void -get_coap_rx_uart1_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_coap_rx_uart1_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { content_len = 0; CONTENT_PRINTF("%s", rx_buf); - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } } @@ -101,7 +101,7 @@ static void event_coap_rx_uart1_handler(void) { /* Registered observers are notified and will trigger the GET handler to create the response. */ - REST.notify_subscribers(&resource_coap_rx_uart1); + coap_notify_observers(&resource_coap_rx_uart1); } /*****************************************************************************/ @@ -115,14 +115,14 @@ RESOURCE(resource_coap_tx_uart1, /* name */ NULL); /* DELETE handler */ static void -put_post_tx_uart1_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +put_post_tx_uart1_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *request_content = NULL; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.get_request_payload(request, &request_content); + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_get_payload(request, &request_content); string2uart1((uint8_t *)request_content); } } @@ -154,9 +154,9 @@ PROCESS_THREAD(start_app, ev, data) } printf("Starting RPL node\n"); - rest_init_engine(); - rest_activate_resource(&resource_coap_rx_uart1, "UART1-RX"); - rest_activate_resource(&resource_coap_tx_uart1, "UART1-TX"); + coap_engine_init(); + coap_activate_resource(&resource_coap_rx_uart1, "UART1-RX"); + coap_activate_resource(&resource_coap_tx_uart1, "UART1-TX"); PROCESS_END(); } @@ -256,4 +256,3 @@ put_ringbuf(uint8_t c) uart1_enable_interrupts(); return return_val; } - diff --git a/examples/platform-specific/nrf52dk/coap-demo/Makefile b/examples/platform-specific/nrf52dk/coap-demo/Makefile index 37b4cef4d..0ad01fc57 100644 --- a/examples/platform-specific/nrf52dk/coap-demo/Makefile +++ b/examples/platform-specific/nrf52dk/coap-demo/Makefile @@ -5,10 +5,10 @@ $(error Please specify whether coap-client or coap-server should be built) endif ifneq ($(filter coap-client coap-client.flash, $(MAKECMDGOALS)),) -ifeq ($(SERVER_IPV6_ADDR),) -$(error Please define SERVER_IPV6_ADDR=) +ifeq ($(SERVER_IPV6_EP),) +$(error Please define SERVER_IPV6_EP=) else -CFLAGS += -DSERVER_IPV6_ADDR=\"$(SERVER_IPV6_ADDR)\" +CFLAGS += -DSERVER_IPV6_EP=\"$(SERVER_IPV6_EP)\" CFLAGS += -DDEVICE_NAME=\"nRF52_DK_CoAP_Client\" endif else diff --git a/examples/platform-specific/nrf52dk/coap-demo/coap-client.c b/examples/platform-specific/nrf52dk/coap-demo/coap-client.c index 1ef59b369..4effcc876 100644 --- a/examples/platform-specific/nrf52dk/coap-demo/coap-client.c +++ b/examples/platform-specific/nrf52dk/coap-demo/coap-client.c @@ -51,6 +51,7 @@ #include "contiki.h" #include "contiki-net.h" #include "coap-engine.h" +#include "coap-endpoint.h" #include "dev/button-sensor.h" #include "dev/leds.h" @@ -63,13 +64,11 @@ #endif /*----------------------------------------------------------------------------*/ -#define REMOTE_PORT UIP_HTONS(COAP_DEFAULT_PORT) #define OBS_RESOURCE_URI "lights/led3" #define SUBS_LED LEDS_4 #define OBS_LED LEDS_3 /*----------------------------------------------------------------------------*/ -static uip_ipaddr_t server_ipaddr[1]; /* holds the server ip address */ static coap_observee_t *obs; static struct ctimer ct; /*----------------------------------------------------------------------------*/ @@ -146,11 +145,11 @@ notification_callback(coap_observee_t *obs, void *notification, PROCESS_THREAD(er_example_observe_client, ev, data) { PROCESS_BEGIN(); - - uiplib_ipaddrconv(SERVER_IPV6_ADDR, server_ipaddr); + static coap_endpoint_t server_endpoint; + coap_endpoint_parse(SERVER_IPV6_EP, strlen(SERVER_IPV6_EP), &server_endpoint); /* receives all CoAP messages */ - coap_init_engine(); + coap_engine_init(); #if PLATFORM_HAS_BUTTON SENSORS_ACTIVATE(button_1); @@ -164,7 +163,7 @@ PROCESS_THREAD(er_example_observe_client, ev, data) if (ev == sensors_event) { if (data == &button_1 && button_1.value(BUTTON_SENSOR_VALUE_STATE) == 0) { PRINTF("Starting observation\n"); - obs = coap_obs_request_registration(server_ipaddr, REMOTE_PORT, + obs = coap_obs_request_registration(&server_endpoint, OBS_RESOURCE_URI, notification_callback, NULL); } diff --git a/examples/platform-specific/nrf52dk/coap-demo/coap-server.c b/examples/platform-specific/nrf52dk/coap-demo/coap-server.c index 9df517886..6b4025cd3 100644 --- a/examples/platform-specific/nrf52dk/coap-demo/coap-server.c +++ b/examples/platform-specific/nrf52dk/coap-demo/coap-server.c @@ -51,7 +51,7 @@ #include #include "contiki.h" #include "contiki-net.h" -#include "rest-engine.h" +#include "coap-engine.h" #include "uip.h" #include "dev/button-sensor.h" #include "dev/leds.h" @@ -63,7 +63,7 @@ * Resources to be activated need to be imported through the extern keyword. * The build system automatically compiles the resources in the corresponding sub-directory. */ -extern resource_t res_led3; +extern coap_resource_t res_led3; static void print_local_addresses(void) @@ -99,13 +99,13 @@ PROCESS_THREAD(er_example_server, ev, data) PRINTF("uIP buffer: %u\n", UIP_BUFSIZE); PRINTF("LL header: %u\n", UIP_LLH_LEN); PRINTF("IP+UDP header: %u\n", UIP_IPUDPH_LEN); - PRINTF("REST max chunk: %u\n", REST_MAX_CHUNK_SIZE); + PRINTF("REST max chunk: %u\n", COAP_MAX_CHUNK_SIZE); print_local_addresses(); /* Initialize the REST engine. */ - rest_init_engine(); - rest_activate_resource(&res_led3, "lights/led3"); + coap_engine_init(); + coap_activate_resource(&res_led3, "lights/led3"); SENSORS_ACTIVATE(button_1); diff --git a/examples/platform-specific/nrf52dk/coap-demo/resources/res-leds.c b/examples/platform-specific/nrf52dk/coap-demo/resources/res-leds.c index f990fcf38..906952b94 100644 --- a/examples/platform-specific/nrf52dk/coap-demo/resources/res-leds.c +++ b/examples/platform-specific/nrf52dk/coap-demo/resources/res-leds.c @@ -40,22 +40,25 @@ #include #include "contiki.h" -#include "rest-engine.h" +#include "coap.h" +#include "coap-engine.h" #include "dev/leds.h" #define DEBUG DEBUG_NONE #include "net/ipv6/uip-debug.h" static void -res_post_put_handler(void *request, void *response, uint8_t *buffer, +res_post_put_handler(coap_packet_t *request, coap_packet_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset); static void -res_get_handler(void *request, void *response, uint8_t *buffer, +res_get_handler(coap_packet_t *request, coap_packet_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset); static void -res_event_handler(); +res_event_handler(void); /*A simple actuator example, depending on the color query parameter and post variable mode, corresponding led is activated or deactivated*/ EVENT_RESOURCE(res_led3, @@ -68,30 +71,30 @@ EVENT_RESOURCE(res_led3, ); static void -res_post_put_handler(void *request, void *response, uint8_t *buffer, - uint16_t preferred_size, int32_t *offset) +res_post_put_handler(coap_packet_t *request, coap_packet_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *payload; - REST.get_request_payload(request, &payload); + coap_get_payload(request, &payload); - if (*payload == '0' || *payload == '1') { - if (*payload == '1') { + if(*payload == '0' || *payload == '1') { + if(*payload == '1') { leds_on(LEDS_3); } else { leds_off(LEDS_3); } - REST.notify_subscribers(&res_led3); - REST.set_response_status(response, REST.status.CHANGED); + coap_notify_observers(&res_led3); + coap_set_status_code(response, CHANGED_2_04); } else { - REST.set_response_status(response, REST.status.BAD_REQUEST); + coap_set_status_code(response, BAD_REQUEST_4_00); } } static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, buffer, snprintf((char *)buffer, preferred_size, "%d", (leds_get() & LEDS_3) ? 1 : 0)); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, buffer, snprintf((char *)buffer, preferred_size, "%d", (leds_get() & LEDS_3) ? 1 : 0)); } /* @@ -102,5 +105,5 @@ static void res_event_handler() { /* Notify the registered observers which will trigger the res_get_handler to create the response. */ - REST.notify_subscribers(&res_led3); + coap_notify_observers(&res_led3); } From 4a82bda54359c4a3cb3ea9d09c302478de51e311 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Tue, 7 Nov 2017 18:23:21 +0100 Subject: [PATCH 11/51] Various updates in LWM2M standalone example * Use LWM2M security object as DTLS keystore by default * Mark endpoint as secure regardless if DTLS peer exists or not * Somewhat less debug output by default --- examples/lwm2m/standalone/.gitignore | 4 +- examples/lwm2m/standalone/Makefile | 2 +- examples/lwm2m/standalone/Makefile.contiki | 6 +- examples/lwm2m/standalone/README.md | 83 ++++++++++-------- .../lwm2m/standalone/coap-ipv4/coap-ipv4.c | 84 ++++++++++--------- examples/lwm2m/standalone/contiki.h | 7 +- examples/lwm2m/standalone/lwm2m-example.c | 7 +- .../tinydtls-support/dtls-support.c | 1 + 8 files changed, 111 insertions(+), 83 deletions(-) diff --git a/examples/lwm2m/standalone/.gitignore b/examples/lwm2m/standalone/.gitignore index f1e834bc0..131f2183a 100644 --- a/examples/lwm2m/standalone/.gitignore +++ b/examples/lwm2m/standalone/.gitignore @@ -1,3 +1,3 @@ *.o -oma-lwm2m-src -lwm2m-example +/lwm2m-src +/lwm2m-example diff --git a/examples/lwm2m/standalone/Makefile b/examples/lwm2m/standalone/Makefile index 03a8fda23..c25819b38 100644 --- a/examples/lwm2m/standalone/Makefile +++ b/examples/lwm2m/standalone/Makefile @@ -2,7 +2,7 @@ PROJECT = lwm2m-example all: $(PROJECT) -TARGETCDIR = oma-lwm2m-src +TARGETCDIR = lwm2m-src COREDIRS = sys lib SOURCEDIRS = . SOURCE_FILES = posix-main.c posix-coap-timer.c ipso-sensor-temp.c \ diff --git a/examples/lwm2m/standalone/Makefile.contiki b/examples/lwm2m/standalone/Makefile.contiki index ecd46311a..807bb1b82 100644 --- a/examples/lwm2m/standalone/Makefile.contiki +++ b/examples/lwm2m/standalone/Makefile.contiki @@ -10,7 +10,11 @@ IPSO_FILES = ${addprefix ipso-objects/,${filter-out ipso-leds-control.c ipso-obj TARGET_FILES += ${addprefix $(TARGETCDIR)/,$(CORE_FILES) $(CORE_FILES:.c=.h) \ $(COAP_FILES) $(LWM2M_FILES) $(IPSO_FILES)} -ifneq ($(MAKE_WITH_DTLS),) +ifeq ($(MAKE_WITH_DTLS),1) + ifeq (${wildcard $(DTLS_PATH)/tinydtls/Makefile},) + ${error Could not find the tinyDTLS submodule. Please run "git submodule update --init" and try again} + endif + DTLS_FILES = ${subst $(DTLS_PATH)/,,${wildcard ${addprefix $(DTLS_PATH)/tinydtls/,*.[ch] ${addsuffix /*.[ch],$(TINYDTLS_DIRS)}}}} TARGET_FILES += ${addprefix $(TARGETCDIR)/,$(DTLS_FILES)} endif diff --git a/examples/lwm2m/standalone/README.md b/examples/lwm2m/standalone/README.md index 2a582645f..b762d1595 100644 --- a/examples/lwm2m/standalone/README.md +++ b/examples/lwm2m/standalone/README.md @@ -1,58 +1,68 @@ -OMA LWM2M Standalone Example +LWM2M Standalone Example ==================================== This is an example of how to make use of the OMA LWM2M and CoAP -implementation from Contiki in a native application. +implementation from Contiki-NG in a native application. -The Makefile will copy necessary files from Contiki to the subfolder -```oma-lwm2m-src``` and then compile the example ```lwm2m-example``` +The Makefile will copy necessary files from Contiki-NG to the subfolder +```lwm2m-src``` and then compile the example ```lwm2m-example``` as a native application. By copying only the needed source files, -the example can be used outside the Contiki source tree. +the example can be used outside the Contiki-NG source tree. -### Running the OMA LWM2M example +### Running the LWM2M example ```bash -cd contiki/examples/oma-lwm2m/standalone +cd contiki/examples/lwm2m/standalone make ./lwm2m-example ``` -The example application will start a CoAP server listening on -localhost port 5683 with an example OMA LWM2M device object. +The example application will start a CoAP server listening on localhost port +5683 with some example LWM2M objects. By default, the example application will +also register itself with the Leshan server at leshan.eclipse.org. To specify +a different LWM2M server: +`./lwm2m-example coap:// `. - -### Testing the OMA LWM2M example - -The Copper (Cu) Firefox addon can be used to access the LWM2M example. - -1. Start the OMA LWM2M example as described above. - -2. Get the Copper (Cu) CoAP user-agent from -[https://addons.mozilla.org/en-US/firefox/addon/copper-270430](https://addons.mozilla.org/en-US/firefox/addon/copper-270430). - -3. Start Copper and discover resources at coap://127.0.0.1:5683/ - It should find three objects named 0, 1, and 3. - -4. Browse to the device type resource at coap://127.0.0.1:5683/3/0/17 - (object 3, instance 0, resource 17) and then click ```GET```. - As device type the LWM2M example should return the text "lwm2m-example". - -5. Browse to the time resource at coap://127.0.0.1:5683/3/0/13 - Every time you click ```GET```, it should return the number of seconds - since the example application was started. - -### Moving the example outside Contiki +For example to connect to a locally running LWM2M server: ```bash -cd contiki/examples/oma-lwm2m/standalone +./lwm2m-example coap://127.0.0.1/ example-endpoint-name +``` + +### Running the LWM2M example with DTLS + +The example currently only supports PSK and the default credentials can be +changed in the file `lwm2m-example.c`. + +```c +#define PSK_DEFAULT_IDENTITY "Client_identity" +#define PSK_DEFAULT_KEY "secretPSK" +``` + +To compile with DTLS support and connect to a local LWM2M server with matching +credentials configured: + +```bash +cd contiki/examples/lwm2m/standalone +make clean +make MAKE_WITH_DTLS=1 +./lwm2m-example coaps://127.0.0.1 +``` + +### Moving the example outside Contiki-NG + +```bash +cd contiki/examples/lwm2m/standalone make copy ``` -Copy the example directory contents to a directory outside Contiki. +Copy the example directory contents to a directory outside Contiki-NG. Remove the Makefile ```Makefile.contiki``` and the remaining Makefile -will compile the example independent of the Contiki source tree. +will compile the example independent of the Contiki-NG source tree. +### Running the LWM2M examle with HEX transport + The Hex Transport can be tested together with DTLS using: ```bash @@ -62,7 +72,6 @@ javac Hex2UDP.java java Hex2UDP leshan.eclipse.org 5684 ./lwm2m-example ``` -Note that you need to configure the Leshan server with the correct -key and ID. +Note that you need to configure the Leshan server with the correct key and ID. -(without DTLS it should be 5683 for CoAP) +(without DTLS it should be 5683 for CoAP). diff --git a/examples/lwm2m/standalone/coap-ipv4/coap-ipv4.c b/examples/lwm2m/standalone/coap-ipv4/coap-ipv4.c index 95659ef6f..8733bafe6 100644 --- a/examples/lwm2m/standalone/coap-ipv4/coap-ipv4.c +++ b/examples/lwm2m/standalone/coap-ipv4/coap-ipv4.c @@ -51,6 +51,7 @@ #include #define DEBUG 1 +#define DEBUG_VERBOSE ((DEBUG) && 0) #if DEBUG #define PRINTF(...) printf(__VA_ARGS__) #define PRINTEP(ep) coap_endpoint_print(ep) @@ -108,12 +109,12 @@ coap_endpoint_is_connected(const coap_endpoint_t *ep) peer = dtls_get_peer(dtls_context, ep); if(peer != NULL) { /* only if handshake is done! */ - PRINTF("peer state for "); + PRINTF("DTLS peer state for "); PRINTEP(ep); PRINTF(" is %d %d\n", peer->state, dtls_peer_is_connected(peer)); return dtls_peer_is_connected(peer); } else { - PRINTF("Did not find peer "); + PRINTF("DTLS did not find peer "); PRINTEP(ep); PRINTF("\n"); } @@ -130,8 +131,9 @@ coap_endpoint_connect(coap_endpoint_t *ep) if(ep->secure == 0) { return 1; } + #ifdef WITH_DTLS - PRINTF("DTLS EP:"); + PRINTF("DTLS connect to "); PRINTEP(ep); PRINTF(" len:%d\n", ep->size); @@ -141,6 +143,7 @@ coap_endpoint_connect(coap_endpoint_t *ep) return 1; } #endif /* WITH_DTLS */ + return 0; } /*---------------------------------------------------------------------------*/ @@ -181,7 +184,7 @@ coap_endpoint_print(const coap_endpoint_t *ep) const char *address; address = inet_ntoa(ep->addr.sin_addr); if(address != NULL) { - printf("coap%s://%s:%u",ep->secure ? "s":"", + printf("coap%s://%s:%u", ep->secure ? "s" : "", address, ntohs(ep->addr.sin_port)); } else { printf("<#N/A>"); @@ -200,15 +203,14 @@ coap_endpoint_parse(const char *text, size_t size, coap_endpoint_t *ep) int secure; int offset = 0; int i; - PRINTF("CoAP-IPv4: Parsing endpoint: %.*s\n", (int)size, text); + PRINTF("CoAP-IPv4: parsing endpoint %.*s => ", (int)size, text); if(strncmp("coap://", text, 7) == 0) { secure = 0; offset = 7; - PRINTF("COAP found\n"); } else if(strncmp("coaps://", text, 8) == 0) { secure = 1; offset = 8; - PRINTF("COAPS found\n"); + PRINTF("secure "); } else { secure = 0; } @@ -225,7 +227,7 @@ coap_endpoint_parse(const char *text, size_t size, coap_endpoint_t *ep) port = atoi(&text[i + 1]); } - PRINTF("CoAP-IPv4: endpoint %s:%u\n", host, port); + PRINTF("endpoint at %s:%u\n", host, port); ep->addr.sin_family = AF_INET; ep->addr.sin_port = htons(port); @@ -252,7 +254,7 @@ coap_datalen() } /*---------------------------------------------------------------------------*/ static int -read_packet_to_coapbuf(int fd) +read_packet_to_coapbuf(int fd, int is_secure) { int len; @@ -268,7 +270,9 @@ read_packet_to_coapbuf(int fd) return 0; } - PRINTF("RECV from "); + last_source.secure = is_secure; + + PRINTF("CoAP-IPv4: RECV from "); PRINTEP(&last_source); PRINTF(" %u bytes\n", len); coap_buf_len = len; @@ -298,8 +302,8 @@ coap_ipv4_handle_fd(fd_set *rset, fd_set *wset) { if(coap_ipv4_fd >= 0 && FD_ISSET(coap_ipv4_fd, rset)) { - if(read_packet_to_coapbuf(coap_ipv4_fd)) { -#if DEBUG + if(read_packet_to_coapbuf(coap_ipv4_fd, 0)) { +#if DEBUG_VERBOSE int i; uint8_t *data; data = coap_databuf(); @@ -308,7 +312,7 @@ coap_ipv4_handle_fd(fd_set *rset, fd_set *wset) PRINTF("%02x", data[i]); } PRINTF("\n"); -#endif /* DEBUG */ +#endif /* DEBUG_VERBOSE */ coap_receive(coap_src_endpoint(), coap_databuf(), coap_datalen()); } } @@ -335,9 +339,8 @@ static void dtls_ipv4_handle_fd(fd_set *rset, fd_set *wset) { if(dtls_ipv4_fd >= 0 && FD_ISSET(dtls_ipv4_fd, rset)) { - if(read_packet_to_coapbuf(dtls_ipv4_fd) && dtls_context) { + if(read_packet_to_coapbuf(dtls_ipv4_fd, 1) && dtls_context) { /* DTLS receive */ - last_source.secure = 1; dtls_handle_message(dtls_context, &last_source, coap_databuf(), coap_datalen()); } @@ -370,7 +373,7 @@ coap_transport_init(void) server.sin_addr.s_addr = htonl(INADDR_ANY); if(bind(coap_ipv4_fd, (struct sockaddr *)&server, sizeof(server)) == -1) { - PRINTF("Could not bind CoAP UDP port to %u\n", COAP_SERVER_PORT); + fprintf(stderr, "Could not bind CoAP UDP port to %u\n", COAP_SERVER_PORT); exit(1); } @@ -394,7 +397,7 @@ coap_transport_init(void) server.sin_addr.s_addr = htonl(INADDR_ANY); if(bind(dtls_ipv4_fd, (struct sockaddr *)&server, sizeof(server)) == -1) { - PRINTF("Could not bind CoAP DTLS UDP port to %u\n", + fprintf(stderr, "Could not bind CoAP DTLS UDP port to %u\n", COAP_DEFAULT_SECURE_PORT); exit(1); } @@ -405,7 +408,7 @@ coap_transport_init(void) /* create new contet with app-data */ dtls_context = dtls_new_context(&dtls_ipv4_fd); if(!dtls_context) { - PRINTF("DTLS: cannot create context\n"); + fprintf(stderr, "DTLS: cannot create context\n"); exit(-1); } @@ -417,7 +420,9 @@ void coap_send_message(const coap_endpoint_t *ep, const uint8_t *data, uint16_t len) { if(!coap_endpoint_is_connected(ep)) { - PRINTF("CoAP endpoint not connected\n"); + PRINTF("CoAP-IPv4: endpoint "); + PRINTEP(ep); + PRINTF(" not connected - dropping packet\n"); return; } @@ -433,15 +438,15 @@ coap_send_message(const coap_endpoint_t *ep, const uint8_t *data, uint16_t len) if(coap_ipv4_fd >= 0) { if(sendto(coap_ipv4_fd, data, len, 0, (struct sockaddr *)&ep->addr, ep->size) < 1) { - PRINTF("failed to send to "); + PRINTF("CoAP-IPv4: failed to send to "); PRINTEP(ep); PRINTF(" %u bytes: %s\n", len, strerror(errno)); } else { - PRINTF("SENT to "); + PRINTF("CoAP-IPv4: SENT to "); PRINTEP(ep); PRINTF(" %u bytes\n", len); - if(DEBUG) { + if(DEBUG_VERBOSE) { int i; PRINTF("Sent:"); for(i = 0; i < len; i++) { @@ -462,28 +467,26 @@ static int input_from_peer(struct dtls_context_t *ctx, session_t *session, uint8_t *data, size_t len) { +#if DEBUG_VERBOSE size_t i; - dtls_peer_t *peer; - printf("received data:"); - for (i = 0; i < len; i++) { - printf("%c", data[i]); + PRINTF("DTLS received data:"); + for(i = 0; i < len; i++) { + PRINTF("%c", data[i]); } - printf("\nHex:"); - for (i = 0; i < len; i++) { - printf("%02x", data[i]); + PRINTF("\nHex:"); + for(i = 0; i < len; i++) { + PRINTF("%02x", data[i]); } - printf("\n"); + PRINTF("\n"); +#endif /* DEBUG_VERBOSE */ /* Send this into coap-input */ memmove(coap_databuf(), data, len); coap_buf_len = len; - peer = dtls_get_peer(ctx, session); - /* If we have a peer then ensure that the endpoint is tagged as secure */ - if(peer) { - session->secure = 1; - } + /* Ensure that the endpoint is tagged as secure */ + session->secure = 1; coap_receive(session, coap_databuf(), coap_datalen()); @@ -496,8 +499,10 @@ output_to_peer(struct dtls_context_t *ctx, session_t *session, uint8_t *data, size_t len) { int fd = *(int *)dtls_get_app_data(ctx); - printf("output_to_peer len:%d %d (s-size: %d)\n", (int)len, fd, +#if DEBUG_VERBOSE + PRINTF("DTLS output_to_peer len:%d %d (s-size: %d)\n", (int)len, fd, session->size); +#endif /* DEBUG_VERBOSE */ return sendto(fd, data, len, MSG_DONTWAIT, (struct sockaddr *)&session->addr, session->size); } @@ -543,14 +548,16 @@ get_psk_info(struct dtls_context_t *ctx, keystore->coap_get_psk_info((coap_endpoint_t *)session, &ks); } if(ks.identity == NULL || ks.identity_len == 0) { + PRINTF("no psk_identity found\n"); return 0; } if(result_length < ks.identity_len) { - PRINTF("cannot set psk_identity -- buffer too small\n"); + PRINTF("cannot return psk_identity -- buffer too small\n"); return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); } memcpy(result, ks.identity, ks.identity_len); + PRINTF("psk_identity with %u bytes found\n", ks.identity_len); return ks.identity_len; case DTLS_PSK_KEY: @@ -566,10 +573,11 @@ get_psk_info(struct dtls_context_t *ctx, } if(result_length < ks.key_len) { - PRINTF("cannot set psk -- buffer too small\n"); + PRINTF("cannot return psk -- buffer too small\n"); return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); } memcpy(result, ks.key, ks.key_len); + PRINTF("psk with %u bytes found\n", ks.key_len); return ks.key_len; default: diff --git a/examples/lwm2m/standalone/contiki.h b/examples/lwm2m/standalone/contiki.h index 6149da0e3..43a85eaf2 100644 --- a/examples/lwm2m/standalone/contiki.h +++ b/examples/lwm2m/standalone/contiki.h @@ -45,16 +45,21 @@ #define COAP_TIMER_CONF_DRIVER coap_timer_native_driver #define LWM2M_ENGINE_CLIENT_ENDPOINT_NAME "lwm2m-ex" -#define LWM2M_DEVICE_MANUFACTURER "SICS, Swedish ICT AB" +#define LWM2M_DEVICE_MANUFACTURER "RISE SICS" #define LWM2M_DEVICE_TYPE "lwm2m-example" #define LWM2M_DEVICE_MODEL_NUMBER "000" #define LWM2M_DEVICE_SERIAL_NO "1" #define LWM2M_DEVICE_FIRMWARE_VERSION "0.1" +/* Use LWM2M as DTLS keystore */ +#define COAP_DTLS_KEYSTORE_CONF_WITH_LWM2M 1 + #ifdef COAP_TRANSPORT_CONF_H #include COAP_TRANSPORT_CONF_H #endif +#ifndef COAP_MAX_CHUNK_SIZE #define COAP_MAX_CHUNK_SIZE 256 +#endif /* COAP_MAX_CHUNK_SIZE */ #endif /* CONTIKI_H_ */ diff --git a/examples/lwm2m/standalone/lwm2m-example.c b/examples/lwm2m/standalone/lwm2m-example.c index 543539ca5..772a524d1 100644 --- a/examples/lwm2m/standalone/lwm2m-example.c +++ b/examples/lwm2m/standalone/lwm2m-example.c @@ -149,6 +149,7 @@ start_application(int argc, char *argv[]) printf("\n"); #ifdef WITH_DTLS +#if COAP_DTLS_KEYSTORE_CONF_WITH_LWM2M #if defined(PSK_DEFAULT_IDENTITY) && defined(PSK_DEFAULT_KEY) { lwm2m_security_server_t *server; @@ -176,20 +177,20 @@ start_application(int argc, char *argv[]) } } #endif /* defined(PSK_DEFAULT_IDENTITY) && defined(PSK_DEFAULT_KEY) */ +#endif /* COAP_DTLS_KEYSTORE_CONF_WITH_LWM2M */ #endif /* WITH_DTLS */ #define BOOTSTRAP 0 #if BOOTSTRAP lwm2m_rd_client_register_with_bootstrap_server(&server_ep); lwm2m_rd_client_use_bootstrap_server(1); -#else +#else /* BOOTSTRAP */ lwm2m_rd_client_register_with_server(&server_ep); -#endif +#endif /* BOOTSTRAP */ lwm2m_rd_client_use_registration_server(1); lwm2m_rd_client_init(name); - printf("Callback: %p\n", session_callback); lwm2m_rd_client_set_session_callback(session_callback); } else { diff --git a/examples/lwm2m/standalone/tinydtls-support/dtls-support.c b/examples/lwm2m/standalone/tinydtls-support/dtls-support.c index c39962d3f..35d04d2a0 100644 --- a/examples/lwm2m/standalone/tinydtls-support/dtls-support.c +++ b/examples/lwm2m/standalone/tinydtls-support/dtls-support.c @@ -39,6 +39,7 @@ #include "coap-timer.h" #include +#include #include #include #include From b117a8bba8006154bd5c3f30ba1b87a72a6e594c Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Tue, 7 Nov 2017 18:27:09 +0100 Subject: [PATCH 12/51] CoAP: Various minor updates in CoAP example --- examples/coap/Makefile | 20 +++--------- examples/coap/README.md | 35 ++++++++++----------- examples/coap/coap-example-client.c | 13 ++------ examples/coap/coap-example-observe-client.c | 11 ------- examples/coap/coap-example-server.c | 20 +++++------- examples/coap/plugtest.h | 4 --- examples/coap/project-conf.h | 29 +++++++---------- examples/coap/resources/res-light.c | 2 +- examples/coap/resources/res-sht11.c | 1 + 9 files changed, 43 insertions(+), 92 deletions(-) diff --git a/examples/coap/Makefile b/examples/coap/Makefile index 379ffb104..cb27da2ab 100644 --- a/examples/coap/Makefile +++ b/examples/coap/Makefile @@ -13,20 +13,8 @@ MODULES_REL += ./resources # Include the CoAP implementation MODULES += os/net/app-layer/coap -# optional rules to get assembly -#CUSTOM_RULE_C_TO_OBJECTDIR_O = 1 -#CUSTOM_RULE_S_TO_OBJECTDIR_O = 1 - include $(CONTIKI)/Makefile.include -# optional rules to get assembly -#$(OBJECTDIR)/%.o: asmdir/%.S -# $(CC) $(CFLAGS) -MMD -c $< -o $@ -# @$(FINALIZE_DEPENDENCY) -# -#asmdir/%.S: %.c -# $(CC) $(CFLAGS) -MMD -S $< -o $@ - # border router rules $(CONTIKI)/tools/tunslip6: $(CONTIKI)/tools/tunslip6.c (cd $(CONTIKI)/tools && $(MAKE) tunslip6) @@ -37,8 +25,8 @@ connect-router: $(CONTIKI)/tools/tunslip6 connect-router-cooja: $(CONTIKI)/tools/tunslip6 sudo $(CONTIKI)/tools/tunslip6 -a 127.0.0.1 -p 60001 fd00::1/64 -connect-router-native: $(CONTIKI)/examples/native-border-router/border-router.native - sudo $(CONTIKI)/examples/native-border-router/border-router.native -a 127.0.0.1 -p 60001 fd00::1/64 +connect-router-native: $(CONTIKI)/examples/rpl-border-router/border-router.native + sudo $(CONTIKI)/examples/rpl-border-router/border-router.native -a 127.0.0.1 -p 60001 fd00::1/64 -connect-minimal: - sudo ip address add fdfd::1/64 dev tap0 +connect-native: + sudo ip address add fdfd::1/64 dev tun0 diff --git a/examples/coap/README.md b/examples/coap/README.md index f74ddfb9e..6ba2f6071 100644 --- a/examples/coap/README.md +++ b/examples/coap/README.md @@ -1,26 +1,23 @@ -A Quick Introduction to the Erbium (Er) REST Engine +A Quick Introduction to the Erbium (Er) CoAP Engine =================================================== EXAMPLE FILES ------------- -- coap-example-server.c: A RESTful server example showing how to use the REST - layer to develop server-side applications (at the moment only CoAP is - implemented for the REST Engine). +- coap-example-server.c: A CoAP server example showing how to use the CoAP + layer to develop server-side applications. - coap-example-client.c: A CoAP client that polls the /actuators/toggle resource every 10 seconds and cycles through 4 resources on button press (target address is hard-coded). - plugtest-server.c: The server used for draft compliance testing at ETSI IoT CoAP Plugtests. Erbium (Er) participated in Paris, France, March 2012 and - Sophia-Antipolis, France, November 2012 (configured for minimal-net). + Sophia-Antipolis, France, November 2012 (configured for native). PRELIMINARIES ------------- -- Make sure rpl-border-router has the same stack and fits into mote memory: - You can disable RDC in border-router project-conf.h (not really required as BR keeps radio turned on). - #define NETSTACK_CONF_RDC nullrdc_driver -- Alternatively, you can use the native-border-router together with the slip-radio. +- Make sure rpl-border-router has the same network stack and fits into mote memory. +- Alternatively, you can use the native rpl-border-router together with the slip-radio. - For convenience, define the Cooja addresses in /etc/hosts fd00::0212:7401:0001:0101 cooja1 fd00::0212:7402:0002:0202 cooja2 @@ -58,8 +55,8 @@ Open new terminal - Choose "Click button on Sky 3" from the context menu of mote 3 (client) and watch serial output -TMOTES HOWTO ------------- +TMOTE SKY HOWTO +--------------- ###Server: @@ -90,20 +87,20 @@ TMOTES HOWTO make TARGET=sky coap-example-client.upload MOTE=3 -MINIMAL-NET HOWTO ------------------ +NATIVE HOWTO +------------ -With the target minimal-net you can test your CoAP applications without +With the target native you can test your CoAP applications without constraints, i.e., with large buffers, debug output, memory protection, etc. -The plugtest-server is thought for the minimal-net platform, as it requires +The plugtest-server is thought for the native platform, as it requires an 1280-byte IP buffer and 1024-byte blocks. - make TARGET=minimal-net plugtest-server - sudo ./plugtest-server.minimal-net + make TARGET=native plugtest-server + sudo ./plugtest-server.native Open new terminal - make connect-minimal + make connect-native - Start Copper and discover resources at coap://[fdfd::ff:fe00:10]:5683/ - You can enable the ETSI Plugtest menu in Copper's preferences @@ -130,7 +127,7 @@ in coap-example-server.c. In general, coap supports: - All draft-18 header options - CON Retransmissions (note COAP_MAX_OPEN_TRANSACTIONS) -- Blockwise Transfers (note REST_MAX_CHUNK_SIZE, see plugtest-server.c for +- Blockwise Transfers (note COAP_MAX_CHUNK_SIZE, see plugtest-server.c for Block1 uploads) - Separate Responses (no rest_set_pre_handler() required anymore, note coap_separate_accept(), _reject(), and _resume()) diff --git a/examples/coap/coap-example-client.c b/examples/coap/coap-example-client.c index 0e021f2f0..9339c9048 100644 --- a/examples/coap/coap-example-client.c +++ b/examples/coap/coap-example-client.c @@ -45,17 +45,8 @@ #include "coap-blocking-api.h" #include "dev/button-sensor.h" -#define DEBUG 0 -#if DEBUG -#include -#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 +#define DEBUG DEBUG_NONE +#include "net/ipv6/uip-debug.h" /* FIXME: This server address is hard-coded for Cooja and link-local for unconnected border router. */ #define SERVER_NODE(ipaddr) uip_ip6addr(ipaddr, 0xfe80, 0, 0, 0, 0x0212, 0x7402, 0x0002, 0x0202) /* cooja2 */ diff --git a/examples/coap/coap-example-observe-client.c b/examples/coap/coap-example-observe-client.c index 6d6b0c5cb..611658e69 100644 --- a/examples/coap/coap-example-observe-client.c +++ b/examples/coap/coap-example-observe-client.c @@ -49,19 +49,8 @@ #if DEBUG #define PRINTF(...) printf(__VA_ARGS__) #define PRINTFLN(format, ...) printf(format "\n", ##__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]) #else #define PRINTF(...) -#define PRINT6ADDR(addr) #define PRINTFLN(...) #endif diff --git a/examples/coap/coap-example-server.c b/examples/coap/coap-example-server.c index 9d7be130a..968afb548 100644 --- a/examples/coap/coap-example-server.c +++ b/examples/coap/coap-example-server.c @@ -51,12 +51,8 @@ #if DEBUG #include #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 /* @@ -143,24 +139,24 @@ PROCESS_THREAD(er_example_server, ev, data) coap_activate_resource(&res_toggle, "actuators/toggle"); #endif #if PLATFORM_HAS_LIGHT - coap_activate_resource(&res_light, "sensors/light"); - SENSORS_ACTIVATE(light_sensor); + coap_activate_resource(&res_light, "sensors/light"); + SENSORS_ACTIVATE(light_sensor); #endif #if PLATFORM_HAS_BATTERY - coap_activate_resource(&res_battery, "sensors/battery"); - SENSORS_ACTIVATE(battery_sensor); + coap_activate_resource(&res_battery, "sensors/battery"); + SENSORS_ACTIVATE(battery_sensor); #endif #if PLATFORM_HAS_TEMPERATURE - coap_activate_resource(&res_temperature, "sensors/temperature"); - SENSORS_ACTIVATE(temperature_sensor); + coap_activate_resource(&res_temperature, "sensors/temperature"); + SENSORS_ACTIVATE(temperature_sensor); #endif /* #if PLATFORM_HAS_RADIO coap_activate_resource(&res_radio, "sensors/radio"); #endif #if PLATFORM_HAS_SHT11 - coap_activate_resource(&res_sht11, "sensors/sht11"); - SENSORS_ACTIVATE(sht11_sensor); + coap_activate_resource(&res_sht11, "sensors/sht11"); + SENSORS_ACTIVATE(sht11_sensor); #endif */ diff --git a/examples/coap/plugtest.h b/examples/coap/plugtest.h index 78b168d4b..dff97282f 100644 --- a/examples/coap/plugtest.h +++ b/examples/coap/plugtest.h @@ -47,12 +47,8 @@ #if DEBUG #include #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 /* double expansion */ diff --git a/examples/coap/project-conf.h b/examples/coap/project-conf.h index d8a3b1122..6f7d132e0 100644 --- a/examples/coap/project-conf.h +++ b/examples/coap/project-conf.h @@ -36,35 +36,27 @@ * Matthias Kovatsch */ -#ifndef __PROJECT_ERBIUM_CONF_H__ -#define __PROJECT_ERBIUM_CONF_H__ +#ifndef PROJECT_ERBIUM_CONF_H_ +#define PROJECT_ERBIUM_CONF_H_ /* Custom channel and PAN ID configuration for your project. */ -/* - #define RF_CHANNEL 26 - #define IEEE802154_CONF_PANID 0xABCD - */ +/* #define RF_CHANNEL 26 */ +/* #define IEEE802154_CONF_PANID 0xABCD */ /* IP buffer size must match all other hops, in particular the border router. */ -/* - #define UIP_CONF_BUFFER_SIZE 256 - */ +/* #define UIP_CONF_BUFFER_SIZE 256 */ /* Increase rpl-border-router IP-buffer when using more than 64. */ -#define REST_MAX_CHUNK_SIZE 48 +#define COAP_MAX_CHUNK_SIZE 48 /* Estimate your header size, especially when using Proxy-Uri. */ -/* - #define COAP_MAX_HEADER_SIZE 70 - */ +/* #define COAP_MAX_HEADER_SIZE 70 */ /* Multiplies with chunk size, be aware of memory constraints. */ #define COAP_MAX_OPEN_TRANSACTIONS 4 /* Must be <= open transactions, default is COAP_MAX_OPEN_TRANSACTIONS-1. */ -/* - #define COAP_MAX_OBSERVERS 2 - */ +/* #define COAP_MAX_OBSERVERS 2 */ /* Filtering .well-known/core per query can be disabled to save space. */ #define COAP_LINK_FORMAT_FILTERING 0 @@ -74,5 +66,6 @@ #define RPL_CONF_WITH_DAO_ACK 0 /* Enable client-side support for COAP observe */ -#define COAP_OBSERVE_CLIENT 1 -#endif /* __PROJECT_ERBIUM_CONF_H__ */ +#define COAP_OBSERVE_CLIENT 1 + +#endif /* PROJECT_ERBIUM_CONF_H_ */ diff --git a/examples/coap/resources/res-light.c b/examples/coap/resources/res-light.c index cf55e0302..23655a138 100644 --- a/examples/coap/resources/res-light.c +++ b/examples/coap/resources/res-light.c @@ -43,7 +43,7 @@ #include #include #include "coap-engine.h" -//#include "dev/light-sensor.h" +#include "dev/light-sensor.h" static void res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); diff --git a/examples/coap/resources/res-sht11.c b/examples/coap/resources/res-sht11.c index cecb5d0da..e853cea47 100644 --- a/examples/coap/resources/res-sht11.c +++ b/examples/coap/resources/res-sht11.c @@ -43,6 +43,7 @@ #if PLATFORM_HAS_SHT11 +#include #include #include "coap-engine.h" #include "dev/sht11/sht11-sensor.h" From 074391fa7da79854395d0640df825dbeb605d7aa Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Tue, 7 Nov 2017 23:20:39 +0100 Subject: [PATCH 13/51] CoAP: Various updates in coap-uip transport implementation * Mark endpoint as secure regardless if DTLS peer exists or not * Drop CoAP transmissions to endpoints that are not connected * Debug output cleanup --- os/net/app-layer/coap/coap-uip.c | 72 ++++++++++++++++++++------------ 1 file changed, 45 insertions(+), 27 deletions(-) diff --git a/os/net/app-layer/coap/coap-uip.c b/os/net/app-layer/coap/coap-uip.c index 61fdf49f0..97d5f2b50 100644 --- a/os/net/app-layer/coap/coap-uip.c +++ b/os/net/app-layer/coap/coap-uip.c @@ -56,6 +56,8 @@ #define DEBUG DEBUG_FULL #include "net/ipv6/uip-debug.h" +#define DEBUG_VERBOSE ((DEBUG) && 0) + #if DEBUG #define PRINTEP(X) coap_endpoint_print(X) #else @@ -220,17 +222,20 @@ coap_endpoint_is_connected(const coap_endpoint_t *ep) #endif /* UIP_CONF_IPV6_RPL */ #ifdef WITH_DTLS - if(ep != NULL && ep->secure != 0 && dtls_context != NULL) { + if(ep != NULL && ep->secure != 0) { dtls_peer_t *peer; + if(dtls_context == NULL) { + return 0; + } peer = dtls_get_peer(dtls_context, ep); if(peer != NULL) { /* only if handshake is done! */ - PRINTF("peer state for "); + PRINTF("DTLS peer state for "); PRINTEP(ep); PRINTF(" is %d %d\n", peer->state, dtls_peer_is_connected(peer)); return dtls_peer_is_connected(peer); } else { - PRINTF("Did not find peer "); + PRINTF("DTLS did not find peer "); PRINTEP(ep); PRINTF("\n"); } @@ -245,24 +250,25 @@ int coap_endpoint_connect(coap_endpoint_t *ep) { if(ep->secure == 0) { - PRINTF("Connect - Non secure EP:"); + PRINTF("CoAP connect to "); PRINTEP(ep); PRINTF("\n"); return 1; } #ifdef WITH_DTLS - PRINTF("Connect - DTLS EP:"); + PRINTF("DTLS connect to "); PRINTEP(ep); - PRINTF(" len:%d\n", sizeof(ep)); + PRINTF("\n"); /* setup all address info here... should be done to connect */ if(dtls_context) { dtls_connect(dtls_context, ep); + return 1; } #endif /* WITH_DTLS */ - return 1; + return 0; } /*---------------------------------------------------------------------------*/ void @@ -334,7 +340,14 @@ coap_send_message(const coap_endpoint_t *ep, const uint8_t *data, uint16_t length) { if(ep == NULL) { - PRINTF("failed to send - no endpoint\n"); + PRINTF("coap-uip: failed to send - no endpoint\n"); + return; + } + + if(!coap_endpoint_is_connected(ep)) { + PRINTF("coap-uip: endpoint "); + PRINTEP(ep); + PRINTF(" not connected - dropping packet\n"); return; } @@ -342,14 +355,18 @@ coap_send_message(const coap_endpoint_t *ep, const uint8_t *data, if(coap_endpoint_is_secure(ep)) { if(dtls_context) { dtls_write(dtls_context, (session_t *)ep, (uint8_t *)data, length); - PRINTF("-sent secure UDP datagram (%u)-\n", length); + PRINTF("coap-uip: sent DTLS to "); + PRINTEP(ep); + PRINTF(" %u bytes\n", length); } return; } #endif /* WITH_DTLS */ uip_udp_packet_sendto(udp_conn, data, length, &ep->ipaddr, ep->port); - PRINTF("-sent UDP datagram (%u)-\n", length); + PRINTF("coap-uip: sent to "); + PRINTEP(ep); + PRINTF(" %u bytes\n", length); } /*---------------------------------------------------------------------------*/ PROCESS_THREAD(coap_engine, ev, data) @@ -405,24 +422,22 @@ static int input_from_peer(struct dtls_context_t *ctx, session_t *session, uint8_t *data, size_t len) { +#if DEBUG_VERBOSE size_t i; - dtls_peer_t *peer; PRINTF("received DTLS data:"); - for (i = 0; i < len; i++) { + for(i = 0; i < len; i++) { PRINTF("%c", data[i]); } PRINTF("\nHex:"); - for (i = 0; i < len; i++) { + for(i = 0; i < len; i++) { PRINTF("%02x", data[i]); } PRINTF("\n"); +#endif /* DEBUG_VERBOSE */ - peer = dtls_get_peer(ctx, session); - /* If we have a peer then ensure that the endpoint is tagged as secure */ - if(peer) { - session->secure = 1; - } + /* Ensure that the endpoint is tagged as secure */ + session->secure = 1; coap_receive(session, data, len); @@ -435,9 +450,9 @@ output_to_peer(struct dtls_context_t *ctx, session_t *session, uint8_t *data, size_t len) { struct uip_udp_conn *udp_connection = dtls_get_app_data(ctx); - PRINTF("output_to DTLS peer ["); + PRINTF("coap-uip: output_to DTLS peer ["); PRINT6ADDR(&session->ipaddr); - PRINTF("]:%u len:%d\n", session->port,(int)len); + PRINTF("]:%u %d bytes\n", session->port, (int)len); uip_udp_packet_sendto(udp_connection, data, len, &session->ipaddr, session->port); return len; @@ -463,18 +478,18 @@ get_psk_info(struct dtls_context_t *ctx, coap_keystore_psk_entry_t ks; if(dtls_keystore == NULL) { - PRINTF("--- No key store available ---\n"); + PRINTF("coap-uip: --- No key store available ---\n"); return 0; } memset(&ks, 0, sizeof(ks)); - PRINTF("---===>>> Getting the Key or ID <<<===---\n"); + PRINTF("coap-uip: ---===>>> Getting the Key or ID <<<===---\n"); switch(type) { case DTLS_PSK_IDENTITY: if(id && id_len) { ks.identity_hint = id; ks.identity_hint_len = id_len; - PRINTF("got psk_identity_hint: '%.*s'\n", id_len, id); + PRINTF("coap-uip: got psk_identity_hint: '%.*s'\n", id_len, id); } if(dtls_keystore->coap_get_psk_info) { @@ -482,14 +497,16 @@ get_psk_info(struct dtls_context_t *ctx, dtls_keystore->coap_get_psk_info((coap_endpoint_t *)session, &ks); } if(ks.identity == NULL || ks.identity_len == 0) { + PRINTF("coap-uip: no psk_identity found\n"); return 0; } if(result_length < ks.identity_len) { - PRINTF("cannot set psk_identity -- buffer too small\n"); + PRINTF("coap-uip: cannot return psk_identity -- buffer too small\n"); return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); } memcpy(result, ks.identity, ks.identity_len); + PRINTF("coap-uip: psk_identity with %u bytes found\n", ks.identity_len); return ks.identity_len; case DTLS_PSK_KEY: @@ -500,19 +517,20 @@ get_psk_info(struct dtls_context_t *ctx, dtls_keystore->coap_get_psk_info((coap_endpoint_t *)session, &ks); } if(ks.key == NULL || ks.key_len == 0) { - PRINTF("PSK for unknown id requested, exiting\n"); + PRINTF("coap-uip: PSK for unknown id requested, exiting\n"); return dtls_alert_fatal_create(DTLS_ALERT_ILLEGAL_PARAMETER); } if(result_length < ks.key_len) { - PRINTF("cannot set psk -- buffer too small\n"); + PRINTF("coap-uip: cannot return psk -- buffer too small\n"); return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); } memcpy(result, ks.key, ks.key_len); + PRINTF("coap-uip: psk with %u bytes found\n", ks.key_len); return ks.key_len; default: - PRINTF("unsupported request type: %d\n", type); + PRINTF("coap-uip: unsupported key store request type: %d\n", type); } return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); From a866fcbfad8bb0a7961cef6b872621f0e62eb78b Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Thu, 9 Nov 2017 14:42:45 +0100 Subject: [PATCH 14/51] CoAP: replaced coap_send_message() with coap_sendto() that returns number of bytes sent or error. --- examples/lwm2m/standalone/coap-hex/coap-hex.c | 11 ++--- .../lwm2m/standalone/coap-ipv4/coap-ipv4.c | 40 +++++++++++++------ os/net/app-layer/coap/coap-engine.c | 2 +- os/net/app-layer/coap/coap-observe-client.c | 2 +- os/net/app-layer/coap/coap-separate.c | 4 +- os/net/app-layer/coap/coap-transactions.c | 2 +- os/net/app-layer/coap/coap-transport.h | 3 +- os/net/app-layer/coap/coap-uip.c | 24 +++++++---- 8 files changed, 55 insertions(+), 33 deletions(-) diff --git a/examples/lwm2m/standalone/coap-hex/coap-hex.c b/examples/lwm2m/standalone/coap-hex/coap-hex.c index 67e887619..7fba02ccf 100644 --- a/examples/lwm2m/standalone/coap-hex/coap-hex.c +++ b/examples/lwm2m/standalone/coap-hex/coap-hex.c @@ -230,18 +230,17 @@ coap_transport_init(void) } /*---------------------------------------------------------------------------*/ -void -coap_send_message(const coap_endpoint_t *ep, const uint8_t *data, uint16_t len) +int +coap_sendto(const coap_endpoint_t *ep, const uint8_t *data, uint16_t len) { if(!coap_endpoint_is_connected(ep)) { PRINTF("CoAP endpoint not connected\n"); - return; + return -1; } #ifdef WITH_DTLS if(coap_endpoint_is_secure(ep)) { - dtls_write(dtls_context, (session_t *)ep, (uint8_t *)data, len); - return; + return dtls_write(dtls_context, (session_t *)ep, (uint8_t *)data, len); } #endif /* WITH_DTLS */ @@ -251,6 +250,8 @@ coap_send_message(const coap_endpoint_t *ep, const uint8_t *data, uint16_t len) printf("%02x", data[i]); } printf("\n"); + + return len; } /*---------------------------------------------------------------------------*/ int diff --git a/examples/lwm2m/standalone/coap-ipv4/coap-ipv4.c b/examples/lwm2m/standalone/coap-ipv4/coap-ipv4.c index 8733bafe6..2b493b9a6 100644 --- a/examples/lwm2m/standalone/coap-ipv4/coap-ipv4.c +++ b/examples/lwm2m/standalone/coap-ipv4/coap-ipv4.c @@ -416,35 +416,45 @@ coap_transport_init(void) #endif /* WITH_DTLS */ } /*---------------------------------------------------------------------------*/ -void -coap_send_message(const coap_endpoint_t *ep, const uint8_t *data, uint16_t len) +int +coap_sendto(const coap_endpoint_t *ep, const uint8_t *data, uint16_t len) { + int ret; + if(!coap_endpoint_is_connected(ep)) { PRINTF("CoAP-IPv4: endpoint "); PRINTEP(ep); PRINTF(" not connected - dropping packet\n"); - return; + return -1; } #ifdef WITH_DTLS if(coap_endpoint_is_secure(ep)) { if(dtls_context) { - dtls_write(dtls_context, (session_t *)ep, (uint8_t *)data, len); + ret = dtls_write(dtls_context, (session_t *)ep, (uint8_t *)data, len); + PRINTF("CoAP-IPv4: SENT DTLS to "); + PRINTEP(ep); + if(ret < 0) { + PRINTF(" - error %d\n", ret); + } else { + PRINTF(" %d/%u bytes\n", ret, len); + } + return ret; } - return; + PRINTF("CoAP-IPv4: no DTLS context\n"); + return -1; } #endif /* WITH_DTLS */ if(coap_ipv4_fd >= 0) { - if(sendto(coap_ipv4_fd, data, len, 0, - (struct sockaddr *)&ep->addr, ep->size) < 1) { - PRINTF("CoAP-IPv4: failed to send to "); - PRINTEP(ep); - PRINTF(" %u bytes: %s\n", len, strerror(errno)); + ret = sendto(coap_ipv4_fd, data, len, 0, (struct sockaddr *)&ep->addr, + ep->size); + PRINTF("CoAP-IPv4: SENT to "); + PRINTEP(ep); + if(ret < 0) { + PRINTF(" - error %d: %s\n", ret, strerror(errno)); } else { - PRINTF("CoAP-IPv4: SENT to "); - PRINTEP(ep); - PRINTF(" %u bytes\n", len); + PRINTF(" %d/%u bytes\n", ret, len); if(DEBUG_VERBOSE) { int i; @@ -455,7 +465,11 @@ coap_send_message(const coap_endpoint_t *ep, const uint8_t *data, uint16_t len) PRINTF("\n"); } } + return ret; } + + PRINTF("CoAP-IPv4: failed to send - no socket\n"); + return -1; } /*---------------------------------------------------------------------------*/ /* DTLS */ diff --git a/os/net/app-layer/coap/coap-engine.c b/os/net/app-layer/coap/coap-engine.c index 18dc79392..ed99e90c7 100644 --- a/os/net/app-layer/coap/coap-engine.c +++ b/os/net/app-layer/coap/coap-engine.c @@ -356,7 +356,7 @@ coap_receive(const coap_endpoint_t *src, message->mid); coap_set_payload(message, coap_error_message, strlen(coap_error_message)); - coap_send_message(src, payload, coap_serialize_message(message, payload)); + coap_sendto(src, payload, coap_serialize_message(message, payload)); } /* if(new data) */ diff --git a/os/net/app-layer/coap/coap-observe-client.c b/os/net/app-layer/coap/coap-observe-client.c index 569a6bc83..ebe4a776f 100644 --- a/os/net/app-layer/coap/coap-observe-client.c +++ b/os/net/app-layer/coap/coap-observe-client.c @@ -179,7 +179,7 @@ simple_reply(coap_message_type_t type, const coap_endpoint_t *endpoint, coap_init_message(response, type, NO_ERROR, notification->mid); len = coap_serialize_message(response, coap_databuf()); - coap_send_message(endpoint, coap_databuf(), len); + coap_sendto(endpoint, coap_databuf(), len); } /*----------------------------------------------------------------------------*/ static coap_notification_flag_t diff --git a/os/net/app-layer/coap/coap-separate.c b/os/net/app-layer/coap/coap-separate.c index 066dc74a7..32dcd0aba 100644 --- a/os/net/app-layer/coap/coap-separate.c +++ b/os/net/app-layer/coap/coap-separate.c @@ -100,8 +100,8 @@ coap_separate_accept(coap_packet_t *coap_req, coap_separate_t *separate_store) /* ACK with empty code (0) */ coap_init_message(ack, COAP_TYPE_ACK, 0, coap_req->mid); /* serializing into IPBUF: Only overwrites header parts that are already parsed into the request struct */ - coap_send_message(ep, coap_databuf(), - coap_serialize_message(ack, coap_databuf())); + coap_sendto(ep, coap_databuf(), + coap_serialize_message(ack, coap_databuf())); } } diff --git a/os/net/app-layer/coap/coap-transactions.c b/os/net/app-layer/coap/coap-transactions.c index 60f4f7f72..fa2d2d3c8 100644 --- a/os/net/app-layer/coap/coap-transactions.c +++ b/os/net/app-layer/coap/coap-transactions.c @@ -98,7 +98,7 @@ coap_send_transaction(coap_transaction_t *t) { PRINTF("Sending transaction %u\n", t->mid); - coap_send_message(&t->endpoint, t->packet, t->packet_len); + coap_sendto(&t->endpoint, t->packet, t->packet_len); if(COAP_TYPE_CON == ((COAP_HEADER_TYPE_MASK & t->packet[0]) >> COAP_HEADER_TYPE_POSITION)) { diff --git a/os/net/app-layer/coap/coap-transport.h b/os/net/app-layer/coap/coap-transport.h index 693081402..71d0ffae1 100644 --- a/os/net/app-layer/coap/coap-transport.h +++ b/os/net/app-layer/coap/coap-transport.h @@ -42,8 +42,7 @@ void coap_transport_init(void); -void coap_send_message(const coap_endpoint_t *ep, const uint8_t *data, - uint16_t length); +int coap_sendto(const coap_endpoint_t *ep, const uint8_t *data, uint16_t len); uint8_t *coap_databuf(void); uint16_t coap_datalen(void); diff --git a/os/net/app-layer/coap/coap-uip.c b/os/net/app-layer/coap/coap-uip.c index 97d5f2b50..70e720063 100644 --- a/os/net/app-layer/coap/coap-uip.c +++ b/os/net/app-layer/coap/coap-uip.c @@ -335,31 +335,38 @@ process_data(void) coap_receive(get_src_endpoint(0), uip_appdata, uip_datalen()); } /*---------------------------------------------------------------------------*/ -void -coap_send_message(const coap_endpoint_t *ep, const uint8_t *data, - uint16_t length) +int +coap_sendto(const coap_endpoint_t *ep, const uint8_t *data, uint16_t length) { if(ep == NULL) { PRINTF("coap-uip: failed to send - no endpoint\n"); - return; + return -1; } if(!coap_endpoint_is_connected(ep)) { PRINTF("coap-uip: endpoint "); PRINTEP(ep); PRINTF(" not connected - dropping packet\n"); - return; + return -1; } #ifdef WITH_DTLS if(coap_endpoint_is_secure(ep)) { if(dtls_context) { - dtls_write(dtls_context, (session_t *)ep, (uint8_t *)data, length); + int ret; + + ret = dtls_write(dtls_context, (session_t *)ep, (uint8_t *)data, length); PRINTF("coap-uip: sent DTLS to "); PRINTEP(ep); - PRINTF(" %u bytes\n", length); + if(ret < 0) { + PRINTF(" - error %d\n", ret); + } else { + PRINTF(" %d/%u bytes\n", ret, length); + } + return ret; } - return; + PRINTF("coap-uip: no DTLS context\n"); + return -1; } #endif /* WITH_DTLS */ @@ -367,6 +374,7 @@ coap_send_message(const coap_endpoint_t *ep, const uint8_t *data, PRINTF("coap-uip: sent to "); PRINTEP(ep); PRINTF(" %u bytes\n", length); + return length; } /*---------------------------------------------------------------------------*/ PROCESS_THREAD(coap_engine, ev, data) From c86b763e5dc31fcefc5fbe416c586217bd53d4d5 Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Tue, 14 Nov 2017 21:32:43 +0100 Subject: [PATCH 15/51] renamed coap packet to coap message - for naming closer to RFC --- examples/coap/coap-example-client.c | 4 +- .../resources-plugtest/res-plugtest-create1.c | 8 +- .../resources-plugtest/res-plugtest-create2.c | 4 +- .../resources-plugtest/res-plugtest-create3.c | 8 +- .../res-plugtest-large-create.c | 6 +- .../res-plugtest-large-update.c | 10 +- .../resources-plugtest/res-plugtest-large.c | 4 +- .../resources-plugtest/res-plugtest-links.c | 4 +- .../res-plugtest-locquery.c | 6 +- .../res-plugtest-longpath.c | 6 +- .../resources-plugtest/res-plugtest-multi.c | 6 +- .../resources-plugtest/res-plugtest-obs.c | 12 +- .../resources-plugtest/res-plugtest-path.c | 4 +- .../resources-plugtest/res-plugtest-query.c | 6 +- .../res-plugtest-separate.c | 12 +- .../resources-plugtest/res-plugtest-test.c | 24 ++-- .../res-plugtest-validate.c | 12 +- examples/coap/resources/res-b1-sep-b2.c | 8 +- examples/coap/resources/res-battery.c | 4 +- examples/coap/resources/res-chunks.c | 4 +- examples/coap/resources/res-event.c | 4 +- examples/coap/resources/res-hello.c | 4 +- examples/coap/resources/res-leds.c | 4 +- examples/coap/resources/res-light.c | 4 +- examples/coap/resources/res-mirror.c | 6 +- examples/coap/resources/res-push.c | 4 +- examples/coap/resources/res-radio.c | 4 +- examples/coap/resources/res-separate.c | 8 +- examples/coap/resources/res-sht11.c | 4 +- examples/coap/resources/res-sub.c | 4 +- examples/coap/resources/res-temperature.c | 4 +- examples/coap/resources/res-toggle.c | 4 +- examples/ipso-objects/example-server.c | 4 +- .../cc26xx-web-demo/resources/res-ble-advd.c | 2 +- .../cc26xx-web-demo/resources/res-device.c | 8 +- .../cc26xx-web-demo/resources/res-leds.c | 2 +- .../cc26xx-web-demo/resources/res-net.c | 4 +- .../cc26xx-web-demo/resources/res-sensors.c | 36 ++--- .../resources/res-toggle-leds.c | 8 +- .../very-sleepy-demo/very-sleepy-demo.c | 6 +- .../jn516x/rpl/coap-dongle-node/dongle-node.c | 4 +- .../jn516x/rpl/coap-dr1175-node/dr1175-node.c | 44 +++---- .../jn516x/rpl/coap-dr1199-node/dr1199-node.c | 52 ++++---- .../tsch/tx-power-verification/node/node.c | 8 +- .../rpl-border-router/rpl-border-router.c | 8 +- .../tsch/uart1-test-node/uart1-test-node.c | 8 +- .../nrf52dk/coap-demo/resources/res-leds.c | 8 +- os/net/app-layer/coap/coap-block1.c | 2 +- os/net/app-layer/coap/coap-block1.h | 2 +- os/net/app-layer/coap/coap-blocking-api.c | 8 +- os/net/app-layer/coap/coap-blocking-api.h | 6 +- os/net/app-layer/coap/coap-callback-api.c | 12 +- os/net/app-layer/coap/coap-callback-api.h | 6 +- os/net/app-layer/coap/coap-engine.c | 20 +-- os/net/app-layer/coap/coap-engine.h | 14 +- os/net/app-layer/coap/coap-observe-client.c | 18 +-- os/net/app-layer/coap/coap-observe-client.h | 2 +- os/net/app-layer/coap/coap-observe.c | 16 +-- os/net/app-layer/coap/coap-observe.h | 4 +- .../app-layer/coap/coap-res-well-known-core.c | 2 +- os/net/app-layer/coap/coap-separate.c | 6 +- os/net/app-layer/coap/coap-separate.h | 8 +- os/net/app-layer/coap/coap-transactions.c | 4 +- os/net/app-layer/coap/coap-transactions.h | 4 +- os/net/app-layer/coap/coap.c | 124 ++++++++++-------- os/net/app-layer/coap/coap.h | 123 +++++++++-------- os/services/lwm2m/lwm2m-engine.c | 12 +- os/services/lwm2m/lwm2m-object.h | 4 +- os/services/lwm2m/lwm2m-rd-client.c | 6 +- 69 files changed, 417 insertions(+), 394 deletions(-) diff --git a/examples/coap/coap-example-client.c b/examples/coap/coap-example-client.c index 9339c9048..ca203c210 100644 --- a/examples/coap/coap-example-client.c +++ b/examples/coap/coap-example-client.c @@ -76,7 +76,7 @@ static int uri_switch = 0; /* This function is will be passed to COAP_BLOCKING_REQUEST() to handle responses. */ void -client_chunk_handler(coap_packet_t *response) +client_chunk_handler(coap_message_t *response) { const uint8_t *chunk; @@ -89,7 +89,7 @@ PROCESS_THREAD(er_example_client, ev, data) coap_endpoint_t server_ep; PROCESS_BEGIN(); - static coap_packet_t request[1]; /* This way the packet can be treated as pointer as usual. */ + static coap_message_t request[1]; /* This way the packet can be treated as pointer as usual. */ /* SERVER_NODE(&server_ipaddr); */ diff --git a/examples/coap/resources-plugtest/res-plugtest-create1.c b/examples/coap/resources-plugtest/res-plugtest-create1.c index 661a3f210..50f48a09e 100644 --- a/examples/coap/resources-plugtest/res-plugtest-create1.c +++ b/examples/coap/resources-plugtest/res-plugtest-create1.c @@ -41,8 +41,8 @@ #include "coap.h" #include "plugtest.h" -static void res_put_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void res_delete_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_delete_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); RESOURCE(res_plugtest_create1, "title=\"Creates on PUT\"", @@ -54,7 +54,7 @@ RESOURCE(res_plugtest_create1, static uint8_t create1_exists = 0; static void -res_put_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { PRINTF("/create1 PUT"); @@ -71,7 +71,7 @@ res_put_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer } } static void -res_delete_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_delete_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { PRINTF("/create1 DELETE "); coap_set_status_code(response, DELETED_2_02); diff --git a/examples/coap/resources-plugtest/res-plugtest-create2.c b/examples/coap/resources-plugtest/res-plugtest-create2.c index 756d9b0fa..169f47812 100644 --- a/examples/coap/resources-plugtest/res-plugtest-create2.c +++ b/examples/coap/resources-plugtest/res-plugtest-create2.c @@ -41,7 +41,7 @@ #include "coap.h" #include "plugtest.h" -static void res_post_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_post_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); RESOURCE(res_plugtest_create2, "title=\"Creates on POST\"", @@ -51,7 +51,7 @@ RESOURCE(res_plugtest_create2, NULL); static void -res_post_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_post_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { PRINTF("/create2 "); diff --git a/examples/coap/resources-plugtest/res-plugtest-create3.c b/examples/coap/resources-plugtest/res-plugtest-create3.c index 9356dd2a6..178a0089e 100644 --- a/examples/coap/resources-plugtest/res-plugtest-create3.c +++ b/examples/coap/resources-plugtest/res-plugtest-create3.c @@ -41,8 +41,8 @@ #include "coap.h" #include "plugtest.h" -static void res_put_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void res_delete_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_delete_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); RESOURCE(res_plugtest_create3, "title=\"Default test resource\"", @@ -54,7 +54,7 @@ RESOURCE(res_plugtest_create3, static uint8_t create3_exists = 0; static void -res_put_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { PRINTF("/create3 PUT "); @@ -71,7 +71,7 @@ res_put_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer } } static void -res_delete_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_delete_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { PRINTF("/create3 DELETE "); coap_set_status_code(response, DELETED_2_02); diff --git a/examples/coap/resources-plugtest/res-plugtest-large-create.c b/examples/coap/resources-plugtest/res-plugtest-large-create.c index aa7e60ac2..78d21b69b 100644 --- a/examples/coap/resources-plugtest/res-plugtest-large-create.c +++ b/examples/coap/resources-plugtest/res-plugtest-large-create.c @@ -41,7 +41,7 @@ #include "coap.h" #include "plugtest.h" -static void res_post_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_post_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); /* * Large resource that can be created using POST method @@ -54,9 +54,9 @@ RESOURCE(res_plugtest_large_create, NULL); static void -res_post_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_post_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { - coap_packet_t *const coap_req = (coap_packet_t *)request; + coap_message_t *const coap_req = (coap_message_t *)request; uint8_t *incoming = NULL; size_t len = 0; diff --git a/examples/coap/resources-plugtest/res-plugtest-large-update.c b/examples/coap/resources-plugtest/res-plugtest-large-update.c index a8e4b9c5a..a79978be1 100644 --- a/examples/coap/resources-plugtest/res-plugtest-large-update.c +++ b/examples/coap/resources-plugtest/res-plugtest-large-update.c @@ -43,8 +43,8 @@ #include "coap.h" #include "plugtest.h" -static void res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void res_put_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); RESOURCE( res_plugtest_large_update, @@ -59,7 +59,7 @@ static uint8_t large_update_store[MAX_PLUGFEST_BODY] = { 0 }; static unsigned int large_update_ct = APPLICATION_OCTET_STREAM; static void -res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { /* Check the offset for boundaries of the resource data. */ if(*offset >= large_update_size) { @@ -84,9 +84,9 @@ res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer } } static void -res_put_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { - coap_packet_t *const coap_req = (coap_packet_t *)request; + coap_message_t *const coap_req = (coap_message_t *)request; uint8_t *incoming = NULL; size_t len = 0; diff --git a/examples/coap/resources-plugtest/res-plugtest-large.c b/examples/coap/resources-plugtest/res-plugtest-large.c index cb4a53c9a..f828e4dbe 100644 --- a/examples/coap/resources-plugtest/res-plugtest-large.c +++ b/examples/coap/resources-plugtest/res-plugtest-large.c @@ -42,7 +42,7 @@ #include "coap.h" #include "plugtest.h" -static void res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); RESOURCE(res_plugtest_large, "title=\"Large resource\";rt=\"block\";sz=\"" TO_STRING(CHUNKS_TOTAL) "\"", @@ -52,7 +52,7 @@ RESOURCE(res_plugtest_large, NULL); static void -res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { int32_t strpos = 0; diff --git a/examples/coap/resources-plugtest/res-plugtest-links.c b/examples/coap/resources-plugtest/res-plugtest-links.c index 63344e9a4..99315a17f 100644 --- a/examples/coap/resources-plugtest/res-plugtest-links.c +++ b/examples/coap/resources-plugtest/res-plugtest-links.c @@ -41,7 +41,7 @@ #include "coap.h" #include "plugtest.h" -static void res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); RESOURCE(res_plugtest_link1, "rt=\"Type1 Type2\";if=\"If1\"", @@ -63,7 +63,7 @@ RESOURCE(res_plugtest_link3, NULL); static void -res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const char *msg = "Dummy link"; coap_set_header_content_format(response, TEXT_PLAIN); diff --git a/examples/coap/resources-plugtest/res-plugtest-locquery.c b/examples/coap/resources-plugtest/res-plugtest-locquery.c index 8a47aa8c2..e93ef8b65 100644 --- a/examples/coap/resources-plugtest/res-plugtest-locquery.c +++ b/examples/coap/resources-plugtest/res-plugtest-locquery.c @@ -41,7 +41,7 @@ #include "coap.h" #include "plugtest.h" -static void res_post_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_post_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); RESOURCE(res_plugtest_locquery, "title=\"Resource accepting query parameters\"", @@ -51,10 +51,10 @@ RESOURCE(res_plugtest_locquery, NULL); static void -res_post_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_post_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { #if DEBUG - coap_packet_t *const coap_req = (coap_packet_t *)request; + coap_message_t *const coap_req = (coap_message_t *)request; #endif PRINTF( diff --git a/examples/coap/resources-plugtest/res-plugtest-longpath.c b/examples/coap/resources-plugtest/res-plugtest-longpath.c index fb18f84bb..7a1271321 100644 --- a/examples/coap/resources-plugtest/res-plugtest-longpath.c +++ b/examples/coap/resources-plugtest/res-plugtest-longpath.c @@ -43,7 +43,7 @@ #include "coap.h" #include "plugtest.h" -static void res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); RESOURCE(res_plugtest_longpath, "title=\"Long path resource\"", @@ -53,9 +53,9 @@ RESOURCE(res_plugtest_longpath, NULL); static void -res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { - coap_packet_t *const coap_req = (coap_packet_t *)request; + coap_message_t *const coap_req = (coap_message_t *)request; PRINTF("/seg1/seg2/seg3 GET "); /* Code 2.05 CONTENT is default. */ diff --git a/examples/coap/resources-plugtest/res-plugtest-multi.c b/examples/coap/resources-plugtest/res-plugtest-multi.c index 3e23d7ecc..f0a388430 100644 --- a/examples/coap/resources-plugtest/res-plugtest-multi.c +++ b/examples/coap/resources-plugtest/res-plugtest-multi.c @@ -42,7 +42,7 @@ #include "coap.h" #include "plugtest.h" -static void res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); RESOURCE(res_plugtest_multi, "title=\"Resource providing text/plain and application/xml\";ct=\"0 41\"", @@ -52,9 +52,9 @@ RESOURCE(res_plugtest_multi, NULL); static void -res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { - coap_packet_t *const coap_req = (coap_packet_t *)request; + coap_message_t *const coap_req = (coap_message_t *)request; unsigned int accept = -1; coap_get_header_accept(request, &accept); diff --git a/examples/coap/resources-plugtest/res-plugtest-obs.c b/examples/coap/resources-plugtest/res-plugtest-obs.c index 9c4e30672..d60aaec04 100644 --- a/examples/coap/resources-plugtest/res-plugtest-obs.c +++ b/examples/coap/resources-plugtest/res-plugtest-obs.c @@ -43,9 +43,9 @@ #include "coap-observe.h" #include "plugtest.h" -static void res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void res_put_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void res_delete_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_delete_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); static void res_periodic_handler(void); PERIODIC_RESOURCE(res_plugtest_obs, @@ -71,7 +71,7 @@ obs_purge_list() coap_remove_observer_by_uri(NULL, res_plugtest_obs.url); } static void -res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { /* Keep server log clean from ticking events */ if(request != NULL) { @@ -91,7 +91,7 @@ res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer /* A post_handler that handles subscriptions will be called for periodic resources by the CoAP framework. */ } static void -res_put_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { uint8_t *incoming = NULL; unsigned int ct = -1; @@ -113,7 +113,7 @@ res_put_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer coap_set_status_code(response, CHANGED_2_04); } static void -res_delete_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_delete_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { PRINTF("/obs DELETE\n"); diff --git a/examples/coap/resources-plugtest/res-plugtest-path.c b/examples/coap/resources-plugtest/res-plugtest-path.c index 2f3ad7d94..fac05ccb0 100644 --- a/examples/coap/resources-plugtest/res-plugtest-path.c +++ b/examples/coap/resources-plugtest/res-plugtest-path.c @@ -42,7 +42,7 @@ #include "coap.h" #include "plugtest.h" -static void res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); PARENT_RESOURCE(res_plugtest_path, "title=\"Path test resource\";ct=\"40\"", @@ -52,7 +52,7 @@ PARENT_RESOURCE(res_plugtest_path, NULL); static void -res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { diff --git a/examples/coap/resources-plugtest/res-plugtest-query.c b/examples/coap/resources-plugtest/res-plugtest-query.c index 249db6998..10df145b3 100644 --- a/examples/coap/resources-plugtest/res-plugtest-query.c +++ b/examples/coap/resources-plugtest/res-plugtest-query.c @@ -42,7 +42,7 @@ #include "coap.h" #include "plugtest.h" -static void res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); RESOURCE(res_plugtest_query, "title=\"Resource accepting query parameters\"", @@ -52,9 +52,9 @@ RESOURCE(res_plugtest_query, NULL); static void -res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { - coap_packet_t *const coap_req = (coap_packet_t *)request; + coap_message_t *const coap_req = (coap_message_t *)request; int len = 0; const char *query = NULL; diff --git a/examples/coap/resources-plugtest/res-plugtest-separate.c b/examples/coap/resources-plugtest/res-plugtest-separate.c index 3cbe7a896..16aa267ce 100644 --- a/examples/coap/resources-plugtest/res-plugtest-separate.c +++ b/examples/coap/resources-plugtest/res-plugtest-separate.c @@ -44,7 +44,7 @@ #include "coap-separate.h" #include "plugtest.h" -static void res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); static void res_resume_handler(void); PERIODIC_RESOURCE(res_plugtest_separate, @@ -68,9 +68,9 @@ static uint8_t separate_active = 0; static application_separate_store_t separate_store[1]; void -res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { - coap_packet_t *const coap_req = (coap_packet_t *)request; + coap_message_t *const coap_req = (coap_message_t *)request; PRINTF("/separate "); if(separate_active) { @@ -102,7 +102,7 @@ res_resume_handler() PRINTF( "RESPONSE (%s %u)\n", separate_store->request_metadata.type == COAP_TYPE_CON ? "CON" : "NON", separate_store->request_metadata.mid); - coap_packet_t response[1]; /* This way the packet can be treated as pointer as usual. */ + coap_message_t response[1]; /* This way the message can be treated as pointer as usual. */ /* Restore the request information for the response. */ coap_separate_resume(response, &separate_store->request_metadata, CONTENT_2_05); @@ -120,8 +120,8 @@ res_resume_handler() separate_store->request_metadata.block2_size); /* Warning: No check for serialization error. */ - transaction->packet_len = coap_serialize_message(response, - transaction->packet); + transaction->message_len = coap_serialize_message(response, + transaction->message); coap_send_transaction(transaction); /* The engine will clear the transaction (right after send for NON, after acked for CON). */ diff --git a/examples/coap/resources-plugtest/res-plugtest-test.c b/examples/coap/resources-plugtest/res-plugtest-test.c index 7146726c1..f7ac97c83 100644 --- a/examples/coap/resources-plugtest/res-plugtest-test.c +++ b/examples/coap/resources-plugtest/res-plugtest-test.c @@ -43,10 +43,10 @@ #include "plugtest.h" #include "random.h" -static void res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void res_post_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void res_put_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void res_delete_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_post_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_delete_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); RESOURCE(res_plugtest_test, "title=\"Default test resource\"", res_get_handler, res_post_handler, res_put_handler, res_delete_handler); @@ -71,9 +71,9 @@ test_update_etag() PRINTF("### SERVER ACTION ### Changed ETag %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", test_etag_len, test_etag[0], test_etag[1], test_etag[2], test_etag[3], test_etag[4], test_etag[5], test_etag[6], test_etag[7]); } static void -res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { - coap_packet_t *const coap_req = (coap_packet_t *)request; + coap_message_t *const coap_req = (coap_message_t *)request; if(test_change) { test_update_etag(); @@ -101,20 +101,20 @@ res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer } } static void -res_post_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_post_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { #if DEBUG - coap_packet_t *const coap_req = (coap_packet_t *)request; + coap_message_t *const coap_req = (coap_message_t *)request; PRINTF("/test POST (%s %u)\n", coap_req->type == COAP_TYPE_CON ? "CON" : "NON", coap_req->mid); #endif coap_set_status_code(response, CREATED_2_01); coap_set_header_location_path(response, "/location1/location2/location3"); } static void -res_put_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { #if DEBUG - coap_packet_t *const coap_req = (coap_packet_t *)request; + coap_message_t *const coap_req = (coap_message_t *)request; PRINTF("/test PUT (%s %u)\n", coap_req->type == COAP_TYPE_CON ? "CON" : "NON", coap_req->mid); #endif @@ -154,10 +154,10 @@ res_put_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer } } static void -res_delete_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_delete_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { #if DEBUG - coap_packet_t *const coap_req = (coap_packet_t *)request; + coap_message_t *const coap_req = (coap_message_t *)request; PRINTF("/test DELETE (%s %u)\n", coap_req->type == COAP_TYPE_CON ? "CON" : "NON", coap_req->mid); #endif coap_set_status_code(response, DELETED_2_02); diff --git a/examples/coap/resources-plugtest/res-plugtest-validate.c b/examples/coap/resources-plugtest/res-plugtest-validate.c index 45c7ebc06..30d97e727 100644 --- a/examples/coap/resources-plugtest/res-plugtest-validate.c +++ b/examples/coap/resources-plugtest/res-plugtest-validate.c @@ -43,8 +43,8 @@ #include "plugtest.h" #include "random.h" -static void res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void res_put_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); RESOURCE(res_plugtest_validate, "title=\"Validation test resource\"", @@ -74,9 +74,9 @@ validate_update_etag() validate_etag_len, validate_etag[0], validate_etag[1], validate_etag[2], validate_etag[3], validate_etag[4], validate_etag[5], validate_etag[6], validate_etag[7]); } static void -res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { - coap_packet_t *const coap_req = (coap_packet_t *)request; + coap_message_t *const coap_req = (coap_message_t *)request; if(validate_change) { validate_update_etag(); @@ -106,10 +106,10 @@ res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer } } static void -res_put_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { #if DEBUG - coap_packet_t *const coap_req = (coap_packet_t *)request; + coap_message_t *const coap_req = (coap_message_t *)request; #endif PRINTF("/validate PUT "); diff --git a/examples/coap/resources/res-b1-sep-b2.c b/examples/coap/resources/res-b1-sep-b2.c index a295549a7..0fa76726f 100644 --- a/examples/coap/resources/res-b1-sep-b2.c +++ b/examples/coap/resources/res-b1-sep-b2.c @@ -43,7 +43,7 @@ #include "coap-separate.h" #include "coap-transactions.h" -static void res_post_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_post_handler(coap_message_t *request, coap_message_t *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 @@ -53,7 +53,7 @@ static size_t big_msg_len = 0; static coap_separate_t request_metadata; static void -res_post_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_post_handler(coap_message_t *request, coap_message_t *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) { @@ -77,7 +77,7 @@ res_post_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffe /* Send first block */ coap_transaction_t *transaction = NULL; if((transaction = coap_new_transaction(request_metadata.mid, &request_metadata.endpoint))) { - coap_packet_t resp[1]; /* This way the packet can be treated as pointer as usual. */ + coap_message_t resp[1]; /* This way the message can be treated as pointer as usual. */ /* Restore the request information for the response. */ coap_separate_resume(resp, &request_metadata, CONTENT_2_05); @@ -89,7 +89,7 @@ res_post_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffe } /* Warning: No check for serialization error. */ - transaction->packet_len = coap_serialize_message(resp, transaction->packet); + transaction->message_len = coap_serialize_message(resp, transaction->message); coap_send_transaction(transaction); } } else { diff --git a/examples/coap/resources/res-battery.c b/examples/coap/resources/res-battery.c index 4d86d05dc..b4c7623b3 100644 --- a/examples/coap/resources/res-battery.c +++ b/examples/coap/resources/res-battery.c @@ -45,7 +45,7 @@ #include "coap-engine.h" #include "dev/battery-sensor.h" -static void res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); /* A simple getter example. Returns the reading from light sensor with a simple etag */ RESOURCE(res_battery, @@ -56,7 +56,7 @@ RESOURCE(res_battery, NULL); static void -res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { int battery = battery_sensor.value(0); diff --git a/examples/coap/resources/res-chunks.c b/examples/coap/resources/res-chunks.c index bc2d31226..39555d091 100644 --- a/examples/coap/resources/res-chunks.c +++ b/examples/coap/resources/res-chunks.c @@ -40,7 +40,7 @@ #include #include "coap-engine.h" -static void res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); /* * For data larger than COAP_MAX_CHUNK_SIZE (e.g., when stored in flash) resources must be aware of the buffer limitation @@ -59,7 +59,7 @@ RESOURCE(res_chunks, #define CHUNKS_TOTAL 2050 static void -res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { int32_t strpos = 0; diff --git a/examples/coap/resources/res-event.c b/examples/coap/resources/res-event.c index 709405d4d..5640353b3 100644 --- a/examples/coap/resources/res-event.c +++ b/examples/coap/resources/res-event.c @@ -53,7 +53,7 @@ #define PRINTLLADDR(addr) #endif -static void res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); static void res_event_handler(void); /* @@ -75,7 +75,7 @@ EVENT_RESOURCE(res_event, static int32_t event_counter = 0; static void -res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { coap_set_header_content_format(response, TEXT_PLAIN); coap_set_payload(response, buffer, snprintf((char *)buffer, preferred_size, "EVENT %lu", (unsigned long) event_counter)); diff --git a/examples/coap/resources/res-hello.c b/examples/coap/resources/res-hello.c index ac0852ee1..46b0139ef 100644 --- a/examples/coap/resources/res-hello.c +++ b/examples/coap/resources/res-hello.c @@ -40,7 +40,7 @@ #include #include "coap-engine.h" -static void res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); /* * A handler function named [resource name]_handler must be implemented for each RESOURCE. @@ -56,7 +56,7 @@ RESOURCE(res_hello, NULL); static void -res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const char *len = NULL; /* Some data that has the length up to REST_MAX_CHUNK_SIZE. For more, see the chunk resource. */ diff --git a/examples/coap/resources/res-leds.c b/examples/coap/resources/res-leds.c index 9203a5c99..243d438ae 100644 --- a/examples/coap/resources/res-leds.c +++ b/examples/coap/resources/res-leds.c @@ -55,7 +55,7 @@ #define PRINTLLADDR(addr) #endif -static void res_post_put_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_post_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); /* A simple actuator example, depending on the color query parameter and post variable mode, corresponding led is activated or deactivated */ RESOURCE(res_leds, @@ -66,7 +66,7 @@ RESOURCE(res_leds, NULL); static void -res_post_put_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_post_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { size_t len = 0; const char *color = NULL; diff --git a/examples/coap/resources/res-light.c b/examples/coap/resources/res-light.c index 23655a138..3384b2e5f 100644 --- a/examples/coap/resources/res-light.c +++ b/examples/coap/resources/res-light.c @@ -45,7 +45,7 @@ #include "coap-engine.h" #include "dev/light-sensor.h" -static void res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); /* A simple getter example. Returns the reading from light sensor with a simple etag */ RESOURCE(res_light, @@ -56,7 +56,7 @@ RESOURCE(res_light, NULL); static void -res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { uint16_t light_photosynthetic = light_sensor.value(LIGHT_SENSOR_PHOTOSYNTHETIC); uint16_t light_solar = light_sensor.value(LIGHT_SENSOR_TOTAL_SOLAR); diff --git a/examples/coap/resources/res-mirror.c b/examples/coap/resources/res-mirror.c index b4a15b7de..1ba948b0d 100644 --- a/examples/coap/resources/res-mirror.c +++ b/examples/coap/resources/res-mirror.c @@ -53,7 +53,7 @@ #define PRINTLLADDR(addr) #endif -static void res_any_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_any_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); /* This resource mirrors the incoming request. It shows how to access the options and how to set them for the response. */ RESOURCE(res_mirror, @@ -64,7 +64,7 @@ RESOURCE(res_mirror, res_any_handler); static void -res_any_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_any_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { /* The ETag and Token is copied to the header. */ uint8_t opaque[] = { 0x0A, 0xBC, 0xDE }; @@ -122,7 +122,7 @@ res_any_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "LQ %.*s\n", len, str); /* CoAP-specific example: actions not required for normal RESTful Web service. */ } - coap_packet_t *const coap_pkt = (coap_packet_t *)request; + coap_message_t *const coap_pkt = (coap_message_t *)request; if(strpos <= REST_MAX_CHUNK_SIZE && coap_pkt->token_len > 0) { strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "To 0x"); diff --git a/examples/coap/resources/res-push.c b/examples/coap/resources/res-push.c index 824d23ee5..ffc8c9c07 100644 --- a/examples/coap/resources/res-push.c +++ b/examples/coap/resources/res-push.c @@ -41,7 +41,7 @@ #include "coap-engine.h" #include "coap.h" -static void res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); static void res_periodic_handler(void); PERIODIC_RESOURCE(res_push, @@ -59,7 +59,7 @@ PERIODIC_RESOURCE(res_push, static int32_t event_counter = 0; static void -res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { /* * For minimal complexity, request query and options should be ignored for GET on observable resources. diff --git a/examples/coap/resources/res-radio.c b/examples/coap/resources/res-radio.c index 95f311274..c23436bb6 100644 --- a/examples/coap/resources/res-radio.c +++ b/examples/coap/resources/res-radio.c @@ -44,7 +44,7 @@ #include "coap-engine.h" #include "net/netstack.h" -static void res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); /* A simple getter example. Returns the reading of the rssi/lqi from radio sensor */ RESOURCE(res_radio, @@ -55,7 +55,7 @@ RESOURCE(res_radio, NULL); static void -res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { size_t len = 0; const char *p = NULL; diff --git a/examples/coap/resources/res-separate.c b/examples/coap/resources/res-separate.c index 639cd8c25..6b98345bb 100644 --- a/examples/coap/resources/res-separate.c +++ b/examples/coap/resources/res-separate.c @@ -42,7 +42,7 @@ #include "coap-separate.h" #include "coap-transactions.h" -static void res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); static void res_resume_handler(void); SEPARATE_RESOURCE(res_separate, @@ -69,7 +69,7 @@ static uint8_t separate_active = 0; static application_separate_store_t separate_store[COAP_MAX_OPEN_SEPARATE]; static void -res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { /* * Example allows only one open separate response. @@ -98,7 +98,7 @@ res_resume_handler() if(separate_active) { coap_transaction_t *transaction = NULL; if((transaction = coap_new_transaction(separate_store->request_metadata.mid, &separate_store->request_metadata.endpoint))) { - coap_packet_t response[1]; /* This way the packet can be treated as pointer as usual. */ + coap_message_t response[1]; /* This way the message can be treated as pointer as usual. */ /* Restore the request information for the response. */ coap_separate_resume(response, &separate_store->request_metadata, CONTENT_2_05); @@ -112,7 +112,7 @@ res_resume_handler() coap_set_header_block2(response, separate_store->request_metadata.block2_num, 0, separate_store->request_metadata.block2_size); /* Warning: No check for serialization error. */ - transaction->packet_len = coap_serialize_message(response, transaction->packet); + transaction->message_len = coap_serialize_message(response, transaction->message); coap_send_transaction(transaction); /* The engine will clear the transaction (right after send for NON, after acked for CON). */ diff --git a/examples/coap/resources/res-sht11.c b/examples/coap/resources/res-sht11.c index e853cea47..4dcf30e70 100644 --- a/examples/coap/resources/res-sht11.c +++ b/examples/coap/resources/res-sht11.c @@ -48,7 +48,7 @@ #include "coap-engine.h" #include "dev/sht11/sht11-sensor.h" -static void res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); /* Get Method Example. Returns the reading from temperature and humidity sensors. */ RESOURCE(res_sht11, @@ -59,7 +59,7 @@ RESOURCE(res_sht11, NULL); static void -res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { /* Temperature in Celsius (t in 14 bits resolution at 3 Volts) * T = -39.60 + 0.01*t diff --git a/examples/coap/resources/res-sub.c b/examples/coap/resources/res-sub.c index 2a2abcbcf..88bc6a584 100644 --- a/examples/coap/resources/res-sub.c +++ b/examples/coap/resources/res-sub.c @@ -40,7 +40,7 @@ #include #include "coap-engine.h" -static void res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); /* * Example for a resource that also handles all its sub-resources. @@ -54,7 +54,7 @@ PARENT_RESOURCE(res_sub, NULL); static void -res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { coap_set_header_content_format(response, TEXT_PLAIN); diff --git a/examples/coap/resources/res-temperature.c b/examples/coap/resources/res-temperature.c index 918fb31ad..ac34dbe33 100644 --- a/examples/coap/resources/res-temperature.c +++ b/examples/coap/resources/res-temperature.c @@ -49,7 +49,7 @@ #include "coap-engine.h" #include "dev/temperature-sensor.h" -static void res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); static void res_periodic_handler(void); #define MAX_AGE 60 @@ -70,7 +70,7 @@ PERIODIC_RESOURCE(res_temperature, res_periodic_handler); static void -res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { /* * For minimal complexity, request query and options should be ignored for GET on observable resources. diff --git a/examples/coap/resources/res-toggle.c b/examples/coap/resources/res-toggle.c index 81f558732..7f341c4f8 100644 --- a/examples/coap/resources/res-toggle.c +++ b/examples/coap/resources/res-toggle.c @@ -45,7 +45,7 @@ #include "coap-engine.h" #include "dev/leds.h" -static void res_post_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_post_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); /* A simple actuator example. Toggles the red led */ RESOURCE(res_toggle, @@ -56,7 +56,7 @@ RESOURCE(res_toggle, NULL); static void -res_post_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_post_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { leds_toggle(LEDS_RED); } diff --git a/examples/ipso-objects/example-server.c b/examples/ipso-objects/example-server.c index 4da82c9f0..a62ba4ffd 100644 --- a/examples/ipso-objects/example-server.c +++ b/examples/ipso-objects/example-server.c @@ -257,8 +257,8 @@ setup_network(void) /*---------------------------------------------------------------------------*/ PROCESS_THREAD(router_process, ev, data) { - /* This way the packet can be treated as pointer as usual. */ - static coap_packet_t request[1]; + /* This way the message can be treated as pointer as usual. */ + static coap_message_t request[1]; static struct etimer timer; uip_ds6_route_t *r; uip_ipaddr_t *nexthop; diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-ble-advd.c b/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-ble-advd.c index 99b0866fe..a94a0b7a0 100644 --- a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-ble-advd.c +++ b/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-ble-advd.c @@ -49,7 +49,7 @@ const char *forbidden_payload = "Name to advertise unspecified.\n" "Use name= in the request"; /*---------------------------------------------------------------------------*/ static void -res_ble_post_put_handler(coap_packet_t *request, coap_packet_t *response, +res_ble_post_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-device.c b/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-device.c index 6f0fe8bbb..46344d1ef 100644 --- a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-device.c +++ b/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-device.c @@ -75,7 +75,7 @@ detect_chip(void) } /*---------------------------------------------------------------------------*/ static void -res_get_handler_hw(coap_packet_t *request, coap_packet_t *response, +res_get_handler_hw(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { @@ -111,7 +111,7 @@ res_get_handler_hw(coap_packet_t *request, coap_packet_t *response, } /*---------------------------------------------------------------------------*/ static void -res_get_handler_sw(coap_packet_t *request, coap_packet_t *response, +res_get_handler_sw(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { @@ -144,7 +144,7 @@ res_get_handler_sw(coap_packet_t *request, coap_packet_t *response, } /*---------------------------------------------------------------------------*/ static void -res_get_handler_uptime(coap_packet_t *request, coap_packet_t *response, +res_get_handler_uptime(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { @@ -177,7 +177,7 @@ res_get_handler_uptime(coap_packet_t *request, coap_packet_t *response, } /*---------------------------------------------------------------------------*/ static void -res_post_handler_cfg_reset(coap_packet_t *request, coap_packet_t *response, +res_post_handler_cfg_reset(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-leds.c b/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-leds.c index c3c2d1ca4..6c396145c 100644 --- a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-leds.c +++ b/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-leds.c @@ -46,7 +46,7 @@ #include /*---------------------------------------------------------------------------*/ static void -res_post_put_handler(coap_packet_t *request, coap_packet_t *response, +res_post_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-net.c b/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-net.c index 35c4d50a8..81575f345 100644 --- a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-net.c +++ b/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-net.c @@ -51,7 +51,7 @@ extern int def_rt_rssi; /*---------------------------------------------------------------------------*/ static void -res_get_handler_parent_rssi(coap_packet_t *request, coap_packet_t *response, +res_get_handler_parent_rssi(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { @@ -84,7 +84,7 @@ res_get_handler_parent_rssi(coap_packet_t *request, coap_packet_t *response, } /*---------------------------------------------------------------------------*/ static void -res_get_handler_pref_parent(coap_packet_t *request, coap_packet_t *response, +res_get_handler_pref_parent(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-sensors.c b/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-sensors.c index ba161a397..9ccc79e97 100644 --- a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-sensors.c +++ b/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-sensors.c @@ -51,8 +51,8 @@ * called by all handlers and populates the CoAP response */ static void -res_get_handler_all(int sens_type, coap_packet_t *request, - coap_packet_t *response, +res_get_handler_all(int sens_type, coap_message_t *request, + coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; @@ -97,7 +97,7 @@ res_get_handler_all(int sens_type, coap_packet_t *request, /*---------------------------------------------------------------------------*/ /* BatMon resources and handler: Temperature, Voltage */ static void -res_get_handler_batmon_temp(coap_packet_t *request, coap_packet_t *response, +res_get_handler_batmon_temp(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { @@ -106,7 +106,7 @@ res_get_handler_batmon_temp(coap_packet_t *request, coap_packet_t *response, } /*---------------------------------------------------------------------------*/ static void -res_get_handler_batmon_volt(coap_packet_t *request, coap_packet_t *response, +res_get_handler_batmon_volt(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { @@ -123,7 +123,7 @@ RESOURCE(res_batmon_volt, "title=\"Battery Voltage\";rt=\"mV\"", #if CC26XX_WEB_DEMO_ADC_DEMO /*---------------------------------------------------------------------------*/ static void -res_get_handler_adc_dio23(coap_packet_t *request, coap_packet_t *response, +res_get_handler_adc_dio23(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { @@ -140,7 +140,7 @@ RESOURCE(res_adc_dio23, "title=\"ADC DIO23\";rt=\"mV\"", /*---------------------------------------------------------------------------*/ /* MPU resources and handler: Accelerometer and Gyro */ static void -res_get_handler_mpu_acc_x(coap_packet_t *request, coap_packet_t *response, +res_get_handler_mpu_acc_x(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { @@ -149,7 +149,7 @@ res_get_handler_mpu_acc_x(coap_packet_t *request, coap_packet_t *response, } /*---------------------------------------------------------------------------*/ static void -res_get_handler_mpu_acc_y(coap_packet_t *request, coap_packet_t *response, +res_get_handler_mpu_acc_y(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { @@ -158,7 +158,7 @@ res_get_handler_mpu_acc_y(coap_packet_t *request, coap_packet_t *response, } /*---------------------------------------------------------------------------*/ static void -res_get_handler_mpu_acc_z(coap_packet_t *request, coap_packet_t *response, +res_get_handler_mpu_acc_z(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { @@ -167,7 +167,7 @@ res_get_handler_mpu_acc_z(coap_packet_t *request, coap_packet_t *response, } /*---------------------------------------------------------------------------*/ static void -res_get_handler_mpu_gyro_x(coap_packet_t *request, coap_packet_t *response, +res_get_handler_mpu_gyro_x(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { @@ -176,7 +176,7 @@ res_get_handler_mpu_gyro_x(coap_packet_t *request, coap_packet_t *response, } /*---------------------------------------------------------------------------*/ static void -res_get_handler_mpu_gyro_y(coap_packet_t *request, coap_packet_t *response, +res_get_handler_mpu_gyro_y(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { @@ -185,7 +185,7 @@ res_get_handler_mpu_gyro_y(coap_packet_t *request, coap_packet_t *response, } /*---------------------------------------------------------------------------*/ static void -res_get_handler_mpu_gyro_z(coap_packet_t *request, coap_packet_t *response, +res_get_handler_mpu_gyro_z(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { @@ -209,7 +209,7 @@ RESOURCE(res_mpu_gyro_z, "title=\"Gyro Z\";rt=\"deg/sec\"", /*---------------------------------------------------------------------------*/ /* TMP sensor resources and handlers: Object, Ambient */ static void -res_get_handler_obj_temp(coap_packet_t *request, coap_packet_t *response, +res_get_handler_obj_temp(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { @@ -218,7 +218,7 @@ res_get_handler_obj_temp(coap_packet_t *request, coap_packet_t *response, } /*---------------------------------------------------------------------------*/ static void -res_get_handler_amb_temp(coap_packet_t *request, coap_packet_t *response, +res_get_handler_amb_temp(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { @@ -234,7 +234,7 @@ RESOURCE(res_tmp007_amb, "title=\"Temperature (Ambient)\";rt=\"C\"", /*---------------------------------------------------------------------------*/ /* BMP sensor resources: Temperature, Pressure */ static void -res_get_handler_bmp_temp(coap_packet_t *request, coap_packet_t *response, +res_get_handler_bmp_temp(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { @@ -243,7 +243,7 @@ res_get_handler_bmp_temp(coap_packet_t *request, coap_packet_t *response, } /*---------------------------------------------------------------------------*/ static void -res_get_handler_bmp_press(coap_packet_t *request, coap_packet_t *response, +res_get_handler_bmp_press(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { @@ -260,7 +260,7 @@ RESOURCE(res_bmp280_press, /*---------------------------------------------------------------------------*/ /* HDC1000 sensor resources and handler: Temperature, Pressure */ static void -res_get_handler_hdc_temp(coap_packet_t *request, coap_packet_t *response, +res_get_handler_hdc_temp(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { @@ -269,7 +269,7 @@ res_get_handler_hdc_temp(coap_packet_t *request, coap_packet_t *response, } /*---------------------------------------------------------------------------*/ static void -res_get_handler_hdc_humidity(coap_packet_t *request, coap_packet_t *response, +res_get_handler_hdc_humidity(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { @@ -285,7 +285,7 @@ RESOURCE(res_hdc1000_hum, "title=\"Humidity\";rt=\"%RH\"", /*---------------------------------------------------------------------------*/ /* Illuminance resources and handler */ static void -res_get_handler_opt(coap_packet_t *request, coap_packet_t *response, +res_get_handler_opt(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-toggle-leds.c b/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-toggle-leds.c index 5e45bed48..1c708b539 100644 --- a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-toggle-leds.c +++ b/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-toggle-leds.c @@ -48,7 +48,7 @@ #include /*---------------------------------------------------------------------------*/ static void -res_post_handler_red(coap_packet_t *request, coap_packet_t *response, +res_post_handler_red(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { @@ -56,7 +56,7 @@ res_post_handler_red(coap_packet_t *request, coap_packet_t *response, } /*---------------------------------------------------------------------------*/ static void -res_post_handler_green(coap_packet_t *request, coap_packet_t *response, +res_post_handler_green(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { @@ -83,7 +83,7 @@ RESOURCE(res_toggle_green, #if BOARD_SMARTRF06EB /*---------------------------------------------------------------------------*/ static void -res_post_handler_yellow(coap_packet_t *request, coap_packet_t *response, +res_post_handler_yellow(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { @@ -91,7 +91,7 @@ res_post_handler_yellow(coap_packet_t *request, coap_packet_t *response, } /*---------------------------------------------------------------------------*/ static void -res_post_handler_orange(coap_packet_t *request, coap_packet_t *response, +res_post_handler_orange(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { diff --git a/examples/platform-specific/cc26xx/very-sleepy-demo/very-sleepy-demo.c b/examples/platform-specific/cc26xx/very-sleepy-demo/very-sleepy-demo.c index 0c035839f..5c6690f34 100644 --- a/examples/platform-specific/cc26xx/very-sleepy-demo/very-sleepy-demo.c +++ b/examples/platform-specific/cc26xx/very-sleepy-demo/very-sleepy-demo.c @@ -104,7 +104,7 @@ PROCESS(very_sleepy_demo_process, "CC13xx/CC26xx very sleepy process"); AUTOSTART_PROCESSES(&very_sleepy_demo_process); /*---------------------------------------------------------------------------*/ static void -readings_get_handler(coap_packet_t *request, coap_packet_t *response, +readings_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; @@ -144,7 +144,7 @@ RESOURCE(readings_resource, "title=\"Sensor Readings\";obs", readings_get_handler, NULL, NULL, NULL); /*---------------------------------------------------------------------------*/ static void -conf_get_handler(coap_packet_t *request, coap_packet_t *response, +conf_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; @@ -175,7 +175,7 @@ conf_get_handler(coap_packet_t *request, coap_packet_t *response, } /*---------------------------------------------------------------------------*/ static void -conf_post_handler(coap_packet_t *request, coap_packet_t *response, +conf_post_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const char *ptr = NULL; diff --git a/examples/platform-specific/jn516x/rpl/coap-dongle-node/dongle-node.c b/examples/platform-specific/jn516x/rpl/coap-dongle-node/dongle-node.c index 5f113feef..a41c64b1c 100644 --- a/examples/platform-specific/jn516x/rpl/coap-dongle-node/dongle-node.c +++ b/examples/platform-specific/jn516x/rpl/coap-dongle-node/dongle-node.c @@ -41,7 +41,7 @@ #include "dev/leds.h" static void ct_callback(void *ptr); -static void put_post_led_toggle_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void put_post_led_toggle_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); static char content[COAP_MAX_CHUNK_SIZE]; static int content_len = 0; @@ -77,7 +77,7 @@ RESOURCE(resource_led_toggle, put_post_led_toggle_handler, NULL); static void -put_post_led_toggle_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +put_post_led_toggle_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { static int led_state = 0; unsigned int accept = -1; diff --git a/examples/platform-specific/jn516x/rpl/coap-dr1175-node/dr1175-node.c b/examples/platform-specific/jn516x/rpl/coap-dr1175-node/dr1175-node.c index 6a86837ac..4c59f3d7b 100644 --- a/examples/platform-specific/jn516x/rpl/coap-dr1175-node/dr1175-node.c +++ b/examples/platform-specific/jn516x/rpl/coap-dr1175-node/dr1175-node.c @@ -46,17 +46,17 @@ #include static void event_sensors_dr1175_handler(void); -static void get_sensors_dr1175_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_light_sensor_value_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_light_sensor_unit_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_temperature_value_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_temperature_unit_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_humidity_value_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_humidity_unit_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void put_post_white_led_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void put_post_rgb_led_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void put_post_led_d3_1174_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void put_post_led_d6_1174_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_sensors_dr1175_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_light_sensor_value_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_light_sensor_unit_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_temperature_value_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_temperature_unit_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_humidity_value_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_humidity_unit_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void put_post_white_led_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void put_post_rgb_led_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void put_post_led_d3_1174_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void put_post_led_d6_1174_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); static char content[COAP_MAX_CHUNK_SIZE]; static int content_len = 0; @@ -90,7 +90,7 @@ EVENT_RESOURCE(resource_sensors_dr1175, /* name */ NULL, /* DELETE handler */ event_sensors_dr1175_handler); /* event handler */ static void -get_sensors_dr1175_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_sensors_dr1175_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; coap_get_header_accept(request, &accept); @@ -121,7 +121,7 @@ RESOURCE(resource_light_sensor_value, NULL, NULL); static void -get_light_sensor_value_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_light_sensor_value_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; coap_get_header_accept(request, &accept); @@ -142,7 +142,7 @@ RESOURCE(resource_light_sensor_unit, NULL, NULL); static void -get_light_sensor_unit_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_light_sensor_unit_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; coap_get_header_accept(request, &accept); @@ -163,7 +163,7 @@ RESOURCE(resource_temperature_value, NULL, NULL); static void -get_temperature_value_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_temperature_value_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; coap_get_header_accept(request, &accept); @@ -184,7 +184,7 @@ RESOURCE(resource_temperature_unit, NULL, NULL); static void -get_temperature_unit_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_temperature_unit_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; coap_get_header_accept(request, &accept); @@ -205,7 +205,7 @@ RESOURCE(resource_humidity_value, NULL, NULL); static void -get_humidity_value_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_humidity_value_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; coap_get_header_accept(request, &accept); @@ -226,7 +226,7 @@ RESOURCE(resource_humidity_unit, NULL, NULL); static void -get_humidity_unit_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_humidity_unit_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; coap_get_header_accept(request, &accept); @@ -247,7 +247,7 @@ RESOURCE(resource_white_led, put_post_white_led_handler, NULL); static void -put_post_white_led_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +put_post_white_led_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *request_content = NULL; int level; @@ -271,7 +271,7 @@ RESOURCE(resource_rgb_led, put_post_rgb_led_handler, NULL); static void -put_post_rgb_led_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +put_post_rgb_led_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *request_content = NULL; char *pch; @@ -306,7 +306,7 @@ RESOURCE(resource_led_d3_1174, put_post_led_d3_1174_handler, NULL); static void -put_post_led_d3_1174_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +put_post_led_d3_1174_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *request_content; unsigned int accept = -1; @@ -326,7 +326,7 @@ RESOURCE(resource_led_d6_1174, put_post_led_d6_1174_handler, NULL); static void -put_post_led_d6_1174_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +put_post_led_d6_1174_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *request_content; unsigned int accept = -1; diff --git a/examples/platform-specific/jn516x/rpl/coap-dr1199-node/dr1199-node.c b/examples/platform-specific/jn516x/rpl/coap-dr1199-node/dr1199-node.c index d1677e6b9..e03e76747 100644 --- a/examples/platform-specific/jn516x/rpl/coap-dr1199-node/dr1199-node.c +++ b/examples/platform-specific/jn516x/rpl/coap-dr1199-node/dr1199-node.c @@ -46,19 +46,19 @@ static char content[COAP_MAX_CHUNK_SIZE]; static int content_len = 0; static void event_sensors_dr1199_handler(); -static void get_sensors_dr1199_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_switch_sw1_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_switch_sw2_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_switch_sw3_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_switch_sw4_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_switch_dio8_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_pot_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void put_post_led_d1_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void put_post_led_d2_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void put_post_led_d3_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void put_post_led_d3_1174_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void put_post_led_d6_1174_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void put_post_led_all_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_sensors_dr1199_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_switch_sw1_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_switch_sw2_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_switch_sw3_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_switch_sw4_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_switch_dio8_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_pot_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void put_post_led_d1_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void put_post_led_d2_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void put_post_led_d3_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void put_post_led_d3_1174_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void put_post_led_d6_1174_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void put_post_led_all_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); #define CONTENT_PRINTF(...) { if(content_len < sizeof(content)) { content_len += snprintf(content + content_len, sizeof(content) - content_len, __VA_ARGS__); } } @@ -93,7 +93,7 @@ EVENT_RESOURCE(resource_sensors_dr1199, /* name */ NULL, /* DELETE handler */ event_sensors_dr1199_handler); /* event handler */ static void -get_sensors_dr1199_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_sensors_dr1199_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; coap_get_header_accept(request, &accept); @@ -123,7 +123,7 @@ RESOURCE(resource_switch_sw1, NULL, NULL); static void -get_switch_sw1_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_switch_sw1_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { content_len = 0; unsigned int accept = -1; @@ -141,7 +141,7 @@ RESOURCE(resource_switch_sw2, NULL, NULL); static void -get_switch_sw2_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_switch_sw2_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { content_len = 0; unsigned int accept = -1; @@ -159,7 +159,7 @@ RESOURCE(resource_switch_sw3, NULL, NULL); static void -get_switch_sw3_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_switch_sw3_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { content_len = 0; unsigned int accept = -1; @@ -177,7 +177,7 @@ RESOURCE(resource_switch_sw4, NULL, NULL); static void -get_switch_sw4_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_switch_sw4_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { content_len = 0; unsigned int accept = -1; @@ -195,7 +195,7 @@ RESOURCE(resource_switch_dio8, NULL, NULL); static void -get_switch_dio8_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_switch_dio8_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { content_len = 0; unsigned int accept = -1; @@ -216,7 +216,7 @@ RESOURCE(resource_pot, NULL, NULL); static void -get_pot_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_pot_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { content_len = 0; unsigned int accept = -1; @@ -237,7 +237,7 @@ RESOURCE(resource_led_d1, put_post_led_d1_handler, NULL); static void -put_post_led_d1_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +put_post_led_d1_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *request_content; unsigned int accept = -1; @@ -254,7 +254,7 @@ RESOURCE(resource_led_d2, put_post_led_d2_handler, NULL); static void -put_post_led_d2_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +put_post_led_d2_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *request_content; unsigned int accept = -1; @@ -271,7 +271,7 @@ RESOURCE(resource_led_d3, put_post_led_d3_handler, NULL); static void -put_post_led_d3_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +put_post_led_d3_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *request_content; unsigned int accept = -1; @@ -288,7 +288,7 @@ RESOURCE(resource_led_d3_1174, put_post_led_d3_1174_handler, NULL); static void -put_post_led_d3_1174_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +put_post_led_d3_1174_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *request_content; unsigned int accept = -1; @@ -305,7 +305,7 @@ RESOURCE(resource_led_d6_1174, put_post_led_d6_1174_handler, NULL); static void -put_post_led_d6_1174_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +put_post_led_d6_1174_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *request_content; unsigned int accept = -1; @@ -322,7 +322,7 @@ RESOURCE(resource_led_all, put_post_led_all_handler, NULL); static void -put_post_led_all_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +put_post_led_all_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *request_content; unsigned int accept = -1; diff --git a/examples/platform-specific/jn516x/tsch/tx-power-verification/node/node.c b/examples/platform-specific/jn516x/tsch/tx-power-verification/node/node.c index df3197525..b8ad8bc7b 100644 --- a/examples/platform-specific/jn516x/tsch/tx-power-verification/node/node.c +++ b/examples/platform-specific/jn516x/tsch/tx-power-verification/node/node.c @@ -42,8 +42,8 @@ #include #include -static void set_tx_power_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_tx_power_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void set_tx_power_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_tx_power_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); static char content[COAP_MAX_CHUNK_SIZE]; static int content_len = 0; @@ -63,7 +63,7 @@ RESOURCE(resource_set_tx_power, set_tx_power_handler, NULL); static void -set_tx_power_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +set_tx_power_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *request_content = NULL; int tx_level; @@ -84,7 +84,7 @@ RESOURCE(resource_get_tx_power, NULL, NULL); static void -get_tx_power_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_tx_power_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { int tx_level; unsigned int accept = -1; diff --git a/examples/platform-specific/jn516x/tsch/tx-power-verification/rpl-border-router/rpl-border-router.c b/examples/platform-specific/jn516x/tsch/tx-power-verification/rpl-border-router/rpl-border-router.c index 76e0a72ec..5d9f83df1 100644 --- a/examples/platform-specific/jn516x/tsch/tx-power-verification/rpl-border-router/rpl-border-router.c +++ b/examples/platform-specific/jn516x/tsch/tx-power-verification/rpl-border-router/rpl-border-router.c @@ -56,8 +56,8 @@ static uip_ipaddr_t prefix; static uint8_t prefix_set; -static void get_rssi_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_last_rssi_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_rssi_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_last_rssi_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); static char content[COAP_MAX_CHUNK_SIZE]; static int content_len = 0; @@ -74,7 +74,7 @@ RESOURCE(resource_get_rssi, NULL, NULL); static void -get_rssi_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_rssi_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { int rssi_level; unsigned int accept = -1; @@ -95,7 +95,7 @@ RESOURCE(resource_get_last_rssi, NULL, NULL); static void -get_last_rssi_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_last_rssi_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { int last_rssi_level; unsigned int accept = -1; diff --git a/examples/platform-specific/jn516x/tsch/uart1-test-node/uart1-test-node.c b/examples/platform-specific/jn516x/tsch/uart1-test-node/uart1-test-node.c index b5003e452..affb6e6ca 100644 --- a/examples/platform-specific/jn516x/tsch/uart1-test-node/uart1-test-node.c +++ b/examples/platform-specific/jn516x/tsch/uart1-test-node/uart1-test-node.c @@ -42,9 +42,9 @@ #include "uart1.h" #include -static void get_coap_rx_uart1_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_coap_rx_uart1_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); static void event_coap_rx_uart1_handler(void); -static void put_post_tx_uart1_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void put_post_tx_uart1_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); static void string2uart1(uint8_t *c); static int handleRxChar(uint8_t c); static int get_ringbuf(uint8_t *c); @@ -85,7 +85,7 @@ EVENT_RESOURCE(resource_coap_rx_uart1, /* name */ NULL, /* DELETE handler */ event_coap_rx_uart1_handler); /* event handler */ static void -get_coap_rx_uart1_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_coap_rx_uart1_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; coap_get_header_accept(request, &accept); @@ -115,7 +115,7 @@ RESOURCE(resource_coap_tx_uart1, /* name */ NULL); /* DELETE handler */ static void -put_post_tx_uart1_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +put_post_tx_uart1_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *request_content = NULL; unsigned int accept = -1; diff --git a/examples/platform-specific/nrf52dk/coap-demo/resources/res-leds.c b/examples/platform-specific/nrf52dk/coap-demo/resources/res-leds.c index 906952b94..695eca6a2 100644 --- a/examples/platform-specific/nrf52dk/coap-demo/resources/res-leds.c +++ b/examples/platform-specific/nrf52dk/coap-demo/resources/res-leds.c @@ -48,12 +48,12 @@ #include "net/ipv6/uip-debug.h" static void -res_post_put_handler(coap_packet_t *request, coap_packet_t *response, +res_post_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); static void -res_get_handler(coap_packet_t *request, coap_packet_t *response, +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); @@ -71,7 +71,7 @@ EVENT_RESOURCE(res_led3, ); static void -res_post_put_handler(coap_packet_t *request, coap_packet_t *response, +res_post_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *payload; @@ -91,7 +91,7 @@ res_post_put_handler(coap_packet_t *request, coap_packet_t *response, } static void -res_get_handler(coap_packet_t *request, coap_packet_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { coap_set_header_content_format(response, TEXT_PLAIN); coap_set_payload(response, buffer, snprintf((char *)buffer, preferred_size, "%d", (leds_get() & LEDS_3) ? 1 : 0)); diff --git a/os/net/app-layer/coap/coap-block1.c b/os/net/app-layer/coap/coap-block1.c index ca32f51b9..4ecd8a1c5 100644 --- a/os/net/app-layer/coap/coap-block1.c +++ b/os/net/app-layer/coap/coap-block1.c @@ -73,7 +73,7 @@ * -1 if initialisation failed */ int -coap_block1_handler(coap_packet_t *request, coap_packet_t *response, +coap_block1_handler(coap_message_t *request, coap_message_t *response, uint8_t *target, size_t *len, size_t max_len) { const uint8_t *payload = 0; diff --git a/os/net/app-layer/coap/coap-block1.h b/os/net/app-layer/coap/coap-block1.h index 86ccda52a..2d61eaf36 100644 --- a/os/net/app-layer/coap/coap-block1.h +++ b/os/net/app-layer/coap/coap-block1.h @@ -43,7 +43,7 @@ #include #include -int coap_block1_handler(coap_packet_t *request, coap_packet_t *response, +int coap_block1_handler(coap_message_t *request, coap_message_t *response, uint8_t *target, size_t *len, size_t max_len); #endif /* COAP_BLOCK1_H_ */ diff --git a/os/net/app-layer/coap/coap-blocking-api.c b/os/net/app-layer/coap/coap-blocking-api.c index a49d46902..bd0877a67 100644 --- a/os/net/app-layer/coap/coap-blocking-api.c +++ b/os/net/app-layer/coap/coap-blocking-api.c @@ -55,7 +55,7 @@ /*- Client Part -------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ void -coap_blocking_request_callback(void *callback_data, coap_packet_t *response) +coap_blocking_request_callback(void *callback_data, coap_message_t *response) { coap_request_state_t *state = (coap_request_state_t *)callback_data; @@ -66,7 +66,7 @@ coap_blocking_request_callback(void *callback_data, coap_packet_t *response) PT_THREAD(coap_blocking_request (coap_request_state_t *state, process_event_t ev, coap_endpoint_t *remote_ep, - coap_packet_t *request, + coap_message_t *request, coap_blocking_response_handler_t request_callback)) { PT_BEGIN(&state->pt); @@ -93,10 +93,10 @@ PT_THREAD(coap_blocking_request coap_set_header_block2(request, state->block_num, 0, COAP_MAX_CHUNK_SIZE); } - state->transaction->packet_len = coap_serialize_message(request, + state->transaction->message_len = coap_serialize_message(request, state-> transaction-> - packet); + message); coap_send_transaction(state->transaction); PRINTF("Requested #%lu (MID %u)\n", state->block_num, request->mid); diff --git a/os/net/app-layer/coap/coap-blocking-api.h b/os/net/app-layer/coap/coap-blocking-api.h index c6ba82552..4a8fba6f0 100644 --- a/os/net/app-layer/coap/coap-blocking-api.h +++ b/os/net/app-layer/coap/coap-blocking-api.h @@ -42,16 +42,16 @@ typedef struct coap_request_state { struct pt pt; struct process *process; coap_transaction_t *transaction; - coap_packet_t *response; + coap_message_t *response; uint32_t block_num; } coap_request_state_t; -typedef void (* coap_blocking_response_handler_t)(coap_packet_t *response); +typedef void (* coap_blocking_response_handler_t)(coap_message_t *response); PT_THREAD(coap_blocking_request (coap_request_state_t *state, process_event_t ev, coap_endpoint_t *remote, - coap_packet_t *request, + coap_message_t *request, coap_blocking_response_handler_t request_callback)); #define COAP_BLOCKING_REQUEST(server_endpoint, request, chunk_handler) \ diff --git a/os/net/app-layer/coap/coap-callback-api.c b/os/net/app-layer/coap/coap-callback-api.c index dd8289b69..1f20e0a86 100644 --- a/os/net/app-layer/coap/coap-callback-api.c +++ b/os/net/app-layer/coap/coap-callback-api.c @@ -60,13 +60,13 @@ static uint32_t res_block; static uint8_t more; static uint8_t block_error; -static void coap_request_callback(void *callback_data, coap_packet_t *response); +static void coap_request_callback(void *callback_data, coap_message_t *response); /*---------------------------------------------------------------------------*/ static void progress_request(coap_request_state_t *state) { - coap_packet_t *request = state->request; + coap_message_t *request = state->request; request->mid = coap_get_mid(); if((state->transaction = coap_new_transaction(request->mid, state->remote_endpoint))) { @@ -77,8 +77,8 @@ progress_request(coap_request_state_t *state) { coap_set_header_block2(request, state->block_num, 0, COAP_MAX_CHUNK_SIZE); } - state->transaction->packet_len = - coap_serialize_message(request, state->transaction->packet); + state->transaction->message_len = + coap_serialize_message(request, state->transaction->message); coap_send_transaction(state->transaction); PRINTF("Requested #%lu (MID %u)\n", (unsigned long) state->block_num, @@ -89,7 +89,7 @@ progress_request(coap_request_state_t *state) { /*---------------------------------------------------------------------------*/ static void -coap_request_callback(void *callback_data, coap_packet_t *response) +coap_request_callback(void *callback_data, coap_message_t *response) { coap_request_state_t *state = (coap_request_state_t *)callback_data; uint32_t res_block1; @@ -137,7 +137,7 @@ coap_request_callback(void *callback_data, coap_packet_t *response) void coap_send_request(coap_request_state_t *state, coap_endpoint_t *endpoint, - coap_packet_t *request, + coap_message_t *request, void (*callback)(coap_request_state_t *state)) { /* can we have these variables shared between multiple requests? */ diff --git a/os/net/app-layer/coap/coap-callback-api.h b/os/net/app-layer/coap/coap-callback-api.h index 455c1ebab..612157587 100644 --- a/os/net/app-layer/coap/coap-callback-api.h +++ b/os/net/app-layer/coap/coap-callback-api.h @@ -51,8 +51,8 @@ typedef struct coap_request_state coap_request_state_t; struct coap_request_state { coap_transaction_t *transaction; - coap_packet_t *response; - coap_packet_t *request; + coap_message_t *response; + coap_message_t *request; coap_endpoint_t *remote_endpoint; uint32_t block_num; void *user_data; @@ -61,7 +61,7 @@ struct coap_request_state { }; void coap_send_request(coap_request_state_t *state, coap_endpoint_t *endpoint, - coap_packet_t *request, + coap_message_t *request, void (*callback)(coap_request_state_t *state)); #endif /* COAP_CALLBACK_API_H_ */ diff --git a/os/net/app-layer/coap/coap-engine.c b/os/net/app-layer/coap/coap-engine.c index ed99e90c7..43d9a2c8d 100644 --- a/os/net/app-layer/coap/coap-engine.c +++ b/os/net/app-layer/coap/coap-engine.c @@ -62,8 +62,8 @@ static void process_callback(coap_timer_t *t); * To be called by HTTP/COAP server as a callback function when a new service * request appears. This function dispatches the corresponding CoAP service. */ -static int invoke_coap_resource_service(coap_packet_t *request, - coap_packet_t *response, +static int invoke_coap_resource_service(coap_message_t *request, + coap_message_t *response, uint8_t *buffer, uint16_t buffer_size, int32_t *offset); @@ -91,7 +91,7 @@ coap_remove_handler(coap_handler_t *handler) } /*---------------------------------------------------------------------------*/ coap_handler_status_t -coap_call_handlers(coap_packet_t *request, coap_packet_t *response, +coap_call_handlers(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t buffer_size, int32_t *offset) { coap_handler_status_t status; @@ -115,7 +115,7 @@ coap_call_handlers(coap_packet_t *request, coap_packet_t *response, } /*---------------------------------------------------------------------------*/ static CC_INLINE coap_handler_status_t -call_service(coap_packet_t *request, coap_packet_t *response, +call_service(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t buffer_size, int32_t *offset) { coap_handler_status_t status; @@ -148,8 +148,8 @@ coap_receive(const coap_endpoint_t *src, uint8_t *payload, uint16_t payload_length) { /* static declaration reduces stack peaks and program code size */ - static coap_packet_t message[1]; /* this way the packet can be treated as pointer as usual */ - static coap_packet_t response[1]; + static coap_message_t message[1]; /* this way the message can be treated as pointer as usual */ + static coap_message_t response[1]; coap_transaction_t *transaction = NULL; coap_handler_status_t status; @@ -203,7 +203,7 @@ coap_receive(const coap_endpoint_t *src, /* call CoAP framework and check if found and allowed */ status = call_service(message, response, - transaction->packet + COAP_MAX_HEADER_SIZE, + transaction->message + COAP_MAX_HEADER_SIZE, block_size, &new_offset); if(status != COAP_HANDLER_STATUS_CONTINUE) { @@ -277,9 +277,9 @@ coap_receive(const coap_endpoint_t *src, /* serialize response */ } if(coap_status_code == NO_ERROR) { - if((transaction->packet_len = coap_serialize_message(response, + if((transaction->message_len = coap_serialize_message(response, transaction-> - packet)) == + message)) == 0) { coap_status_code = PACKET_SERIALIZATION_ERROR; } @@ -434,7 +434,7 @@ coap_get_next_resource(coap_resource_t *resource) } /*---------------------------------------------------------------------------*/ static int -invoke_coap_resource_service(coap_packet_t *request, coap_packet_t *response, +invoke_coap_resource_service(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t buffer_size, int32_t *offset) { diff --git a/os/net/app-layer/coap/coap-engine.h b/os/net/app-layer/coap/coap-engine.h index 0d3c2ea64..48cd4cb63 100644 --- a/os/net/app-layer/coap/coap-engine.h +++ b/os/net/app-layer/coap/coap-engine.h @@ -51,8 +51,8 @@ typedef enum { } coap_handler_status_t; typedef coap_handler_status_t -(* coap_handler_callback_t)(coap_packet_t *request, - coap_packet_t *response, +(* coap_handler_callback_t)(coap_message_t *request, + coap_message_t *response, uint8_t *buffer, uint16_t buffer_size, int32_t *offset); @@ -74,21 +74,21 @@ void coap_engine_init(void); int coap_receive(const coap_endpoint_t *src, uint8_t *payload, uint16_t payload_length); -coap_handler_status_t coap_call_handlers(coap_packet_t *request, - coap_packet_t *response, +coap_handler_status_t coap_call_handlers(coap_message_t *request, + coap_message_t *response, uint8_t *buffer, uint16_t buffer_size, int32_t *offset); /*---------------------------------------------------------------------------*/ /* signatures of handler functions */ -typedef void (* coap_resource_handler_t)(coap_packet_t *request, - coap_packet_t *response, +typedef void (* coap_resource_handler_t)(coap_message_t *request, + coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); typedef void (* coap_resource_periodic_handler_t)(void); typedef void (* coap_resource_response_handler_t)(void *data, - coap_packet_t *response); + coap_message_t *response); typedef void (* coap_resource_trigger_handler_t)(void); /* data structure representing a resource in CoAP */ diff --git a/os/net/app-layer/coap/coap-observe-client.c b/os/net/app-layer/coap/coap-observe-client.c index ebe4a776f..93ad47f12 100644 --- a/os/net/app-layer/coap/coap-observe-client.c +++ b/os/net/app-layer/coap/coap-observe-client.c @@ -62,7 +62,7 @@ LIST(obs_subjects_list); /*----------------------------------------------------------------------------*/ static size_t -get_token(coap_packet_t *coap_pkt, const uint8_t **token) +get_token(coap_message_t *coap_pkt, const uint8_t **token) { *token = coap_pkt->token; @@ -70,7 +70,7 @@ get_token(coap_packet_t *coap_pkt, const uint8_t **token) } /*----------------------------------------------------------------------------*/ static int -set_token(coap_packet_t *coap_pkt, const uint8_t *token, size_t token_len) +set_token(coap_message_t *coap_pkt, const uint8_t *token, size_t token_len) { coap_pkt->token_len = MIN(COAP_TOKEN_LEN, token_len); memcpy(coap_pkt->token, token, coap_pkt->token_len); @@ -172,9 +172,9 @@ coap_obs_remove_observee_by_url(const coap_endpoint_t *endpoint, /*----------------------------------------------------------------------------*/ static void simple_reply(coap_message_type_t type, const coap_endpoint_t *endpoint, - coap_packet_t *notification) + coap_message_t *notification) { - static coap_packet_t response[1]; + static coap_message_t response[1]; size_t len; coap_init_message(response, type, NO_ERROR, notification->mid); @@ -183,7 +183,7 @@ simple_reply(coap_message_type_t type, const coap_endpoint_t *endpoint, } /*----------------------------------------------------------------------------*/ static coap_notification_flag_t -classify_notification(coap_packet_t *response, int first) +classify_notification(coap_message_t *response, int first) { if(!response) { PRINTF("no response\n"); @@ -206,7 +206,7 @@ classify_notification(coap_packet_t *response, int first) /*----------------------------------------------------------------------------*/ void coap_handle_notification(const coap_endpoint_t *endpoint, - coap_packet_t *notification) + coap_message_t *notification) { const uint8_t *token; int token_len; @@ -250,7 +250,7 @@ coap_handle_notification(const coap_endpoint_t *endpoint, } /*----------------------------------------------------------------------------*/ static void -handle_obs_registration_response(void *data, coap_packet_t *response) +handle_obs_registration_response(void *data, coap_message_t *response) { coap_observee_t *obs; notification_callback_t notification_callback; @@ -284,7 +284,7 @@ coap_obs_request_registration(const coap_endpoint_t *endpoint, char *uri, notification_callback_t notification_callback, void *data) { - coap_packet_t request[1]; + coap_message_t request[1]; coap_transaction_t *t; uint8_t *token; uint8_t token_len; @@ -303,7 +303,7 @@ coap_obs_request_registration(const coap_endpoint_t *endpoint, char *uri, if(obs) { t->callback = handle_obs_registration_response; t->callback_data = obs; - t->packet_len = coap_serialize_message(request, t->packet); + t->message_len = coap_serialize_message(request, t->message); coap_send_transaction(t); } else { PRINTF("Could not allocate obs_subject resource buffer"); diff --git a/os/net/app-layer/coap/coap-observe-client.h b/os/net/app-layer/coap/coap-observe-client.h index adbc859a4..5c1a9a816 100644 --- a/os/net/app-layer/coap/coap-observe-client.h +++ b/os/net/app-layer/coap/coap-observe-client.h @@ -107,7 +107,7 @@ int coap_obs_remove_observee_by_url(const coap_endpoint_t *endpoint, const char *url); void coap_handle_notification(const coap_endpoint_t *endpoint, - coap_packet_t *notification); + coap_message_t *notification); coap_observee_t *coap_obs_request_registration(const coap_endpoint_t *endpoint, char *uri, diff --git a/os/net/app-layer/coap/coap-observe.c b/os/net/app-layer/coap/coap-observe.c index 791f8929b..dea8414ef 100644 --- a/os/net/app-layer/coap/coap-observe.c +++ b/os/net/app-layer/coap/coap-observe.c @@ -191,8 +191,8 @@ void coap_notify_observers_sub(coap_resource_t *resource, const char *subpath) { /* build notification */ - coap_packet_t notification[1]; /* this way the packet can be treated as pointer as usual */ - coap_packet_t request[1]; /* this way the packet can be treated as pointer as usual */ + coap_message_t notification[1]; /* this way the message can be treated as pointer as usual */ + coap_message_t request[1]; /* this way the message can be treated as pointer as usual */ coap_observer_t *obs = NULL; int url_len, obs_url_len; char url[COAP_OBSERVER_URL_LEN]; @@ -260,14 +260,14 @@ coap_notify_observers_sub(coap_resource_t *resource, const char *subpath) notification->mid = transaction->mid; /* Either old style get_handler or the full handler */ - if(coap_call_handlers(request, notification, transaction->packet + + if(coap_call_handlers(request, notification, transaction->message + COAP_MAX_HEADER_SIZE, COAP_MAX_CHUNK_SIZE, NULL) > 0) { PRINTF("Notification on new handlers\n"); } else { if(resource != NULL) { resource->get_handler(request, notification, - transaction->packet + COAP_MAX_HEADER_SIZE, + transaction->message + COAP_MAX_HEADER_SIZE, COAP_MAX_CHUNK_SIZE, NULL); } else { /* What to do here? */ @@ -282,8 +282,8 @@ coap_notify_observers_sub(coap_resource_t *resource, const char *subpath) } coap_set_token(notification, obs->token, obs->token_len); - transaction->packet_len = - coap_serialize_message(notification, transaction->packet); + transaction->message_len = + coap_serialize_message(notification, transaction->message); coap_send_transaction(transaction); } @@ -292,8 +292,8 @@ coap_notify_observers_sub(coap_resource_t *resource, const char *subpath) } /*---------------------------------------------------------------------------*/ void -coap_observe_handler(coap_resource_t *resource, coap_packet_t *coap_req, - coap_packet_t *coap_res) +coap_observe_handler(coap_resource_t *resource, coap_message_t *coap_req, + coap_message_t *coap_res) { const coap_endpoint_t *src_ep; coap_observer_t *obs; diff --git a/os/net/app-layer/coap/coap-observe.h b/os/net/app-layer/coap/coap-observe.h index e6138426f..5a78237cb 100644 --- a/os/net/app-layer/coap/coap-observe.h +++ b/os/net/app-layer/coap/coap-observe.h @@ -72,7 +72,7 @@ int coap_remove_observer_by_mid(const coap_endpoint_t *ep, void coap_notify_observers(coap_resource_t *resource); void coap_notify_observers_sub(coap_resource_t *resource, const char *subpath); -void coap_observe_handler(coap_resource_t *resource, coap_packet_t *request, - coap_packet_t *response); +void coap_observe_handler(coap_resource_t *resource, coap_message_t *request, + coap_message_t *response); #endif /* COAP_OBSERVE_H_ */ diff --git a/os/net/app-layer/coap/coap-res-well-known-core.c b/os/net/app-layer/coap/coap-res-well-known-core.c index 80577b6a6..248271434 100644 --- a/os/net/app-layer/coap/coap-res-well-known-core.c +++ b/os/net/app-layer/coap/coap-res-well-known-core.c @@ -74,7 +74,7 @@ /*- Resource Handlers -------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ static void -well_known_core_get_handler(coap_packet_t *request, coap_packet_t *response, +well_known_core_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { diff --git a/os/net/app-layer/coap/coap-separate.c b/os/net/app-layer/coap/coap-separate.c index 32dcd0aba..ea2f11261 100644 --- a/os/net/app-layer/coap/coap-separate.c +++ b/os/net/app-layer/coap/coap-separate.c @@ -81,7 +81,7 @@ coap_separate_reject() * then retry later. */ void -coap_separate_accept(coap_packet_t *coap_req, coap_separate_t *separate_store) +coap_separate_accept(coap_message_t *coap_req, coap_separate_t *separate_store) { coap_transaction_t *const t = coap_get_transaction_by_mid(coap_req->mid); @@ -90,7 +90,7 @@ coap_separate_accept(coap_packet_t *coap_req, coap_separate_t *separate_store) if(t) { /* send separate ACK for CON */ if(coap_req->type == COAP_TYPE_CON) { - coap_packet_t ack[1]; + coap_message_t ack[1]; const coap_endpoint_t *ep; ep = coap_get_src_endpoint(coap_req); @@ -131,7 +131,7 @@ coap_separate_accept(coap_packet_t *coap_req, coap_separate_t *separate_store) } /*----------------------------------------------------------------------------*/ void -coap_separate_resume(coap_packet_t *response, coap_separate_t *separate_store, +coap_separate_resume(coap_message_t *response, coap_separate_t *separate_store, uint8_t code) { coap_init_message(response, separate_store->type, code, diff --git a/os/net/app-layer/coap/coap-separate.h b/os/net/app-layer/coap/coap-separate.h index c8b36de48..2f815188a 100644 --- a/os/net/app-layer/coap/coap-separate.h +++ b/os/net/app-layer/coap/coap-separate.h @@ -59,12 +59,12 @@ typedef struct coap_separate { uint16_t block2_size; } coap_separate_t; -int coap_separate_handler(coap_resource_t *resource, coap_packet_t *request, - coap_packet_t *response); +int coap_separate_handler(coap_resource_t *resource, coap_message_t *request, + coap_message_t *response); void coap_separate_reject(void); -void coap_separate_accept(coap_packet_t *request, +void coap_separate_accept(coap_message_t *request, coap_separate_t *separate_store); -void coap_separate_resume(coap_packet_t *response, +void coap_separate_resume(coap_message_t *response, coap_separate_t *separate_store, uint8_t code); diff --git a/os/net/app-layer/coap/coap-transactions.c b/os/net/app-layer/coap/coap-transactions.c index fa2d2d3c8..73efa0650 100644 --- a/os/net/app-layer/coap/coap-transactions.c +++ b/os/net/app-layer/coap/coap-transactions.c @@ -98,10 +98,10 @@ coap_send_transaction(coap_transaction_t *t) { PRINTF("Sending transaction %u\n", t->mid); - coap_sendto(&t->endpoint, t->packet, t->packet_len); + coap_sendto(&t->endpoint, t->message, t->message_len); if(COAP_TYPE_CON == - ((COAP_HEADER_TYPE_MASK & t->packet[0]) >> COAP_HEADER_TYPE_POSITION)) { + ((COAP_HEADER_TYPE_MASK & t->message[0]) >> COAP_HEADER_TYPE_POSITION)) { if(t->retrans_counter < COAP_MAX_RETRANSMIT) { /* not timed out yet */ PRINTF("Keeping transaction %u\n", t->mid); diff --git a/os/net/app-layer/coap/coap-transactions.h b/os/net/app-layer/coap/coap-transactions.h index 0e054ce6c..497c5fc35 100644 --- a/os/net/app-layer/coap/coap-transactions.h +++ b/os/net/app-layer/coap/coap-transactions.h @@ -64,8 +64,8 @@ typedef struct coap_transaction { coap_resource_response_handler_t callback; void *callback_data; - uint16_t packet_len; - uint8_t packet[COAP_MAX_PACKET_SIZE + 1]; /* +1 for the terminating '\0' which will not be sent + uint16_t message_len; + uint8_t message[COAP_MAX_PACKET_SIZE + 1]; /* +1 for the terminating '\0' which will not be sent * Use snprintf(buf, len+1, "", ...) to completely fill payload */ } coap_transaction_t; diff --git a/os/net/app-layer/coap/coap.c b/os/net/app-layer/coap/coap.c index 35d2c0fcf..ad6f68b3e 100644 --- a/os/net/app-layer/coap/coap.c +++ b/os/net/app-layer/coap/coap.c @@ -34,8 +34,17 @@ * An implementation of the Constrained Application Protocol (RFC). * \author * Matthias Kovatsch + * + * Joakim Eriksson, joakim.eriksson@ri.se + * Niclas Finne, niclas.finne@ri.se */ +/** + * \addtogroup coap + * @{ + */ + + #include #include #include "sys/cc.h" @@ -290,11 +299,11 @@ coap_get_mid() } /*---------------------------------------------------------------------------*/ void -coap_init_message(coap_packet_t *coap_pkt, coap_message_type_t type, +coap_init_message(coap_message_t *coap_pkt, coap_message_type_t type, uint8_t code, uint16_t mid) { /* Important thing */ - memset(coap_pkt, 0, sizeof(coap_packet_t)); + memset(coap_pkt, 0, sizeof(coap_message_t)); coap_pkt->type = type; coap_pkt->code = code; @@ -302,7 +311,7 @@ coap_init_message(coap_packet_t *coap_pkt, coap_message_type_t type, } /*---------------------------------------------------------------------------*/ size_t -coap_serialize_message(coap_packet_t *coap_pkt, uint8_t *buffer) +coap_serialize_message(coap_message_t *coap_pkt, uint8_t *buffer) { uint8_t *option; unsigned int current_number = 0; @@ -325,7 +334,7 @@ coap_serialize_message(coap_packet_t *coap_pkt, 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 */ + /* empty message, dont need to do more stuff */ if(!coap_pkt->code) { PRINTF("-Done serializing empty message at %p-\n", coap_pkt->buffer); return 4; @@ -412,16 +421,16 @@ coap_serialize_message(coap_packet_t *coap_pkt, uint8_t *buffer) coap_pkt->buffer[5], coap_pkt->buffer[6], coap_pkt->buffer[7] ); - return (option - buffer) + coap_pkt->payload_len; /* packet length */ + return (option - buffer) + coap_pkt->payload_len; /* message length */ } /*---------------------------------------------------------------------------*/ coap_status_t -coap_parse_message(coap_packet_t *coap_pkt, uint8_t *data, uint16_t data_len) +coap_parse_message(coap_message_t *coap_pkt, uint8_t *data, uint16_t data_len) { - /* initialize packet */ - memset(coap_pkt, 0, sizeof(coap_packet_t)); + /* initialize message */ + memset(coap_pkt, 0, sizeof(coap_message_t)); - /* pointer to packet bytes */ + /* pointer to message bytes */ coap_pkt->buffer = data; /* parse header fields */ @@ -505,7 +514,7 @@ coap_parse_message(coap_packet_t *coap_pkt, uint8_t *data, uint16_t data_len) if(current_option + option_length > data + data_len) { /* Malformed CoAP - out of bounds */ - PRINTF("BAD REQUEST: options outside data packet: %u > %u\n", + PRINTF("BAD REQUEST: options outside data message: %u > %u\n", (unsigned)(current_option + option_length - data), data_len); return BAD_REQUEST_4_00; } @@ -601,7 +610,7 @@ coap_parse_message(coap_packet_t *coap_pkt, uint8_t *data, uint16_t data_len) PRINTF("Uri-Port [%u]\n", coap_pkt->uri_port); break; case COAP_OPTION_URI_PATH: - /* coap_merge_multi_option() operates in-place on the IPBUF, but final packet field should be const string -> cast to string */ + /* coap_merge_multi_option() operates in-place on the IPBUF, but final message field should be const string -> cast to string */ coap_merge_multi_option((char **)&(coap_pkt->uri_path), &(coap_pkt->uri_path_len), current_option, option_length, '/'); @@ -609,7 +618,7 @@ coap_parse_message(coap_packet_t *coap_pkt, uint8_t *data, uint16_t data_len) PRINTF("]\n"); break; case COAP_OPTION_URI_QUERY: - /* coap_merge_multi_option() operates in-place on the IPBUF, but final packet field should be const string -> cast to string */ + /* coap_merge_multi_option() operates in-place on the IPBUF, but final message field should be const string -> cast to string */ coap_merge_multi_option((char **)&(coap_pkt->uri_query), &(coap_pkt->uri_query_len), current_option, option_length, '&'); @@ -618,7 +627,7 @@ coap_parse_message(coap_packet_t *coap_pkt, uint8_t *data, uint16_t data_len) break; case COAP_OPTION_LOCATION_PATH: - /* coap_merge_multi_option() operates in-place on the IPBUF, but final packet field should be const string -> cast to string */ + /* coap_merge_multi_option() operates in-place on the IPBUF, but final message field should be const string -> cast to string */ coap_merge_multi_option((char **)&(coap_pkt->location_path), &(coap_pkt->location_path_len), current_option, option_length, '/'); @@ -628,7 +637,7 @@ coap_parse_message(coap_packet_t *coap_pkt, uint8_t *data, uint16_t data_len) PRINTF("]\n"); break; case COAP_OPTION_LOCATION_QUERY: - /* coap_merge_multi_option() operates in-place on the IPBUF, but final packet field should be const string -> cast to string */ + /* coap_merge_multi_option() operates in-place on the IPBUF, but final message field should be const string -> cast to string */ coap_merge_multi_option((char **)&(coap_pkt->location_query), &(coap_pkt->location_query_len), current_option, option_length, '&'); @@ -693,7 +702,7 @@ coap_parse_message(coap_packet_t *coap_pkt, uint8_t *data, uint16_t data_len) /*- CoAP Engine API ---------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ int -coap_get_query_variable(coap_packet_t *coap_pkt, +coap_get_query_variable(coap_message_t *coap_pkt, const char *name, const char **output) { if(coap_is_option(coap_pkt, COAP_OPTION_URI_QUERY)) { @@ -703,7 +712,7 @@ coap_get_query_variable(coap_packet_t *coap_pkt, return 0; } int -coap_get_post_variable(coap_packet_t *coap_pkt, +coap_get_post_variable(coap_message_t *coap_pkt, const char *name, const char **output) { if(coap_pkt->payload_len) { @@ -714,10 +723,10 @@ coap_get_post_variable(coap_packet_t *coap_pkt, } /*---------------------------------------------------------------------------*/ int -coap_set_status_code(coap_packet_t *packet, unsigned int code) +coap_set_status_code(coap_message_t *message, unsigned int code) { if(code <= 0xFF) { - packet->code = (uint8_t)code; + message->code = (uint8_t)code; return 1; } else { return 0; @@ -725,7 +734,7 @@ coap_set_status_code(coap_packet_t *packet, unsigned int code) } /*---------------------------------------------------------------------------*/ int -coap_set_token(coap_packet_t *coap_pkt, const uint8_t *token, size_t token_len) +coap_set_token(coap_message_t *coap_pkt, const uint8_t *token, size_t token_len) { coap_pkt->token_len = MIN(COAP_TOKEN_LEN, token_len); memcpy(coap_pkt->token, token, coap_pkt->token_len); @@ -736,7 +745,7 @@ coap_set_token(coap_packet_t *coap_pkt, const uint8_t *token, size_t token_len) /*- CoAP Implementation API -------------------------------------------------*/ /*---------------------------------------------------------------------------*/ int -coap_get_header_content_format(coap_packet_t *coap_pkt, unsigned int *format) +coap_get_header_content_format(coap_message_t *coap_pkt, unsigned int *format) { if(!coap_is_option(coap_pkt, COAP_OPTION_CONTENT_FORMAT)) { return 0; @@ -745,7 +754,7 @@ coap_get_header_content_format(coap_packet_t *coap_pkt, unsigned int *format) return 1; } int -coap_set_header_content_format(coap_packet_t *coap_pkt, unsigned int format) +coap_set_header_content_format(coap_message_t *coap_pkt, unsigned int format) { coap_pkt->content_format = format; coap_set_option(coap_pkt, COAP_OPTION_CONTENT_FORMAT); @@ -753,7 +762,7 @@ coap_set_header_content_format(coap_packet_t *coap_pkt, unsigned int format) } /*---------------------------------------------------------------------------*/ int -coap_get_header_accept(coap_packet_t *coap_pkt, unsigned int *accept) +coap_get_header_accept(coap_message_t *coap_pkt, unsigned int *accept) { if(!coap_is_option(coap_pkt, COAP_OPTION_ACCEPT)) { return 0; @@ -762,7 +771,7 @@ coap_get_header_accept(coap_packet_t *coap_pkt, unsigned int *accept) return 1; } int -coap_set_header_accept(coap_packet_t *coap_pkt, unsigned int accept) +coap_set_header_accept(coap_message_t *coap_pkt, unsigned int accept) { coap_pkt->accept = accept; coap_set_option(coap_pkt, COAP_OPTION_ACCEPT); @@ -770,7 +779,7 @@ coap_set_header_accept(coap_packet_t *coap_pkt, unsigned int accept) } /*---------------------------------------------------------------------------*/ int -coap_get_header_max_age(coap_packet_t *coap_pkt, uint32_t *age) +coap_get_header_max_age(coap_message_t *coap_pkt, uint32_t *age) { if(!coap_is_option(coap_pkt, COAP_OPTION_MAX_AGE)) { *age = COAP_DEFAULT_MAX_AGE; @@ -779,7 +788,7 @@ coap_get_header_max_age(coap_packet_t *coap_pkt, uint32_t *age) } return 1; } int -coap_set_header_max_age(coap_packet_t *coap_pkt, uint32_t age) +coap_set_header_max_age(coap_message_t *coap_pkt, uint32_t age) { coap_pkt->max_age = age; coap_set_option(coap_pkt, COAP_OPTION_MAX_AGE); @@ -787,7 +796,7 @@ coap_set_header_max_age(coap_packet_t *coap_pkt, uint32_t age) } /*---------------------------------------------------------------------------*/ int -coap_get_header_etag(coap_packet_t *coap_pkt, const uint8_t **etag) +coap_get_header_etag(coap_message_t *coap_pkt, const uint8_t **etag) { if(!coap_is_option(coap_pkt, COAP_OPTION_ETAG)) { return 0; @@ -796,7 +805,7 @@ coap_get_header_etag(coap_packet_t *coap_pkt, const uint8_t **etag) return coap_pkt->etag_len; } int -coap_set_header_etag(coap_packet_t *coap_pkt, const uint8_t *etag, size_t etag_len) +coap_set_header_etag(coap_message_t *coap_pkt, const uint8_t *etag, size_t etag_len) { coap_pkt->etag_len = MIN(COAP_ETAG_LEN, etag_len); memcpy(coap_pkt->etag, etag, coap_pkt->etag_len); @@ -807,7 +816,7 @@ coap_set_header_etag(coap_packet_t *coap_pkt, const uint8_t *etag, size_t etag_l /*---------------------------------------------------------------------------*/ /*FIXME support multiple ETags */ int -coap_get_header_if_match(coap_packet_t *coap_pkt, const uint8_t **etag) +coap_get_header_if_match(coap_message_t *coap_pkt, const uint8_t **etag) { if(!coap_is_option(coap_pkt, COAP_OPTION_IF_MATCH)) { return 0; @@ -816,7 +825,7 @@ coap_get_header_if_match(coap_packet_t *coap_pkt, const uint8_t **etag) return coap_pkt->if_match_len; } int -coap_set_header_if_match(coap_packet_t *coap_pkt, const uint8_t *etag, size_t etag_len) +coap_set_header_if_match(coap_message_t *coap_pkt, const uint8_t *etag, size_t etag_len) { coap_pkt->if_match_len = MIN(COAP_ETAG_LEN, etag_len); memcpy(coap_pkt->if_match, etag, coap_pkt->if_match_len); @@ -826,19 +835,19 @@ coap_set_header_if_match(coap_packet_t *coap_pkt, const uint8_t *etag, size_t et } /*---------------------------------------------------------------------------*/ int -coap_get_header_if_none_match(coap_packet_t *packet) +coap_get_header_if_none_match(coap_message_t *message) { - return coap_is_option(packet, COAP_OPTION_IF_NONE_MATCH) ? 1 : 0; + return coap_is_option(message, COAP_OPTION_IF_NONE_MATCH) ? 1 : 0; } int -coap_set_header_if_none_match(coap_packet_t *packet) +coap_set_header_if_none_match(coap_message_t *message) { - coap_set_option(packet, COAP_OPTION_IF_NONE_MATCH); + coap_set_option(message, COAP_OPTION_IF_NONE_MATCH); return 1; } /*---------------------------------------------------------------------------*/ int -coap_get_header_proxy_uri(coap_packet_t *coap_pkt, const char **uri) +coap_get_header_proxy_uri(coap_message_t *coap_pkt, const char **uri) { if(!coap_is_option(coap_pkt, COAP_OPTION_PROXY_URI)) { return 0; @@ -847,7 +856,7 @@ coap_get_header_proxy_uri(coap_packet_t *coap_pkt, const char **uri) return coap_pkt->proxy_uri_len; } int -coap_set_header_proxy_uri(coap_packet_t *coap_pkt, const char *uri) +coap_set_header_proxy_uri(coap_message_t *coap_pkt, const char *uri) { /* TODO Provide alternative that sets Proxy-Scheme and Uri-* options and provide coap-conf define */ @@ -859,7 +868,7 @@ coap_set_header_proxy_uri(coap_packet_t *coap_pkt, const char *uri) } /*---------------------------------------------------------------------------*/ int -coap_get_header_uri_host(coap_packet_t *coap_pkt, const char **host) +coap_get_header_uri_host(coap_message_t *coap_pkt, const char **host) { if(!coap_is_option(coap_pkt, COAP_OPTION_URI_HOST)) { return 0; @@ -868,7 +877,7 @@ coap_get_header_uri_host(coap_packet_t *coap_pkt, const char **host) return coap_pkt->uri_host_len; } int -coap_set_header_uri_host(coap_packet_t *coap_pkt, const char *host) +coap_set_header_uri_host(coap_message_t *coap_pkt, const char *host) { coap_pkt->uri_host = host; coap_pkt->uri_host_len = strlen(host); @@ -878,7 +887,7 @@ coap_set_header_uri_host(coap_packet_t *coap_pkt, const char *host) } /*---------------------------------------------------------------------------*/ int -coap_get_header_uri_path(coap_packet_t *coap_pkt, const char **path) +coap_get_header_uri_path(coap_message_t *coap_pkt, const char **path) { if(!coap_is_option(coap_pkt, COAP_OPTION_URI_PATH)) { return 0; @@ -887,7 +896,7 @@ coap_get_header_uri_path(coap_packet_t *coap_pkt, const char **path) return coap_pkt->uri_path_len; } int -coap_set_header_uri_path(coap_packet_t *coap_pkt, const char *path) +coap_set_header_uri_path(coap_message_t *coap_pkt, const char *path) { while(path[0] == '/') { ++path; @@ -901,7 +910,7 @@ coap_set_header_uri_path(coap_packet_t *coap_pkt, const char *path) } /*---------------------------------------------------------------------------*/ int -coap_get_header_uri_query(coap_packet_t *coap_pkt, const char **query) +coap_get_header_uri_query(coap_message_t *coap_pkt, const char **query) { if(!coap_is_option(coap_pkt, COAP_OPTION_URI_QUERY)) { return 0; @@ -910,7 +919,7 @@ coap_get_header_uri_query(coap_packet_t *coap_pkt, const char **query) return coap_pkt->uri_query_len; } int -coap_set_header_uri_query(coap_packet_t *coap_pkt, const char *query) +coap_set_header_uri_query(coap_message_t *coap_pkt, const char *query) { while(query[0] == '?') { ++query; @@ -924,7 +933,7 @@ coap_set_header_uri_query(coap_packet_t *coap_pkt, const char *query) } /*---------------------------------------------------------------------------*/ int -coap_get_header_location_path(coap_packet_t *coap_pkt, const char **path) +coap_get_header_location_path(coap_message_t *coap_pkt, const char **path) { if(!coap_is_option(coap_pkt, COAP_OPTION_LOCATION_PATH)) { return 0; @@ -933,7 +942,7 @@ coap_get_header_location_path(coap_packet_t *coap_pkt, const char **path) return coap_pkt->location_path_len; } int -coap_set_header_location_path(coap_packet_t *coap_pkt, const char *path) +coap_set_header_location_path(coap_message_t *coap_pkt, const char *path) { char *query; @@ -955,7 +964,7 @@ coap_set_header_location_path(coap_packet_t *coap_pkt, const char *path) } /*---------------------------------------------------------------------------*/ int -coap_get_header_location_query(coap_packet_t *coap_pkt, const char **query) +coap_get_header_location_query(coap_message_t *coap_pkt, const char **query) { if(!coap_is_option(coap_pkt, COAP_OPTION_LOCATION_QUERY)) { return 0; @@ -964,7 +973,7 @@ coap_get_header_location_query(coap_packet_t *coap_pkt, const char **query) return coap_pkt->location_query_len; } int -coap_set_header_location_query(coap_packet_t *coap_pkt, const char *query) +coap_set_header_location_query(coap_message_t *coap_pkt, const char *query) { while(query[0] == '?') { ++query; @@ -978,7 +987,7 @@ coap_set_header_location_query(coap_packet_t *coap_pkt, const char *query) } /*---------------------------------------------------------------------------*/ int -coap_get_header_observe(coap_packet_t *coap_pkt, uint32_t *observe) +coap_get_header_observe(coap_message_t *coap_pkt, uint32_t *observe) { if(!coap_is_option(coap_pkt, COAP_OPTION_OBSERVE)) { return 0; @@ -987,7 +996,7 @@ coap_get_header_observe(coap_packet_t *coap_pkt, uint32_t *observe) return 1; } int -coap_set_header_observe(coap_packet_t *coap_pkt, uint32_t observe) +coap_set_header_observe(coap_message_t *coap_pkt, uint32_t observe) { coap_pkt->observe = observe; coap_set_option(coap_pkt, COAP_OPTION_OBSERVE); @@ -995,7 +1004,7 @@ coap_set_header_observe(coap_packet_t *coap_pkt, uint32_t observe) } /*---------------------------------------------------------------------------*/ int -coap_get_header_block2(coap_packet_t *coap_pkt, uint32_t *num, uint8_t *more, +coap_get_header_block2(coap_message_t *coap_pkt, uint32_t *num, uint8_t *more, uint16_t *size, uint32_t *offset) { if(!coap_is_option(coap_pkt, COAP_OPTION_BLOCK2)) { @@ -1017,7 +1026,7 @@ coap_get_header_block2(coap_packet_t *coap_pkt, uint32_t *num, uint8_t *more, return 1; } int -coap_set_header_block2(coap_packet_t *coap_pkt, uint32_t num, uint8_t more, +coap_set_header_block2(coap_message_t *coap_pkt, uint32_t num, uint8_t more, uint16_t size) { if(size < 16) { @@ -1038,7 +1047,7 @@ coap_set_header_block2(coap_packet_t *coap_pkt, uint32_t num, uint8_t more, } /*---------------------------------------------------------------------------*/ int -coap_get_header_block1(coap_packet_t *coap_pkt, uint32_t *num, uint8_t *more, +coap_get_header_block1(coap_message_t *coap_pkt, uint32_t *num, uint8_t *more, uint16_t *size, uint32_t *offset) { if(!coap_is_option(coap_pkt, COAP_OPTION_BLOCK1)) { @@ -1060,7 +1069,7 @@ coap_get_header_block1(coap_packet_t *coap_pkt, uint32_t *num, uint8_t *more, return 1; } int -coap_set_header_block1(coap_packet_t *coap_pkt, uint32_t num, uint8_t more, +coap_set_header_block1(coap_message_t *coap_pkt, uint32_t num, uint8_t more, uint16_t size) { if(size < 16) { @@ -1081,7 +1090,7 @@ coap_set_header_block1(coap_packet_t *coap_pkt, uint32_t num, uint8_t more, } /*---------------------------------------------------------------------------*/ int -coap_get_header_size2(coap_packet_t *coap_pkt, uint32_t *size) +coap_get_header_size2(coap_message_t *coap_pkt, uint32_t *size) { if(!coap_is_option(coap_pkt, COAP_OPTION_SIZE2)) { return 0; @@ -1090,7 +1099,7 @@ coap_get_header_size2(coap_packet_t *coap_pkt, uint32_t *size) return 1; } int -coap_set_header_size2(coap_packet_t *coap_pkt, uint32_t size) +coap_set_header_size2(coap_message_t *coap_pkt, uint32_t size) { coap_pkt->size2 = size; coap_set_option(coap_pkt, COAP_OPTION_SIZE2); @@ -1098,7 +1107,7 @@ coap_set_header_size2(coap_packet_t *coap_pkt, uint32_t size) } /*---------------------------------------------------------------------------*/ int -coap_get_header_size1(coap_packet_t *coap_pkt, uint32_t *size) +coap_get_header_size1(coap_message_t *coap_pkt, uint32_t *size) { if(!coap_is_option(coap_pkt, COAP_OPTION_SIZE1)) { return 0; @@ -1107,7 +1116,7 @@ coap_get_header_size1(coap_packet_t *coap_pkt, uint32_t *size) return 1; } int -coap_set_header_size1(coap_packet_t *coap_pkt, uint32_t size) +coap_set_header_size1(coap_message_t *coap_pkt, uint32_t size) { coap_pkt->size1 = size; coap_set_option(coap_pkt, COAP_OPTION_SIZE1); @@ -1115,7 +1124,7 @@ coap_set_header_size1(coap_packet_t *coap_pkt, uint32_t size) } /*---------------------------------------------------------------------------*/ int -coap_get_payload(coap_packet_t *coap_pkt, const uint8_t **payload) +coap_get_payload(coap_message_t *coap_pkt, const uint8_t **payload) { if(coap_pkt->payload) { *payload = coap_pkt->payload; @@ -1126,7 +1135,7 @@ coap_get_payload(coap_packet_t *coap_pkt, const uint8_t **payload) } } int -coap_set_payload(coap_packet_t *coap_pkt, const void *payload, size_t length) +coap_set_payload(coap_message_t *coap_pkt, const void *payload, size_t length) { coap_pkt->payload = (uint8_t *)payload; coap_pkt->payload_len = MIN(COAP_MAX_CHUNK_SIZE, length); @@ -1134,3 +1143,4 @@ coap_set_payload(coap_packet_t *coap_pkt, const void *payload, size_t length) return coap_pkt->payload_len; } /*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/net/app-layer/coap/coap.h b/os/net/app-layer/coap/coap.h index f93fcf7e9..4cc97a869 100644 --- a/os/net/app-layer/coap/coap.h +++ b/os/net/app-layer/coap/coap.h @@ -36,6 +36,14 @@ * Matthias Kovatsch */ +/** + * \defgroup coap CoAP + * @{ + * + * The Constrained Application Protocol - RFC 7252 + */ + + #ifndef COAP_H_ #define COAP_H_ @@ -44,6 +52,9 @@ #include "coap-conf.h" #include "coap-transport.h" +/** + * \brief The max size of the CoAP messages + */ #define COAP_MAX_PACKET_SIZE (COAP_MAX_HEADER_SIZE + COAP_MAX_CHUNK_SIZE) /* COAP_MAX_CHUNK_SIZE can be different from 2^x so we need to get next lower 2^x for COAP_MAX_BLOCK_SIZE */ @@ -62,7 +73,7 @@ /* parsed message struct */ typedef struct { - uint8_t *buffer; /* pointer to CoAP header / incoming packet buffer / memory to serialize packet */ + uint8_t *buffer; /* pointer to CoAP header / incoming message buffer / memory to serialize message */ uint8_t version; coap_message_type_t type; @@ -113,23 +124,23 @@ typedef struct { uint16_t payload_len; uint8_t *payload; -} coap_packet_t; +} coap_message_t; static inline int -coap_set_option(coap_packet_t *packet, unsigned int opt) +coap_set_option(coap_message_t *message, unsigned int opt) { if(opt > COAP_OPTION_SIZE1) { return 0; } - packet->options[opt / OPTION_MAP_SIZE] |= 1 << (opt % OPTION_MAP_SIZE); + message->options[opt / OPTION_MAP_SIZE] |= 1 << (opt % OPTION_MAP_SIZE); return 1; } static inline int -coap_is_option(const coap_packet_t *packet, unsigned int opt) +coap_is_option(const coap_message_t *message, unsigned int opt) { return (opt <= COAP_OPTION_SIZE1) && - (packet->options[opt / OPTION_MAP_SIZE] & (1 << (opt % OPTION_MAP_SIZE))) != 0; + (message->options[opt / OPTION_MAP_SIZE] & (1 << (opt % OPTION_MAP_SIZE))) != 0; } /* option format serialization */ @@ -180,110 +191,112 @@ extern const char *coap_error_message; void coap_init_connection(void); uint16_t coap_get_mid(void); -void coap_init_message(coap_packet_t *packet, coap_message_type_t type, +void coap_init_message(coap_message_t *message, coap_message_type_t type, uint8_t code, uint16_t mid); -size_t coap_serialize_message(coap_packet_t *packet, uint8_t *buffer); -coap_status_t coap_parse_message(coap_packet_t *request, uint8_t *data, +size_t coap_serialize_message(coap_message_t *message, uint8_t *buffer); +coap_status_t coap_parse_message(coap_message_t *request, uint8_t *data, uint16_t data_len); -int coap_get_query_variable(coap_packet_t *packet, const char *name, +int coap_get_query_variable(coap_message_t *message, const char *name, const char **output); -int coap_get_post_variable(coap_packet_t *packet, const char *name, +int coap_get_post_variable(coap_message_t *message, const char *name, const char **output); static inline coap_resource_flags_t -coap_get_method_type(coap_packet_t *packet) +coap_get_method_type(coap_message_t *message) { - return (coap_resource_flags_t)(1 << (packet->code - 1)); + return (coap_resource_flags_t)(1 << (message->code - 1)); } static inline const coap_endpoint_t * -coap_get_src_endpoint(coap_packet_t *request) +coap_get_src_endpoint(coap_message_t *request) { return request->src_ep; } static inline void -coap_set_src_endpoint(coap_packet_t *request, const coap_endpoint_t *ep) +coap_set_src_endpoint(coap_message_t *request, const coap_endpoint_t *ep) { request->src_ep = ep; } /*---------------------------------------------------------------------------*/ -int coap_set_status_code(coap_packet_t *packet, unsigned int code); +int coap_set_status_code(coap_message_t *message, unsigned int code); -int coap_set_token(coap_packet_t *packet, const uint8_t *token, +int coap_set_token(coap_message_t *message, const uint8_t *token, size_t token_len); -int coap_get_header_content_format(coap_packet_t *packet, unsigned int *format); -int coap_set_header_content_format(coap_packet_t *packet, unsigned int format); +int coap_get_header_content_format(coap_message_t *message, unsigned int *format); +int coap_set_header_content_format(coap_message_t *message, unsigned int format); -int coap_get_header_accept(coap_packet_t *packet, unsigned int *accept); -int coap_set_header_accept(coap_packet_t *packet, unsigned int accept); +int coap_get_header_accept(coap_message_t *message, unsigned int *accept); +int coap_set_header_accept(coap_message_t *message, unsigned int accept); -int coap_get_header_max_age(coap_packet_t *packet, uint32_t *age); -int coap_set_header_max_age(coap_packet_t *packet, uint32_t age); +int coap_get_header_max_age(coap_message_t *message, uint32_t *age); +int coap_set_header_max_age(coap_message_t *message, uint32_t age); -int coap_get_header_etag(coap_packet_t *packet, const uint8_t **etag); -int coap_set_header_etag(coap_packet_t *packet, const uint8_t *etag, +int coap_get_header_etag(coap_message_t *message, const uint8_t **etag); +int coap_set_header_etag(coap_message_t *message, const uint8_t *etag, size_t etag_len); -int coap_get_header_if_match(coap_packet_t *packet, const uint8_t **etag); -int coap_set_header_if_match(coap_packet_t *packet, const uint8_t *etag, +int coap_get_header_if_match(coap_message_t *message, const uint8_t **etag); +int coap_set_header_if_match(coap_message_t *message, const uint8_t *etag, size_t etag_len); -int coap_get_header_if_none_match(coap_packet_t *packet); -int coap_set_header_if_none_match(coap_packet_t *packet); +int coap_get_header_if_none_match(coap_message_t *message); +int coap_set_header_if_none_match(coap_message_t *message); /* in-place string might not be 0-terminated. */ -int coap_get_header_proxy_uri(coap_packet_t *packet, const char **uri); -int coap_set_header_proxy_uri(coap_packet_t *packet, const char *uri); +int coap_get_header_proxy_uri(coap_message_t *message, const char **uri); +int coap_set_header_proxy_uri(coap_message_t *message, const char *uri); /* in-place string might not be 0-terminated. */ -int coap_get_header_proxy_scheme(coap_packet_t *packet, const char **scheme); -int coap_set_header_proxy_scheme(coap_packet_t *packet, const char *scheme); +int coap_get_header_proxy_scheme(coap_message_t *message, const char **scheme); +int coap_set_header_proxy_scheme(coap_message_t *message, const char *scheme); /* in-place string might not be 0-terminated. */ -int coap_get_header_uri_host(coap_packet_t *packet, const char **host); -int coap_set_header_uri_host(coap_packet_t *packet, const char *host); +int coap_get_header_uri_host(coap_message_t *message, const char **host); +int coap_set_header_uri_host(coap_message_t *message, const char *host); /* in-place string might not be 0-terminated. */ -int coap_get_header_uri_path(coap_packet_t *packet, const char **path); -int coap_set_header_uri_path(coap_packet_t *packet, const char *path); +int coap_get_header_uri_path(coap_message_t *message, const char **path); +int coap_set_header_uri_path(coap_message_t *message, const char *path); /* in-place string might not be 0-terminated. */ -int coap_get_header_uri_query(coap_packet_t *packet, const char **query); -int coap_set_header_uri_query(coap_packet_t *packet, const char *query); +int coap_get_header_uri_query(coap_message_t *message, const char **query); +int coap_set_header_uri_query(coap_message_t *message, const char *query); /* in-place string might not be 0-terminated. */ -int coap_get_header_location_path(coap_packet_t *packet, const char **path); +int coap_get_header_location_path(coap_message_t *message, const char **path); /* also splits optional query into Location-Query option. */ -int coap_set_header_location_path(coap_packet_t *packet, const char *path); +int coap_set_header_location_path(coap_message_t *message, const char *path); /* in-place string might not be 0-terminated. */ -int coap_get_header_location_query(coap_packet_t *packet, const char **query); -int coap_set_header_location_query(coap_packet_t *packet, const char *query); +int coap_get_header_location_query(coap_message_t *message, const char **query); +int coap_set_header_location_query(coap_message_t *message, const char *query); -int coap_get_header_observe(coap_packet_t *packet, uint32_t *observe); -int coap_set_header_observe(coap_packet_t *packet, uint32_t observe); +int coap_get_header_observe(coap_message_t *message, uint32_t *observe); +int coap_set_header_observe(coap_message_t *message, uint32_t observe); -int coap_get_header_block2(coap_packet_t *packet, uint32_t *num, uint8_t *more, +int coap_get_header_block2(coap_message_t *message, uint32_t *num, uint8_t *more, uint16_t *size, uint32_t *offset); -int coap_set_header_block2(coap_packet_t *packet, uint32_t num, uint8_t more, +int coap_set_header_block2(coap_message_t *message, uint32_t num, uint8_t more, uint16_t size); -int coap_get_header_block1(coap_packet_t *packet, uint32_t *num, uint8_t *more, +int coap_get_header_block1(coap_message_t *message, uint32_t *num, uint8_t *more, uint16_t *size, uint32_t *offset); -int coap_set_header_block1(coap_packet_t *packet, uint32_t num, uint8_t more, +int coap_set_header_block1(coap_message_t *message, uint32_t num, uint8_t more, uint16_t size); -int coap_get_header_size2(coap_packet_t *packet, uint32_t *size); -int coap_set_header_size2(coap_packet_t *packet, uint32_t size); +int coap_get_header_size2(coap_message_t *message, uint32_t *size); +int coap_set_header_size2(coap_message_t *message, uint32_t size); -int coap_get_header_size1(coap_packet_t *packet, uint32_t *size); -int coap_set_header_size1(coap_packet_t *packet, uint32_t size); +int coap_get_header_size1(coap_message_t *message, uint32_t *size); +int coap_set_header_size1(coap_message_t *message, uint32_t size); -int coap_get_payload(coap_packet_t *packet, const uint8_t **payload); -int coap_set_payload(coap_packet_t *packet, const void *payload, size_t length); +int coap_get_payload(coap_message_t *message, const uint8_t **payload); +int coap_set_payload(coap_message_t *message, const void *payload, size_t length); #endif /* COAP_H_ */ + +/** @} */ diff --git a/os/services/lwm2m/lwm2m-engine.c b/os/services/lwm2m/lwm2m-engine.c index c9f85c4bc..1413d803a 100644 --- a/os/services/lwm2m/lwm2m-engine.c +++ b/os/services/lwm2m/lwm2m-engine.c @@ -120,8 +120,8 @@ static uint64_t lwm2m_buf_lock_timeout = 0; static lwm2m_write_opaque_callback current_opaque_callback; static int current_opaque_offset = 0; -static coap_handler_status_t lwm2m_handler_callback(coap_packet_t *request, - coap_packet_t *response, +static coap_handler_status_t lwm2m_handler_callback(coap_message_t *request, + coap_message_t *response, uint8_t *buffer, uint16_t buffer_size, int32_t *offset); @@ -350,7 +350,7 @@ parse_path(const char *path, int path_len, /*--------------------------------------------------------------------------*/ static int lwm2m_engine_parse_context(const char *path, int path_len, - coap_packet_t *request, coap_packet_t *response, + coap_message_t *request, coap_message_t *response, uint8_t *outbuf, size_t outsize, lwm2m_context_t *context) { @@ -470,7 +470,7 @@ lwm2m_engine_set_rd_data(lwm2m_buffer_t *outbuf, int block) } if(instance == NULL && object == NULL && lwm2m_buf.len <= maxsize) { - /* Data generation is done. No more packets are needed after this. */ + /* Data generation is done. No more messages are needed after this. */ break; } } @@ -1296,7 +1296,7 @@ next_object_instance(const lwm2m_context_t *context, lwm2m_object_t *object, } /*---------------------------------------------------------------------------*/ static coap_handler_status_t -lwm2m_handler_callback(coap_packet_t *request, coap_packet_t *response, +lwm2m_handler_callback(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t buffer_size, int32_t *offset) { const char *url; @@ -1568,7 +1568,7 @@ lwm2m_handler_callback(coap_packet_t *request, coap_packet_t *response, if(context.writer_flags & WRITER_HAS_MORE) { *offset = context.offset; } else { - /* this signals to CoAP that there is no more CoAP packets to expect */ + /* this signals to CoAP that there is no more CoAP messages to expect */ *offset = -1; } } diff --git a/os/services/lwm2m/lwm2m-object.h b/os/services/lwm2m/lwm2m-object.h index cd0eb0f5d..d466a9e70 100644 --- a/os/services/lwm2m/lwm2m-object.h +++ b/os/services/lwm2m/lwm2m-object.h @@ -180,8 +180,8 @@ typedef struct lwm2m_context { uint8_t level; /* 0/1/2/3 = 3 = resource */ lwm2m_operation_t operation; - coap_packet_t *request; - coap_packet_t *response; + coap_message_t *request; + coap_message_t *response; unsigned int content_type; lwm2m_buffer_t *outbuf; diff --git a/os/services/lwm2m/lwm2m-rd-client.c b/os/services/lwm2m/lwm2m-rd-client.c index 25400025e..8118a9cb8 100644 --- a/os/services/lwm2m/lwm2m-rd-client.c +++ b/os/services/lwm2m/lwm2m-rd-client.c @@ -92,7 +92,7 @@ static struct lwm2m_session_info session_info; static coap_request_state_t rd_request_state; -static coap_packet_t request[1]; /* This way the packet can be treated as pointer as usual. */ +static coap_message_t request[1]; /* This way the message can be treated as pointer as usual. */ /* The states for the RD client state machine */ /* When node is unregistered it ends up in UNREGISTERED @@ -135,7 +135,7 @@ static void check_periodic_observations(); static void update_callback(coap_request_state_t *state); static int -set_rd_data(coap_packet_t *request) +set_rd_data(coap_message_t *request) { lwm2m_buffer_t outbuf; @@ -157,7 +157,7 @@ set_rd_data(coap_packet_t *request) } /*---------------------------------------------------------------------------*/ static void -prepare_update(coap_packet_t *request, int triggered) { +prepare_update(coap_message_t *request, int triggered) { coap_init_message(request, COAP_TYPE_CON, COAP_POST, 0); coap_set_header_uri_path(request, session_info.assigned_ep); From 6c729f50d64a5a4c142c0be523db5b31c71f6200 Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Wed, 29 Nov 2017 22:44:41 +0100 Subject: [PATCH 16/51] added lwm2m-ipso test --- os/net/app-layer/coap/coap-uip.c | 2 + os/services/ipso-objects/ipso-leds-control.c | 2 +- os/services/lwm2m/lwm2m-rd-client.c | 3 + tests/18-coap-lwm2m/06-lwm2m-ipso-test.sh | 60 +++++++++++++++++ tests/18-coap-lwm2m/Makefile | 1 + tests/18-coap-lwm2m/pytests/test-device.py | 71 ++++++++++++++++++++ 6 files changed, 138 insertions(+), 1 deletion(-) create mode 100755 tests/18-coap-lwm2m/06-lwm2m-ipso-test.sh create mode 100644 tests/18-coap-lwm2m/Makefile create mode 100644 tests/18-coap-lwm2m/pytests/test-device.py diff --git a/os/net/app-layer/coap/coap-uip.c b/os/net/app-layer/coap/coap-uip.c index 70e720063..5ea982d93 100644 --- a/os/net/app-layer/coap/coap-uip.c +++ b/os/net/app-layer/coap/coap-uip.c @@ -216,9 +216,11 @@ int coap_endpoint_is_connected(const coap_endpoint_t *ep) { #if UIP_CONF_IPV6_RPL +#ifndef CONTIKI_TARGET_NATIVE if(rpl_get_any_dag() == NULL) { return 0; } +#endif #endif /* UIP_CONF_IPV6_RPL */ #ifdef WITH_DTLS diff --git a/os/services/ipso-objects/ipso-leds-control.c b/os/services/ipso-objects/ipso-leds-control.c index 74e599c14..8cfbdac41 100644 --- a/os/services/ipso-objects/ipso-leds-control.c +++ b/os/services/ipso-objects/ipso-leds-control.c @@ -72,11 +72,11 @@ static led_state_t leds_controls[LEDS_CONTROL_NUMBER]; static lwm2m_status_t set_value(ipso_control_t *control, uint8_t value) { +#if PLATFORM_HAS_LEDS led_state_t *state; state = (led_state_t *)control; -#if PLATFORM_HAS_LEDS if(value) { leds_on(state->led_value); } else { diff --git a/os/services/lwm2m/lwm2m-rd-client.c b/os/services/lwm2m/lwm2m-rd-client.c index 8118a9cb8..36d934323 100644 --- a/os/services/lwm2m/lwm2m-rd-client.c +++ b/os/services/lwm2m/lwm2m-rd-client.c @@ -176,9 +176,12 @@ static int has_network_access(void) { #if UIP_CONF_IPV6_RPL +/* NATIVE PLATFORM is not really running RPL */ +#ifndef CONTIKI_TARGET_NATIVE if(rpl_get_any_dag() == NULL) { return 0; } +#endif #endif /* UIP_CONF_IPV6_RPL */ return 1; } diff --git a/tests/18-coap-lwm2m/06-lwm2m-ipso-test.sh b/tests/18-coap-lwm2m/06-lwm2m-ipso-test.sh new file mode 100755 index 000000000..e3a4bfa45 --- /dev/null +++ b/tests/18-coap-lwm2m/06-lwm2m-ipso-test.sh @@ -0,0 +1,60 @@ +#!/bin/bash + +# Contiki directory +CONTIKI=$1 +# Test basename +BASENAME=06-lwm2m-test + +IPADDR=fd00::302:304:506:708 + +echo "Enabling IPv6" +sudo sysctl -w net.ipv6.conf.all.disable_ipv6=0 + +# Starting Contiki-NG native node +echo "Starting native node - lwm2m/ipso objects" +make -C $CONTIKI/examples/ipso-objects/example-ipso-objects > make.log 2> make.err +sudo $CONTIKI/examples/ipso-objects/example-ipso-objects.native > node.log 2> node.err & +CPID=$! +sleep 10 + +echo "Downloading leshan" +wget -nc https://joakimeriksson.github.io/resources/leshan-server-demo-1.0.0-SNAPSHOT-jar-with-dependencies.jar +echo "Starting leshan server" +java -jar leshan-server-demo-1.0.0-SNAPSHOT-jar-with-dependencies.jar >leshan.log 2>leshan.err & +LESHID=$! +sleep 50 + +echo "Closing native node" +sleep 1 +pgrep ipso | sudo xargs kill -9 + +echo "Closing leshan" +sleep 1 +pgrep java | sudo xargs kill -9 + + +if grep -q 'OK' leshan.err ; then + cp leshan.err $BASENAME.testlog; + printf "%-32s TEST OK\n" "$BASENAME" | tee $BASENAME.testlog; +else + echo "==== make.log ====" ; cat make.log; + echo "==== make.err ====" ; cat make.err; + echo "==== node.log ====" ; cat node.log; + echo "==== node.err ====" ; cat node.err; + echo "==== leshan.log ====" ; cat leshan.log; + echo "==== leshan.err ====" ; cat leshan.err; + echo "==== $BASENAME.log ====" ; cat $BASENAME.log; + + printf "%-32s TEST FAIL\n" "$BASENAME" | tee $BASENAME.testlog; +fi + +rm make.log +rm make.err +rm node.log +rm node.err +rm leshan.log +rm leshan.err + +# We do not want Make to stop -> Return 0 +# The Makefile will check if a log contains FAIL at the end +exit 0 diff --git a/tests/18-coap-lwm2m/Makefile b/tests/18-coap-lwm2m/Makefile new file mode 100644 index 000000000..c46e5271d --- /dev/null +++ b/tests/18-coap-lwm2m/Makefile @@ -0,0 +1 @@ +include ../Makefile.script-test diff --git a/tests/18-coap-lwm2m/pytests/test-device.py b/tests/18-coap-lwm2m/pytests/test-device.py new file mode 100644 index 000000000..84147d2f5 --- /dev/null +++ b/tests/18-coap-lwm2m/pytests/test-device.py @@ -0,0 +1,71 @@ +import unittest, array, time + +class TestDevice(unittest.TestCase): + global client + + def test_available_power_sources(self): + r = client.readTLV("3/0/6") + self.assertEqual(r.getCode().getName(), "CONTENT") + + def test_device_read_JSON(self): + r = client.readJSON("3/0/1") + self.assertEqual(r.getCode().getName(), "CONTENT") + + def test_manufacturer_read(self): + r = client.read("3/0/0") + self.assertEqual(r.getCode().getName(), "CONTENT") + + def test_manufacturer_readJSON(self): + r = client.readJSON("3/0/0") + self.assertEqual(r.getCode().getName(), "CONTENT") + + def test_manufacturer_write(self): + r = client.write(3, 0, 0, "abc"); + self.assertEqual(r.getCode().getName(), "METHOD_NOT_ALLOWED") + + def test_manufacturer_execute(self): + r = client.execute("3/0/0") + self.assertEqual(r.getCode().getName(), "METHOD_NOT_ALLOWED") + + def test_reboot_read(self): + r = client.read("3/0/4") + self.assertEqual(r.getCode().getName(), "METHOD_NOT_ALLOWED") + +# def test_opaque_read(self): +# r = client.readTLV("4711/0/11000") +# v = r.getContent().getValue(); + #print "Result:", v + #print "Type: ", type(v) + #print "Type code: ", v.typecode + #print "Data size: ", len(v) +# self.assertEqual(len(v), 900) + +# def test_object_with_opaque_read(self): +# r = client.readTLV("4711/0/") +# self.assertEqual(r.getCode().getName(), "CONTENT") + + def test_device_time_write(self): + r = client.write(3,0,13,1000) + self.assertEqual(r.getCode().getName(), "CHANGED") + time.sleep(4.9) + r = client.read("3/0/13") + v = r.getContent().getValue().getTime() + self.assertTrue(v > 1000) + print "Time: ", v + + + +print "----------------------------------------" +print "LWM2M Tester - name of client: ", client.endpoint +print "----------------------------------------" + +r = client.read("3/0/0"); +print "Code:", r.getCode(), r.getCode().getName() == "CONTENT" +print "Objects: ", client.links +print "Read Manufacturer => ", client.read("3/0/0") +print "Read Device => ", client.readTLV("3/0/") +print "Write Manufacturer => ", client.write(3, 0, 0, "abc") +print "Exe Manufacturer => ", client.execute("3/0/0") + +suite = unittest.TestLoader().loadTestsFromTestCase(TestDevice) +unittest.TextTestRunner(verbosity=2).run(suite) From 68bb8cd037ead6b80223ab4ba42029396833e284 Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Wed, 29 Nov 2017 22:53:55 +0100 Subject: [PATCH 17/51] added travis config --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 7591dd772..23b972a13 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,6 +26,7 @@ env: - TEST_NAME='rpl-lite' - TEST_NAME='rpl-classic' - TEST_NAME='tun-rpl-br' + - TEST_NAME='coap-lwm2m' - TEST_NAME='simulation-base' - TEST_NAME='ieee802154' - TEST_NAME='compile-nxp-ports' From bbe2836beeebdf52751b523c2a67bac09f074fe3 Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Wed, 29 Nov 2017 23:02:45 +0100 Subject: [PATCH 18/51] fixed compilation makefile for NFR52DK compile tests --- tests/02-compile-arm-ports-01/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/02-compile-arm-ports-01/Makefile b/tests/02-compile-arm-ports-01/Makefile index b54acc303..854d138b1 100644 --- a/tests/02-compile-arm-ports-01/Makefile +++ b/tests/02-compile-arm-ports-01/Makefile @@ -30,7 +30,7 @@ hello-world/cc2538dk \ rpl-border-router/cc2538dk \ hello-world/nrf52dk \ platform-specific/nrf52dk/coap-demo/nrf52dk:coap-server \ -platform-specific/nrf52dk/coap-demo/nrf52dk:coap-client:SERVER_IPV6_ADDR=ffff \ +platform-specific/nrf52dk/coap-demo/nrf52dk:coap-client:SERVER_IPV6_EP=ffff \ platform-specific/nrf52dk/mqtt-demo/nrf52dk \ platform-specific/nrf52dk/blink-hello/nrf52dk \ platform-specific/nrf52dk/timer-test/nrf52dk \ From 63643042e1c7abbd6c2a7e33db8a71afda4386bd Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Wed, 29 Nov 2017 23:11:33 +0100 Subject: [PATCH 19/51] fixed compilation of ipso objects in test script --- tests/18-coap-lwm2m/06-lwm2m-ipso-test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/18-coap-lwm2m/06-lwm2m-ipso-test.sh b/tests/18-coap-lwm2m/06-lwm2m-ipso-test.sh index e3a4bfa45..537d7a15e 100755 --- a/tests/18-coap-lwm2m/06-lwm2m-ipso-test.sh +++ b/tests/18-coap-lwm2m/06-lwm2m-ipso-test.sh @@ -12,7 +12,7 @@ sudo sysctl -w net.ipv6.conf.all.disable_ipv6=0 # Starting Contiki-NG native node echo "Starting native node - lwm2m/ipso objects" -make -C $CONTIKI/examples/ipso-objects/example-ipso-objects > make.log 2> make.err +make -C $CONTIKI/examples/ipso-objects > make.log 2> make.err sudo $CONTIKI/examples/ipso-objects/example-ipso-objects.native > node.log 2> node.err & CPID=$! sleep 10 From 032bf31a1d0d05c7f110f8a6fe49a8ead1678c1d Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Thu, 30 Nov 2017 09:53:09 +0100 Subject: [PATCH 20/51] removed some not needed test printouts for lwm2m regression test --- tests/18-coap-lwm2m/pytests/test-device.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/18-coap-lwm2m/pytests/test-device.py b/tests/18-coap-lwm2m/pytests/test-device.py index 84147d2f5..9c441e4a0 100644 --- a/tests/18-coap-lwm2m/pytests/test-device.py +++ b/tests/18-coap-lwm2m/pytests/test-device.py @@ -64,8 +64,6 @@ print "Code:", r.getCode(), r.getCode().getName() == "CONTENT" print "Objects: ", client.links print "Read Manufacturer => ", client.read("3/0/0") print "Read Device => ", client.readTLV("3/0/") -print "Write Manufacturer => ", client.write(3, 0, 0, "abc") -print "Exe Manufacturer => ", client.execute("3/0/0") suite = unittest.TestLoader().loadTestsFromTestCase(TestDevice) unittest.TextTestRunner(verbosity=2).run(suite) From 0731c4f158d0a1fc2148bce29f2c1de884e40b7f Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Wed, 29 Nov 2017 00:32:48 +0100 Subject: [PATCH 21/51] Added functions in uiplib to print a IP address to string and normal output. Changed uip-debug to use the uiplib functions instead of its own print functions. --- os/net/ipv6/uip-debug.c | 90 --------------------------- os/net/ipv6/uip-debug.h | 11 ++-- os/net/ipv6/uiplib.c | 133 +++++++++++++++++++++++++++++++++++++--- os/net/ipv6/uiplib.h | 24 ++++++++ 4 files changed, 155 insertions(+), 103 deletions(-) delete mode 100755 os/net/ipv6/uip-debug.c diff --git a/os/net/ipv6/uip-debug.c b/os/net/ipv6/uip-debug.c deleted file mode 100755 index f83f0ee5b..000000000 --- a/os/net/ipv6/uip-debug.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2010, Swedish Institute of Computer Science. - * 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. - * - */ - -/** - * \file - * A set of debugging tools for the IP stack - * \author - * Nicolas Tsiftes - * Niclas Finne - * Joakim Eriksson - */ - -#include "net/ipv6/uip-debug.h" -#include "net/ipv6/ip64-addr.h" - -/*---------------------------------------------------------------------------*/ -void -uip_debug_ipaddr_print(const uip_ipaddr_t *addr) -{ - uint16_t a; - unsigned int i; - int f; - - if(addr == NULL) { - PRINTA("(NULL IP addr)"); - return; - } - - if(ip64_addr_is_ipv4_mapped_addr(addr)) { - /* - * Printing IPv4-mapped addresses is done according to RFC 4291 [1] - * - * "An alternative form that is sometimes more - * convenient when dealing with a mixed environment - * of IPv4 and IPv6 nodes is x:x:x:x:x:x:d.d.d.d, - * where the 'x's are the hexadecimal values of the - * six high-order 16-bit pieces of the address, and - * the 'd's are the decimal values of the four - * low-order 8-bit pieces of the address (standard - * IPv4 representation)." - * - * [1] https://tools.ietf.org/html/rfc4291#page-4 - */ - PRINTA("::FFFF:%u.%u.%u.%u", addr->u8[12], addr->u8[13], addr->u8[14], addr->u8[15]); - } else { - for(i = 0, f = 0; i < sizeof(uip_ipaddr_t); i += 2) { - a = (addr->u8[i] << 8) + addr->u8[i + 1]; - if(a == 0 && f >= 0) { - if(f++ == 0) { - PRINTA("::"); - } - } else { - if(f > 0) { - f = -1; - } else if(i > 0) { - PRINTA(":"); - } - PRINTA("%x", a); - } - } - } -} -/*---------------------------------------------------------------------------*/ diff --git a/os/net/ipv6/uip-debug.h b/os/net/ipv6/uip-debug.h index 267a36aca..6ebbf0aaa 100644 --- a/os/net/ipv6/uip-debug.h +++ b/os/net/ipv6/uip-debug.h @@ -43,13 +43,16 @@ #define UIP_DEBUG_H #include "net/net-debug.h" -#include "net/ipv6/uip.h" -#include +#include "net/ipv6/uiplib.h" -void uip_debug_ipaddr_print(const uip_ipaddr_t *addr); +static inline void +uip_debug_ipaddr_print(const uip_ipaddr_t *addr) +{ + uiplib_ipaddr_print(addr); +} #if (DEBUG) & DEBUG_PRINT -#define PRINT6ADDR(addr) uip_debug_ipaddr_print(addr) +#define PRINT6ADDR(addr) uiplib_ipaddr_print(addr) #else #define PRINT6ADDR(addr) #endif /* (DEBUG) & DEBUG_PRINT */ diff --git a/os/net/ipv6/uiplib.c b/os/net/ipv6/uiplib.c index 4cc9179eb..693626c87 100644 --- a/os/net/ipv6/uiplib.c +++ b/os/net/ipv6/uiplib.c @@ -32,15 +32,27 @@ * */ +/** + * \file + * Various uIP library functions. + * \author + * Nicolas Tsiftes + * Niclas Finne + * Joakim Eriksson + */ #include "net/ipv6/uip.h" #include "net/ipv6/uiplib.h" +#include "net/ipv6/ip64-addr.h" #include +#include -#define DEBUG DEBUG_NONE -#include "net/ipv6/uip-debug.h" +/* Log configuration */ +#include "sys/log.h" +#define LOG_MODULE "uiplib" +#define LOG_LEVEL LOG_LEVEL_NONE -/*-----------------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ #if NETSTACK_CONF_WITH_IPV6 int uiplib_ip6addrconv(const char *addrstr, uip_ip6addr_t *ipaddr) @@ -81,19 +93,19 @@ uiplib_ip6addrconv(const char *addrstr, uip_ip6addr_t *ipaddr) } else if(c >= 'A' && c <= 'F') { tmp = c - 'A' + 10; } else { - PRINTF("uiplib: illegal char: '%c'\n", c); + LOG_ERR("illegal char: '%c'\n", c); return 0; } value = (value << 4) + (tmp & 0xf); } } if(c != '\0' && c != ']' && c != '/') { - PRINTF("uiplib: too large address\n"); + LOG_ERR("too large address\n"); return 0; } if(len < sizeof(uip_ip6addr_t)) { if(zero < 0) { - PRINTF("uiplib: too short address\n"); + LOG_ERR("too short address\n"); return 0; } memmove(&ipaddr->u8[zero + sizeof(uip_ip6addr_t) - len], @@ -104,7 +116,7 @@ uiplib_ip6addrconv(const char *addrstr, uip_ip6addr_t *ipaddr) return 1; } #endif /* NETSTACK_CONF_WITH_IPV6 */ -/*-----------------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /* Parse a IPv4-address from a string. Returns the number of characters read * for the address. */ int @@ -138,6 +150,109 @@ uiplib_ip4addrconv(const char *addrstr, uip_ip4addr_t *ipaddr) } while(c != '.' && c != 0 && c != ' '); } - return charsread-1; + return charsread - 1; } -/*-----------------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +void +uiplib_ipaddr_print(const uip_ipaddr_t *addr) +{ + uint16_t a; + unsigned int i; + int f; + + if(addr == NULL) { + printf("(NULL IP addr)"); + return; + } + + if(ip64_addr_is_ipv4_mapped_addr(addr)) { + /* + * Printing IPv4-mapped addresses is done according to RFC 4291 [1] + * + * "An alternative form that is sometimes more + * convenient when dealing with a mixed environment + * of IPv4 and IPv6 nodes is x:x:x:x:x:x:d.d.d.d, + * where the 'x's are the hexadecimal values of the + * six high-order 16-bit pieces of the address, and + * the 'd's are the decimal values of the four + * low-order 8-bit pieces of the address (standard + * IPv4 representation)." + * + * [1] https://tools.ietf.org/html/rfc4291#page-4 + */ + printf("::FFFF:%u.%u.%u.%u", addr->u8[12], addr->u8[13], addr->u8[14], addr->u8[15]); + } else { + for(i = 0, f = 0; i < sizeof(uip_ipaddr_t); i += 2) { + a = (addr->u8[i] << 8) + addr->u8[i + 1]; + if(a == 0 && f >= 0) { + if(f++ == 0) { + printf("::"); + } + } else { + if(f > 0) { + f = -1; + } else if(i > 0) { + printf(":"); + } + printf("%x", a); + } + } + } +} +/*---------------------------------------------------------------------------*/ +int +uiplib_ipaddr_snprint(char *buf, size_t size, const uip_ipaddr_t *addr) +{ + uint16_t a; + unsigned int i; + int f, n; + + if(size == 0) { + return 0; + } + + if(addr == NULL) { + n = snprintf(buf, size - 1, "(NULL IP addr)"); + + } else if(ip64_addr_is_ipv4_mapped_addr(addr)) { + /* + * Printing IPv4-mapped addresses is done according to RFC 4291 [1] + * + * "An alternative form that is sometimes more + * convenient when dealing with a mixed environment + * of IPv4 and IPv6 nodes is x:x:x:x:x:x:d.d.d.d, + * where the 'x's are the hexadecimal values of the + * six high-order 16-bit pieces of the address, and + * the 'd's are the decimal values of the four + * low-order 8-bit pieces of the address (standard + * IPv4 representation)." + * + * [1] https://tools.ietf.org/html/rfc4291#page-4 + */ + n = snprintf(buf, size - 1, "::FFFF:%u.%u.%u.%u", addr->u8[12], + addr->u8[13], addr->u8[14], addr->u8[15]); + } else { + for(n = 0, i = 0, f = 0; i < sizeof(uip_ipaddr_t) && n < size - 1; i += 2) { + a = (addr->u8[i] << 8) + addr->u8[i + 1]; + if(a == 0 && f >= 0) { + if(f++ == 0) { + buf[n++] = ':'; + buf[n++] = ':'; + } + } else { + if(f > 0) { + f = -1; + } else if(i > 0) { + buf[n++] = ':'; + } + n += snprintf(&buf[n], size - n - 1, "%x", a); + } + } + } + + if(n >= size - 1) { + buf[size - 1] = '\0'; + } + return n; +} +/*---------------------------------------------------------------------------*/ diff --git a/os/net/ipv6/uiplib.h b/os/net/ipv6/uiplib.h index aa23435e0..6b0d4ac84 100644 --- a/os/net/ipv6/uiplib.h +++ b/os/net/ipv6/uiplib.h @@ -77,4 +77,28 @@ CCIF int uiplib_ip4addrconv(const char *addrstr, uip_ip4addr_t *addr); CCIF int uiplib_ip6addrconv(const char *addrstr, uip_ip6addr_t *addr); /** @} */ +/** + * \addtogroup uiplib + * @{ + */ + +/** + * Print an IP address using printf(). + * + * \param addr A pointer to a uip_ipaddr_t that will be printed with printf(). + */ +void uiplib_ipaddr_print(const uip_ipaddr_t *addr); + +/** + * Write at most size - 1 characters of the IP address to the output string. + * The output is always null-terminated, unless size is 0. + * + * \param buffer A pointer to an output string with at least size bytes. + * \param size The max number of characters to write to the output string. + * \param addr A pointer to a uip_ipaddr_t that will be printed with printf(). + */ +int uiplib_ipaddr_snprint(char *buffer, size_t size, const uip_ipaddr_t *addr); + +/** @} */ + #endif /* UIPLIB_H_ */ From 21d464952b698c6f7f57b22d10e6146ed0ca5a8a Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Thu, 30 Nov 2017 18:52:03 +0100 Subject: [PATCH 22/51] Added CoAP runtime log level to the logging module --- examples/libs/logging/project-conf.h | 1 + os/sys/log-conf.h | 4 ++++ os/sys/log.c | 2 ++ os/sys/log.h | 2 ++ tools/viewconf.c | 1 + 5 files changed, 10 insertions(+) diff --git a/examples/libs/logging/project-conf.h b/examples/libs/logging/project-conf.h index f42f08723..2a39f6d5f 100644 --- a/examples/libs/logging/project-conf.h +++ b/examples/libs/logging/project-conf.h @@ -45,6 +45,7 @@ #define LOG_CONF_LEVEL_TCPIP LOG_LEVEL_DBG #define LOG_CONF_LEVEL_MAC LOG_LEVEL_DBG #define LOG_CONF_LEVEL_FRAMER LOG_LEVEL_DBG +#define LOG_CONF_LEVEL_COAP LOG_LEVEL_DBG #define LOG_CONF_LEVEL_6TOP LOG_LEVEL_DBG /* Enable cooja annotations */ diff --git a/os/sys/log-conf.h b/os/sys/log-conf.h index d52765c31..1b3f26d03 100644 --- a/os/sys/log-conf.h +++ b/os/sys/log-conf.h @@ -133,6 +133,10 @@ #define LOG_CONF_LEVEL_6TOP LOG_LEVEL_NONE #endif /* LOG_CONF_LEVEL_6TOP */ +#ifndef LOG_CONF_LEVEL_COAP +#define LOG_CONF_LEVEL_COAP LOG_LEVEL_NONE +#endif /* LOG_CONF_LEVEL_COAP */ + #ifndef LOG_CONF_LEVEL_MAIN #define LOG_CONF_LEVEL_MAIN LOG_LEVEL_INFO #endif /* LOG_CONF_LEVEL_MAIN */ diff --git a/os/sys/log.c b/os/sys/log.c index d4b21639d..c2d8c8c5e 100644 --- a/os/sys/log.c +++ b/os/sys/log.c @@ -59,6 +59,7 @@ int curr_log_level_nullnet = LOG_CONF_LEVEL_NULLNET; int curr_log_level_mac = LOG_CONF_LEVEL_MAC; int curr_log_level_framer = LOG_CONF_LEVEL_FRAMER; int curr_log_level_6top = LOG_CONF_LEVEL_6TOP; +int curr_log_level_coap = LOG_CONF_LEVEL_COAP; int curr_log_level_main = LOG_CONF_LEVEL_MAIN; struct log_module all_modules[] = { @@ -70,6 +71,7 @@ struct log_module all_modules[] = { {"mac", &curr_log_level_mac, LOG_CONF_LEVEL_MAC}, {"framer", &curr_log_level_framer, LOG_CONF_LEVEL_FRAMER}, {"6top", &curr_log_level_6top, LOG_CONF_LEVEL_6TOP}, + {"coap", &curr_log_level_coap, LOG_CONF_LEVEL_COAP}, {"main", &curr_log_level_main, LOG_CONF_LEVEL_MAIN}, {NULL, NULL, 0}, }; diff --git a/os/sys/log.h b/os/sys/log.h index b0624bbc7..49ffd3ba6 100644 --- a/os/sys/log.h +++ b/os/sys/log.h @@ -81,6 +81,7 @@ extern int curr_log_level_nullnet; extern int curr_log_level_mac; extern int curr_log_level_framer; extern int curr_log_level_6top; +extern int curr_log_level_coap; extern int curr_log_level_main; extern struct log_module all_modules[]; @@ -93,6 +94,7 @@ extern struct log_module all_modules[]; #define LOG_LEVEL_MAC MIN((LOG_CONF_LEVEL_MAC), curr_log_level_mac) #define LOG_LEVEL_FRAMER MIN((LOG_CONF_LEVEL_FRAMER), curr_log_level_framer) #define LOG_LEVEL_6TOP MIN((LOG_CONF_LEVEL_6TOP), curr_log_level_6top) +#define LOG_LEVEL_COAP MIN((LOG_CONF_LEVEL_COAP), curr_log_level_coap) #define LOG_LEVEL_MAIN MIN((LOG_CONF_LEVEL_MAIN), curr_log_level_main) /* Main log function */ diff --git a/tools/viewconf.c b/tools/viewconf.c index f742b66a0..610ec0f9f 100644 --- a/tools/viewconf.c +++ b/tools/viewconf.c @@ -150,4 +150,5 @@ ##### "LOG_CONF_LEVEL_MAC": ____________________ == LOG_CONF_LEVEL_MAC ##### "LOG_CONF_LEVEL_FRAMER": _________________ == LOG_CONF_LEVEL_FRAMER ##### "LOG_CONF_LEVEL_6TOP": ___________________ == LOG_CONF_LEVEL_6TOP +##### "LOG_CONF_LEVEL_COAP": ___________________ == LOG_CONF_LEVEL_COAP ##### "LOG_CONF_LEVEL_MAIN": ___________________ == LOG_CONF_LEVEL_MAIN From 4c56184a9bd171ad03ed3200efd5d9154ac30394 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Fri, 1 Dec 2017 00:41:58 +0100 Subject: [PATCH 23/51] Updated CoAP to use the logging module --- examples/lwm2m/standalone/coap-hex/coap-hex.c | 92 ++++---- .../lwm2m/standalone/coap-ipv4/coap-ipv4.c | 167 +++++++++------ examples/lwm2m/standalone/coap-log-conf.h | 111 ++++++++++ examples/lwm2m/standalone/contiki.h | 2 + os/net/app-layer/coap/coap-block1.c | 23 +- os/net/app-layer/coap/coap-blocking-api.c | 25 ++- os/net/app-layer/coap/coap-callback-api.c | 31 ++- os/net/app-layer/coap/coap-endpoint.h | 3 + os/net/app-layer/coap/coap-engine.c | 82 ++++--- os/net/app-layer/coap/coap-log.c | 54 +++++ os/net/app-layer/coap/coap-log.h | 78 +++++++ os/net/app-layer/coap/coap-observe-client.c | 56 +++-- os/net/app-layer/coap/coap-observe.c | 49 ++--- .../app-layer/coap/coap-res-well-known-core.c | 41 ++-- os/net/app-layer/coap/coap-separate.c | 20 +- os/net/app-layer/coap/coap-timer-default.c | 13 +- os/net/app-layer/coap/coap-timer.c | 20 +- os/net/app-layer/coap/coap-transactions.c | 35 ++- os/net/app-layer/coap/coap-uip.c | 201 +++++++++++------- os/net/app-layer/coap/coap.c | 197 ++++++++--------- os/net/app-layer/coap/coap.h | 20 +- 21 files changed, 805 insertions(+), 515 deletions(-) create mode 100644 examples/lwm2m/standalone/coap-log-conf.h create mode 100644 os/net/app-layer/coap/coap-log.c create mode 100644 os/net/app-layer/coap/coap-log.h diff --git a/examples/lwm2m/standalone/coap-hex/coap-hex.c b/examples/lwm2m/standalone/coap-hex/coap-hex.c index 7fba02ccf..d663d7e24 100644 --- a/examples/lwm2m/standalone/coap-hex/coap-hex.c +++ b/examples/lwm2m/standalone/coap-hex/coap-hex.c @@ -42,14 +42,10 @@ #include #include -#define DEBUG 0 -#if DEBUG -#define PRINTF(...) printf(__VA_ARGS__) -#define PRINTEP(ep) coap_endpoint_print(ep) -#else -#define PRINTF(...) -#define PRINTEP(ep) -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "coap-hex" +#define LOG_LEVEL LOG_LEVEL_COAP #ifdef WITH_DTLS #include "tinydtls.h" @@ -104,12 +100,32 @@ coap_endpoint_cmp(const coap_endpoint_t *e1, const coap_endpoint_t *e2) } /*---------------------------------------------------------------------------*/ void +coap_endpoint_log(const coap_endpoint_t *ep) +{ + LOG_OUTPUT("%u", ep->addr); +} +/*---------------------------------------------------------------------------*/ +void coap_endpoint_print(const coap_endpoint_t *ep) { printf("%u", ep->addr); } /*---------------------------------------------------------------------------*/ int +coap_endpoint_snprint(char *buf, size_t size, const coap_endpoint_t *ep) +{ + int n; + if(size == 0) { + return 0; + } + n = snprintf(buf, size - 1, "%u", ep->addr); + if(n >= size - 1) { + buf[size - 1] = '\0'; + } + return n; +} +/*---------------------------------------------------------------------------*/ +int coap_endpoint_parse(const char *text, size_t size, coap_endpoint_t *ep) { /* Hex based CoAP has no addresses, just writes data to standard out */ @@ -178,20 +194,20 @@ stdin_callback(const char *line) buf[len] = (uint8_t)(((v1 << 4) | v2) & 0xff); } - PRINTF("RECV from "); - PRINTEP(&last_source); - PRINTF(" %u bytes\n", len); + LOG_INFO("RECV from "); + LOG_INFO_COAP_EP(&last_source); + LOG_INFO_(" %u bytes\n", len); coap_buf_len = len; - if(DEBUG) { + if(LOG_DBG_ENABLED) { int i; uint8_t *data; data = coap_databuf(); - printf("Received:"); + LOG_DBG("Received: "); for(i = 0; i < len; i++) { - printf("%02x", data[i]); + LOG_DBG_("%02x", data[i]); } - printf("\n"); + LOG_DBG_("\n"); } #ifdef WITH_DTLS @@ -208,13 +224,13 @@ coap_transport_init(void) { select_set_stdin_callback(stdin_callback); - printf("CoAP listening on standard in\n"); + LOG_INFO("CoAP listening on standard in\n"); #ifdef WITH_DTLS /* create new contet with app-data - no real app-data... */ dtls_context = dtls_new_context(&last_source); - if (!dtls_context) { - PRINTF("DTLS: cannot create context\n"); + if(!dtls_context) { + LOG_ERR("DTLS: cannot create context\n"); exit(-1); } @@ -224,7 +240,7 @@ coap_transport_init(void) memcpy(psk_id, PSK_DEFAULT_IDENTITY, psk_id_length); memcpy(psk_key, PSK_DEFAULT_KEY, psk_key_length); #endif /* DTLS_PSK */ - PRINTF("Setting DTLS handler\n"); + LOG_DBG("Setting DTLS handler\n"); dtls_set_handler(dtls_context, &cb); #endif /* WITH_DTLS */ @@ -234,7 +250,7 @@ int coap_sendto(const coap_endpoint_t *ep, const uint8_t *data, uint16_t len) { if(!coap_endpoint_is_connected(ep)) { - PRINTF("CoAP endpoint not connected\n"); + LOG_WARN("CoAP endpoint not connected\n"); return -1; } @@ -261,9 +277,9 @@ coap_endpoint_connect(coap_endpoint_t *ep) return 1; } #ifdef WITH_DTLS - PRINTF("DTLS EP:"); - PRINTEP(ep); - PRINTF(" len:%d\n", ep->size); + LOG_DBG("DTLS EP:"); + LOG_DBG_COAP_EP(ep); + LOG_DBG_(" len:%d\n", ep->size); /* setup all address info here... should be done to connect */ @@ -295,14 +311,14 @@ coap_endpoint_is_connected(const coap_endpoint_t *ep) peer = dtls_get_peer(dtls_context, ep); if(peer != NULL) { /* only if handshake is done! */ - PRINTF("peer state for "); - PRINTEP(ep); - PRINTF(" is %d %d\n", peer->state, dtls_peer_is_connected(peer)); + LOG_DBG("peer state for "); + LOG_DBG_COAP_EP(ep); + LOG_DBG_(" is %d %d\n", peer->state, dtls_peer_is_connected(peer)); return dtls_peer_is_connected(peer); } else { - PRINTF("Did not find peer "); - PRINTEP(ep); - PRINTF("\n"); + LOG_DBG("Did not find peer "); + LOG_DBG_COAP_EP(ep); + LOG_DBG_("\n"); } #endif /* WITH_DTLS */ return 0; @@ -324,11 +340,13 @@ input_from_peer(struct dtls_context_t *ctx, dtls_peer_t *peer; printf("received data:"); - for (i = 0; i < len; i++) + for(i = 0; i < len; i++) { printf("%c", data[i]); + } printf("\nHex:"); - for (i = 0; i < len; i++) + for(i = 0; i < len; i++) { printf("%02x", data[i]); + } printf("\n"); /* Send this into coap-input */ @@ -377,14 +395,14 @@ get_psk_info(struct dtls_context_t *ctx, const unsigned char *id, size_t id_len, unsigned char *result, size_t result_length) { - PRINTF("---===>>> Getting the Key or ID <<<===---\n"); - switch (type) { + LOG_DBG("---===>>> Getting the Key or ID <<<===---\n"); + switch(type) { case DTLS_PSK_IDENTITY: - if (id_len) { + if(id_len) { dtls_debug("got psk_identity_hint: '%.*s'\n", id_len, id); } - if (result_length < psk_id_length) { + if(result_length < psk_id_length) { dtls_warn("cannot set psk_identity -- buffer too small\n"); return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); } @@ -392,10 +410,10 @@ get_psk_info(struct dtls_context_t *ctx, memcpy(result, psk_id, psk_id_length); return psk_id_length; case DTLS_PSK_KEY: - if (id_len != psk_id_length || memcmp(psk_id, id, id_len) != 0) { + if(id_len != psk_id_length || memcmp(psk_id, id, id_len) != 0) { dtls_warn("PSK for unknown id requested, exiting\n"); return dtls_alert_fatal_create(DTLS_ALERT_ILLEGAL_PARAMETER); - } else if (result_length < psk_key_length) { + } else if(result_length < psk_key_length) { dtls_warn("cannot set psk -- buffer too small\n"); return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); } diff --git a/examples/lwm2m/standalone/coap-ipv4/coap-ipv4.c b/examples/lwm2m/standalone/coap-ipv4/coap-ipv4.c index 2b493b9a6..b8b5c464c 100644 --- a/examples/lwm2m/standalone/coap-ipv4/coap-ipv4.c +++ b/examples/lwm2m/standalone/coap-ipv4/coap-ipv4.c @@ -50,15 +50,10 @@ #include #include -#define DEBUG 1 -#define DEBUG_VERBOSE ((DEBUG) && 0) -#if DEBUG -#define PRINTF(...) printf(__VA_ARGS__) -#define PRINTEP(ep) coap_endpoint_print(ep) -#else /* DEBUG */ -#define PRINTF(...) -#define PRINTEP(ep) -#endif /* DEBUG */ +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "coap-ipv4" +#define LOG_LEVEL LOG_LEVEL_COAP #ifdef WITH_DTLS #include "tinydtls.h" @@ -109,14 +104,14 @@ coap_endpoint_is_connected(const coap_endpoint_t *ep) peer = dtls_get_peer(dtls_context, ep); if(peer != NULL) { /* only if handshake is done! */ - PRINTF("DTLS peer state for "); - PRINTEP(ep); - PRINTF(" is %d %d\n", peer->state, dtls_peer_is_connected(peer)); + LOG_DBG("DTLS peer state for "); + LOG_DBG_COAP_EP(ep); + LOG_DBG_(" is %d %d\n", peer->state, dtls_peer_is_connected(peer)); return dtls_peer_is_connected(peer); } else { - PRINTF("DTLS did not find peer "); - PRINTEP(ep); - PRINTF("\n"); + LOG_DBG("DTLS did not find peer "); + LOG_DBG_COAP_EP(ep); + LOG_DBG_("\n"); } #endif /* WITH_DTLS */ return 0; @@ -133,9 +128,9 @@ coap_endpoint_connect(coap_endpoint_t *ep) } #ifdef WITH_DTLS - PRINTF("DTLS connect to "); - PRINTEP(ep); - PRINTF(" len:%d\n", ep->size); + LOG_DBG("DTLS connect to "); + LOG_DBG_COAP_EP(ep); + LOG_DBG_(" len:%d\n", ep->size); /* setup all address info here... should be done to connect */ if(dtls_context) { @@ -179,6 +174,19 @@ coap_endpoint_cmp(const coap_endpoint_t *e1, const coap_endpoint_t *e2) } /*---------------------------------------------------------------------------*/ void +coap_endpoint_log(const coap_endpoint_t *ep) +{ + const char *address; + address = inet_ntoa(ep->addr.sin_addr); + if(address != NULL) { + LOG_OUTPUT("coap%s://%s:%u", ep->secure ? "s" : "", + address, ntohs(ep->addr.sin_port)); + } else { + LOG_OUTPUT("<#N/A>"); + } +} +/*---------------------------------------------------------------------------*/ +void coap_endpoint_print(const coap_endpoint_t *ep) { const char *address; @@ -192,6 +200,28 @@ coap_endpoint_print(const coap_endpoint_t *ep) } /*---------------------------------------------------------------------------*/ int +coap_endpoint_snprint(char *buf, size_t size, const coap_endpoint_t *ep) +{ + const char *address; + int n; + if(size == 0) { + return 0; + } + address = inet_ntoa(ep->addr.sin_addr); + if(address != NULL) { + n = snprintf(buf, size - 1, + "coap%s://%s:%u", ep->secure ? "s" : "", + address, ntohs(ep->addr.sin_port)); + } else { + n = snprintf(buf, size - 1, "<#N/A>"); + } + if(n >= size - 1) { + buf[size - 1] = '\0'; + } + return n; +} +/*---------------------------------------------------------------------------*/ +int coap_endpoint_parse(const char *text, size_t size, coap_endpoint_t *ep) { /* text = format coap://host:port/... we assume */ @@ -203,14 +233,14 @@ coap_endpoint_parse(const char *text, size_t size, coap_endpoint_t *ep) int secure; int offset = 0; int i; - PRINTF("CoAP-IPv4: parsing endpoint %.*s => ", (int)size, text); + LOG_DBG("parsing endpoint %.*s => ", (int)size, text); if(strncmp("coap://", text, 7) == 0) { secure = 0; offset = 7; } else if(strncmp("coaps://", text, 8) == 0) { secure = 1; offset = 8; - PRINTF("secure "); + LOG_DBG_("secure "); } else { secure = 0; } @@ -227,7 +257,7 @@ coap_endpoint_parse(const char *text, size_t size, coap_endpoint_t *ep) port = atoi(&text[i + 1]); } - PRINTF("endpoint at %s:%u\n", host, port); + LOG_DBG_("endpoint at %s:%u\n", host, port); ep->addr.sin_family = AF_INET; ep->addr.sin_port = htons(port); @@ -235,7 +265,7 @@ coap_endpoint_parse(const char *text, size_t size, coap_endpoint_t *ep) ep->secure = secure; if(inet_aton(host, &ep->addr.sin_addr) == 0) { /* Failed to parse the address */ - PRINTF("CoAP-IPv4: Failed to parse endpoint host '%s'\n", host); + LOG_WARN("Failed to parse endpoint host '%s'\n", host); return 0; } return 1; @@ -272,13 +302,13 @@ read_packet_to_coapbuf(int fd, int is_secure) last_source.secure = is_secure; - PRINTF("CoAP-IPv4: RECV from "); - PRINTEP(&last_source); - PRINTF(" %u bytes\n", len); + LOG_INFO("RECV from "); + LOG_INFO_COAP_EP(&last_source); + LOG_INFO_(" %u bytes\n", len); coap_buf_len = len; #if 0 - if((rand() & 0xffff) < 0x1000) { + if((rand() & 0xffff) < 0x1000) { printf("*********---- PACKET LOSS ----********\n"); return 0; } @@ -303,16 +333,16 @@ coap_ipv4_handle_fd(fd_set *rset, fd_set *wset) if(coap_ipv4_fd >= 0 && FD_ISSET(coap_ipv4_fd, rset)) { if(read_packet_to_coapbuf(coap_ipv4_fd, 0)) { -#if DEBUG_VERBOSE +#if LOG_DBG_ENABLED int i; uint8_t *data; data = coap_databuf(); - PRINTF("Received:"); + LOG_DBG("Received: "); for(i = 0; i < coap_buf_len; i++) { - PRINTF("%02x", data[i]); + LOG_DBG_("%02x", data[i]); } - PRINTF("\n"); -#endif /* DEBUG_VERBOSE */ + LOG_DBG_("\n"); +#endif /* LOG_DBG_ENABLED */ coap_receive(coap_src_endpoint(), coap_databuf(), coap_datalen()); } } @@ -377,7 +407,7 @@ coap_transport_init(void) exit(1); } - printf("CoAP server listening on port %u\n", COAP_SERVER_PORT); + LOG_INFO("CoAP server listening on port %u\n", COAP_SERVER_PORT); select_set_callback(coap_ipv4_fd, &udp_callback); #ifdef WITH_DTLS @@ -402,7 +432,7 @@ coap_transport_init(void) exit(1); } - printf("CoAP DTLS server listening on port %u\n", COAP_DEFAULT_SECURE_PORT); + LOG_INFO("CoAP DTLS server listening on port %u\n", COAP_DEFAULT_SECURE_PORT); select_set_callback(dtls_ipv4_fd, &dtls_callback); /* create new contet with app-data */ @@ -422,9 +452,9 @@ coap_sendto(const coap_endpoint_t *ep, const uint8_t *data, uint16_t len) int ret; if(!coap_endpoint_is_connected(ep)) { - PRINTF("CoAP-IPv4: endpoint "); - PRINTEP(ep); - PRINTF(" not connected - dropping packet\n"); + LOG_WARN("endpoint "); + LOG_WARN_COAP_EP(ep); + LOG_WARN_(" not connected - dropping packet\n"); return -1; } @@ -432,16 +462,16 @@ coap_sendto(const coap_endpoint_t *ep, const uint8_t *data, uint16_t len) if(coap_endpoint_is_secure(ep)) { if(dtls_context) { ret = dtls_write(dtls_context, (session_t *)ep, (uint8_t *)data, len); - PRINTF("CoAP-IPv4: SENT DTLS to "); - PRINTEP(ep); + LOG_DBG("SENT DTLS to "); + LOG_DBG_COAP_EP(ep); if(ret < 0) { - PRINTF(" - error %d\n", ret); + LOG_DBG_(" - error %d\n", ret); } else { - PRINTF(" %d/%u bytes\n", ret, len); + LOG_DBG_(" %d/%u bytes\n", ret, len); } return ret; } - PRINTF("CoAP-IPv4: no DTLS context\n"); + LOG_WARN("no DTLS context\n"); return -1; } #endif /* WITH_DTLS */ @@ -449,26 +479,26 @@ coap_sendto(const coap_endpoint_t *ep, const uint8_t *data, uint16_t len) if(coap_ipv4_fd >= 0) { ret = sendto(coap_ipv4_fd, data, len, 0, (struct sockaddr *)&ep->addr, ep->size); - PRINTF("CoAP-IPv4: SENT to "); - PRINTEP(ep); + LOG_INFO("SENT to "); + LOG_INFO_COAP_EP(ep); if(ret < 0) { - PRINTF(" - error %d: %s\n", ret, strerror(errno)); + LOG_INFO_(" - error %d: %s\n", ret, strerror(errno)); } else { - PRINTF(" %d/%u bytes\n", ret, len); + LOG_INFO_(" %d/%u bytes\n", ret, len); - if(DEBUG_VERBOSE) { + if(LOG_DBG_ENABLED) { int i; - PRINTF("Sent:"); + LOG_DBG("Sent: "); for(i = 0; i < len; i++) { - PRINTF("%02x", data[i]); + LOG_DBG_("%02x", data[i]); } - PRINTF("\n"); + LOG_DBG_("\n"); } } return ret; } - PRINTF("CoAP-IPv4: failed to send - no socket\n"); + LOG_DBG("failed to send - no socket\n"); return -1; } /*---------------------------------------------------------------------------*/ @@ -481,19 +511,20 @@ static int input_from_peer(struct dtls_context_t *ctx, session_t *session, uint8_t *data, size_t len) { -#if DEBUG_VERBOSE +#if LOG_DBG_ENABLED size_t i; - PRINTF("DTLS received data:"); + LOG_DBG("DTLS received data: "); for(i = 0; i < len; i++) { - PRINTF("%c", data[i]); + LOG_DBG_("%c", data[i]); } - PRINTF("\nHex:"); + LOG_DBG_("\n"); + LOG_DBG("Hex: "); for(i = 0; i < len; i++) { - PRINTF("%02x", data[i]); + LOG_DBG_("%02x", data[i]); } - PRINTF("\n"); -#endif /* DEBUG_VERBOSE */ + LOG_DBG_("\n"); +#endif /* LOG_DBG_ENABLED */ /* Send this into coap-input */ memmove(coap_databuf(), data, len); @@ -513,10 +544,8 @@ output_to_peer(struct dtls_context_t *ctx, session_t *session, uint8_t *data, size_t len) { int fd = *(int *)dtls_get_app_data(ctx); -#if DEBUG_VERBOSE - PRINTF("DTLS output_to_peer len:%d %d (s-size: %d)\n", (int)len, fd, - session->size); -#endif /* DEBUG_VERBOSE */ + LOG_DBG("DTLS output_to_peer len:%d %d (s-size: %d)\n", (int)len, fd, + session->size); return sendto(fd, data, len, MSG_DONTWAIT, (struct sockaddr *)&session->addr, session->size); } @@ -543,12 +572,12 @@ get_psk_info(struct dtls_context_t *ctx, keystore = dtls_keystore; if(keystore == NULL) { - PRINTF("--- No key store available ---\n"); + LOG_DBG("--- No key store available ---\n"); return 0; } memset(&ks, 0, sizeof(ks)); - PRINTF("---===>>> Getting the Key or ID <<<===---\n"); + LOG_DBG("---===>>> Getting the Key or ID <<<===---\n"); switch(type) { case DTLS_PSK_IDENTITY: if(id && id_len) { @@ -562,16 +591,16 @@ get_psk_info(struct dtls_context_t *ctx, keystore->coap_get_psk_info((coap_endpoint_t *)session, &ks); } if(ks.identity == NULL || ks.identity_len == 0) { - PRINTF("no psk_identity found\n"); + LOG_DBG("no psk_identity found\n"); return 0; } if(result_length < ks.identity_len) { - PRINTF("cannot return psk_identity -- buffer too small\n"); + LOG_DBG("cannot return psk_identity -- buffer too small\n"); return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); } memcpy(result, ks.identity, ks.identity_len); - PRINTF("psk_identity with %u bytes found\n", ks.identity_len); + LOG_DBG("psk_identity with %u bytes found\n", ks.identity_len); return ks.identity_len; case DTLS_PSK_KEY: @@ -582,16 +611,16 @@ get_psk_info(struct dtls_context_t *ctx, keystore->coap_get_psk_info((coap_endpoint_t *)session, &ks); } if(ks.key == NULL || ks.key_len == 0) { - PRINTF("PSK for unknown id requested, exiting\n"); + LOG_DBG("PSK for unknown id requested, exiting\n"); return dtls_alert_fatal_create(DTLS_ALERT_ILLEGAL_PARAMETER); } if(result_length < ks.key_len) { - PRINTF("cannot return psk -- buffer too small\n"); + LOG_DBG("cannot return psk -- buffer too small\n"); return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); } memcpy(result, ks.key, ks.key_len); - PRINTF("psk with %u bytes found\n", ks.key_len); + LOG_DBG("psk with %u bytes found\n", ks.key_len); return ks.key_len; default: diff --git a/examples/lwm2m/standalone/coap-log-conf.h b/examples/lwm2m/standalone/coap-log-conf.h new file mode 100644 index 000000000..a6c58c218 --- /dev/null +++ b/examples/lwm2m/standalone/coap-log-conf.h @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2017, RISE SICS. + * 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 copyright holder 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 COPYRIGHT HOLDER 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 + * COPYRIGHT HOLDER 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. + */ + +/** + * \file + * Standalone CoAP log configuration + * \author + * Niclas Finne + * Joakim Eriksson + */ + +#ifndef COAP_LOG_CONF_H_ +#define COAP_LOG_CONF_H_ + +#include "contiki.h" +#include + +/* The different log levels available */ +#define LOG_LEVEL_NONE 0 /* No log */ +#define LOG_LEVEL_ERR 1 /* Errors */ +#define LOG_LEVEL_WARN 2 /* Warnings */ +#define LOG_LEVEL_INFO 3 /* Basic info */ +#define LOG_LEVEL_DBG 4 /* Detailed debug */ + +#ifndef LOG_LEVEL_COAP +#define LOG_LEVEL_COAP LOG_LEVEL_DBG +#endif /* LOG_LEVEL_COAP */ + +#ifndef LOG_WITH_LOC +#define LOG_WITH_LOC 0 +#endif /* LOG_WITH_LOC */ + +#ifndef LOG_WITH_MODULE_PREFIX +#define LOG_WITH_MODULE_PREFIX 1 +#endif /* LOG_WITH_MODULE_PREFIX */ + +/* Custom output function -- default is printf */ +#ifdef LOG_CONF_OUTPUT +#define LOG_OUTPUT(...) LOG_CONF_OUTPUT(__VA_ARGS__) +#else /* LOG_CONF_OUTPUT */ +#define LOG_OUTPUT(...) printf(__VA_ARGS__) +#endif /* LOG_CONF_OUTPUT */ + +/* Custom line prefix output function -- default is LOG_OUTPUT */ +#ifdef LOG_CONF_OUTPUT_PREFIX +#define LOG_OUTPUT_PREFIX(level, levelstr, module) LOG_CONF_OUTPUT_PREFIX(level, levelstr, module) +#else /* LOG_CONF_OUTPUT_PREFIX */ +#define LOG_OUTPUT_PREFIX(level, levelstr, module) LOG_OUTPUT("[%-4s: %-10s] ", levelstr, module) +#endif /* LOG_CONF_OUTPUT_PREFIX */ + +/* Main log function */ + +#define LOG(newline, level, levelstr, ...) do { \ + if(level <= (LOG_LEVEL)) { \ + if(newline) { \ + if(LOG_WITH_MODULE_PREFIX) { \ + LOG_OUTPUT_PREFIX(level, levelstr, LOG_MODULE); \ + } \ + if(LOG_WITH_LOC) { \ + LOG_OUTPUT("[%s: %d] ", __FILE__, __LINE__); \ + } \ + } \ + LOG_OUTPUT(__VA_ARGS__); \ + } \ + } while (0) + +/* More compact versions of LOG macros */ +#define LOG_ERR(...) LOG(1, LOG_LEVEL_ERR, "ERR", __VA_ARGS__) +#define LOG_WARN(...) LOG(1, LOG_LEVEL_WARN, "WARN", __VA_ARGS__) +#define LOG_INFO(...) LOG(1, LOG_LEVEL_INFO, "INFO", __VA_ARGS__) +#define LOG_DBG(...) LOG(1, LOG_LEVEL_DBG, "DBG", __VA_ARGS__) + +#define LOG_ERR_(...) LOG(0, LOG_LEVEL_ERR, "ERR", __VA_ARGS__) +#define LOG_WARN_(...) LOG(0, LOG_LEVEL_WARN, "WARN", __VA_ARGS__) +#define LOG_INFO_(...) LOG(0, LOG_LEVEL_INFO, "INFO", __VA_ARGS__) +#define LOG_DBG_(...) LOG(0, LOG_LEVEL_DBG, "DBG", __VA_ARGS__) + +/* For testing log level */ +#define LOG_ERR_ENABLED ((LOG_LEVEL) >= (LOG_LEVEL_ERR)) +#define LOG_WARN_ENABLED ((LOG_LEVEL) >= (LOG_LEVEL_WARN)) +#define LOG_INFO_ENABLED ((LOG_LEVEL) >= (LOG_LEVEL_INFO)) +#define LOG_DBG_ENABLED ((LOG_LEVEL) >= (LOG_LEVEL_DBG)) + +#endif /* COAP_LOG_CONF_H_ */ diff --git a/examples/lwm2m/standalone/contiki.h b/examples/lwm2m/standalone/contiki.h index 43a85eaf2..e626cc816 100644 --- a/examples/lwm2m/standalone/contiki.h +++ b/examples/lwm2m/standalone/contiki.h @@ -42,6 +42,8 @@ #include "posix-main.h" +#define COAP_LOG_CONF_PATH "coap-log-conf.h" + #define COAP_TIMER_CONF_DRIVER coap_timer_native_driver #define LWM2M_ENGINE_CLIENT_ENDPOINT_NAME "lwm2m-ex" diff --git a/os/net/app-layer/coap/coap-block1.c b/os/net/app-layer/coap/coap-block1.c index 4ecd8a1c5..d39e3d730 100644 --- a/os/net/app-layer/coap/coap-block1.c +++ b/os/net/app-layer/coap/coap-block1.c @@ -36,18 +36,16 @@ * Lars Schmertmann */ -#include #include +#include #include "coap.h" #include "coap-block1.h" -#define DEBUG 0 -#if DEBUG -#define PRINTF(...) printf(__VA_ARGS__) -#else -#define PRINTF(...) -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "coap-block1" +#define LOG_LEVEL LOG_LEVEL_COAP /*----------------------------------------------------------------------------*/ @@ -97,11 +95,12 @@ coap_block1_handler(coap_message_t *request, coap_message_t *response, } if(coap_is_option(request, COAP_OPTION_BLOCK1)) { - PRINTF("Blockwise: block 1 request: Num: %u, More: %u, Size: %u, Offset: %u\n", - request->block1_num, - request->block1_more, - request->block1_size, - request->block1_offset); + LOG_DBG("Blockwise: block 1 request: Num: %"PRIu32 + ", More: %u, Size: %u, Offset: %"PRIu32"\n", + request->block1_num, + request->block1_more, + request->block1_size, + request->block1_offset); coap_set_header_block1(response, request->block1_num, request->block1_more, request->block1_size); if(request->block1_more) { diff --git a/os/net/app-layer/coap/coap-blocking-api.c b/os/net/app-layer/coap/coap-blocking-api.c index bd0877a67..c8e8a1c6c 100644 --- a/os/net/app-layer/coap/coap-blocking-api.c +++ b/os/net/app-layer/coap/coap-blocking-api.c @@ -42,14 +42,12 @@ #include #include #include +#include -#define DEBUG 0 -#if DEBUG -#include -#define PRINTF(...) printf(__VA_ARGS__) -#else -#define PRINTF(...) -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "coap-blocking-api" +#define LOG_LEVEL LOG_LEVEL_COAP /*---------------------------------------------------------------------------*/ /*- Client Part -------------------------------------------------------------*/ @@ -99,29 +97,30 @@ PT_THREAD(coap_blocking_request message); coap_send_transaction(state->transaction); - PRINTF("Requested #%lu (MID %u)\n", state->block_num, request->mid); + LOG_DBG("Requested #%"PRIu32" (MID %u)\n", state->block_num, request->mid); PT_YIELD_UNTIL(&state->pt, ev == PROCESS_EVENT_POLL); if(!state->response) { - PRINTF("Server not responding\n"); + LOG_WARN("Server not responding\n"); PT_EXIT(&state->pt); } coap_get_header_block2(state->response, &res_block, &more, NULL, NULL); - PRINTF("Received #%lu%s (%u bytes)\n", res_block, more ? "+" : "", - state->response->payload_len); + LOG_DBG("Received #%"PRIu32"%s (%u bytes)\n", res_block, more ? "+" : "", + state->response->payload_len); if(res_block == state->block_num) { request_callback(state->response); ++(state->block_num); } else { - PRINTF("WRONG BLOCK %lu/%lu\n", res_block, state->block_num); + LOG_WARN("WRONG BLOCK %"PRIu32"/%"PRIu32"\n", + res_block, state->block_num); ++block_error; } } else { - PRINTF("Could not allocate transaction buffer"); + LOG_WARN("Could not allocate transaction buffer"); PT_EXIT(&state->pt); } } while(more && block_error < COAP_MAX_ATTEMPTS); diff --git a/os/net/app-layer/coap/coap-callback-api.c b/os/net/app-layer/coap/coap-callback-api.c index 1f20e0a86..a83806727 100644 --- a/os/net/app-layer/coap/coap-callback-api.c +++ b/os/net/app-layer/coap/coap-callback-api.c @@ -45,13 +45,10 @@ #include #include -#define DEBUG 0 -#if DEBUG -#include -#define PRINTF(...) printf(__VA_ARGS__) -#else -#define PRINTF(...) -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "coap-callback-api" +#define LOG_LEVEL LOG_LEVEL_COAP /* These should go into the state struct so that we can have multiple requests */ @@ -81,8 +78,8 @@ progress_request(coap_request_state_t *state) { coap_serialize_message(request, state->transaction->message); coap_send_transaction(state->transaction); - PRINTF("Requested #%lu (MID %u)\n", (unsigned long) state->block_num, - request->mid); + LOG_DBG("Requested #%lu (MID %u)\n", (unsigned long)state->block_num, + request->mid); } } @@ -96,10 +93,10 @@ coap_request_callback(void *callback_data, coap_message_t *response) state->response = response; - PRINTF("COAP: request callback\n"); + LOG_DBG("request callback\n"); if(!state->response) { - PRINTF("Server not responding giving up...\n"); + LOG_WARN("Server not responding giving up...\n"); state->callback(state); return; } @@ -108,10 +105,10 @@ coap_request_callback(void *callback_data, coap_message_t *response) coap_get_header_block2(state->response, &res_block, &more, NULL, NULL); coap_get_header_block1(state->response, &res_block1, NULL, NULL, NULL); - PRINTF("Received #%lu%s B1:%lu (%u bytes)\n", - (unsigned long) res_block, (unsigned) more ? "+" : "", - (unsigned long) res_block1, - state->response->payload_len); + LOG_DBG("Received #%lu%s B1:%lu (%u bytes)\n", + (unsigned long)res_block, (unsigned)more ? "+" : "", + (unsigned long)res_block1, + state->response->payload_len); if(res_block == state->block_num) { /* Call the callback function as we have more data */ @@ -119,8 +116,8 @@ coap_request_callback(void *callback_data, coap_message_t *response) /* this is only for counting BLOCK2 blocks.*/ ++(state->block_num); } else { - PRINTF("WRONG BLOCK %lu/%lu\n", (unsigned long) res_block, - (unsigned long) state->block_num); + LOG_WARN("WRONG BLOCK %lu/%lu\n", (unsigned long)res_block, + (unsigned long)state->block_num); ++block_error; } diff --git a/os/net/app-layer/coap/coap-endpoint.h b/os/net/app-layer/coap/coap-endpoint.h index 208eb49a7..705b10fa2 100644 --- a/os/net/app-layer/coap/coap-endpoint.h +++ b/os/net/app-layer/coap/coap-endpoint.h @@ -56,7 +56,10 @@ void coap_endpoint_copy(coap_endpoint_t *destination, int coap_endpoint_cmp(const coap_endpoint_t *e1, const coap_endpoint_t *e2); +void coap_endpoint_log(const coap_endpoint_t *ep); void coap_endpoint_print(const coap_endpoint_t *ep); +int coap_endpoint_snprint(char *str, size_t size, + const coap_endpoint_t *ep); int coap_endpoint_parse(const char *text, size_t size, coap_endpoint_t *ep); diff --git a/os/net/app-layer/coap/coap-engine.c b/os/net/app-layer/coap/coap-engine.c index 43d9a2c8d..25d48671e 100644 --- a/os/net/app-layer/coap/coap-engine.c +++ b/os/net/app-layer/coap/coap-engine.c @@ -44,17 +44,10 @@ #include #include -#define DEBUG 0 -#if DEBUG -#include -#define PRINTF(...) printf(__VA_ARGS__) -#define PRINTS(l,s,f) do { int i; \ - for(i = 0; i < l; i++) printf(f, s[i]); \ - } while(0) -#else -#define PRINTF(...) -#define PRINTS(l,s,f) -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "coap-engine" +#define LOG_LEVEL LOG_LEVEL_COAP static void process_callback(coap_timer_t *t); @@ -160,13 +153,14 @@ coap_receive(const coap_endpoint_t *src, /*TODO duplicates suppression, if required by application */ - PRINTF(" Parsed: v %u, t %u, tkl %u, c %u, mid %u\n", message->version, - message->type, message->token_len, message->code, message->mid); - PRINTF(" URL:"); - PRINTS(message->uri_path_len, message->uri_path, "%c"); - PRINTF("\n Payload: "); - PRINTS(message->payload_len, message->payload, "%c"); - PRINTF("\n"); + LOG_DBG(" Parsed: v %u, t %u, tkl %u, c %u, mid %u\n", message->version, + message->type, message->token_len, message->code, message->mid); + LOG_DBG(" URL:"); + LOG_DBG_COAP_STRING(message->uri_path, message->uri_path_len); + LOG_DBG_("\n"); + LOG_DBG(" Payload: "); + LOG_DBG_COAP_STRING((const char *)message->payload, message->payload_len); + LOG_DBG_("\n"); /* handle requests */ if(message->code >= COAP_GET && message->code <= COAP_DELETE) { @@ -195,8 +189,8 @@ coap_receive(const coap_endpoint_t *src, } if(coap_get_header_block2 (message, &block_num, NULL, &block_size, &block_offset)) { - PRINTF("Blockwise: block request %"PRIu32" (%u/%u) @ %"PRIu32" bytes\n", - block_num, block_size, COAP_MAX_BLOCK_SIZE, block_offset); + LOG_DBG("Blockwise: block request %"PRIu32" (%u/%u) @ %"PRIu32" bytes\n", + block_num, block_size, COAP_MAX_BLOCK_SIZE, block_offset); block_size = MIN(block_size, COAP_MAX_BLOCK_SIZE); new_offset = block_offset; } @@ -215,7 +209,7 @@ coap_receive(const coap_endpoint_t *src, if(coap_is_option(message, COAP_OPTION_BLOCK1) && response->code < BAD_REQUEST_4_00 && !coap_is_option(response, COAP_OPTION_BLOCK1)) { - PRINTF("Block1 NOT IMPLEMENTED\n"); + LOG_DBG("Block1 NOT IMPLEMENTED\n"); coap_status_code = NOT_IMPLEMENTED_5_01; coap_error_message = "NoBlock1Support"; @@ -225,12 +219,10 @@ coap_receive(const coap_endpoint_t *src, /* unchanged new_offset indicates that resource is unaware of blockwise transfer */ if(new_offset == block_offset) { - PRINTF - ("Blockwise: unaware resource with payload length %u/%u\n", - response->payload_len, block_size); + LOG_DBG("Blockwise: unaware resource with payload length %u/%u\n", + response->payload_len, block_size); if(block_offset >= response->payload_len) { - PRINTF - ("handle_incoming_data(): block_offset >= response->payload_len\n"); + LOG_DBG("handle_incoming_data(): block_offset >= response->payload_len\n"); response->code = BAD_OPTION_4_02; coap_set_payload(response, "BlockOutOfScope", 15); /* a const char str[] and sizeof(str) produces larger code size */ @@ -247,8 +239,8 @@ coap_receive(const coap_endpoint_t *src, /* resource provides chunk-wise data */ } else { - PRINTF("Blockwise: blockwise resource, new offset %"PRId32"\n", - new_offset); + LOG_DBG("Blockwise: blockwise resource, new offset %"PRId32"\n", + new_offset); coap_set_header_block2(response, block_num, new_offset != -1 || response->payload_len > @@ -262,9 +254,8 @@ coap_receive(const coap_endpoint_t *src, /* Resource requested Block2 transfer */ } else if(new_offset != 0) { - PRINTF - ("Blockwise: no block option for blockwise resource, using block size %u\n", - COAP_MAX_BLOCK_SIZE); + LOG_DBG("Blockwise: no block option for blockwise resource, using block size %u\n", + COAP_MAX_BLOCK_SIZE); coap_set_header_block2(response, 0, new_offset != -1, COAP_MAX_BLOCK_SIZE); @@ -293,13 +284,13 @@ coap_receive(const coap_endpoint_t *src, } else { if(message->type == COAP_TYPE_CON && message->code == 0) { - PRINTF("Received Ping\n"); + LOG_INFO("Received Ping\n"); coap_status_code = PING_RESPONSE; } else if(message->type == COAP_TYPE_ACK) { /* transactions are closed through lookup below */ - PRINTF("Received ACK\n"); + LOG_DBG("Received ACK\n"); } else if(message->type == COAP_TYPE_RST) { - PRINTF("Received RST\n"); + LOG_INFO("Received RST\n"); /* cancel possible subscriptions */ coap_remove_observer_by_mid(src, message->mid); } @@ -323,7 +314,7 @@ coap_receive(const coap_endpoint_t *src, /* if observe notification */ if((message->type == COAP_TYPE_CON || message->type == COAP_TYPE_NON) && coap_is_option(message, COAP_OPTION_OBSERVE)) { - PRINTF("Observe [%u]\n", message->observe); + LOG_DBG("Observe [%"PRId32"]\n", message->observe); coap_handle_notification(src, message); } #endif /* COAP_OBSERVE_CLIENT */ @@ -336,12 +327,12 @@ coap_receive(const coap_endpoint_t *src, coap_send_transaction(transaction); } } else if(coap_status_code == MANUAL_RESPONSE) { - PRINTF("Clearing transaction for manual response"); + LOG_DBG("Clearing transaction for manual response"); coap_clear_transaction(transaction); } else { coap_message_type_t reply_type = COAP_TYPE_ACK; - PRINTF("ERROR %u: %s\n", coap_status_code, coap_error_message); + LOG_WARN("ERROR %u: %s\n", coap_status_code, coap_error_message); coap_clear_transaction(transaction); if(coap_status_code == PING_RESPONSE) { @@ -368,12 +359,12 @@ coap_engine_init(void) { /* avoid initializing twice */ if(is_initialized) { - PRINTF("CoAP engine process already running - double initialization?\n"); + LOG_DBG("already running - double initialization?\n"); return; } is_initialized = 1; - PRINTF("Starting CoAP engine...\n"); + LOG_INFO("Starting CoAP engine...\n"); list_init(coap_handlers); list_init(coap_resource_services); @@ -401,14 +392,13 @@ coap_activate_resource(coap_resource_t *resource, const char *path) resource->url = path; list_add(coap_resource_services, resource); - PRINTF("Activating: %s\n", resource->url); + LOG_INFO("Activating: %s\n", resource->url); /* Only add periodic resources with a periodic_handler and a period > 0. */ if(resource->flags & IS_PERIODIC && resource->periodic && resource->periodic->periodic_handler && resource->periodic->period) { - PRINTF("Periodic resource: %p (%s)\n", resource->periodic, - resource->periodic->resource->url); + LOG_DBG("Periodic resource: %p (%s)\n", resource->periodic, path); list_add(coap_resource_periodic_services, resource->periodic); periodic = resource->periodic; coap_timer_set_callback(&periodic->periodic_timer, process_callback); @@ -459,8 +449,8 @@ invoke_coap_resource_service(coap_message_t *request, coap_message_t *response, coap_resource_flags_t method = coap_get_method_type(request); found = 1; - PRINTF("/%s, method %u, resource->flags %u\n", resource->url, - (uint16_t)method, resource->flags); + LOG_INFO("/%s, method %u, resource->flags %u\n", resource->url, + (uint16_t)method, resource->flags); if((method & METHOD_GET) && resource->get_handler != NULL) { /* call handler function */ @@ -502,8 +492,8 @@ process_callback(coap_timer_t *t) resource = coap_timer_get_user_data(t); if(resource != NULL && (resource->flags & IS_PERIODIC) && resource->periodic != NULL && resource->periodic->period) { - PRINTF("Periodic: timer expired for /%s (period: %lu)\n", - resource->url, resource->periodic->period); + LOG_DBG("Periodic: timer expired for /%s (period: %"PRIu32")\n", + resource->url, resource->periodic->period); if(!is_initialized) { /* CoAP has not yet been initialized. */ diff --git a/os/net/app-layer/coap/coap-log.c b/os/net/app-layer/coap/coap-log.c new file mode 100644 index 000000000..083c9aaf4 --- /dev/null +++ b/os/net/app-layer/coap/coap-log.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2017, RISE SICS. + * 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 copyright holder 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 COPYRIGHT HOLDER 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 + * COPYRIGHT HOLDER 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. + */ + +/** + * \file + * Log support for CoAP + * \author + * Niclas Finne + * Joakim Eriksson + */ + +#include "coap-log.h" +/*---------------------------------------------------------------------------*/ +void +coap_log_string(const char *text, size_t len) +{ + int i; + if(text == NULL) { + LOG_OUTPUT("(NULL STR)"); + return; + } + + for(i = 0; i < len && *text != '\0'; i++, text++) { + LOG_OUTPUT("%c", *text); + } +} +/*---------------------------------------------------------------------------*/ diff --git a/os/net/app-layer/coap/coap-log.h b/os/net/app-layer/coap/coap-log.h new file mode 100644 index 000000000..79457bbe4 --- /dev/null +++ b/os/net/app-layer/coap/coap-log.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2017, RISE SICS. + * 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 copyright holder 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 COPYRIGHT HOLDER 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 + * COPYRIGHT HOLDER 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. + */ + +/** + * \file + * Log support for CoAP + * \author + * Niclas Finne + * Joakim Eriksson + */ + +#ifndef COAP_LOG_H_ +#define COAP_LOG_H_ + +#include "contiki.h" + +#ifdef COAP_LOG_CONF_PATH +#include COAP_LOG_CONF_PATH +#else /* COAP_LOG_CONF_PATH */ +#include "sys/log.h" +#endif /* COAP_LOG_CONF_PATH */ + +#include "coap-endpoint.h" + +/* CoAP endpoint */ +#define LOG_COAP_EP(level, endpoint) do { \ + if(level <= (LOG_LEVEL)) { \ + coap_endpoint_log(endpoint); \ + } \ + } while (0) + +#define LOG_ERR_COAP_EP(endpoint) LOG_COAP_EP(LOG_LEVEL_ERR, endpoint) +#define LOG_WARN_COAP_EP(endpoint) LOG_COAP_EP(LOG_LEVEL_WARN, endpoint) +#define LOG_INFO_COAP_EP(endpoint) LOG_COAP_EP(LOG_LEVEL_INFO, endpoint) +#define LOG_DBG_COAP_EP(endpoint) LOG_COAP_EP(LOG_LEVEL_DBG, endpoint) + +/* CoAP strings */ +#define LOG_COAP_STRING(level, text, len) do { \ + if(level <= (LOG_LEVEL)) { \ + coap_log_string(text, len); \ + } \ + } while (0) + +#define LOG_ERR_COAP_STRING(text, len) LOG_COAP_STRING(LOG_LEVEL_ERR, text, len) +#define LOG_WARN_COAP_STRING(text, len) LOG_COAP_STRING(LOG_LEVEL_WARN, text, len) +#define LOG_INFO_COAP_STRING(text, len) LOG_COAP_STRING(LOG_LEVEL_INFO, text, len) +#define LOG_DBG_COAP_STRING(text, len) LOG_COAP_STRING(LOG_LEVEL_DBG, text, len) + +void coap_log_string(const char *text, size_t len); + +#endif /* COAP_LOG_H_ */ diff --git a/os/net/app-layer/coap/coap-observe-client.c b/os/net/app-layer/coap/coap-observe-client.c index 93ad47f12..f264663eb 100644 --- a/os/net/app-layer/coap/coap-observe-client.c +++ b/os/net/app-layer/coap/coap-observe-client.c @@ -48,14 +48,10 @@ /* Compile this code only if client-side support for CoAP Observe is required */ #if COAP_OBSERVE_CLIENT -#define DEBUG 0 -#if DEBUG -#define PRINTF(...) printf(__VA_ARGS__) -#define PRINTEP(ep) coap_endpoint_print(ep) -#else -#define PRINTF(...) -#define PRINTEP(ep) -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "coap-observe-client" +#define LOG_LEVEL LOG_LEVEL_COAP MEMB(obs_subjects_memb, coap_observee_t, COAP_MAX_OBSERVEES); LIST(obs_subjects_list); @@ -97,8 +93,8 @@ coap_obs_add_observee(const coap_endpoint_t *endpoint, /* o->last_mid = 0; */ o->notification_callback = notification_callback; o->data = data; - PRINTF("Adding obs_subject for /%s [0x%02X%02X]\n", o->url, o->token[0], - o->token[1]); + LOG_DBG("Adding obs_subject for /%s [0x%02X%02X]\n", o->url, o->token[0], + o->token[1]); list_add(obs_subjects_list, o); } @@ -108,8 +104,8 @@ coap_obs_add_observee(const coap_endpoint_t *endpoint, void coap_obs_remove_observee(coap_observee_t *o) { - PRINTF("Removing obs_subject for /%s [0x%02X%02X]\n", o->url, o->token[0], - o->token[1]); + LOG_DBG("Removing obs_subject for /%s [0x%02X%02X]\n", o->url, o->token[0], + o->token[1]); memb_free(&obs_subjects_memb, o); list_remove(obs_subjects_list, o); } @@ -121,7 +117,7 @@ coap_get_obs_subject_by_token(const uint8_t *token, size_t token_len) for(obs = (coap_observee_t *)list_head(obs_subjects_list); obs; obs = obs->next) { - PRINTF("Looking for token 0x%02X%02X\n", token[0], token[1]); + LOG_DBG("Looking for token 0x%02X%02X\n", token[0], token[1]); if(obs->token_len == token_len && memcmp(obs->token, token, token_len) == 0) { return obs; @@ -140,7 +136,7 @@ coap_obs_remove_observee_by_token(const coap_endpoint_t *endpoint, for(obs = (coap_observee_t *)list_head(obs_subjects_list); obs; obs = obs->next) { - PRINTF("Remove check Token 0x%02X%02X\n", token[0], token[1]); + LOG_DBG("Remove check Token 0x%02X%02X\n", token[0], token[1]); if(coap_endpoint_cmp(&obs->endpoint, endpoint) && obs->token_len == token_len && memcmp(obs->token, token, token_len) == 0) { @@ -160,7 +156,7 @@ coap_obs_remove_observee_by_url(const coap_endpoint_t *endpoint, for(obs = (coap_observee_t *)list_head(obs_subjects_list); obs; obs = obs->next) { - PRINTF("Remove check URL %s\n", url); + LOG_DBG("Remove check URL %s\n", url); if(coap_endpoint_cmp(&obs->endpoint, endpoint) && (obs->url == url || memcmp(obs->url, url, strlen(obs->url)) == 0)) { coap_obs_remove_observee(obs); @@ -186,16 +182,16 @@ static coap_notification_flag_t classify_notification(coap_message_t *response, int first) { if(!response) { - PRINTF("no response\n"); + LOG_DBG("no response\n"); return NO_REPLY_FROM_SERVER; } - PRINTF("server replied\n"); + LOG_DBG("server replied\n"); if(!IS_RESPONSE_CODE_2_XX(response)) { - PRINTF("error response code\n"); + LOG_DBG("error response code\n"); return ERROR_RESPONSE_CODE; } if(!coap_is_option(response, COAP_OPTION_OBSERVE)) { - PRINTF("server does not support observe\n"); + LOG_DBG("server does not support observe\n"); return OBSERVE_NOT_SUPPORTED; } if(first) { @@ -214,19 +210,19 @@ coap_handle_notification(const coap_endpoint_t *endpoint, coap_notification_flag_t flag; uint32_t observe; - PRINTF("coap_handle_notification()\n"); + LOG_DBG("coap_handle_notification()\n"); token_len = get_token(notification, &token); - PRINTF("Getting token\n"); + LOG_DBG("Getting token\n"); if(0 == token_len) { - PRINTF("Error while handling coap observe notification: " - "no token in message\n"); + LOG_DBG("Error while handling coap observe notification: " + "no token in message\n"); return; } - PRINTF("Getting observee info\n"); + LOG_DBG("Getting observee info\n"); obs = coap_get_obs_subject_by_token(token, token_len); if(NULL == obs) { - PRINTF("Error while handling coap observe notification: " - "no matching token found\n"); + LOG_DBG("Error while handling coap observe notification: " + "no matching token found\n"); simple_reply(COAP_TYPE_RST, endpoint, notification); return; } @@ -240,7 +236,7 @@ coap_handle_notification(const coap_endpoint_t *endpoint, if(flag == NOTIFICATION_OK) { coap_get_header_observe(notification, &observe); if(observe == obs->last_observe) { - PRINTF("Discarding duplicate\n"); + LOG_DBG("Discarding duplicate\n"); return; } obs->last_observe = observe; @@ -256,7 +252,7 @@ handle_obs_registration_response(void *data, coap_message_t *response) notification_callback_t notification_callback; coap_notification_flag_t flag; - PRINTF("handle_obs_registration_response(): "); + LOG_DBG("handle_obs_registration_response()\n"); obs = (coap_observee_t *)data; notification_callback = obs->notification_callback; flag = classify_notification(response, 1); @@ -306,11 +302,11 @@ coap_obs_request_registration(const coap_endpoint_t *endpoint, char *uri, t->message_len = coap_serialize_message(request, t->message); coap_send_transaction(t); } else { - PRINTF("Could not allocate obs_subject resource buffer"); + LOG_DBG("Could not allocate obs_subject resource buffer\n"); coap_clear_transaction(t); } } else { - PRINTF("Could not allocate transaction buffer"); + LOG_DBG("Could not allocate transaction buffer\n"); } return obs; } diff --git a/os/net/app-layer/coap/coap-observe.c b/os/net/app-layer/coap/coap-observe.c index dea8414ef..ae3fe843f 100644 --- a/os/net/app-layer/coap/coap-observe.c +++ b/os/net/app-layer/coap/coap-observe.c @@ -43,15 +43,10 @@ #include "lib/memb.h" #include "lib/list.h" -#define DEBUG 0 -#if DEBUG -#include -#define PRINTF(...) printf(__VA_ARGS__) -#define PRINTEP(ep) coap_endpoint_print(ep) -#else -#define PRINTF(...) -#define PRINTEP(ep) -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "coap-observe" +#define LOG_LEVEL LOG_LEVEL_COAP /*---------------------------------------------------------------------------*/ MEMB(observers_memb, coap_observer_t, COAP_MAX_OBSERVERS); @@ -80,9 +75,9 @@ add_observer(const coap_endpoint_t *endpoint, const uint8_t *token, memcpy(o->token, token, token_len); o->last_mid = 0; - PRINTF("Adding observer (%u/%u) for /%s [0x%02X%02X]\n", - list_length(observers_list) + 1, COAP_MAX_OBSERVERS, - o->url, o->token[0], o->token[1]); + LOG_INFO("Adding observer (%u/%u) for /%s [0x%02X%02X]\n", + list_length(observers_list) + 1, COAP_MAX_OBSERVERS, + o->url, o->token[0], o->token[1]); list_add(observers_list, o); } @@ -94,8 +89,8 @@ add_observer(const coap_endpoint_t *endpoint, const uint8_t *token, void coap_remove_observer(coap_observer_t *o) { - PRINTF("Removing observer for /%s [0x%02X%02X]\n", o->url, o->token[0], - o->token[1]); + LOG_INFO("Removing observer for /%s [0x%02X%02X]\n", o->url, o->token[0], + o->token[1]); memb_free(&observers_memb, o); list_remove(observers_list, o); @@ -107,9 +102,9 @@ coap_remove_observer_by_client(const coap_endpoint_t *endpoint) int removed = 0; coap_observer_t *obs = NULL; - PRINTF("Remove check client "); - PRINTEP(endpoint); - PRINTF("\n"); + LOG_DBG("Remove check client "); + LOG_DBG_COAP_EP(endpoint); + LOG_DBG_("\n"); for(obs = (coap_observer_t *)list_head(observers_list); obs; obs = obs->next) { if(coap_endpoint_cmp(&obs->endpoint, endpoint)) { @@ -129,7 +124,7 @@ coap_remove_observer_by_token(const coap_endpoint_t *endpoint, for(obs = (coap_observer_t *)list_head(observers_list); obs; obs = obs->next) { - PRINTF("Remove check Token 0x%02X%02X\n", token[0], token[1]); + LOG_DBG("Remove check Token 0x%02X%02X\n", token[0], token[1]); if(coap_endpoint_cmp(&obs->endpoint, endpoint) && obs->token_len == token_len && memcmp(obs->token, token, token_len) == 0) { @@ -149,7 +144,7 @@ coap_remove_observer_by_uri(const coap_endpoint_t *endpoint, for(obs = (coap_observer_t *)list_head(observers_list); obs; obs = obs->next) { - PRINTF("Remove check URL %p\n", uri); + LOG_DBG("Remove check URL %p\n", uri); if((endpoint == NULL || (coap_endpoint_cmp(&obs->endpoint, endpoint))) && (obs->url == uri || memcmp(obs->url, uri, strlen(obs->url)) == 0)) { @@ -168,7 +163,7 @@ coap_remove_observer_by_mid(const coap_endpoint_t *endpoint, uint16_t mid) for(obs = (coap_observer_t *)list_head(observers_list); obs; obs = obs->next) { - PRINTF("Remove check MID %u\n", mid); + LOG_DBG("Remove check MID %u\n", mid); if(coap_endpoint_cmp(&obs->endpoint, endpoint) && obs->last_mid == mid) { coap_remove_observer(obs); @@ -214,7 +209,7 @@ coap_notify_observers_sub(coap_resource_t *resource, const char *subpath) /* Ensure url is null terminated because strncpy does not guarantee this */ url[COAP_OBSERVER_URL_LEN - 1] = '\0'; /* url now contains the notify URL that needs to match the observer */ - PRINTF("Observe: Notification from %s\n", url); + LOG_INFO("Notification from %s\n", url); coap_init_message(notification, COAP_TYPE_NON, CONTENT_2_05, 0); /* create a "fake" request for the URI */ @@ -245,13 +240,13 @@ coap_notify_observers_sub(coap_resource_t *resource, const char *subpath) if((transaction = coap_new_transaction(coap_get_mid(), &obs->endpoint))) { if(obs->obs_counter % COAP_OBSERVE_REFRESH_INTERVAL == 0) { - PRINTF(" Force Confirmable for\n"); + LOG_DBG(" Force Confirmable for\n"); notification->type = COAP_TYPE_CON; } - PRINTF(" Observer "); - PRINTEP(&obs->endpoint); - PRINTF("\n"); + LOG_DBG(" Observer "); + LOG_DBG_COAP_EP(&obs->endpoint); + LOG_DBG_("\n"); /* update last MID for RST matching */ obs->last_mid = transaction->mid; @@ -263,7 +258,7 @@ coap_notify_observers_sub(coap_resource_t *resource, const char *subpath) if(coap_call_handlers(request, notification, transaction->message + COAP_MAX_HEADER_SIZE, COAP_MAX_CHUNK_SIZE, NULL) > 0) { - PRINTF("Notification on new handlers\n"); + LOG_DBG("Notification on new handlers\n"); } else { if(resource != NULL) { resource->get_handler(request, notification, @@ -298,7 +293,7 @@ coap_observe_handler(coap_resource_t *resource, coap_message_t *coap_req, const coap_endpoint_t *src_ep; coap_observer_t *obs; - PRINTF("CoAP observer handler rsc: %d\n", resource != NULL); + LOG_DBG("CoAP observer handler rsc: %d\n", resource != NULL); if(coap_req->code == COAP_GET && coap_res->code < 128) { /* GET request and response without error code */ if(coap_is_option(coap_req, COAP_OPTION_OBSERVE)) { diff --git a/os/net/app-layer/coap/coap-res-well-known-core.c b/os/net/app-layer/coap/coap-res-well-known-core.c index 248271434..752cfa90e 100644 --- a/os/net/app-layer/coap/coap-res-well-known-core.c +++ b/os/net/app-layer/coap/coap-res-well-known-core.c @@ -40,13 +40,10 @@ #include #include -#define DEBUG 0 -#if DEBUG -#include -#define PRINTF(...) printf(__VA_ARGS__) -#else -#define PRINTF(...) -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "coap-res-well-known-core" +#define LOG_LEVEL LOG_LEVEL_COAP #define ADD_CHAR_IF_POSSIBLE(char) \ if(strpos >= *offset && bufpos < preferred_size) { \ @@ -64,7 +61,7 @@ + (*offset - (int32_t)strpos > 0 ? \ *offset - (int32_t)strpos : 0)); \ if(bufpos op preferred_size) { \ - PRINTF("res: BREAK at %s (%p)\n", string, resource); \ + LOG_DBG("BREAK at %s (%p)\n", string, resource); \ break; \ } \ } \ @@ -99,7 +96,9 @@ well_known_core_get_handler(coap_message_t *request, coap_message_t *response, ++value; len -= strlen(filter) + 1; - PRINTF("Filter %s = %.*s\n", filter, len, value); + LOG_DBG("Filter %s = ", filter); + LOG_DBG_COAP_STRING(value, len); + LOG_DBG_("\n"); if(strcmp(filter, "href") == 0 && value[0] == '/') { ++value; @@ -109,7 +108,7 @@ well_known_core_get_handler(coap_message_t *request, coap_message_t *response, lastchar = value[len - 1]; value[len - 1] = '\0'; } -#endif +#endif /* COAP_LINK_FORMAT_FILTERING */ for(resource = coap_get_first_resource(); resource; resource = coap_get_next_resource(resource)) { @@ -133,7 +132,7 @@ well_known_core_get_handler(coap_message_t *request, coap_message_t *response, end = strchr(attrib, '"'); } - PRINTF("Filter: res has attrib %s (%s)\n", attrib, value); + LOG_DBG("Filter: res has attrib %s (%s)\n", attrib, value); found = attrib; while((found = strstr(found, value)) != NULL) { if(found > end) { @@ -148,17 +147,17 @@ well_known_core_get_handler(coap_message_t *request, coap_message_t *response, if(found == NULL) { continue; } - PRINTF("Filter: res has prefix %s\n", found); + LOG_DBG("Filter: res has prefix %s\n", found); if(lastchar != '*' && (found[len] != '"' && found[len] != ' ' && found[len] != '\0')) { continue; } - PRINTF("Filter: res has match\n"); + LOG_DBG("Filter: res has match\n"); } #endif - PRINTF("res: /%s (%p)\npos: s%zu, o%ld, b%zu\n", resource->url, resource, - strpos, (long)*offset, bufpos); + LOG_DBG("/%s (%p)\npos: s%zu, o%ld, b%zu\n", resource->url, resource, + strpos, (long)*offset, bufpos); if(strpos > 0) { ADD_CHAR_IF_POSSIBLE(','); @@ -175,28 +174,30 @@ well_known_core_get_handler(coap_message_t *request, coap_message_t *response, /* buffer full, but resource not completed yet; or: do not break if resource exactly fills buffer. */ if(bufpos > preferred_size && strpos - bufpos > *offset) { - PRINTF("res: BREAK at %s (%p)\n", resource->url, resource); + LOG_DBG("BREAK at %s (%p)\n", resource->url, resource); break; } } if(bufpos > 0) { - PRINTF("BUF %zu: %.*s\n", bufpos, (int)bufpos, (char *)buffer); + LOG_DBG("BUF %zu: ", bufpos); + LOG_DBG_COAP_STRING((char *)buffer, bufpos); + LOG_DBG_("\n"); coap_set_payload(response, buffer, bufpos); coap_set_header_content_format(response, APPLICATION_LINK_FORMAT); } else if(strpos > 0) { - PRINTF("well_known_core_handler(): bufpos<=0\n"); + LOG_DBG("well_known_core_handler(): bufpos<=0\n"); coap_set_status_code(response, BAD_OPTION_4_02); coap_set_payload(response, "BlockOutOfScope", 15); } if(resource == NULL) { - PRINTF("res: DONE\n"); + LOG_DBG("DONE\n"); *offset = -1; } else { - PRINTF("res: MORE at %s (%p)\n", resource->url, resource); + LOG_DBG("MORE at %s (%p)\n", resource->url, resource); *offset += preferred_size; } } diff --git a/os/net/app-layer/coap/coap-separate.c b/os/net/app-layer/coap/coap-separate.c index ea2f11261..15f20eefa 100644 --- a/os/net/app-layer/coap/coap-separate.c +++ b/os/net/app-layer/coap/coap-separate.c @@ -42,13 +42,10 @@ #include "sys/cc.h" #include -#define DEBUG 0 -#if DEBUG -#include -#define PRINTF(...) printf(__VA_ARGS__) -#else -#define PRINTF(...) -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "coap-separate" +#define LOG_LEVEL LOG_LEVEL_COAP /*---------------------------------------------------------------------------*/ /*- Separate Response API ---------------------------------------------------*/ @@ -85,8 +82,9 @@ coap_separate_accept(coap_message_t *coap_req, coap_separate_t *separate_store) { coap_transaction_t *const t = coap_get_transaction_by_mid(coap_req->mid); - PRINTF("Separate ACCEPT: /%.*s MID %u\n", (int)coap_req->uri_path_len, - coap_req->uri_path, coap_req->mid); + LOG_DBG("Separate ACCEPT: /"); + LOG_DBG_COAP_STRING(coap_req->uri_path, coap_req->uri_path_len); + LOG_DBG_(" MID %u\n", coap_req->mid); if(t) { /* send separate ACK for CON */ if(coap_req->type == COAP_TYPE_CON) { @@ -95,7 +93,7 @@ coap_separate_accept(coap_message_t *coap_req, coap_separate_t *separate_store) ep = coap_get_src_endpoint(coap_req); if(ep == NULL) { - PRINTF("ERROR: no endpoint in request\n"); + LOG_ERR("ERROR: no endpoint in request\n"); } else { /* ACK with empty code (0) */ coap_init_message(ack, COAP_TYPE_ACK, 0, coap_req->mid); @@ -125,7 +123,7 @@ coap_separate_accept(coap_message_t *coap_req, coap_separate_t *separate_store) /* signal the engine to skip automatic response and clear transaction by engine */ coap_status_code = MANUAL_RESPONSE; } else { - PRINTF("ERROR: Response transaction for separate request not found!\n"); + LOG_ERR("ERROR: Response transaction for separate request not found!\n"); coap_status_code = INTERNAL_SERVER_ERROR_5_00; } } diff --git a/os/net/app-layer/coap/coap-timer-default.c b/os/net/app-layer/coap/coap-timer-default.c index 707d6367d..f0323dfee 100644 --- a/os/net/app-layer/coap/coap-timer-default.c +++ b/os/net/app-layer/coap/coap-timer-default.c @@ -40,13 +40,10 @@ #include "sys/etimer.h" #include "sys/process.h" -#define DEBUG 0 -#if DEBUG -#include -#define PRINTF(...) printf(__VA_ARGS__) -#else -#define PRINTF(...) -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "coap-timer-default" +#define LOG_LEVEL LOG_LEVEL_NONE PROCESS(coap_timer_process, "coap timer process"); @@ -58,7 +55,7 @@ update_timer(void) { uint64_t remaining; remaining = coap_timer_time_to_next_expiration(); - PRINTF("coap-timer-default: remaining %lu msec\n", (unsigned long)remaining); + LOG_DBG("remaining %lu msec\n", (unsigned long)remaining); if(remaining == 0) { /* Run as soon as possible */ process_poll(&coap_timer_process); diff --git a/os/net/app-layer/coap/coap-timer.c b/os/net/app-layer/coap/coap-timer.c index 6e2b15616..30583d33b 100644 --- a/os/net/app-layer/coap/coap-timer.c +++ b/os/net/app-layer/coap/coap-timer.c @@ -38,13 +38,10 @@ #include "coap-timer.h" #include "lib/list.h" -#define DEBUG 0 -#if DEBUG -#include -#define PRINTF(...) printf(__VA_ARGS__) -#else -#define PRINTF(...) -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "coap-timer" +#define LOG_LEVEL LOG_LEVEL_NONE #ifndef NULL #define NULL 0 @@ -63,8 +60,8 @@ add_timer(coap_timer_t *timer) coap_timer_init(); } - PRINTF("coap-timer: adding timer %p at %lu\n", timer, - (unsigned long)timer->expiration_time); + LOG_DBG("adding timer %p at %lu\n", timer, + (unsigned long)timer->expiration_time); p = list_head(timer_list); @@ -92,7 +89,7 @@ add_timer(coap_timer_t *timer) void coap_timer_stop(coap_timer_t *timer) { - PRINTF("coap-timer: stopping timer %p\n", timer); + LOG_DBG("stopping timer %p\n", timer); /* Mark timer as expired right now */ timer->expiration_time = coap_timer_uptime(); @@ -150,8 +147,7 @@ coap_timer_run(void) } if(next->expiration_time <= now) { - PRINTF("coap-timer: timer %p expired at %lu\n", next, - (unsigned long)now); + LOG_DBG("timer %p expired at %lu\n", next, (unsigned long)now); /* This timer should expire now */ list_remove(timer_list, next); diff --git a/os/net/app-layer/coap/coap-transactions.c b/os/net/app-layer/coap/coap-transactions.c index 73efa0650..b10d5a31a 100644 --- a/os/net/app-layer/coap/coap-transactions.c +++ b/os/net/app-layer/coap/coap-transactions.c @@ -43,15 +43,10 @@ #include "lib/list.h" #include -#define DEBUG 0 -#if DEBUG -#include -#define PRINTF(...) printf(__VA_ARGS__) -#define PRINTEP(ep) coap_endpoint_print(ep) -#else -#define PRINTF(...) -#define PRINTEP(ep) -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "coap-transactions" +#define LOG_LEVEL LOG_LEVEL_COAP /*---------------------------------------------------------------------------*/ MEMB(transactions_memb, coap_transaction_t, COAP_MAX_OPEN_TRANSACTIONS); @@ -63,11 +58,11 @@ coap_retransmit_transaction(coap_timer_t *nt) { coap_transaction_t *t = coap_timer_get_user_data(nt); if(t == NULL) { - PRINTF("No retransmission data in coap_timer!\n"); + LOG_DBG("No retransmission data in coap_timer!\n"); return; } ++(t->retrans_counter); - PRINTF("Retransmitting %u (%u)\n", t->mid, t->retrans_counter); + LOG_DBG("Retransmitting %u (%u)\n", t->mid, t->retrans_counter); coap_send_transaction(t); } /*---------------------------------------------------------------------------*/ @@ -96,7 +91,7 @@ coap_new_transaction(uint16_t mid, const coap_endpoint_t *endpoint) void coap_send_transaction(coap_transaction_t *t) { - PRINTF("Sending transaction %u\n", t->mid); + LOG_DBG("Sending transaction %u\n", t->mid); coap_sendto(&t->endpoint, t->message, t->message_len); @@ -104,7 +99,7 @@ coap_send_transaction(coap_transaction_t *t) ((COAP_HEADER_TYPE_MASK & t->message[0]) >> COAP_HEADER_TYPE_POSITION)) { if(t->retrans_counter < COAP_MAX_RETRANSMIT) { /* not timed out yet */ - PRINTF("Keeping transaction %u\n", t->mid); + LOG_DBG("Keeping transaction %u\n", t->mid); if(t->retrans_counter == 0) { coap_timer_set_callback(&t->retrans_timer, coap_retransmit_transaction); @@ -112,19 +107,19 @@ coap_send_transaction(coap_transaction_t *t) t->retrans_interval = COAP_RESPONSE_TIMEOUT_TICKS + (rand() % COAP_RESPONSE_TIMEOUT_BACKOFF_MASK); - PRINTF("Initial interval %lu msec\n", - (unsigned long)t->retrans_interval); + LOG_DBG("Initial interval %lu msec\n", + (unsigned long)t->retrans_interval); } else { t->retrans_interval <<= 1; /* double */ - PRINTF("Doubled (%u) interval %d s\n", t->retrans_counter, - t->retrans_interval / 1000); + LOG_DBG("Doubled (%u) interval %lu s\n", t->retrans_counter, + (unsigned long)(t->retrans_interval / 1000)); } /* interval updated above */ coap_timer_set(&t->retrans_timer, t->retrans_interval); } else { /* timed out */ - PRINTF("Timeout\n"); + LOG_DBG("Timeout\n"); coap_resource_response_handler_t callback = t->callback; void *callback_data = t->callback_data; @@ -146,7 +141,7 @@ void coap_clear_transaction(coap_transaction_t *t) { if(t) { - PRINTF("Freeing transaction %u: %p\n", t->mid, t); + LOG_DBG("Freeing transaction %u: %p\n", t->mid, t); coap_timer_stop(&t->retrans_timer); list_remove(transactions_list, t); @@ -161,7 +156,7 @@ coap_get_transaction_by_mid(uint16_t mid) for(t = (coap_transaction_t *)list_head(transactions_list); t; t = t->next) { if(t->mid == mid) { - PRINTF("Found transaction for MID %u: %p\n", t->mid, t); + LOG_DBG("Found transaction for MID %u: %p\n", t->mid, t); return t; } } diff --git a/os/net/app-layer/coap/coap-uip.c b/os/net/app-layer/coap/coap-uip.c index 5ea982d93..2468b6f47 100644 --- a/os/net/app-layer/coap/coap-uip.c +++ b/os/net/app-layer/coap/coap-uip.c @@ -36,7 +36,6 @@ */ #include "contiki.h" -#include "sys/cc.h" #include "net/ipv6/uip-udp-packet.h" #include "net/ipv6/uiplib.h" #include "coap.h" @@ -48,21 +47,14 @@ #include "coap-keystore.h" #include "coap-keystore-simple.h" - #if UIP_CONF_IPV6_RPL #include "rpl.h" #endif /* UIP_CONF_IPV6_RPL */ -#define DEBUG DEBUG_FULL -#include "net/ipv6/uip-debug.h" - -#define DEBUG_VERBOSE ((DEBUG) && 0) - -#if DEBUG -#define PRINTEP(X) coap_endpoint_print(X) -#else -#define PRINTEP(X) -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "coap-uip" +#define LOG_LEVEL LOG_LEVEL_COAP #ifdef WITH_DTLS #include "tinydtls.h" @@ -70,7 +62,6 @@ #include "dtls_debug.h" #endif /* WITH_DTLS */ - /* sanity check for configured values */ #if COAP_MAX_PACKET_SIZE > (UIP_BUFSIZE - UIP_IPH_LEN - UIP_UDPH_LEN) #error "UIP_CONF_BUFFER_SIZE too small for COAP_MAX_CHUNK_SIZE" @@ -99,20 +90,67 @@ PROCESS(coap_engine, "CoAP Engine"); static struct uip_udp_conn *udp_conn = NULL; +/*---------------------------------------------------------------------------*/ +void +coap_endpoint_log(const coap_endpoint_t *ep) +{ + if(ep == NULL) { + LOG_OUTPUT("(NULL EP)"); + return; + } + if(ep->secure) { + LOG_OUTPUT("coaps://["); + } else { + LOG_OUTPUT("coap://["); + } + log_6addr(&ep->ipaddr); + LOG_OUTPUT("]:%u", uip_ntohs(ep->port)); +} /*---------------------------------------------------------------------------*/ void coap_endpoint_print(const coap_endpoint_t *ep) { - if(ep->secure) { - printf("coaps:"); - } else { - printf("coap:"); + if(ep == NULL) { + printf("(NULL EP)"); + return; } - printf("//["); - uip_debug_ipaddr_print(&ep->ipaddr); + if(ep->secure) { + printf("coaps://["); + } else { + printf("coap://["); + } + uiplib_ipaddr_print(&ep->ipaddr); printf("]:%u", uip_ntohs(ep->port)); } /*---------------------------------------------------------------------------*/ +int +coap_endpoint_snprint(char *buf, size_t size, const coap_endpoint_t *ep) +{ + int n; + if(buf == NULL || size == 0) { + return 0; + } + if(ep == NULL) { + n = snprintf(buf, size - 1, "(NULL EP)"); + } else { + if(ep->secure) { + n = snprintf(buf, size - 1, "coaps://["); + } else { + n = snprintf(buf, size - 1, "coap://["); + } + if(n < size - 1) { + n += uiplib_ipaddr_snprint(&buf[n], size - n - 1, &ep->ipaddr); + } + if(n < size - 1) { + n += snprintf(&buf[n], size -n - 1, "]:%u", uip_ntohs(ep->port)); + } + } + if(n >= size - 1) { + buf[size - 1] = '\0'; + } + return n; +} +/*---------------------------------------------------------------------------*/ void coap_endpoint_copy(coap_endpoint_t *destination, const coap_endpoint_t *from) @@ -178,7 +216,7 @@ coap_endpoint_parse(const char *text, size_t size, coap_endpoint_t *ep) * Secure CoAP should use a different port but for now * the same port is used. */ - PRINTF("Using secure port (coaps)\n"); + LOG_DBG("Using secure port (coaps)\n"); ep->port = SERVER_LISTEN_SECURE_PORT; ep->secure = 1; } else { @@ -232,14 +270,15 @@ coap_endpoint_is_connected(const coap_endpoint_t *ep) peer = dtls_get_peer(dtls_context, ep); if(peer != NULL) { /* only if handshake is done! */ - PRINTF("DTLS peer state for "); - PRINTEP(ep); - PRINTF(" is %d %d\n", peer->state, dtls_peer_is_connected(peer)); + LOG_DBG("DTLS peer state for "); + LOG_DBG_COAP_EP(ep); + LOG_DBG_(" is %d %d\n", peer->state, dtls_peer_is_connected(peer)); return dtls_peer_is_connected(peer); } else { - PRINTF("DTLS did not find peer "); - PRINTEP(ep); - PRINTF("\n"); + LOG_DBG("DTLS did not find peer "); + LOG_DBG_COAP_EP(ep); + LOG_DBG_("\n"); + return 0; } } #endif /* WITH_DTLS */ @@ -252,16 +291,16 @@ int coap_endpoint_connect(coap_endpoint_t *ep) { if(ep->secure == 0) { - PRINTF("CoAP connect to "); - PRINTEP(ep); - PRINTF("\n"); + LOG_DBG("connect to "); + LOG_DBG_COAP_EP(ep); + LOG_DBG_("\n"); return 1; } #ifdef WITH_DTLS - PRINTF("DTLS connect to "); - PRINTEP(ep); - PRINTF("\n"); + LOG_DBG("DTLS connect to "); + LOG_DBG_COAP_EP(ep); + LOG_DBG_("\n"); /* setup all address info here... should be done to connect */ if(dtls_context) { @@ -314,10 +353,10 @@ coap_transport_init(void) static void process_secure_data(void) { - PRINTF("receiving secure UDP datagram from ["); - PRINT6ADDR(&UIP_IP_BUF->srcipaddr); - PRINTF("]:%u\n Length: %u\n", uip_ntohs(UIP_UDP_BUF->srcport), - uip_datalen()); + LOG_INFO("receiving secure UDP datagram from ["); + LOG_INFO_6ADDR(&UIP_IP_BUF->srcipaddr); + LOG_INFO_("]:%u\n Length: %u\n", uip_ntohs(UIP_UDP_BUF->srcport), + uip_datalen()); if(dtls_context) { dtls_handle_message(dtls_context, (coap_endpoint_t *)get_src_endpoint(1), @@ -329,10 +368,10 @@ process_secure_data(void) static void process_data(void) { - PRINTF("receiving UDP datagram from ["); - PRINT6ADDR(&UIP_IP_BUF->srcipaddr); - PRINTF("]:%u\n Length: %u\n", uip_ntohs(UIP_UDP_BUF->srcport), - uip_datalen()); + LOG_INFO("receiving UDP datagram from ["); + LOG_INFO_6ADDR(&UIP_IP_BUF->srcipaddr); + LOG_INFO_("]:%u\n Length: %u\n", uip_ntohs(UIP_UDP_BUF->srcport), + uip_datalen()); coap_receive(get_src_endpoint(0), uip_appdata, uip_datalen()); } @@ -341,14 +380,14 @@ int coap_sendto(const coap_endpoint_t *ep, const uint8_t *data, uint16_t length) { if(ep == NULL) { - PRINTF("coap-uip: failed to send - no endpoint\n"); + LOG_WARN("failed to send - no endpoint\n"); return -1; } if(!coap_endpoint_is_connected(ep)) { - PRINTF("coap-uip: endpoint "); - PRINTEP(ep); - PRINTF(" not connected - dropping packet\n"); + LOG_WARN("endpoint "); + LOG_WARN_COAP_EP(ep); + LOG_WARN_(" not connected - dropping packet\n"); return -1; } @@ -358,24 +397,25 @@ coap_sendto(const coap_endpoint_t *ep, const uint8_t *data, uint16_t length) int ret; ret = dtls_write(dtls_context, (session_t *)ep, (uint8_t *)data, length); - PRINTF("coap-uip: sent DTLS to "); - PRINTEP(ep); + LOG_INFO("sent DTLS to "); + LOG_INFO_COAP_EP(ep); if(ret < 0) { - PRINTF(" - error %d\n", ret); + LOG_INFO_(" - error %d\n", ret); } else { - PRINTF(" %d/%u bytes\n", ret, length); + LOG_INFO_(" %d/%u bytes\n", ret, length); } return ret; + } else { + LOG_WARN("no DTLS context\n"); + return -1; } - PRINTF("coap-uip: no DTLS context\n"); - return -1; } #endif /* WITH_DTLS */ uip_udp_packet_sendto(udp_conn, data, length, &ep->ipaddr, ep->port); - PRINTF("coap-uip: sent to "); - PRINTEP(ep); - PRINTF(" %u bytes\n", length); + LOG_INFO("sent to "); + LOG_INFO_COAP_EP(ep); + LOG_INFO_(" %u bytes\n", length); return length; } /*---------------------------------------------------------------------------*/ @@ -386,18 +426,18 @@ PROCESS_THREAD(coap_engine, ev, data) /* new connection with remote host */ udp_conn = udp_new(NULL, 0, NULL); udp_bind(udp_conn, SERVER_LISTEN_PORT); - PRINTF("Listening on port %u\n", uip_ntohs(udp_conn->lport)); + LOG_INFO("Listening on port %u\n", uip_ntohs(udp_conn->lport)); #ifdef WITH_DTLS /* create new context with app-data */ dtls_conn = udp_new(NULL, 0, NULL); if(dtls_conn != NULL) { udp_bind(dtls_conn, SERVER_LISTEN_SECURE_PORT); - PRINTF("DTLS listening on port %u\n", uip_ntohs(dtls_conn->lport)); + LOG_INFO("DTLS listening on port %u\n", uip_ntohs(dtls_conn->lport)); dtls_context = dtls_new_context(dtls_conn); } if(!dtls_context) { - PRINTF("DTLS: cannot create context\n"); + LOG_WARN("DTLS: cannot create context\n"); } else { dtls_set_handler(dtls_context, &cb); } @@ -432,19 +472,20 @@ static int input_from_peer(struct dtls_context_t *ctx, session_t *session, uint8_t *data, size_t len) { -#if DEBUG_VERBOSE size_t i; - PRINTF("received DTLS data:"); - for(i = 0; i < len; i++) { - PRINTF("%c", data[i]); + if(LOG_DBG_ENABLED) { + LOG_DBG("received DTLS data:"); + for(i = 0; i < len; i++) { + LOG_DBG_("%c", data[i]); + } + LOG_DBG_("\n"); + LOG_DBG("Hex:"); + for(i = 0; i < len; i++) { + LOG_DBG_("%02x", data[i]); + } + LOG_DBG_("\n"); } - PRINTF("\nHex:"); - for(i = 0; i < len; i++) { - PRINTF("%02x", data[i]); - } - PRINTF("\n"); -#endif /* DEBUG_VERBOSE */ /* Ensure that the endpoint is tagged as secure */ session->secure = 1; @@ -460,9 +501,9 @@ output_to_peer(struct dtls_context_t *ctx, session_t *session, uint8_t *data, size_t len) { struct uip_udp_conn *udp_connection = dtls_get_app_data(ctx); - PRINTF("coap-uip: output_to DTLS peer ["); - PRINT6ADDR(&session->ipaddr); - PRINTF("]:%u %d bytes\n", session->port, (int)len); + LOG_DBG("output_to DTLS peer ["); + LOG_DBG_6ADDR(&session->ipaddr); + LOG_DBG_("]:%u %d bytes\n", session->port, (int)len); uip_udp_packet_sendto(udp_connection, data, len, &session->ipaddr, session->port); return len; @@ -488,18 +529,20 @@ get_psk_info(struct dtls_context_t *ctx, coap_keystore_psk_entry_t ks; if(dtls_keystore == NULL) { - PRINTF("coap-uip: --- No key store available ---\n"); + LOG_DBG("--- No key store available ---\n"); return 0; } memset(&ks, 0, sizeof(ks)); - PRINTF("coap-uip: ---===>>> Getting the Key or ID <<<===---\n"); + LOG_DBG("---===>>> Getting the Key or ID <<<===---\n"); switch(type) { case DTLS_PSK_IDENTITY: if(id && id_len) { ks.identity_hint = id; ks.identity_hint_len = id_len; - PRINTF("coap-uip: got psk_identity_hint: '%.*s'\n", id_len, id); + LOG_DBG("got psk_identity_hint: '"); + LOG_DBG_COAP_STRING(id, id_len); + LOG_DBG_("'\n"); } if(dtls_keystore->coap_get_psk_info) { @@ -507,16 +550,16 @@ get_psk_info(struct dtls_context_t *ctx, dtls_keystore->coap_get_psk_info((coap_endpoint_t *)session, &ks); } if(ks.identity == NULL || ks.identity_len == 0) { - PRINTF("coap-uip: no psk_identity found\n"); + LOG_DBG("no psk_identity found\n"); return 0; } if(result_length < ks.identity_len) { - PRINTF("coap-uip: cannot return psk_identity -- buffer too small\n"); + LOG_DBG("cannot return psk_identity -- buffer too small\n"); return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); } memcpy(result, ks.identity, ks.identity_len); - PRINTF("coap-uip: psk_identity with %u bytes found\n", ks.identity_len); + LOG_DBG("psk_identity with %u bytes found\n", ks.identity_len); return ks.identity_len; case DTLS_PSK_KEY: @@ -527,20 +570,20 @@ get_psk_info(struct dtls_context_t *ctx, dtls_keystore->coap_get_psk_info((coap_endpoint_t *)session, &ks); } if(ks.key == NULL || ks.key_len == 0) { - PRINTF("coap-uip: PSK for unknown id requested, exiting\n"); + LOG_DBG("PSK for unknown id requested, exiting\n"); return dtls_alert_fatal_create(DTLS_ALERT_ILLEGAL_PARAMETER); } if(result_length < ks.key_len) { - PRINTF("coap-uip: cannot return psk -- buffer too small\n"); + LOG_DBG("cannot return psk -- buffer too small\n"); return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); } memcpy(result, ks.key, ks.key_len); - PRINTF("coap-uip: psk with %u bytes found\n", ks.key_len); + LOG_DBG("psk with %u bytes found\n", ks.key_len); return ks.key_len; default: - PRINTF("coap-uip: unsupported key store request type: %d\n", type); + LOG_WARN("unsupported key store request type: %d\n", type); } return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); diff --git a/os/net/app-layer/coap/coap.c b/os/net/app-layer/coap/coap.c index ad6f68b3e..9e46eea5a 100644 --- a/os/net/app-layer/coap/coap.c +++ b/os/net/app-layer/coap/coap.c @@ -52,19 +52,10 @@ #include "coap.h" #include "coap-transactions.h" -#define DEBUG 0 -#if DEBUG -#include -#define PRINTF(...) printf(__VA_ARGS__) -#define PRINTS(l,s,f) do { int i; \ - for(i = 0; i < l; i++) printf(f, s[i]); \ - } while(0) -#define PRINTPRE(p,l,s) do { PRINTF(p);PRINTS(l,s,"%c"); } while(0); -#else -#define PRINTF(...) -#define PRINTS(l,s,f) -#define PRINTPRE(p,l,s) -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "coap" +#define LOG_LEVEL LOG_LEVEL_COAP /*---------------------------------------------------------------------------*/ /*- Variables ---------------------------------------------------------------*/ @@ -135,7 +126,7 @@ coap_set_option_header(unsigned int delta, size_t length, uint8_t *buffer) buffer[++written] = (length - 13); } - PRINTF("WRITTEN %zu B opt header\n", 1 + written); + LOG_DBG("WRITTEN %zu B opt header\n", 1 + written); return ++written; } @@ -158,8 +149,8 @@ coap_serialize_int_option(unsigned int number, unsigned int current_number, if(0xFFFFFFFF & value) { ++i; } - PRINTF("OPTION %u (delta %u, len %zu)\n", number, number - current_number, - i); + LOG_DBG("OPTION %u (delta %u, len %zu)\n", number, number - current_number, + i); i = coap_set_option_header(number - current_number, i, buffer); @@ -185,9 +176,9 @@ coap_serialize_array_option(unsigned int number, unsigned int current_number, { size_t i = 0; - PRINTF("ARRAY type %u, len %zu, full [", number, length); - PRINTS(length, array, "%c"); - PRINTF("]\n"); + LOG_DBG("ARRAY type %u, len %zu, full [", number, length); + LOG_DBG_COAP_STRING((const char *)array, length); + LOG_DBG_("]\n"); if(split_char != '\0') { int j; @@ -196,7 +187,7 @@ coap_serialize_array_option(unsigned int number, unsigned int current_number, size_t temp_length; for(j = 0; j <= length + 1; ++j) { - PRINTF("STEP %u/%zu (%c)\n", j, length, array[j]); + LOG_DBG("STEP %u/%zu (%c)\n", j, length, array[j]); if(array[j] == split_char || j == length) { part_end = array + j; temp_length = part_end - part_start; @@ -206,10 +197,10 @@ coap_serialize_array_option(unsigned int number, unsigned int current_number, memcpy(&buffer[i], part_start, temp_length); i += temp_length; - PRINTF("OPTION type %u, delta %u, len %zu, part [", number, - number - current_number, i); - PRINTS((int)temp_length, part_start, "%c"); - PRINTF("]\n"); + LOG_DBG("OPTION type %u, delta %u, len %zu, part [", number, + number - current_number, i); + LOG_DBG_COAP_STRING((const char *)part_start, temp_length); + LOG_DBG_("]\n"); ++j; /* skip the splitter */ current_number = number; part_start = array + j; @@ -220,8 +211,8 @@ coap_serialize_array_option(unsigned int number, unsigned int current_number, memcpy(&buffer[i], array, length); i += length; - PRINTF("OPTION type %u, delta %u, len %zu\n", number, - number - current_number, length); + LOG_DBG("OPTION type %u, delta %u, len %zu\n", number, + number - current_number, length); } return i; @@ -320,7 +311,7 @@ coap_serialize_message(coap_message_t *coap_pkt, uint8_t *buffer) coap_pkt->buffer = buffer; coap_pkt->version = 1; - PRINTF("-Serializing MID %u to %p, ", coap_pkt->mid, coap_pkt->buffer); + LOG_DBG("-Serializing MID %u to %p, ", coap_pkt->mid, coap_pkt->buffer); /* set header fields */ coap_pkt->buffer[0] = 0x00; @@ -336,25 +327,25 @@ coap_serialize_message(coap_message_t *coap_pkt, uint8_t *buffer) /* empty message, dont need to do more stuff */ if(!coap_pkt->code) { - PRINTF("-Done serializing empty message at %p-\n", coap_pkt->buffer); + LOG_DBG_("-Done serializing empty message at %p-\n", coap_pkt->buffer); return 4; } /* set Token */ - PRINTF("Token (len %u)", coap_pkt->token_len); + LOG_DBG_("Token (len %u)", coap_pkt->token_len); option = coap_pkt->buffer + COAP_HEADER_LEN; for(current_number = 0; current_number < coap_pkt->token_len; ++current_number) { - PRINTF(" %02X", coap_pkt->token[current_number]); + LOG_DBG_(" %02X", coap_pkt->token[current_number]); *option = coap_pkt->token[current_number]; ++option; } - PRINTF("-\n"); + LOG_DBG_("-\n"); /* Serialize options */ current_number = 0; - PRINTF("-Serializing options at %p-\n", option); + LOG_DBG("-Serializing options at %p-\n", option); /* The options must be serialized in the order of their number */ COAP_SERIALIZE_BYTE_OPTION(COAP_OPTION_IF_MATCH, if_match, "If-Match"); @@ -372,7 +363,7 @@ coap_serialize_message(coap_message_t *coap_pkt, uint8_t *buffer) "Location-Path"); COAP_SERIALIZE_STRING_OPTION(COAP_OPTION_URI_PATH, uri_path, '/', "Uri-Path"); - PRINTF("Serialize content format: %d\n", coap_pkt->content_format); + LOG_DBG("Serialize content format: %d\n", coap_pkt->content_format); COAP_SERIALIZE_INT_OPTION(COAP_OPTION_CONTENT_FORMAT, content_format, "Content-Format"); COAP_SERIALIZE_INT_OPTION(COAP_OPTION_MAX_AGE, max_age, "Max-Age"); @@ -390,7 +381,7 @@ coap_serialize_message(coap_message_t *coap_pkt, uint8_t *buffer) "Proxy-Scheme"); COAP_SERIALIZE_INT_OPTION(COAP_OPTION_SIZE1, size1, "Size1"); - PRINTF("-Done serializing at %p----\n", option); + LOG_DBG("-Done serializing at %p----\n", option); /* Pack payload */ if((option - coap_pkt->buffer) <= COAP_MAX_HEADER_SIZE) { @@ -407,19 +398,15 @@ coap_serialize_message(coap_message_t *coap_pkt, uint8_t *buffer) return 0; } - PRINTF("-Done %u B (header len %u, payload len %u)-\n", - (unsigned int)(coap_pkt->payload_len + option - buffer), - (unsigned int)(option - buffer), - (unsigned int)coap_pkt->payload_len); + LOG_DBG("-Done %u B (header len %u, payload len %u)-\n", + (unsigned int)(coap_pkt->payload_len + option - buffer), + (unsigned int)(option - buffer), + (unsigned int)coap_pkt->payload_len); - PRINTF("Dump [0x%02X %02X %02X %02X %02X %02X %02X %02X]\n", - coap_pkt->buffer[0], - coap_pkt->buffer[1], - coap_pkt->buffer[2], - coap_pkt->buffer[3], - coap_pkt->buffer[4], - coap_pkt->buffer[5], coap_pkt->buffer[6], coap_pkt->buffer[7] - ); + LOG_DBG("Dump [0x%02X %02X %02X %02X %02X %02X %02X %02X]\n", + coap_pkt->buffer[0], coap_pkt->buffer[1], coap_pkt->buffer[2], + coap_pkt->buffer[3], coap_pkt->buffer[4], coap_pkt->buffer[5], + coap_pkt->buffer[6], coap_pkt->buffer[7]); return (option - buffer) + coap_pkt->payload_len; /* message length */ } @@ -456,11 +443,11 @@ coap_parse_message(coap_message_t *coap_pkt, uint8_t *data, uint16_t data_len) uint8_t *current_option = data + COAP_HEADER_LEN; memcpy(coap_pkt->token, current_option, coap_pkt->token_len); - PRINTF("Token (len %u) [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", - coap_pkt->token_len, coap_pkt->token[0], coap_pkt->token[1], - coap_pkt->token[2], coap_pkt->token[3], coap_pkt->token[4], - coap_pkt->token[5], coap_pkt->token[6], coap_pkt->token[7] - ); /*FIXME always prints 8 bytes */ + LOG_DBG("Token (len %u) [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", + coap_pkt->token_len, coap_pkt->token[0], coap_pkt->token[1], + coap_pkt->token[2], coap_pkt->token[3], coap_pkt->token[4], + coap_pkt->token[5], coap_pkt->token[6], coap_pkt->token[7] + ); /* FIXME always prints 8 bytes */ /* parse options */ memset(coap_pkt->options, 0, sizeof(coap_pkt->options)); @@ -514,8 +501,8 @@ coap_parse_message(coap_message_t *coap_pkt, uint8_t *data, uint16_t data_len) if(current_option + option_length > data + data_len) { /* Malformed CoAP - out of bounds */ - PRINTF("BAD REQUEST: options outside data message: %u > %u\n", - (unsigned)(current_option + option_length - data), data_len); + LOG_WARN("BAD REQUEST: options outside data message: %u > %u\n", + (unsigned)(current_option + option_length - data), data_len); return BAD_REQUEST_4_00; } @@ -523,12 +510,12 @@ coap_parse_message(coap_message_t *coap_pkt, uint8_t *data, uint16_t data_len) if(option_number > COAP_OPTION_SIZE1) { /* Malformed CoAP - out of bounds */ - PRINTF("BAD REQUEST: option number too large: %u\n", option_number); + LOG_WARN("BAD REQUEST: option number too large: %u\n", option_number); return BAD_REQUEST_4_00; } - PRINTF("OPTION %u (delta %u, len %zu): ", option_number, option_delta, - option_length); + LOG_DBG("OPTION %u (delta %u, len %zu): ", option_number, option_delta, + option_length); coap_set_option(coap_pkt, option_number); @@ -536,51 +523,51 @@ coap_parse_message(coap_message_t *coap_pkt, uint8_t *data, uint16_t data_len) case COAP_OPTION_CONTENT_FORMAT: coap_pkt->content_format = coap_parse_int_option(current_option, option_length); - PRINTF("Content-Format [%u]\n", coap_pkt->content_format); + LOG_DBG_("Content-Format [%u]\n", coap_pkt->content_format); break; case COAP_OPTION_MAX_AGE: coap_pkt->max_age = coap_parse_int_option(current_option, option_length); - PRINTF("Max-Age [%lu]\n", (unsigned long)coap_pkt->max_age); + LOG_DBG_("Max-Age [%lu]\n", (unsigned long)coap_pkt->max_age); break; case COAP_OPTION_ETAG: coap_pkt->etag_len = MIN(COAP_ETAG_LEN, option_length); memcpy(coap_pkt->etag, current_option, coap_pkt->etag_len); - PRINTF("ETag %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", - coap_pkt->etag_len, coap_pkt->etag[0], coap_pkt->etag[1], - coap_pkt->etag[2], coap_pkt->etag[3], coap_pkt->etag[4], - coap_pkt->etag[5], coap_pkt->etag[6], coap_pkt->etag[7] - ); /*FIXME always prints 8 bytes */ + LOG_DBG_("ETag %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", + coap_pkt->etag_len, coap_pkt->etag[0], coap_pkt->etag[1], + coap_pkt->etag[2], coap_pkt->etag[3], coap_pkt->etag[4], + coap_pkt->etag[5], coap_pkt->etag[6], coap_pkt->etag[7] + ); /*FIXME always prints 8 bytes */ break; case COAP_OPTION_ACCEPT: coap_pkt->accept = coap_parse_int_option(current_option, option_length); - PRINTF("Accept [%u]\n", coap_pkt->accept); + LOG_DBG_("Accept [%u]\n", coap_pkt->accept); break; case COAP_OPTION_IF_MATCH: /* TODO support multiple ETags */ coap_pkt->if_match_len = MIN(COAP_ETAG_LEN, option_length); memcpy(coap_pkt->if_match, current_option, coap_pkt->if_match_len); - PRINTF("If-Match %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", - coap_pkt->if_match_len, coap_pkt->if_match[0], - coap_pkt->if_match[1], coap_pkt->if_match[2], - coap_pkt->if_match[3], coap_pkt->if_match[4], - coap_pkt->if_match[5], coap_pkt->if_match[6], - coap_pkt->if_match[7] - ); /* FIXME always prints 8 bytes */ + LOG_DBG_("If-Match %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", + coap_pkt->if_match_len, coap_pkt->if_match[0], + coap_pkt->if_match[1], coap_pkt->if_match[2], + coap_pkt->if_match[3], coap_pkt->if_match[4], + coap_pkt->if_match[5], coap_pkt->if_match[6], + coap_pkt->if_match[7] + ); /* FIXME always prints 8 bytes */ break; case COAP_OPTION_IF_NONE_MATCH: coap_pkt->if_none_match = 1; - PRINTF("If-None-Match\n"); + LOG_DBG_("If-None-Match\n"); break; case COAP_OPTION_PROXY_URI: #if COAP_PROXY_OPTION_PROCESSING coap_pkt->proxy_uri = (char *)current_option; coap_pkt->proxy_uri_len = option_length; -#endif - PRINTPRE("Proxy-Uri NOT IMPLEMENTED [",(int)coap_pkt->proxy_uri_len, - coap_pkt->proxy_uri); - PRINTF("]\n"); +#endif /* COAP_PROXY_OPTION_PROCESSING */ + LOG_DBG_("Proxy-Uri NOT IMPLEMENTED ["); + LOG_DBG_COAP_STRING(coap_pkt->proxy_uri, coap_pkt->proxy_uri_len); + LOG_DBG_("]\n"); coap_error_message = "This is a constrained server (Contiki)"; return PROXYING_NOT_SUPPORTED_5_05; @@ -590,9 +577,9 @@ coap_parse_message(coap_message_t *coap_pkt, uint8_t *data, uint16_t data_len) coap_pkt->proxy_scheme = (char *)current_option; coap_pkt->proxy_scheme_len = option_length; #endif - PRINTPRE("Proxy-Scheme NOT IMPLEMENTED [", - (int)coap_pkt->proxy_scheme_len, coap_pkt->proxy_scheme); - PRINTF("]\n"); + LOG_DBG_("Proxy-Scheme NOT IMPLEMENTED ["); + LOG_DBG_COAP_STRING(coap_pkt->proxy_scheme, coap_pkt->proxy_scheme_len); + LOG_DBG_("]\n"); coap_error_message = "This is a constrained server (Contiki)"; return PROXYING_NOT_SUPPORTED_5_05; break; @@ -600,30 +587,32 @@ coap_parse_message(coap_message_t *coap_pkt, uint8_t *data, uint16_t data_len) case COAP_OPTION_URI_HOST: coap_pkt->uri_host = (char *)current_option; coap_pkt->uri_host_len = option_length; - PRINTPRE("Uri-Host [", (int)coap_pkt->uri_host_len, - coap_pkt->uri_host); - PRINTF("]\n"); + LOG_DBG_("Uri-Host ["); + LOG_DBG_COAP_STRING(coap_pkt->uri_host, coap_pkt->uri_host_len); + LOG_DBG_("]\n"); break; case COAP_OPTION_URI_PORT: coap_pkt->uri_port = coap_parse_int_option(current_option, option_length); - PRINTF("Uri-Port [%u]\n", coap_pkt->uri_port); + LOG_DBG_("Uri-Port [%u]\n", coap_pkt->uri_port); break; case COAP_OPTION_URI_PATH: /* coap_merge_multi_option() operates in-place on the IPBUF, but final message field should be const string -> cast to string */ coap_merge_multi_option((char **)&(coap_pkt->uri_path), &(coap_pkt->uri_path_len), current_option, option_length, '/'); - PRINTPRE("Uri-Path [",(int)coap_pkt->uri_path_len, coap_pkt->uri_path); - PRINTF("]\n"); + LOG_DBG_("Uri-Path ["); + LOG_DBG_COAP_STRING(coap_pkt->uri_path, coap_pkt->uri_path_len); + LOG_DBG_("]\n"); break; case COAP_OPTION_URI_QUERY: /* coap_merge_multi_option() operates in-place on the IPBUF, but final message field should be const string -> cast to string */ coap_merge_multi_option((char **)&(coap_pkt->uri_query), &(coap_pkt->uri_query_len), current_option, option_length, '&'); - PRINTPRE("Uri-Query[",(int)coap_pkt->uri_query_len,coap_pkt->uri_query); - PRINTF("]\n"); + LOG_DBG_("Uri-Query["); + LOG_DBG_COAP_STRING(coap_pkt->uri_query, coap_pkt->uri_query_len); + LOG_DBG_("]\n"); break; case COAP_OPTION_LOCATION_PATH: @@ -632,24 +621,24 @@ coap_parse_message(coap_message_t *coap_pkt, uint8_t *data, uint16_t data_len) &(coap_pkt->location_path_len), current_option, option_length, '/'); - PRINTPRE("Location-Path [",(int)coap_pkt->location_path_len, - coap_pkt->location_path); - PRINTF("]\n"); + LOG_DBG_("Location-Path ["); + LOG_DBG_COAP_STRING(coap_pkt->location_path, coap_pkt->location_path_len); + LOG_DBG_("]\n"); break; case COAP_OPTION_LOCATION_QUERY: /* coap_merge_multi_option() operates in-place on the IPBUF, but final message field should be const string -> cast to string */ coap_merge_multi_option((char **)&(coap_pkt->location_query), &(coap_pkt->location_query_len), current_option, option_length, '&'); - PRINTPRE("Location-Query [",(int)coap_pkt->location_query_len, - coap_pkt->location_query); - PRINTF("]\n"); + LOG_DBG_("Location-Query ["); + LOG_DBG_COAP_STRING(coap_pkt->location_query, coap_pkt->location_query_len); + LOG_DBG_("]\n"); break; case COAP_OPTION_OBSERVE: coap_pkt->observe = coap_parse_int_option(current_option, option_length); - PRINTF("Observe [%lu]\n", (unsigned long)coap_pkt->observe); + LOG_DBG_("Observe [%lu]\n", (unsigned long)coap_pkt->observe); break; case COAP_OPTION_BLOCK2: coap_pkt->block2_num = coap_parse_int_option(current_option, @@ -659,9 +648,9 @@ coap_parse_message(coap_message_t *coap_pkt, uint8_t *data, uint16_t data_len) coap_pkt->block2_offset = (coap_pkt->block2_num & ~0x0000000F) << (coap_pkt->block2_num & 0x07); coap_pkt->block2_num >>= 4; - PRINTF("Block2 [%lu%s (%u B/blk)]\n", - (unsigned long)coap_pkt->block2_num, - coap_pkt->block2_more ? "+" : "", coap_pkt->block2_size); + LOG_DBG_("Block2 [%lu%s (%u B/blk)]\n", + (unsigned long)coap_pkt->block2_num, + coap_pkt->block2_more ? "+" : "", coap_pkt->block2_size); break; case COAP_OPTION_BLOCK1: coap_pkt->block1_num = coap_parse_int_option(current_option, @@ -671,20 +660,20 @@ coap_parse_message(coap_message_t *coap_pkt, uint8_t *data, uint16_t data_len) coap_pkt->block1_offset = (coap_pkt->block1_num & ~0x0000000F) << (coap_pkt->block1_num & 0x07); coap_pkt->block1_num >>= 4; - PRINTF("Block1 [%lu%s (%u B/blk)]\n", - (unsigned long)coap_pkt->block1_num, - coap_pkt->block1_more ? "+" : "", coap_pkt->block1_size); + LOG_DBG_("Block1 [%lu%s (%u B/blk)]\n", + (unsigned long)coap_pkt->block1_num, + coap_pkt->block1_more ? "+" : "", coap_pkt->block1_size); break; case COAP_OPTION_SIZE2: coap_pkt->size2 = coap_parse_int_option(current_option, option_length); - PRINTF("Size2 [%lu]\n", (unsigned long)coap_pkt->size2); + LOG_DBG_("Size2 [%lu]\n", (unsigned long)coap_pkt->size2); break; case COAP_OPTION_SIZE1: coap_pkt->size1 = coap_parse_int_option(current_option, option_length); - PRINTF("Size1 [%lu]\n", (unsigned long)coap_pkt->size1); + LOG_DBG_("Size1 [%lu]\n", (unsigned long)coap_pkt->size1); break; default: - PRINTF("unknown (%u)\n", option_number); + LOG_DBG_("unknown (%u)\n", option_number); /* check if critical (odd) */ if(option_number & 1) { coap_error_message = "Unsupported critical option"; @@ -694,7 +683,7 @@ coap_parse_message(coap_message_t *coap_pkt, uint8_t *data, uint16_t data_len) current_option += option_length; } /* for */ - PRINTF("-Done parsing-------\n"); + LOG_DBG("-Done parsing-------\n"); return NO_ERROR; } diff --git a/os/net/app-layer/coap/coap.h b/os/net/app-layer/coap/coap.h index 4cc97a869..9a93c7525 100644 --- a/os/net/app-layer/coap/coap.h +++ b/os/net/app-layer/coap/coap.h @@ -146,13 +146,13 @@ coap_is_option(const coap_message_t *message, unsigned int opt) /* option format serialization */ #define COAP_SERIALIZE_INT_OPTION(number, field, text) \ if(coap_is_option(coap_pkt, number)) { \ - PRINTF(text " [%u]\n", (unsigned int)coap_pkt->field); \ + LOG_DBG(text " [%u]\n", (unsigned int)coap_pkt->field); \ option += coap_serialize_int_option(number, current_number, option, coap_pkt->field); \ current_number = number; \ } #define COAP_SERIALIZE_BYTE_OPTION(number, field, text) \ if(coap_is_option(coap_pkt, number)) { \ - PRINTF(text " %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", (unsigned int)coap_pkt->field##_len, \ + LOG_DBG(text " %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", (unsigned int)coap_pkt->field##_len, \ coap_pkt->field[0], \ coap_pkt->field[1], \ coap_pkt->field[2], \ @@ -165,21 +165,21 @@ coap_is_option(const coap_message_t *message, unsigned int opt) option += coap_serialize_array_option(number, current_number, option, coap_pkt->field, coap_pkt->field##_len, '\0'); \ current_number = number; \ } -#define COAP_SERIALIZE_STRING_OPTION(number, field, splitter, text) \ - if(coap_is_option(coap_pkt, number)) { \ - PRINTPRE(text " [", (int)coap_pkt->field##_len, coap_pkt->field); \ - PRINTF("]\n"); \ +#define COAP_SERIALIZE_STRING_OPTION(number, field, splitter, text) \ + if(coap_is_option(coap_pkt, number)) { \ + LOG_DBG(text " ["); \ + LOG_DBG_COAP_STRING(coap_pkt->field, coap_pkt->field##_len); \ + LOG_DBG_("]\n"); \ option += coap_serialize_array_option(number, current_number, option, (uint8_t *)coap_pkt->field, coap_pkt->field##_len, splitter); \ current_number = number; \ } #define COAP_SERIALIZE_BLOCK_OPTION(number, field, text) \ - if(coap_is_option(coap_pkt, number)) \ - { \ - PRINTF(text " [%lu%s (%u B/blk)]\n", (unsigned long)coap_pkt->field##_num, coap_pkt->field##_more ? "+" : "", coap_pkt->field##_size); \ + if(coap_is_option(coap_pkt, number)) { \ + LOG_DBG(text " [%lu%s (%u B/blk)]\n", (unsigned long)coap_pkt->field##_num, coap_pkt->field##_more ? "+" : "", coap_pkt->field##_size); \ uint32_t block = coap_pkt->field##_num << 4; \ if(coap_pkt->field##_more) { block |= 0x8; } \ block |= 0xF & coap_log_2(coap_pkt->field##_size / 16); \ - PRINTF(text " encoded: 0x%lX\n", (unsigned long)block); \ + LOG_DBG(text " encoded: 0x%lX\n", (unsigned long)block); \ option += coap_serialize_int_option(number, current_number, option, block); \ current_number = number; \ } From 49d38e6d06fcaa9332d2363fe111e32c27dcfe75 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Fri, 1 Dec 2017 02:36:17 +0100 Subject: [PATCH 24/51] Added LWM2M runtime log level to the logging module --- examples/libs/logging/project-conf.h | 1 + os/sys/log-conf.h | 4 ++++ os/sys/log.c | 2 ++ os/sys/log.h | 2 ++ tools/viewconf.c | 1 + 5 files changed, 10 insertions(+) diff --git a/examples/libs/logging/project-conf.h b/examples/libs/logging/project-conf.h index 2a39f6d5f..8f393c319 100644 --- a/examples/libs/logging/project-conf.h +++ b/examples/libs/logging/project-conf.h @@ -46,6 +46,7 @@ #define LOG_CONF_LEVEL_MAC LOG_LEVEL_DBG #define LOG_CONF_LEVEL_FRAMER LOG_LEVEL_DBG #define LOG_CONF_LEVEL_COAP LOG_LEVEL_DBG +#define LOG_CONF_LEVEL_LWM2M LOG_LEVEL_DBG #define LOG_CONF_LEVEL_6TOP LOG_LEVEL_DBG /* Enable cooja annotations */ diff --git a/os/sys/log-conf.h b/os/sys/log-conf.h index 1b3f26d03..24cf21f71 100644 --- a/os/sys/log-conf.h +++ b/os/sys/log-conf.h @@ -137,6 +137,10 @@ #define LOG_CONF_LEVEL_COAP LOG_LEVEL_NONE #endif /* LOG_CONF_LEVEL_COAP */ +#ifndef LOG_CONF_LEVEL_LWM2M +#define LOG_CONF_LEVEL_LWM2M LOG_LEVEL_NONE +#endif /* LOG_CONF_LEVEL_LWM2M */ + #ifndef LOG_CONF_LEVEL_MAIN #define LOG_CONF_LEVEL_MAIN LOG_LEVEL_INFO #endif /* LOG_CONF_LEVEL_MAIN */ diff --git a/os/sys/log.c b/os/sys/log.c index c2d8c8c5e..90709ec5f 100644 --- a/os/sys/log.c +++ b/os/sys/log.c @@ -60,6 +60,7 @@ int curr_log_level_mac = LOG_CONF_LEVEL_MAC; int curr_log_level_framer = LOG_CONF_LEVEL_FRAMER; int curr_log_level_6top = LOG_CONF_LEVEL_6TOP; int curr_log_level_coap = LOG_CONF_LEVEL_COAP; +int curr_log_level_lwm2m = LOG_CONF_LEVEL_LWM2M; int curr_log_level_main = LOG_CONF_LEVEL_MAIN; struct log_module all_modules[] = { @@ -72,6 +73,7 @@ struct log_module all_modules[] = { {"framer", &curr_log_level_framer, LOG_CONF_LEVEL_FRAMER}, {"6top", &curr_log_level_6top, LOG_CONF_LEVEL_6TOP}, {"coap", &curr_log_level_coap, LOG_CONF_LEVEL_COAP}, + {"lwm2m", &curr_log_level_lwm2m, LOG_CONF_LEVEL_LWM2M}, {"main", &curr_log_level_main, LOG_CONF_LEVEL_MAIN}, {NULL, NULL, 0}, }; diff --git a/os/sys/log.h b/os/sys/log.h index 49ffd3ba6..7c657060c 100644 --- a/os/sys/log.h +++ b/os/sys/log.h @@ -82,6 +82,7 @@ extern int curr_log_level_mac; extern int curr_log_level_framer; extern int curr_log_level_6top; extern int curr_log_level_coap; +extern int curr_log_level_lwm2m; extern int curr_log_level_main; extern struct log_module all_modules[]; @@ -95,6 +96,7 @@ extern struct log_module all_modules[]; #define LOG_LEVEL_FRAMER MIN((LOG_CONF_LEVEL_FRAMER), curr_log_level_framer) #define LOG_LEVEL_6TOP MIN((LOG_CONF_LEVEL_6TOP), curr_log_level_6top) #define LOG_LEVEL_COAP MIN((LOG_CONF_LEVEL_COAP), curr_log_level_coap) +#define LOG_LEVEL_LWM2M MIN((LOG_CONF_LEVEL_LWM2M), curr_log_level_lwm2m) #define LOG_LEVEL_MAIN MIN((LOG_CONF_LEVEL_MAIN), curr_log_level_main) /* Main log function */ diff --git a/tools/viewconf.c b/tools/viewconf.c index 610ec0f9f..d70e4f3c3 100644 --- a/tools/viewconf.c +++ b/tools/viewconf.c @@ -151,4 +151,5 @@ ##### "LOG_CONF_LEVEL_FRAMER": _________________ == LOG_CONF_LEVEL_FRAMER ##### "LOG_CONF_LEVEL_6TOP": ___________________ == LOG_CONF_LEVEL_6TOP ##### "LOG_CONF_LEVEL_COAP": ___________________ == LOG_CONF_LEVEL_COAP +##### "LOG_CONF_LEVEL_LWM2M": __________________ == LOG_CONF_LEVEL_LWM2M ##### "LOG_CONF_LEVEL_MAIN": ___________________ == LOG_CONF_LEVEL_MAIN From c9d255b847f332365cf41bc96c4f61a25d46c7df Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Fri, 1 Dec 2017 02:58:44 +0100 Subject: [PATCH 25/51] Updated LWM2M to use the logging module --- examples/lwm2m/standalone/coap-log-conf.h | 4 + os/services/lwm2m/lwm2m-device.c | 23 +- os/services/lwm2m/lwm2m-engine.c | 258 +++++++++++----------- os/services/lwm2m/lwm2m-firmware.c | 44 ++-- os/services/lwm2m/lwm2m-json.c | 36 +-- os/services/lwm2m/lwm2m-plain-text.c | 24 +- os/services/lwm2m/lwm2m-rd-client.c | 144 ++++++------ os/services/lwm2m/lwm2m-security.c | 83 ++++--- os/services/lwm2m/lwm2m-server.c | 23 +- os/services/lwm2m/lwm2m-tlv-writer.c | 16 +- os/services/lwm2m/lwm2m-tlv.c | 48 ++-- 11 files changed, 335 insertions(+), 368 deletions(-) diff --git a/examples/lwm2m/standalone/coap-log-conf.h b/examples/lwm2m/standalone/coap-log-conf.h index a6c58c218..aaedb2ebe 100644 --- a/examples/lwm2m/standalone/coap-log-conf.h +++ b/examples/lwm2m/standalone/coap-log-conf.h @@ -53,6 +53,10 @@ #define LOG_LEVEL_COAP LOG_LEVEL_DBG #endif /* LOG_LEVEL_COAP */ +#ifndef LOG_LEVEL_LWM2M +#define LOG_LEVEL_LWM2M LOG_LEVEL_DBG +#endif /* LOG_LEVEL_LWM2M */ + #ifndef LOG_WITH_LOC #define LOG_WITH_LOC 0 #endif /* LOG_WITH_LOC */ diff --git a/os/services/lwm2m/lwm2m-device.c b/os/services/lwm2m/lwm2m-device.c index 8436f67aa..460e9426e 100644 --- a/os/services/lwm2m/lwm2m-device.c +++ b/os/services/lwm2m/lwm2m-device.c @@ -46,13 +46,10 @@ #include "lwm2m-engine.h" #include -#define DEBUG 0 -#if DEBUG -#include -#define PRINTF(...) printf(__VA_ARGS__) -#else -#define PRINTF(...) -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "lwm2m-device" +#define LOG_LEVEL LOG_LEVEL_LWM2M static const lwm2m_resource_id_t resources[] = { RO(LWM2M_DEVICE_MANUFACTURER_ID), @@ -161,7 +158,7 @@ lwm2m_callback(lwm2m_object_instance_t *object, lwm2m_context_t *ctx) case LWM2M_DEVICE_TYPE_ID: return write_string(ctx, LWM2M_DEVICE_TYPE); case LWM2M_DEVICE_TIME_ID: - PRINTF("Reading time: %u\n", (unsigned int)lwm2m_device_get_time()); + LOG_DBG("Reading time: %u\n", (unsigned int)lwm2m_device_get_time()); lwm2m_object_write_int(ctx, lwm2m_device_get_time()); return LWM2M_STATUS_OK; case LWM2M_DEVICE_AVAILABLE_POWER_SOURCES: @@ -178,14 +175,14 @@ lwm2m_callback(lwm2m_object_instance_t *object, lwm2m_context_t *ctx) sizeof(power_current)/sizeof(uint16_t)); return LWM2M_STATUS_OK; default: - PRINTF("lwm2m-device: Not found: %u\n", ctx->resource_id); + LOG_WARN("Not found: %u\n", ctx->resource_id); return LWM2M_STATUS_NOT_FOUND; } } else if(ctx->operation == LWM2M_OP_EXECUTE) { if(ctx->resource_id == LWM2M_DEVICE_REBOOT_ID) { /* Do THE REBOOT */ - PRINTF("REBOOT\n"); + LOG_INFO("REBOOT\n"); return LWM2M_STATUS_OK; } @@ -196,12 +193,12 @@ lwm2m_callback(lwm2m_object_instance_t *object, lwm2m_context_t *ctx) len = lwm2m_object_read_int(ctx, ctx->inbuf->buffer, ctx->inbuf->size, &lw_time); if(len == 0) { - PRINTF("FAIL: could not write time\n"); + LOG_WARN("FAIL: could not write time\n"); return LWM2M_STATUS_WRITE_ERROR; } else { lwm2m_device_set_time(lw_time); - PRINTF("Write time %lu sec => offset = %ld\n", - (unsigned long)lw_time, (long)time_offset); + LOG_DBG("Write time %lu sec => offset = %ld\n", + (unsigned long)lw_time, (long)time_offset); return LWM2M_STATUS_OK; } } diff --git a/os/services/lwm2m/lwm2m-engine.c b/os/services/lwm2m/lwm2m-engine.c index 1413d803a..481a28e4d 100644 --- a/os/services/lwm2m/lwm2m-engine.c +++ b/os/services/lwm2m/lwm2m-engine.c @@ -61,18 +61,10 @@ #include "net/ipv6/uip-ds6.h" #endif /* UIP_CONF_IPV6_RPL */ -#define DEBUG 0 -#if DEBUG -#define PRINTF(...) printf(__VA_ARGS__) -#define PRINTS(l,s,f) do { int i; \ - for(i = 0; i < l; i++) printf(f, s[i]); \ - } while(0) -#define PRINTPRE(p,l,s) do { PRINTF(p);PRINTS(l,s,"%c"); } while(0); -#else -#define PRINTF(...) -#define PRINTS(l,s,f) -#define PRINTPRE(p,l,s); -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "lwm2m-engine" +#define LOG_LEVEL LOG_LEVEL_LWM2M #ifndef LWM2M_ENGINE_CLIENT_ENDPOINT_PREFIX #ifdef LWM2M_DEVICE_MODEL_NUMBER @@ -240,8 +232,8 @@ double_buffer_flush(lwm2m_buffer_t *ctxbuf, lwm2m_buffer_t *outbuf, int size) size = ctxbuf->len; } if(ctxbuf->len >= size && outbuf->size >= size) { - PRINTF("Double buffer - copying out %d bytes remaining: %d\n", - size, ctxbuf->len - size); + LOG_DBG("Double buffer - copying out %d bytes remaining: %d\n", + size, ctxbuf->len - size); memcpy(outbuf->buffer, ctxbuf->buffer, size); memcpy(ctxbuf->buffer, &ctxbuf->buffer[size], ctxbuf->len - size); @@ -252,7 +244,6 @@ double_buffer_flush(lwm2m_buffer_t *ctxbuf, lwm2m_buffer_t *outbuf, int size) return 0; } /*---------------------------------------------------------------------------*/ -#if DEBUG static inline const char * get_method_as_string(coap_resource_flags_t method) { @@ -268,9 +259,7 @@ get_method_as_string(coap_resource_flags_t method) return "UNKNOWN"; } } -#endif /* DEBUG */ /*--------------------------------------------------------------------------*/ -#if DEBUG static const char * get_status_as_string(lwm2m_status_t status) { @@ -307,7 +296,6 @@ get_status_as_string(lwm2m_status_t status) return buffer; } } -#endif /* DEBUG */ /*--------------------------------------------------------------------------*/ static int parse_path(const char *path, int path_len, @@ -319,9 +307,9 @@ parse_path(const char *path, int path_len, char c = 0; /* get object id */ - PRINTF("lwm2m: parse PATH: \""); - PRINTS(path_len, path, "%c"); - PRINTF("\"\n"); + LOG_DBG("parse PATH: \""); + LOG_DBG_COAP_STRING(path, path_len); + LOG_DBG_("\"\n"); ret = 0; pos = 0; @@ -374,7 +362,8 @@ void lwm2m_engine_set_opaque_callback(lwm2m_context_t *ctx, lwm2m_write_opaque_c { /* Here we should set the callback for the opaque that we are currently generating... */ /* And we should in the future associate the callback with the CoAP message info - MID */ - PRINTF("Setting opaque handler - offset: %d,%d\n", ctx->offset, ctx->outbuf->len); + LOG_DBG("Setting opaque handler - offset: %d,%d\n", + ctx->offset, ctx->outbuf->len); current_opaque_offset = 0; current_opaque_callback = cb; @@ -393,14 +382,14 @@ lwm2m_engine_set_rd_data(lwm2m_buffer_t *outbuf, int block) if(lwm2m_buf_lock[0] != 0 && (lwm2m_buf_lock_timeout > coap_timer_uptime()) && ((lwm2m_buf_lock[1] != 0xffff) || (lwm2m_buf_lock[2] != 0xffff))) { - PRINTF("Set-RD: already exporting resource: %d/%d/%d\n", - lwm2m_buf_lock[1], lwm2m_buf_lock[2], lwm2m_buf_lock[3]); + LOG_DBG("Set-RD: already exporting resource: %d/%d/%d\n", + lwm2m_buf_lock[1], lwm2m_buf_lock[2], lwm2m_buf_lock[3]); /* fail - what should we return here? */ return 0; } if(block == 0) { - PRINTF("Starting RD genereation\n"); + LOG_DBG("Starting RD generation\n"); /* start with simple object instances */ instance = list_head(object_list); object = NULL; @@ -427,22 +416,22 @@ lwm2m_engine_set_rd_data(lwm2m_buffer_t *outbuf, int block) lwm2m_buf_lock_timeout = coap_timer_uptime() + 1000; - PRINTF("Generating RD list:"); + LOG_DBG("Generating RD list:"); while(instance != NULL || object != NULL) { int pos = lwm2m_buf.len; if(instance != NULL) { len = snprintf((char *) &lwm2m_buf.buffer[pos], lwm2m_buf.size - pos, (pos > 0 || block > 0) ? "," : "", instance->object_id, instance->instance_id); - PRINTF((pos > 0 || block > 0) ? "," : "", - instance->object_id, instance->instance_id); + LOG_DBG_((pos > 0 || block > 0) ? "," : "", + instance->object_id, instance->instance_id); } else if(object->impl != NULL) { len = snprintf((char *) &lwm2m_buf.buffer[pos], lwm2m_buf.size - pos, (pos > 0 || block > 0) ? "," : "", object->impl->object_id); - PRINTF((pos > 0 || block > 0) ? "," : "", - object->impl->object_id); + LOG_DBG_((pos > 0 || block > 0) ? "," : "", + object->impl->object_id); } else { len = 0; } @@ -476,7 +465,8 @@ lwm2m_engine_set_rd_data(lwm2m_buffer_t *outbuf, int block) } if(lwm2m_buf.len >= maxsize) { - PRINTF("**** CoAP MAX BLOCK Reached!!! **** SEND\n"); + LOG_DBG_("\n"); + LOG_DBG("**** CoAP MAX BLOCK Reached!!! **** SEND\n"); /* If the produced data is larger than a CoAP block we need to send this now */ double_buffer_flush(&lwm2m_buf, outbuf, maxsize); @@ -484,7 +474,7 @@ lwm2m_engine_set_rd_data(lwm2m_buffer_t *outbuf, int block) return 1; } } - PRINTF("\n"); + LOG_DBG_("\n"); double_buffer_flush(&lwm2m_buf, outbuf, maxsize); /* unlock the buffer */ lwm2m_buf_lock[0] = 0; @@ -580,7 +570,7 @@ lwm2m_engine_select_writer(lwm2m_context_t *context, unsigned int accept) context->writer = &lwm2m_json_writer; break; default: - PRINTF("Unknown Accept type %u, using LWM2M plain text\n", accept); + LOG_WARN("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; @@ -613,8 +603,8 @@ lwm2m_engine_select_reader(lwm2m_context_t *context, unsigned int content_format context->reader = &lwm2m_plain_text_reader; break; default: - PRINTF("Unknown content type %u, using LWM2M plain text\n", - content_format); + LOG_WARN("Unknown content type %u, using LWM2M plain text\n", + content_format); context->reader = &lwm2m_plain_text_reader; break; } @@ -660,13 +650,14 @@ perform_multi_resource_read_op(lwm2m_object_t *object, ((lwm2m_buf_lock[1] != ctx->object_id) || (lwm2m_buf_lock[2] != ctx->object_instance_id) || (lwm2m_buf_lock[3] != ctx->resource_id))) { - PRINTF("Multi-read: already exporting resource: %d/%d/%d\n", - lwm2m_buf_lock[1], lwm2m_buf_lock[2], lwm2m_buf_lock[3]); + LOG_DBG("Multi-read: already exporting resource: %d/%d/%d\n", + lwm2m_buf_lock[1], lwm2m_buf_lock[2], lwm2m_buf_lock[3]); return LWM2M_STATUS_SERVICE_UNAVAILABLE; } - PRINTF("MultiRead: %d/%d/%d lv:%d offset:%d\n", - ctx->object_id, ctx->object_instance_id, ctx->resource_id, ctx->level, ctx->offset); + LOG_DBG("MultiRead: %d/%d/%d lv:%d offset:%d\n", + ctx->object_id, ctx->object_instance_id, ctx->resource_id, + ctx->level, ctx->offset); /* Make use of the double buffer */ ctx->outbuf = &lwm2m_buf; @@ -705,7 +696,10 @@ perform_multi_resource_read_op(lwm2m_object_t *object, if(instance->resource_ids != NULL && instance->resource_count > 0) { /* show all the available resources (or read all) */ while(last_rsc_pos < instance->resource_count) { - PRINTF("READ: %x %x %x lv:%d\n", instance->resource_ids[last_rsc_pos], RSC_ID(instance->resource_ids[last_rsc_pos]), ctx->resource_id, ctx->level); + LOG_DBG("READ: %x %x %x lv:%d\n", + instance->resource_ids[last_rsc_pos], + RSC_ID(instance->resource_ids[last_rsc_pos]), + ctx->resource_id, ctx->level); /* Check if this is a object read or if it is the correct resource */ if(ctx->level < 3 || ctx->resource_id == RSC_ID(instance->resource_ids[last_rsc_pos])) { @@ -731,7 +725,7 @@ perform_multi_resource_read_op(lwm2m_object_t *object, if(len < 0 || ctx->outbuf->len >= size) { double_buffer_flush(ctx->outbuf, outbuf, size); - PRINTF("Copied lwm2m buf - remaining: %d\n", lwm2m_buf.len); + LOG_DBG("Copied lwm2m buf - remaining: %d\n", lwm2m_buf.len); /* switch buffer */ ctx->outbuf = outbuf; ctx->writer_flags |= WRITER_HAS_MORE; @@ -764,20 +758,20 @@ perform_multi_resource_read_op(lwm2m_object_t *object, /* Now we need to initialize the object writing for this new object */ len = ctx->writer->init_write(ctx); ctx->outbuf->len += len; - PRINTF("INIT WRITE len:%d size:%d\n", len, (int) ctx->outbuf->size); + LOG_DBG("INIT WRITE len:%d size:%d\n", len, (int) ctx->outbuf->size); initialized = 1; } if(current_opaque_callback == NULL) { - PRINTF("Doing the callback to the resource %d\n", ctx->outbuf->len); + LOG_DBG("Doing the callback to the resource %d\n", ctx->outbuf->len); /* No special opaque callback to handle - use regular callback */ success = instance->callback(instance, ctx); - PRINTF("After the callback to the resource %d: %s\n", - ctx->outbuf->len, get_status_as_string(success)); + LOG_DBG("After the callback to the resource %d: %s\n", + ctx->outbuf->len, get_status_as_string(success)); if(success != LWM2M_STATUS_OK) { /* What to do here? */ - PRINTF("Callback failed: %s\n", get_status_as_string(success)); + LOG_DBG("Callback failed: %s\n", get_status_as_string(success)); if(lv < 3) { if(success == LWM2M_STATUS_NOT_FOUND) { /* ok with a not found during a multi read - what more @@ -799,11 +793,11 @@ perform_multi_resource_read_op(lwm2m_object_t *object, we should produce data via that callback until the opaque has fully been handled */ ctx->offset = current_opaque_offset; - /* PRINTF("Calling the opaque handler %x\n", ctx->writer_flags); */ + /* LOG_DBG("Calling the opaque handler %x\n", ctx->writer_flags); */ success = current_opaque_callback(instance, ctx, num_write); if((ctx->writer_flags & WRITER_HAS_MORE) == 0) { /* This opaque stream is now done! */ - /* PRINTF("Setting opaque callback to null - it is done!\n"); */ + /* LOG_DBG("Setting opaque callback to null - it is done!\n"); */ current_opaque_callback = NULL; } else if(ctx->outbuf->len < COAP_MAX_BLOCK_SIZE) { lwm2m_buf_lock[0] = 0; @@ -811,21 +805,21 @@ perform_multi_resource_read_op(lwm2m_object_t *object, } current_opaque_offset += num_write; ctx->offset = old_offset; - /* PRINTF("Setting back offset to: %d\n", ctx->offset); */ + /* LOG_DBG("Setting back offset to: %d\n", ctx->offset); */ } /* here we have "read" out something */ num_read++; /* We will need to handle no-success and other things */ - PRINTF("Called %u/%u/%u outlen:%u %s\n", - ctx->object_id, ctx->object_instance_id, ctx->resource_id, - ctx->outbuf->len, get_status_as_string(success)); + LOG_DBG("Called %u/%u/%u outlen:%u %s\n", + ctx->object_id, ctx->object_instance_id, ctx->resource_id, + ctx->outbuf->len, get_status_as_string(success)); /* we need to handle full buffer, etc here also! */ ctx->level = lv; } else { - PRINTF("Resource %u not readable\n", - RSC_ID(instance->resource_ids[last_rsc_pos])); + LOG_DBG("Resource %u not readable\n", + RSC_ID(instance->resource_ids[last_rsc_pos])); } } } @@ -833,18 +827,18 @@ perform_multi_resource_read_op(lwm2m_object_t *object, /* This resource is now done - (only when the opaque is also done) */ last_rsc_pos++; } else { - PRINTF("Opaque is set - continue with that.\n"); + LOG_DBG("Opaque is set - continue with that.\n"); } if(ctx->outbuf->len >= COAP_MAX_BLOCK_SIZE) { - PRINTF("**** CoAP MAX BLOCK Reached!!! **** SEND\n"); + LOG_DBG("**** CoAP MAX BLOCK Reached!!! **** SEND\n"); /* If the produced data is larger than a CoAP block we need to send this now */ if(ctx->outbuf->len < 2 * COAP_MAX_BLOCK_SIZE) { /* We assume that size is equal to COAP_MAX_BLOCK_SIZE here */ double_buffer_flush(ctx->outbuf, outbuf, size); - PRINTF("Copied lwm2m buf - remaining: %d\n", lwm2m_buf.len); + LOG_DBG("Copied lwm2m buf - remaining: %d\n", lwm2m_buf.len); /* switch buffer */ ctx->outbuf = outbuf; ctx->writer_flags |= WRITER_HAS_MORE; @@ -852,7 +846,7 @@ perform_multi_resource_read_op(lwm2m_object_t *object, /* OK - everything went well... but we have more. - keep the lock here! */ return LWM2M_STATUS_OK; } else { - PRINTF("*** ERROR Overflow?\n"); + LOG_WARN("*** ERROR Overflow?\n"); return LWM2M_STATUS_ERROR; } } @@ -866,10 +860,10 @@ perform_multi_resource_read_op(lwm2m_object_t *object, last_instance_id = NO_INSTANCE; } if(ctx->operation == LWM2M_OP_READ) { - PRINTF("END Writer %d ->", ctx->outbuf->len); + LOG_DBG("END Writer %d ->", ctx->outbuf->len); len = ctx->writer->end_write(ctx); ctx->outbuf->len += len; - PRINTF("%d\n", ctx->outbuf->len); + LOG_DBG("%d\n", ctx->outbuf->len); } initialized = 0; @@ -896,7 +890,7 @@ perform_multi_resource_read_op(lwm2m_object_t *object, lwm2m_buf_lock[0] = 0; } - PRINTF("At END: Copied lwm2m buf %d\n", len); + LOG_DBG("At END: Copied lwm2m buf %d\n", len); return LWM2M_STATUS_OK; } @@ -913,7 +907,7 @@ create_instance(lwm2m_context_t *context, lwm2m_object_t *object) /* NOTE: context->object_instance_id needs to be set before calling */ instance = object->impl->create_instance(context->object_instance_id, NULL); if(instance != NULL) { - PRINTF("Created instance: %u/%u\n", context->object_id, context->object_instance_id); + LOG_DBG("Created instance: %u/%u\n", context->object_id, context->object_instance_id); coap_set_status_code(context->response, CREATED_2_01); #if USE_RD_CLIENT lwm2m_rd_client_set_update_rd(); @@ -934,8 +928,8 @@ get_or_create_instance(lwm2m_context_t *ctx, lwm2m_object_t *object, lwm2m_object_instance_t *instance; instance = get_instance_by_context(ctx, NULL); - PRINTF("Instance: %u/%u/%u = %p\n", ctx->object_id, - ctx->object_instance_id, ctx->resource_id, instance); + LOG_DBG("Instance: %u/%u/%u = %p\n", ctx->object_id, + ctx->object_instance_id, ctx->resource_id, instance); /* by default we assume that the instance is not created... so we set flag to zero */ if(created != NULL) { *created = 0; @@ -980,8 +974,8 @@ process_tlv_write(lwm2m_context_t *ctx, lwm2m_object_t *object, ctx->inbuf->size = len; ctx->level = 3; ctx->resource_id = rid; - PRINTF(" Doing callback to %u/%u/%u\n", ctx->object_id, - ctx->object_instance_id, ctx->resource_id); + LOG_DBG(" Doing callback to %u/%u/%u\n", ctx->object_id, + ctx->object_instance_id, ctx->resource_id); instance = get_or_create_instance(ctx, object, &created); if(instance != NULL && instance->callback != NULL) { if(created || check_write(instance, rid)) { @@ -1019,11 +1013,15 @@ perform_multi_resource_write_op(lwm2m_object_t *object, while(lwm2m_json_next_token(ctx, &json)) { int i; uint8_t created = 0; - PRINTF("JSON: '"); - for(i = 0; i < json.name_len; i++) PRINTF("%c", json.name[i]); - PRINTF("':'"); - for(i = 0; i < json.value_len; i++) PRINTF("%c", json.value[i]); - PRINTF("'\n"); + LOG_DBG("JSON: '"); + for(i = 0; i < json.name_len; i++) { + LOG_DBG_("%c", json.name[i]); + } + LOG_DBG_("':'"); + for(i = 0; i < json.value_len; i++) { + LOG_DBG_("%c", json.value[i]); + } + LOG_DBG_("'\n"); if(json.name[0] == 'n') { i = parse_path((const char *) json.value, json.value_len, &oid, &iid, &rid); if(i > 0) { @@ -1085,10 +1083,10 @@ perform_multi_resource_write_op(lwm2m_object_t *object, future */ if(coap_get_header_block1(ctx->request, &num, &more, &size, &offset)) { - PRINTF("CoAP BLOCK1: %d/%d/%d offset:%d\n", num, more, size, offset); - PRINTF("LWM2M CTX->offset= %d\n", ctx->offset); - PRINTF("Last TLV ID:%d final:%d\n", last_tlv_id, - lwm2m_object_is_final_incoming(ctx)); + LOG_DBG("CoAP BLOCK1: %d/%d/%d offset:%d\n", num, more, size, offset); + LOG_DBG("LWM2M CTX->offset= %d\n", ctx->offset); + LOG_DBG("Last TLV ID:%d final:%d\n", last_tlv_id, + lwm2m_object_is_final_incoming(ctx)); if(offset > 0) { status = process_tlv_write(ctx, object, last_tlv_id, inbuf, size); @@ -1098,7 +1096,7 @@ perform_multi_resource_write_op(lwm2m_object_t *object, while(tlvpos < insize) { len = lwm2m_tlv_read(&tlv, &inbuf[tlvpos], insize - tlvpos); - PRINTF("Got TLV format First is: type:%d id:%d len:%d (p:%d len:%d/%d)\n", + LOG_DBG("Got TLV format First is: type:%d id:%d len:%d (p:%d len:%d/%d)\n", tlv.type, tlv.id, (int) tlv.length, (int) tlvpos, (int) len, (int) insize); if(tlv.type == LWM2M_TLV_TYPE_OBJECT_INSTANCE) { @@ -1114,9 +1112,9 @@ perform_multi_resource_write_op(lwm2m_object_t *object, } while(pos < tlv.length && (len2 = lwm2m_tlv_read(&tlv2, &tlv.value[pos], tlv.length - pos))) { - PRINTF(" TLV type:%d id:%d len:%d (len:%d/%d)\n", - tlv2.type, tlv2.id, (int) tlv2.length, - (int) len2, (int) insize); + LOG_DBG(" TLV type:%d id:%d len:%d (len:%d/%d)\n", + tlv2.type, tlv2.id, (int)tlv2.length, + (int)len2, (int)insize); if(tlv2.type == LWM2M_TLV_TYPE_RESOURCE) { last_tlv_id = tlv2.id; status = process_tlv_write(ctx, object, tlv2.id, @@ -1172,13 +1170,12 @@ lwm2m_engine_add_object(lwm2m_object_instance_t *object) if(object == NULL || object->callback == NULL) { /* Insufficient object configuration */ - PRINTF("lwm2m-engine: failed to register NULL object\n"); + LOG_DBG("failed to register NULL object\n"); return 0; } if(get_object(object->object_id) != NULL) { /* A generic object with this id has already been registered */ - PRINTF("lwm2m-engine: object with id %u already registered\n", - object->object_id); + LOG_DBG("object with id %u already registered\n", object->object_id); return 0; } @@ -1187,7 +1184,7 @@ lwm2m_engine_add_object(lwm2m_object_instance_t *object) instance = instance->next) { if(object->object_id == instance->object_id) { if(object->instance_id == instance->instance_id) { - PRINTF("lwm2m-engine: object with id %u/%u already registered\n", + LOG_DBG("object with id %u/%u already registered\n", instance->object_id, instance->instance_id); return 0; } @@ -1236,19 +1233,19 @@ lwm2m_engine_add_generic_object(lwm2m_object_t *object) || object->impl->get_first == NULL || object->impl->get_next == NULL || object->impl->get_by_id == NULL) { - PRINTF("lwm2m-engine: failed to register NULL object\n"); + LOG_WARN("failed to register NULL object\n"); return 0; } if(get_object(object->impl->object_id) != NULL) { /* A generic object with this id has already been registered */ - PRINTF("lwm2m-engine: object with id %u already registered\n", - object->impl->object_id); + LOG_WARN("object with id %u already registered\n", + object->impl->object_id); return 0; } if(has_non_generic_object(object->impl->object_id)) { /* An object with this id has already been registered */ - PRINTF("lwm2m-engine: object with id %u already registered\n", - object->impl->object_id); + LOG_WARN("object with id %u already registered\n", + object->impl->object_id); return 0; } list_add(generic_object_list, object); @@ -1346,9 +1343,9 @@ lwm2m_handler_callback(coap_message_t *request, coap_message_t *response, uint16_t bsize; coap_get_header_block1(request, NULL, NULL, &bsize, NULL); - PRINTF("Block1 size:%d\n", bsize); + LOG_DBG("Block1 size:%d\n", bsize); if(bsize > COAP_MAX_BLOCK_SIZE) { - PRINTF("Entity too large...\n"); + LOG_WARN("Entity too large: %u...\n", bsize); coap_set_status_code(response, REQUEST_ENTITY_TOO_LARGE_4_13); coap_set_header_size1(response, COAP_MAX_BLOCK_SIZE); return COAP_HANDLER_STATUS_PROCESSED; @@ -1364,7 +1361,7 @@ lwm2m_handler_callback(coap_message_t *request, coap_message_t *response, url_len = coap_get_header_uri_path(request, &url); if(url_len == 2 && strncmp("bs", url, 2) == 0) { - PRINTF("BOOTSTRAPPED!!!\n"); + LOG_INFO("BOOTSTRAPPED!!!\n"); coap_set_status_code(response, CHANGED_2_04); return COAP_HANDLER_STATUS_PROCESSED; } @@ -1376,13 +1373,13 @@ lwm2m_handler_callback(coap_message_t *request, coap_message_t *response, return COAP_HANDLER_STATUS_CONTINUE; } - PRINTF("%s URL:'", get_method_as_string(coap_get_method_type(request))); - PRINTS(url_len, url, "%c"); - PRINTF("' CTX:%u/%u/%u dp:%u bs:%d\n", context.object_id, context.object_instance_id, + LOG_DBG("%s URL:'", get_method_as_string(coap_get_method_type(request))); + LOG_DBG_COAP_STRING(url, url_len); + LOG_DBG_("' CTX:%u/%u/%u dp:%u bs:%d\n", context.object_id, context.object_instance_id, context.resource_id, depth, buffer_size); /* Get format and accept */ if(!coap_get_header_content_format(request, &format)) { - PRINTF("lwm2m: No format given. Assume text plain...\n"); + LOG_DBG("No format given. Assume text plain...\n"); format = TEXT_PLAIN; } else if(format == LWM2M_TEXT_PLAIN) { /* CoAP content format text plain - assume LWM2M text plain */ @@ -1390,11 +1387,10 @@ lwm2m_handler_callback(coap_message_t *request, coap_message_t *response, } if(!coap_get_header_accept(request, &accept)) { if(format == TEXT_PLAIN && depth < 3) { - PRINTF("lwm2m: No Accept header, assume JSON\n"); + LOG_DBG("No Accept header, assume JSON\n"); accept = LWM2M_JSON; } else { - PRINTF("lwm2m: No Accept header, using same as content-format: %d\n", - format); + LOG_DBG("No Accept header, using same as content-format: %d\n", format); accept = format; } } @@ -1407,7 +1403,7 @@ lwm2m_handler_callback(coap_message_t *request, coap_message_t *response, if(depth < 1) { /* No possible object id found in URL - ignore request unless delete all */ if(coap_get_method_type(request) == METHOD_DELETE) { - PRINTF("This is a delete all - for bootstrap...\n"); + LOG_DBG("This is a delete all - for bootstrap...\n"); context.operation = LWM2M_OP_DELETE; coap_set_status_code(response, DELETED_2_02); @@ -1435,8 +1431,8 @@ lwm2m_handler_callback(coap_message_t *request, coap_message_t *response, /* ALLOW generic instance if CREATE / WRITE*/ instance = create_instance(&context, object); if(instance == NULL) { - PRINTF("lwm2m-engine: failed to create instance %u/%u\n", - context.object_id, context.object_instance_id); + LOG_WARN("failed to create instance %u/%u\n", + context.object_id, context.object_instance_id); } } @@ -1449,9 +1445,9 @@ lwm2m_handler_callback(coap_message_t *request, coap_message_t *response, return COAP_HANDLER_STATUS_CONTINUE; } - PRINTF("lwm2m: Context: %u/%u/%u found: %d\n", - context.object_id, - context.object_instance_id, context.resource_id, depth); + LOG_INFO("Context: %u/%u/%u found: %d\n", + context.object_id, context.object_instance_id, + context.resource_id, depth); /* * Select reader and writer based on provided Content type and @@ -1492,24 +1488,25 @@ lwm2m_handler_callback(coap_message_t *request, coap_message_t *response, break; } -#if DEBUG - /* for debugging */ - PRINTPRE("lwm2m: [", url_len, url); - PRINTF("] %s Format:%d ID:%d bsize:%u offset:%d\n", - get_method_as_string(coap_get_method_type(request)), - format, context.object_id, buffer_size, - offset != NULL ? ((int)*offset) : 0); - if(format == TEXT_PLAIN) { - /* a string */ - const uint8_t *data; - int plen = coap_get_payload(request, &data); - if(plen > 0) { - PRINTF("Data: '"); - PRINTS(plen, data, "%c"); - PRINTF("'\n"); + if(LOG_DBG_ENABLED) { + /* for debugging */ + LOG_DBG("["); + LOG_DBG_COAP_STRING(url, url_len); + LOG_DBG_("] %s Format:%d ID:%d bsize:%u offset:%d\n", + get_method_as_string(coap_get_method_type(request)), + format, context.object_id, buffer_size, + offset != NULL ? ((int)*offset) : 0); + if(format == TEXT_PLAIN) { + /* a string */ + const uint8_t *data; + int plen = coap_get_payload(request, &data); + if(plen > 0) { + LOG_DBG("Data: '"); + LOG_DBG_COAP_STRING((const char *)data, plen); + LOG_DBG_("'\n"); + } } } -#endif /* DEBUG */ /* PUT/POST - e.g. write will not send in offset here - Maybe in the future? */ if((offset != NULL && *offset == 0) && @@ -1552,19 +1549,20 @@ lwm2m_handler_callback(coap_message_t *request, coap_message_t *response, if(success == LWM2M_STATUS_OK) { /* Handle blockwise 1 */ if(coap_is_option(request, COAP_OPTION_BLOCK1)) { - PRINTF("Setting BLOCK 1 num:%d o2:%d o:%d\n", (int) bnum, (int) boffset, - (int) (offset != NULL ? *offset : 0)); + LOG_DBG("Setting BLOCK 1 num:%d o2:%d o:%d\n", (int) bnum, (int) boffset, + (int) (offset != NULL ? *offset : 0)); coap_set_header_block1(response, bnum, 0, bsize); } if(context.outbuf->len > 0) { - PRINTPRE("lwm2m: [", url_len, url); - PRINTF("] replying with %u bytes\n", context.outbuf->len); + LOG_DBG("["); + LOG_DBG_COAP_STRING(url, url_len); + LOG_DBG_("] replying with %u bytes\n", context.outbuf->len); coap_set_payload(response, context.outbuf->buffer, context.outbuf->len); coap_set_header_content_format(response, context.content_type); if(offset != NULL) { - PRINTF("Setting new offset: oo %d, no: %d\n", *offset, context.offset); + LOG_DBG("Setting new offset: oo %d, no: %d\n", *offset, context.offset); if(context.writer_flags & WRITER_HAS_MORE) { *offset = context.offset; } else { @@ -1573,8 +1571,9 @@ lwm2m_handler_callback(coap_message_t *request, coap_message_t *response, } } } else { - PRINTPRE("lwm2m: [", url_len, url); - PRINTF("] no data in reply\n"); + LOG_DBG("["); + LOG_DBG_COAP_STRING(url, url_len); + LOG_DBG_("] no data in reply\n"); } } else { switch(success) { @@ -1598,8 +1597,9 @@ lwm2m_handler_callback(coap_message_t *request, coap_message_t *response, coap_set_status_code(response, INTERNAL_SERVER_ERROR_5_00); break; } - PRINTPRE("lwm2m: [", url_len, url); - PRINTF("] resource failed: %s\n", get_status_as_string(success)); + LOG_WARN("["); + LOG_WARN_COAP_STRING(url, url_len); + LOG_WARN("] resource failed: %s\n", get_status_as_string(success)); } return COAP_HANDLER_STATUS_PROCESSED; } diff --git a/os/services/lwm2m/lwm2m-firmware.c b/os/services/lwm2m/lwm2m-firmware.c index 30c1a8229..ba03eb3d3 100644 --- a/os/services/lwm2m/lwm2m-firmware.c +++ b/os/services/lwm2m/lwm2m-firmware.c @@ -41,13 +41,10 @@ #include "coap.h" #include -#define DEBUG 0 -#if DEBUG -#include -#define PRINTF(...) printf(__VA_ARGS__) -#else -#define PRINTF(...) -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "lwm2m-firmware" +#define LOG_LEVEL LOG_LEVEL_LWM2M #define UPDATE_PACKAGE 0 #define UPDATE_PACKAGE_URI 1 @@ -87,14 +84,13 @@ static lwm2m_status_t lwm2m_callback(lwm2m_object_instance_t *object, lwm2m_context_t *ctx) { -#if DEBUG uint32_t num; uint8_t more; uint16_t size; uint32_t offset; -#endif - PRINTF("Got request at: %d/%d/%d lv:%d\n", ctx->object_id, ctx->object_instance_id, ctx->resource_id, ctx->level); + LOG_DBG("Got request at: %d/%d/%d lv:%d\n", ctx->object_id, + ctx->object_instance_id, ctx->resource_id, ctx->level); if(ctx->level == 1 || ctx->level == 2) { /* Should not happen - as it will be taken care of by the lwm2m engine itself. */ @@ -111,17 +107,19 @@ lwm2m_callback(lwm2m_object_instance_t *object, return LWM2M_STATUS_OK; } } else if(ctx->operation == LWM2M_OP_WRITE) { -#if DEBUG - if(coap_get_header_block1(ctx->request, &num, &more, &size, &offset)) { - PRINTF("CoAP BLOCK1: %d/%d/%d offset:%d\n", num, more, size, offset); - PRINTF("LWM2M CTX->offset= %d\n", ctx->offset); + + if(LOG_DBG_ENABLED) { + if(coap_get_header_block1(ctx->request, &num, &more, &size, &offset)) { + LOG_DBG("CoAP BLOCK1: %d/%d/%d offset:%d\n", num, more, size, offset); + LOG_DBG("LWM2M CTX->offset= %d\n", ctx->offset); + } } -#endif + switch(ctx->resource_id) { case UPDATE_PACKAGE: /* The firmware is written */ - PRINTF("Firmware received: %d %d fin:%d\n", ctx->offset, (int) ctx->inbuf->size, - lwm2m_object_is_final_incoming(ctx)); + LOG_DBG("Firmware received: %d %d fin:%d\n", ctx->offset, + (int)ctx->inbuf->size, lwm2m_object_is_final_incoming(ctx)); if(lwm2m_object_is_final_incoming(ctx)) { state = STATE_DOWNLOADED; } else { @@ -130,15 +128,15 @@ lwm2m_callback(lwm2m_object_instance_t *object, return LWM2M_STATUS_OK; case UPDATE_PACKAGE_URI: /* The firmware URI is written */ - PRINTF("Firmware URI received: %d %d fin:%d\n", ctx->offset, (int) ctx->inbuf->size, - lwm2m_object_is_final_incoming(ctx)); - if(DEBUG) { + LOG_DBG("Firmware URI received: %d %d fin:%d\n", ctx->offset, + (int)ctx->inbuf->size, lwm2m_object_is_final_incoming(ctx)); + if(LOG_DBG_ENABLED) { int i; - PRINTF("Data: '"); + LOG_DBG("Data: '"); for(i = 0; i < ctx->inbuf->size; i++) { - PRINTF("%c", ctx->inbuf->buffer[i]); + LOG_DBG_("%c", ctx->inbuf->buffer[i]); } - PRINTF("'\n"); + LOG_DBG_("'\n"); } return LWM2M_STATUS_OK; } diff --git a/os/services/lwm2m/lwm2m-json.c b/os/services/lwm2m/lwm2m-json.c index a247fd9b1..2d623388c 100644 --- a/os/services/lwm2m/lwm2m-json.c +++ b/os/services/lwm2m/lwm2m-json.c @@ -49,12 +49,10 @@ #include #include -#define DEBUG 0 -#if DEBUG -#define PRINTF(...) printf(__VA_ARGS__) -#else -#define PRINTF(...) -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "lwm2m-json" +#define LOG_LEVEL LOG_LEVEL_NONE /*---------------------------------------------------------------------------*/ /* {"e":[{"n":"111/1","v":123},{"n":"111/2","v":42}]} */ @@ -70,7 +68,9 @@ /* Simlified JSON style reader for reading in values from a LWM2M JSON string */ -int lwm2m_json_next_token(lwm2m_context_t *ctx, struct json_data *json) { +int +lwm2m_json_next_token(lwm2m_context_t *ctx, struct json_data *json) +{ int pos = ctx->inbuf->pos; uint8_t type = T_NONE; uint8_t vpos_start = 0; @@ -123,7 +123,7 @@ int lwm2m_json_next_token(lwm2m_context_t *ctx, struct json_data *json) { } else { /* Could be in string or at illegal pos */ if(type != T_STRING_B) { - PRINTF("ERROR - illegal ':'\n"); + LOG_DBG("ERROR - illegal ':'\n"); } } break; @@ -178,7 +178,7 @@ static size_t enter_sub(lwm2m_context_t *ctx) { /* set some flags in state */ - PRINTF("Enter sub-resource rsc=%d\n", ctx->resource_id); + LOG_DBG("Enter sub-resource rsc=%d\n", ctx->resource_id); ctx->writer_flags |= WRITER_RESOURCE_INSTANCE; return 0; } @@ -187,7 +187,7 @@ static size_t exit_sub(lwm2m_context_t *ctx) { /* clear out state info */ - PRINTF("Exit sub-resource rsc=%d\n", ctx->resource_id); + LOG_DBG("Exit sub-resource rsc=%d\n", ctx->resource_id); ctx->writer_flags &= ~WRITER_RESOURCE_INSTANCE; return 0; } @@ -206,7 +206,7 @@ write_boolean(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, if((len < 0) || (len >= outlen)) { return 0; } - PRINTF("JSON: Write bool:%s\n", outbuf); + LOG_DBG("JSON: Write bool:%s\n", outbuf); ctx->writer_flags |= WRITER_OUTPUT_VALUE; return len; @@ -226,7 +226,7 @@ write_int(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, if((len < 0) || (len >= outlen)) { return 0; } - PRINTF("JSON: Write int:%s\n", outbuf); + LOG_DBG("Write int:%s\n", outbuf); ctx->writer_flags |= WRITER_OUTPUT_VALUE; return len; @@ -272,7 +272,7 @@ write_string(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, size_t i; size_t len = 0; int res; - PRINTF("{\"n\":\"%u\",\"sv\":\"", ctx->resource_id); + LOG_DBG("{\"n\":\"%u\",\"sv\":\"", ctx->resource_id); if(ctx->writer_flags & WRITER_RESOURCE_INSTANCE) { res = snprintf((char *)outbuf, outlen, "%s{\"n\":\"%u/%u\",\"sv\":\"", sep, ctx->resource_id, ctx->resource_instance_id); @@ -288,7 +288,7 @@ write_string(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, /* Escape special characters */ /* TODO: Handle UTF-8 strings */ if(value[i] < '\x20') { - PRINTF("\\x%x", value[i]); + LOG_DBG_("\\x%x", value[i]); res = snprintf((char *)&outbuf[len], outlen - len, "\\x%x", value[i]); if((res < 0) || (res >= (outlen - len))) { return 0; @@ -296,27 +296,27 @@ write_string(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, len += res; continue; } else if(value[i] == '"' || value[i] == '\\') { - PRINTF("\\"); + LOG_DBG_("\\"); outbuf[len] = '\\'; ++len; if(len >= outlen) { return 0; } } - PRINTF("%c", value[i]); + LOG_DBG_("%c", value[i]); outbuf[len] = value[i]; ++len; if(len >= outlen) { return 0; } } - PRINTF("\"}\n"); + LOG_DBG_("\"}\n"); res = snprintf((char *)&outbuf[len], outlen - len, "\"}"); if((res < 0) || (res >= (outlen - len))) { return 0; } - PRINTF("JSON: Write string:%s\n", outbuf); + LOG_DBG("JSON: Write string:%s\n", outbuf); len += res; ctx->writer_flags |= WRITER_OUTPUT_VALUE; diff --git a/os/services/lwm2m/lwm2m-plain-text.c b/os/services/lwm2m/lwm2m-plain-text.c index 2bd081c76..4799fcaa6 100644 --- a/os/services/lwm2m/lwm2m-plain-text.c +++ b/os/services/lwm2m/lwm2m-plain-text.c @@ -47,12 +47,10 @@ #include #include -#define DEBUG 0 -#if DEBUG -#define PRINTF(...) printf(__VA_ARGS__) -#else -#define PRINTF(...) -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "lwm2m-plain-text" +#define LOG_LEVEL LOG_LEVEL_NONE /*---------------------------------------------------------------------------*/ static size_t @@ -121,16 +119,16 @@ lwm2m_plain_text_read_float32fix(const uint8_t *inbuf, size_t len, if(frac > 1) { *value += ((counter << bits) / frac); } - PRINTF("READ FLOATFIX: \"%.*s\" => int(%ld) frac(%ld) f=%ld Value=%ld\n", - (int)len, (char *)inbuf, - (long)integerpart, - (long)counter, - (long)frac, - (long)*value); + LOG_DBG("READ FLOATFIX: \"%.*s\" => int(%ld) frac(%ld) f=%ld Value=%ld\n", + (int)len, (char *)inbuf, + (long)integerpart, + (long)counter, + (long)frac, + (long)*value); if(neg) { *value = -*value; } - + return i; } /*---------------------------------------------------------------------------*/ diff --git a/os/services/lwm2m/lwm2m-rd-client.c b/os/services/lwm2m/lwm2m-rd-client.c index 36d934323..556fd8cc4 100644 --- a/os/services/lwm2m/lwm2m-rd-client.c +++ b/os/services/lwm2m/lwm2m-rd-client.c @@ -62,23 +62,10 @@ #include "rpl.h" #endif /* UIP_CONF_IPV6_RPL */ -#define DEBUG 1 -#if DEBUG -#include -#define PRINTF(...) printf(__VA_ARGS__) -#define PRINTS(l,s,f) do { int i; \ - for(i = 0; i < l; i++) printf(f, s[i]); \ - } while(0) -#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]) -#define PRINTEP(ep) coap_endpoint_print(ep) -#else -#define PRINTF(...) -#define PRINTS(l,s,f) -#define PRINT6ADDR(addr) -#define PRINTLLADDR(addr) -#define PRINTEP(ep) -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "lwm2m-rd-client" +#define LOG_LEVEL LOG_LEVEL_LWM2M #ifndef LWM2M_DEFAULT_CLIENT_LIFETIME #define LWM2M_DEFAULT_CLIENT_LIFETIME 600 /* sec */ @@ -150,7 +137,7 @@ set_rd_data(coap_message_t *request) if(rd_more) { /* set the first block here */ - PRINTF("Setting block1 in request\n"); + LOG_DBG("Setting block1 in request\n"); coap_set_header_block1(request, 0, 1, sizeof(rd_data)); } return outbuf.len; @@ -162,7 +149,7 @@ prepare_update(coap_message_t *request, int triggered) { coap_set_header_uri_path(request, session_info.assigned_ep); snprintf(query_data, sizeof(query_data) - 1, "?lt=%d&b=%s", session_info.lifetime, session_info.binding); - PRINTF("UPDATE:%s %s\n", session_info.assigned_ep, query_data); + LOG_DBG("UPDATE:%s %s\n", session_info.assigned_ep, query_data); coap_set_header_uri_query(request, query_data); if((triggered || rd_flags & FLAG_RD_DATA_UPDATE_ON_DIRTY) && (rd_flags & FLAG_RD_DATA_DIRTY)) { @@ -212,8 +199,8 @@ static void perform_session_callback(int state) { if(session_info.callback != NULL) { - PRINTF("Performing session callback: %d cb:%p\n", - state, session_info.callback); + LOG_DBG("Performing session callback: %d cb:%p\n", + state, session_info.callback); session_info.callback(&session_info, state); } } @@ -360,23 +347,23 @@ update_bootstrap_server(void) static void bootstrap_callback(coap_request_state_t *state) { - PRINTF("Bootstrap callback Response: %d, ", state->response != NULL); + LOG_DBG("Bootstrap callback Response: %d, ", state->response != NULL); if(state->response) { if(CHANGED_2_04 == state->response->code) { - PRINTF("Considered done!\n"); + LOG_DBG_("Considered done!\n"); rd_state = BOOTSTRAP_DONE; return; } /* Possible error response codes are 4.00 Bad request & 4.15 Unsupported content format */ - PRINTF("Failed with code %d. Retrying\n", state->response->code); + LOG_DBG_("Failed with code %d. Retrying\n", state->response->code); /* TODO Application callback? */ rd_state = INIT; } else if(BOOTSTRAP_SENT == rd_state) { /* this can handle double invocations */ /* Failure! */ - PRINTF("Bootstrap failed! Retry?"); + LOG_DBG("Bootstrap failed! Retry?"); rd_state = DO_BOOTSTRAP; } else { - PRINTF("Ignore\n"); + LOG_DBG("Ignore\n"); } } /*---------------------------------------------------------------------------*/ @@ -385,7 +372,7 @@ produce_more_rd(void) { lwm2m_buffer_t outbuf; - PRINTF("GOT Continue!\n"); + LOG_DBG("GOT Continue!\n"); /* setup the output buffer */ outbuf.buffer = rd_data; @@ -398,8 +385,8 @@ produce_more_rd(void) rd_more = lwm2m_engine_set_rd_data(&outbuf, rd_block1); coap_set_payload(request, rd_data, outbuf.len); - PRINTF("Setting block1 in request - block: %d more: %d\n", - (int) rd_block1, (int) rd_more); + LOG_DBG("Setting block1 in request - block: %d more: %d\n", + (int)rd_block1, (int)rd_more); coap_set_header_block1(request, rd_block1, rd_more, sizeof(rd_data)); coap_send_request(&rd_request_state, &session_info.server_ep, request, rd_callback); @@ -417,7 +404,7 @@ block1_rd_callback(coap_timer_t *timer) static void registration_callback(coap_request_state_t *state) { - PRINTF("Registration callback. Response: %d, ", state->response != NULL); + LOG_DBG("Registration callback. Response: %d, ", state->response != NULL); if(state->response) { /* check state and possibly set registration to done */ /* If we get a continue - we need to call the rd generator one more time */ @@ -426,6 +413,7 @@ registration_callback(coap_request_state_t *state) coap_get_header_block1(state->response, &rd_block1, NULL, NULL, NULL); coap_timer_set_callback(&block1_timer, block1_rd_callback); coap_timer_set(&block1_timer, 1); /* delay 1 ms */ + LOG_DBG_("Continue\n"); } else if(CREATED_2_01 == state->response->code) { if(state->response->location_path_len < LWM2M_RD_CLIENT_ASSIGNED_ENDPOINT_MAX_LEN) { memcpy(session_info.assigned_ep, state->response->location_path, @@ -435,27 +423,27 @@ registration_callback(coap_request_state_t *state) rd_state = REGISTRATION_DONE; /* remember the last reg time */ last_update = coap_timer_uptime(); - PRINTF("Done (assigned EP='%s')!\n", session_info.assigned_ep); + LOG_DBG_("Done (assigned EP='%s')!\n", session_info.assigned_ep); perform_session_callback(LWM2M_RD_CLIENT_REGISTERED); return; } - PRINTF("failed to handle assigned EP: '"); - PRINTS(state->response->location_path_len, - state->response->location_path, "%c"); - PRINTF("'. Re-init network.\n"); + LOG_DBG_("failed to handle assigned EP: '"); + LOG_DBG_COAP_STRING(state->response->location_path, + state->response->location_path_len); + LOG_DBG_("'. Re-init network.\n"); } else { /* Possible error response codes are 4.00 Bad request & 4.03 Forbidden */ - PRINTF("failed with code %d. Re-init network\n", state->response->code); + LOG_DBG_("failed with code %d. Re-init network\n", state->response->code); } /* TODO Application callback? */ rd_state = INIT; } else if(REGISTRATION_SENT == rd_state) { /* this can handle double invocations */ /* Failure! */ - PRINTF("Registration failed! Retry?\n"); + LOG_DBG_("Registration failed! Retry?\n"); rd_state = DO_REGISTRATION; } else { - PRINTF("Ignore\n"); + LOG_DBG_("Ignore\n"); } } /*---------------------------------------------------------------------------*/ @@ -465,7 +453,7 @@ registration_callback(coap_request_state_t *state) static void update_callback(coap_request_state_t *state) { - PRINTF("Update callback. Response: %d, ", state->response != NULL); + LOG_DBG("Update callback. Response: %d, ", state->response != NULL); if(state->response) { /* If we get a continue - we need to call the rd generator one more time */ @@ -475,7 +463,7 @@ update_callback(coap_request_state_t *state) coap_timer_set_callback(&block1_timer, block1_rd_callback); coap_timer_set(&block1_timer, 1); /* delay 1 ms */ } else if(CHANGED_2_04 == state->response->code) { - PRINTF("Done!\n"); + LOG_DBG_("Done!\n"); /* remember the last reg time */ last_update = coap_timer_uptime(); rd_state = REGISTRATION_DONE; @@ -483,33 +471,33 @@ update_callback(coap_request_state_t *state) return; } /* Possible error response codes are 4.00 Bad request & 4.04 Not Found */ - PRINTF("Failed with code %d. Retrying registration\n", state->response->code); + LOG_DBG_("Failed with code %d. Retrying registration\n", state->response->code); rd_state = DO_REGISTRATION; } else if(REGISTRATION_SENT == rd_state) { /* this can handle the current double invocation */ - /*Failure! */ - PRINTF("Registration failed! Retry?"); + /* Failure! */ + LOG_DBG("Registration failed! Retry?"); rd_state = DO_REGISTRATION; } else if(UPDATE_SENT == rd_state) { /* Update failed */ - PRINTF("Update failed! Retry?"); + LOG_DBG("Update failed! Retry?"); rd_state = DO_REGISTRATION; } else { - PRINTF("Ignore\n"); + LOG_DBG("Ignore\n"); } } /*---------------------------------------------------------------------------*/ static void deregister_callback(coap_request_state_t *state) { - PRINTF("Deregister callback. Response Code: %d\n", - state->response != NULL ? state->response->code : 0); + LOG_DBG("Deregister callback. Response Code: %d\n", + state->response != NULL ? state->response->code : 0); if(state->response && (DELETED_2_02 == state->response->code)) { - PRINTF("Deregistration success\n"); + LOG_DBG("Deregistration success\n"); rd_state = DEREGISTERED; perform_session_callback(LWM2M_RD_CLIENT_DEREGISTERED); } else { - PRINTF("Deregistration failed\n"); + LOG_DBG("Deregistration failed\n"); if(rd_state == DEREGISTER_SENT) { rd_state = DEREGISTER_FAILED; perform_session_callback(LWM2M_RD_CLIENT_DEREGISTER_FAILED); @@ -527,19 +515,19 @@ periodic_process(coap_timer_t *timer) coap_timer_reset(&rd_timer, STATE_MACHINE_UPDATE_INTERVAL); now = coap_timer_uptime(); - PRINTF("RD Client - state: %d, ms: %lu\n", rd_state, - (unsigned long)coap_timer_uptime()); + LOG_DBG("RD Client - state: %d, ms: %lu\n", rd_state, + (unsigned long)coap_timer_uptime()); switch(rd_state) { case INIT: - PRINTF("RD Client started with endpoint '%s' and client lifetime %d\n", session_info.ep, session_info.lifetime); + LOG_DBG("RD Client started with endpoint '%s' and client lifetime %d\n", session_info.ep, session_info.lifetime); rd_state = WAIT_NETWORK; break; case WAIT_NETWORK: if(now > wait_until_network_check) { /* check each 10 seconds before next check */ - PRINTF("Checking for network... %lu\n", - (unsigned long)wait_until_network_check); + LOG_DBG("Checking for network... %lu\n", + (unsigned long)wait_until_network_check); wait_until_network_check = now + 10000; if(has_network_access()) { /* Either do bootstrap then registration */ @@ -561,9 +549,9 @@ periodic_process(coap_timer_t *timer) snprintf(query_data, sizeof(query_data) - 1, "?ep=%s", session_info.ep); coap_set_header_uri_query(request, query_data); - PRINTF("Registering ID with bootstrap server ["); - PRINTEP(&session_info.bs_server_ep); - PRINTF("] as '%s'\n", query_data); + LOG_INFO("Registering ID with bootstrap server ["); + LOG_INFO_COAP_EP(&session_info.bs_server_ep); + LOG_INFO_("] as '%s'\n", query_data); coap_send_request(&rd_request_state, &session_info.bs_server_ep, request, bootstrap_callback); @@ -579,7 +567,7 @@ periodic_process(coap_timer_t *timer) /* check that we should still use bootstrap */ if(session_info.use_bootstrap) { lwm2m_security_server_t *security; - PRINTF("*** Bootstrap - checking for server info...\n"); + LOG_DBG("*** Bootstrap - checking for server info...\n"); /* get the security object - ignore bootstrap servers */ for(security = lwm2m_security_get_first(); security != NULL; @@ -594,9 +582,10 @@ periodic_process(coap_timer_t *timer) if(security->server_uri_len > 0) { uint8_t secure = 0; - PRINTF("**** Found security instance using: "); - PRINTS(security->server_uri_len, security->server_uri, "%c"); - PRINTF(" (len %d) \n", security->server_uri_len); + LOG_DBG("**** Found security instance using: "); + LOG_DBG_COAP_STRING((const char *)security->server_uri, + security->server_uri_len); + LOG_DBG_(" (len %d) \n", security->server_uri_len); /* TODO Should verify it is a URI */ /* Check if secure */ secure = strncmp((const char *)security->server_uri, @@ -605,22 +594,23 @@ periodic_process(coap_timer_t *timer) if(!coap_endpoint_parse((const char *)security->server_uri, security->server_uri_len, &session_info.server_ep)) { - PRINTF("Failed to parse server URI!\n"); + LOG_DBG("Failed to parse server URI!\n"); } else { - PRINTF("Server address:"); - PRINTEP(&session_info.server_ep); - PRINTF("\n"); + LOG_DBG("Server address:"); + LOG_DBG_COAP_EP(&session_info.server_ep); + LOG_DBG_("\n"); if(secure) { - PRINTF("Secure CoAP requested but not supported - can not bootstrap\n"); + LOG_DBG("Secure CoAP requested but not supported - can not bootstrap\n"); } else { lwm2m_rd_client_register_with_server(&session_info.server_ep); session_info.bootstrapped++; } } } else { - PRINTF("** failed to parse URI "); - PRINTS(security->server_uri_len, security->server_uri, "%c"); - PRINTF("\n"); + LOG_DBG("** failed to parse URI "); + LOG_DBG_COAP_STRING((const char *)security->server_uri, + security->server_uri_len); + LOG_DBG_("\n"); } } @@ -637,7 +627,7 @@ periodic_process(coap_timer_t *timer) if(!coap_endpoint_is_connected(&session_info.server_ep)) { /* Not connected... wait a bit... and retry connection */ coap_endpoint_connect(&session_info.server_ep); - PRINTF("Wait until connected... \n"); + LOG_DBG("Wait until connected... \n"); return; } if(session_info.use_registration && !session_info.registered && @@ -654,13 +644,13 @@ periodic_process(coap_timer_t *timer) len = set_rd_data(request); rd_callback = registration_callback; - PRINTF("Registering with ["); - PRINTEP(&session_info.server_ep); - PRINTF("] lwm2m endpoint '%s': '", query_data); + LOG_INFO("Registering with ["); + LOG_INFO_COAP_EP(&session_info.server_ep); + LOG_INFO_("] lwm2m endpoint '%s': '", query_data); if(len) { - PRINTS(len, rd_data, "%c"); + LOG_INFO_COAP_STRING((const char *)rd_data, len); } - PRINTF("' More:%d\n", rd_more); + LOG_INFO_("' More:%d\n", rd_more); coap_send_request(&rd_request_state, &session_info.server_ep, request, registration_callback); @@ -690,7 +680,7 @@ periodic_process(coap_timer_t *timer) /* just wait until the callback kicks us to the next state... */ break; case DEREGISTER: - PRINTF("DEREGISTER %s\n", session_info.assigned_ep); + LOG_INFO("DEREGISTER %s\n", session_info.assigned_ep); coap_init_message(request, COAP_TYPE_CON, COAP_DELETE, 0); coap_set_header_uri_path(request, session_info.assigned_ep); coap_send_request(&rd_request_state, &session_info.server_ep, request, @@ -705,7 +695,7 @@ periodic_process(coap_timer_t *timer) break; default: - PRINTF("Unhandled state: %d\n", rd_state); + LOG_WARN("Unhandled state: %d\n", rd_state); } } /*---------------------------------------------------------------------------*/ diff --git a/os/services/lwm2m/lwm2m-security.c b/os/services/lwm2m/lwm2m-security.c index b680acdc7..1a3507877 100644 --- a/os/services/lwm2m/lwm2m-security.c +++ b/os/services/lwm2m/lwm2m-security.c @@ -51,21 +51,10 @@ #include "coap-keystore.h" #include "lib/list.h" -#define DEBUG 0 -#if DEBUG -#include -#define PRINTF(...) printf(__VA_ARGS__) -#define PRINTS(l,s,f) do { int i; \ - for(i = 0; i < l; i++) printf(f, s[i]); \ - } while(0) -#define PRINTPRE(p,l,s) do { PRINTF(p);PRINTS(l,s,"%c"); } while(0); -#define PRINTEP(ep) coap_endpoint_print(ep) -#else -#define PRINTF(...) -#define PRINTS(l,s,f) -#define PRINTPRE(p,l,s); -#define PRINTEP(ep) -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "lwm2m-security" +#define LOG_LEVEL LOG_LEVEL_LWM2M #define MAX_COUNT LWM2M_SERVER_MAX_COUNT @@ -111,7 +100,7 @@ create_instance(uint16_t instance_id, lwm2m_status_t *status) sizeof(resources) / sizeof(lwm2m_resource_id_t); list_add(instances_list, &instances[i].instance); - PRINTF("SEC: Create new security instance\n"); + LOG_DBG("Create new security instance\n"); return &instances[i].instance; } } @@ -187,7 +176,7 @@ lwm2m_callback(lwm2m_object_instance_t *object, /* Handle the writes */ switch(ctx->resource_id) { case LWM2M_SECURITY_SERVER_URI_ID: - PRINTF("Writing security URI value: len: %d\n", (int)ctx->inbuf->size); + LOG_DBG("Writing security URI value: len: %d\n", (int)ctx->inbuf->size); value = lwm2m_object_read_string(ctx, ctx->inbuf->buffer, ctx->inbuf->size, security->server_uri, URI_SIZE); /* This is string... */ security->server_uri_len = ctx->last_value_len; @@ -195,18 +184,18 @@ lwm2m_callback(lwm2m_object_instance_t *object, case LWM2M_SECURITY_BOOTSTRAP_SERVER_ID: value = lwm2m_object_read_boolean(ctx, ctx->inbuf->buffer, ctx->inbuf->size, &iv); if(value > 0) { - PRINTF("Set Bootstrap: %d\n", iv); + LOG_DBG("Set Bootstrap: %d\n", iv); security->bootstrap = (uint8_t) iv; } else { - PRINTF("Failed to set bootstrap\n"); + LOG_WARN("Failed to set bootstrap\n"); } break; case LWM2M_SECURITY_MODE_ID: { int32_t v2; value = lwm2m_object_read_int(ctx, ctx->inbuf->buffer, ctx->inbuf->size, &v2); - PRINTF("Writing security MODE value: %d len: %d\n", v2, - (int)ctx->inbuf->size); + LOG_DBG("Writing security MODE value: %d len: %d\n", v2, + (int)ctx->inbuf->size); security->security_mode = v2; } break; @@ -214,17 +203,19 @@ lwm2m_callback(lwm2m_object_instance_t *object, value = lwm2m_object_read_string(ctx, ctx->inbuf->buffer, ctx->inbuf->size, security->public_key, KEY_SIZE); security->public_key_len = ctx->last_value_len; - PRINTF("Writing client PKI: len: %d '", (int)ctx->last_value_len); - PRINTS(ctx->last_value_len, security->public_key, "%c"); - PRINTF("'\n"); + LOG_DBG("Writing client PKI: len: %d '", (int)ctx->last_value_len); + LOG_DBG_COAP_STRING((const char *)security->public_key, + ctx->last_value_len); + LOG_DBG_("'\n"); break; case LWM2M_SECURITY_KEY_ID: value = lwm2m_object_read_string(ctx, ctx->inbuf->buffer, ctx->inbuf->size, security->secret_key, URI_SIZE); security->secret_key_len = ctx->last_value_len; - PRINTF("Writing secret key: len: %d '", (int)ctx->last_value_len); - PRINTS(ctx->last_value_len, security->secret_key, "%c"); - PRINTF("'\n"); + LOG_DBG("Writing secret key: len: %d '", (int)ctx->last_value_len); + LOG_DBG_COAP_STRING((const char *)security->secret_key, + ctx->last_value_len); + LOG_DBG_("'\n"); break; } @@ -264,7 +255,7 @@ lwm2m_security_add_server(uint16_t instance_id, int i; if(server_uri_len > URI_SIZE) { - PRINTF("lwm2m-sec: too long server URI\n"); + LOG_WARN("too long server URI: %u\n", server_uri_len); return NULL; } @@ -273,13 +264,13 @@ lwm2m_security_add_server(uint16_t instance_id, server = lwm2m_security_get_next(server)) { if(server->server_id == server_id) { if(server->instance.instance_id != instance_id) { - PRINTF("lwm2m-sec: wrong instance id\n"); + LOG_WARN("wrong instance id\n"); return NULL; } /* Correct server id and instance id */ break; } else if(server->instance.instance_id == instance_id) { - PRINTF("lwm2m-sec: wrong server id\n"); + LOG_WARN("wrong server id\n"); return NULL; } } @@ -299,7 +290,7 @@ lwm2m_security_add_server(uint16_t instance_id, } } if(server == NULL) { - PRINTF("lwm2m-sec: no space for more servers\n"); + LOG_WARN("no space for more servers\n"); return NULL; } } @@ -321,11 +312,11 @@ lwm2m_security_set_server_psk(lwm2m_security_server_t *server, return 0; } if(identity_len > KEY_SIZE) { - PRINTF("lwm2m-sec: too large identity\n"); + LOG_WARN("too large identity: %u\n", identity_len); return 0; } if(key_len > KEY_SIZE) { - PRINTF("lwm2m-sec: too large identity\n"); + LOG_WARN("too large identity: %u\n", key_len); return 0; } memcpy(server->public_key, identity, identity_len); @@ -376,18 +367,18 @@ get_psk_info(const coap_endpoint_t *address_info, } if(!coap_endpoint_parse((char *)e->server_uri, e->server_uri_len, &ep)) { /* Failed to parse URI to endpoint */ - PRINTF("lwm2m-sec: failed to parse server URI "); - PRINTS(e->server_uri_len, e->server_uri, "%c"); - PRINTF("\n"); + LOG_DBG("failed to parse server URI "); + LOG_DBG_COAP_STRING((char *)e->server_uri, e->server_uri_len); + LOG_DBG_("\n"); continue; } if(!coap_endpoint_cmp(address_info, &ep)) { /* Wrong server */ - PRINTF("lwm2m-sec: wrong server "); - PRINTEP(address_info); - PRINTF(" != "); - PRINTEP(&ep); - PRINTF("\n"); + LOG_DBG("wrong server "); + LOG_DBG_COAP_EP(address_info); + LOG_DBG_(" != "); + LOG_DBG_COAP_EP(&ep); + LOG_DBG_("\n"); continue; } if(info->identity_len > 0 && info->identity != NULL) { @@ -395,12 +386,12 @@ get_psk_info(const coap_endpoint_t *address_info, if(info->identity_len != e->public_key_len || memcmp(info->identity, e->public_key, info->identity_len)) { /* Identity not matching */ - PRINTF("lwm2m-sec: identity not matching\n"); + LOG_DBG("identity not matching\n"); continue; } } /* Found security information for this server */ - PRINTF("lwm2m-sec: found security match!\n"); + LOG_DBG("found security match!\n"); break; } @@ -436,7 +427,7 @@ lwm2m_security_init(void) { int i; - PRINTF("lwm2m-sec: init\n"); + LOG_INFO("init\n"); list_init(instances_list); @@ -449,12 +440,12 @@ lwm2m_security_init(void) #if COAP_DTLS_KEYSTORE_CONF_WITH_LWM2M /* Security object handler added - register keystore */ coap_set_keystore(&key_store); - PRINTF("lwm2m-sec: registered keystore\n"); + LOG_DBG("registered keystore\n"); #endif /* COAP_DTLS_KEYSTORE_CONF_WITH_LWM2M */ #endif /* WITH_DTLS */ } else { - PRINTF("lwm2m-sec: failed to register\n"); + LOG_WARN("failed to register\n"); } } /*---------------------------------------------------------------------------*/ diff --git a/os/services/lwm2m/lwm2m-server.c b/os/services/lwm2m/lwm2m-server.c index 31eb4a32c..0378221c6 100644 --- a/os/services/lwm2m/lwm2m-server.c +++ b/os/services/lwm2m/lwm2m-server.c @@ -49,13 +49,10 @@ #include "lwm2m-server.h" #include "lwm2m-rd-client.h" -#define DEBUG 0 -#if DEBUG -#include -#define PRINTF(...) printf(__VA_ARGS__) -#else -#define PRINTF(...) -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "lwm2m-server" +#define LOG_LEVEL LOG_LEVEL_LWM2M #define MAX_COUNT LWM2M_SERVER_MAX_COUNT @@ -205,7 +202,7 @@ lwm2m_callback(lwm2m_object_instance_t *object, server = (lwm2m_server_t *) object; if(ctx->operation == LWM2M_OP_WRITE) { - PRINTF("Write to: %d\n", ctx->resource_id); + LOG_DBG("Write to: %d\n", ctx->resource_id); switch(ctx->resource_id) { case LWM2M_SERVER_LIFETIME_ID: lwm2m_object_read_int(ctx, ctx->inbuf->buffer, ctx->inbuf->size, &value); @@ -247,16 +244,14 @@ lwm2m_server_add(uint16_t instance_id, uint16_t server_id, uint32_t lifetime) /* Found a matching server */ if(server->instance.instance_id != instance_id) { /* Non-matching instance id */ - PRINTF("lwm2m-server: non-matching instance id for server %u\n", - server_id); + LOG_DBG("non-matching instance id for server %u\n", server_id); return NULL; } server->lifetime = lifetime; return server; } else if(server->instance.instance_id == instance_id) { /* Right instance but wrong server id */ - PRINTF("lwm2m-server: non-matching server id for instance %u\n", - instance_id); + LOG_DBG("non-matching server id for instance %u\n", instance_id); return NULL; } } @@ -277,7 +272,7 @@ lwm2m_server_add(uint16_t instance_id, uint16_t server_id, uint32_t lifetime) } } - PRINTF("lwm2m-server: no space for more servers\n"); + LOG_WARN("no space for more servers\n"); return NULL; } @@ -287,7 +282,7 @@ lwm2m_server_init(void) { int i; - PRINTF("*** Init lwm2m-server\n"); + LOG_INFO("init\n"); list_init(server_list); diff --git a/os/services/lwm2m/lwm2m-tlv-writer.c b/os/services/lwm2m/lwm2m-tlv-writer.c index 023fd4700..5d69fe733 100644 --- a/os/services/lwm2m/lwm2m-tlv-writer.c +++ b/os/services/lwm2m/lwm2m-tlv-writer.c @@ -45,12 +45,10 @@ #include "lwm2m-object.h" #include "lwm2m-tlv.h" -#define DEBUG 0 -#if DEBUG -#define PRINTF(...) printf(__VA_ARGS__) -#else -#define PRINTF(...) -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "lwm2m-tlv-writer" +#define LOG_LEVEL LOG_LEVEL_NONE /*---------------------------------------------------------------------------*/ static size_t @@ -125,7 +123,7 @@ enter_sub(lwm2m_context_t *ctx) /* set some flags in state */ lwm2m_tlv_t tlv; int len = 0; - PRINTF("Enter sub-resource rsc=%d mark:%d\n", ctx->resource_id, ctx->outbuf->len); + LOG_DBG("Enter sub-resource rsc=%d mark:%d\n", ctx->resource_id, ctx->outbuf->len); ctx->writer_flags |= WRITER_RESOURCE_INSTANCE; tlv.type = LWM2M_TLV_TYPE_MULTI_RESOURCE; tlv.length = 8; /* create an 8-bit TLV */ @@ -152,8 +150,8 @@ exit_sub(lwm2m_context_t *ctx) } len = ctx->outbuf->len - ctx->out_mark_pos_ri; - PRINTF("Exit sub-resource rsc=%d mark:%d len=%d\n", ctx->resource_id, - ctx->out_mark_pos_ri, len); + LOG_DBG("Exit sub-resource rsc=%d mark:%d len=%d\n", ctx->resource_id, + ctx->out_mark_pos_ri, len); /* update the lenght byte... Assume TLV header is pos + 1 bytes. */ ctx->outbuf->buffer[pos + ctx->out_mark_pos_ri] = len - (pos + 1); diff --git a/os/services/lwm2m/lwm2m-tlv.c b/os/services/lwm2m/lwm2m-tlv.c index 5c5bb471e..37b1afc61 100644 --- a/os/services/lwm2m/lwm2m-tlv.c +++ b/os/services/lwm2m/lwm2m-tlv.c @@ -46,13 +46,10 @@ #include #include "lwm2m-tlv.h" -#define DEBUG 0 -#if DEBUG -#include -#define PRINTF(...) printf(__VA_ARGS__) -#else -#define PRINTF(...) -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "lwm2m-tlv" +#define LOG_LEVEL LOG_LEVEL_NONE /*---------------------------------------------------------------------------*/ static inline uint8_t @@ -131,7 +128,7 @@ lwm2m_tlv_write(const lwm2m_tlv_t *tlv, uint8_t *buffer, size_t buffersize) pos = 1 + len_type; /* ensure that we do not write too much */ if(tlv->value != NULL && buffersize < tlv->length + pos) { - PRINTF("LWM2M-TLV: Could not write the TLV - buffer overflow.\n"); + LOG_WARN("Could not write the TLV - buffer overflow.\n"); return 0; } @@ -167,13 +164,13 @@ lwm2m_tlv_write(const lwm2m_tlv_t *tlv, uint8_t *buffer, size_t buffersize) memcpy(&buffer[pos], tlv->value, tlv->length); } - if(DEBUG) { + if(LOG_DBG_ENABLED) { int i; - PRINTF("TLV:"); + LOG_DBG("TLV: "); for(i = 0; i < pos + ((tlv->value != NULL) ? tlv->length : 0); i++) { - PRINTF("%02x", buffer[i]); + LOG_DBG_("%02x", buffer[i]); } - PRINTF("\n"); + LOG_DBG_("\n"); } return pos + ((tlv->value != NULL) ? tlv->length : 0); @@ -208,7 +205,7 @@ lwm2m_tlv_write_int32(uint8_t type, int16_t id, int32_t value, uint8_t *buffer, int i; int v; int last_bit; - PRINTF("Exporting int32 %d %ld ", id, (long)value); + LOG_DBG("Exporting int32 %d %ld ", id, (long)value); v = value < 0 ? -1 : 0; i = 0; @@ -221,7 +218,7 @@ lwm2m_tlv_write_int32(uint8_t type, int16_t id, int32_t value, uint8_t *buffer, } while((value != v || last_bit) && i < 4); /* export INT as TLV */ - PRINTF("len: %d\n", i); + LOG_DBG("len: %d\n", i); tlv.type = type; tlv.length = i; tlv.value = &buf[3 - (i - 1)]; @@ -255,11 +252,11 @@ lwm2m_tlv_write_float32(uint8_t type, int16_t id, int32_t value, int bits, e++; } - PRINTF("Sign: %d, Fraction: %06lx 0b", value < 0, (long)val); + LOG_DBG("Sign: %d, Fraction: %06lx 0b", value < 0, (long)val); for(i = 0; i < 23; i++) { - PRINTF("%d", (int)((val >> (22 - i)) & 1)); + LOG_DBG_("%d", (int)((val >> (22 - i)) & 1)); } - PRINTF("\nExp:%d\n", e); + LOG_DBG_("\nExp:%d\n", e); /* convert to the thing we should have */ e = e - bits + 127; @@ -274,7 +271,7 @@ lwm2m_tlv_write_float32(uint8_t type, int16_t id, int32_t value, int bits, b[2] = (val >> 8) & 0xff; b[3] = val & 0xff; - PRINTF("B=%02x%02x%02x%02x\n", b[0], b[1], b[2], b[3]); + LOG_DBG("B=%02x%02x%02x%02x\n", b[0], b[1], b[2], b[3]); /* construct the TLV */ tlv.type = type; tlv.length = 4; @@ -295,19 +292,19 @@ lwm2m_tlv_float32_to_fix(const lwm2m_tlv_t *tlv, int32_t *value, int bits) e = ((tlv->value[0] << 1) & 0xff) | (tlv->value[1] >> 7); val = (((long)tlv->value[1] & 0x7f) << 16) | (tlv->value[2] << 8) | tlv->value[3]; - PRINTF("Sign: %d, Fraction: %06lx 0b", val < 0, (long)val); + LOG_DBG("Sign: %d, Fraction: %06lx 0b", val < 0, (long)val); for(i = 0; i < 23; i++) { - PRINTF("%d", (int)((val >> (22 - i)) & 1)); + LOG_DBG_("%d", (int)((val >> (22 - i)) & 1)); } - PRINTF("\nExp:%d => %d\n", e, e - 127); + LOG_DBG("\nExp:%d => %d\n", e, e - 127); e = e - 127 + bits; /* e corresponds to the number of times we need to roll the number */ - PRINTF("Actual e=%d\n", e); + LOG_DBG("Actual e=%d\n", e); e = e - 23; - PRINTF("E after sub %d\n", e); + LOG_DBG("E after sub %d\n", e); val = val | 1L << 23; if(e > 0) { val = val << e; @@ -332,9 +329,8 @@ int main(int argc, char *argv[]) data[0] = 0x00; data[1] = 0x80, - PRINTF("TLV:%d\n", lwm2m_tlv_get_int32(&tlv)); - - PRINTF("Len: %d\n", lwm2m_tlv_write_int32(0, 1, -0x88987f, data, 24)); + printf("TLV:%d\n", lwm2m_tlv_get_int32(&tlv)); + printf("Len: %d\n", lwm2m_tlv_write_int32(0, 1, -0x88987f, data, 24)); } #endif From ffffb0a9adbe170c076a753afffc864f0c276946 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Fri, 1 Dec 2017 18:37:26 +0100 Subject: [PATCH 26/51] Fixed compiler warning in CoAP logging --- os/net/app-layer/coap/coap-uip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/os/net/app-layer/coap/coap-uip.c b/os/net/app-layer/coap/coap-uip.c index 2468b6f47..f6f80fe46 100644 --- a/os/net/app-layer/coap/coap-uip.c +++ b/os/net/app-layer/coap/coap-uip.c @@ -541,7 +541,7 @@ get_psk_info(struct dtls_context_t *ctx, ks.identity_hint = id; ks.identity_hint_len = id_len; LOG_DBG("got psk_identity_hint: '"); - LOG_DBG_COAP_STRING(id, id_len); + LOG_DBG_COAP_STRING((const char *)id, id_len); LOG_DBG_("'\n"); } From 770ace033998a87d5e642ada1af6c2680d16446d Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Sun, 3 Dec 2017 23:22:13 +0100 Subject: [PATCH 27/51] Removed reference to unused variable in the logging module --- os/sys/log.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/os/sys/log.h b/os/sys/log.h index 7c657060c..290ee212c 100644 --- a/os/sys/log.h +++ b/os/sys/log.h @@ -166,10 +166,10 @@ extern struct log_module all_modules[]; #define LOG_DBG_6ADDR(...) LOG_6ADDR(LOG_LEVEL_DBG, __VA_ARGS__) /* For testing log level */ -#define LOG_ERR_ENABLED (MIN(LOG_LEVEL, curr_log_level) >= LOG_LEVEL_ERR) -#define LOG_WARN_ENABLED (MIN(LOG_LEVEL, curr_log_level) >= LOG_LEVEL_WARN) -#define LOG_INFO_ENABLED (MIN(LOG_LEVEL, curr_log_level) >= LOG_LEVEL_INFO) -#define LOG_DBG_ENABLED (MIN(LOG_LEVEL, curr_log_level) >= LOG_LEVEL_DBG) +#define LOG_ERR_ENABLED ((LOG_LEVEL) >= LOG_LEVEL_ERR) +#define LOG_WARN_ENABLED ((LOG_LEVEL) >= LOG_LEVEL_WARN) +#define LOG_INFO_ENABLED ((LOG_LEVEL) >= LOG_LEVEL_INFO) +#define LOG_DBG_ENABLED ((LOG_LEVEL) >= LOG_LEVEL_DBG) #if NETSTACK_CONF_WITH_IPV6 From 04acccf9a083b184b8b2b732c490d70cb27d1458 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Sun, 3 Dec 2017 23:37:00 +0100 Subject: [PATCH 28/51] Fixed compiler warnings in LWM2M logging --- os/services/lwm2m/lwm2m-engine.c | 14 ++++++++------ os/services/lwm2m/lwm2m-firmware.c | 10 ++++++---- os/services/lwm2m/lwm2m-security.c | 5 +++-- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/os/services/lwm2m/lwm2m-engine.c b/os/services/lwm2m/lwm2m-engine.c index 481a28e4d..fccce3a4c 100644 --- a/os/services/lwm2m/lwm2m-engine.c +++ b/os/services/lwm2m/lwm2m-engine.c @@ -362,7 +362,7 @@ void lwm2m_engine_set_opaque_callback(lwm2m_context_t *ctx, lwm2m_write_opaque_c { /* Here we should set the callback for the opaque that we are currently generating... */ /* And we should in the future associate the callback with the CoAP message info - MID */ - LOG_DBG("Setting opaque handler - offset: %d,%d\n", + LOG_DBG("Setting opaque handler - offset: %"PRIu32",%d\n", ctx->offset, ctx->outbuf->len); current_opaque_offset = 0; @@ -655,7 +655,7 @@ perform_multi_resource_read_op(lwm2m_object_t *object, return LWM2M_STATUS_SERVICE_UNAVAILABLE; } - LOG_DBG("MultiRead: %d/%d/%d lv:%d offset:%d\n", + LOG_DBG("MultiRead: %d/%d/%d lv:%d offset:%"PRIu32"\n", ctx->object_id, ctx->object_instance_id, ctx->resource_id, ctx->level, ctx->offset); @@ -696,7 +696,7 @@ perform_multi_resource_read_op(lwm2m_object_t *object, if(instance->resource_ids != NULL && instance->resource_count > 0) { /* show all the available resources (or read all) */ while(last_rsc_pos < instance->resource_count) { - LOG_DBG("READ: %x %x %x lv:%d\n", + LOG_DBG("READ: 0x%"PRIx32" 0x%x 0x%x lv:%d\n", instance->resource_ids[last_rsc_pos], RSC_ID(instance->resource_ids[last_rsc_pos]), ctx->resource_id, ctx->level); @@ -1083,8 +1083,9 @@ perform_multi_resource_write_op(lwm2m_object_t *object, future */ if(coap_get_header_block1(ctx->request, &num, &more, &size, &offset)) { - LOG_DBG("CoAP BLOCK1: %d/%d/%d offset:%d\n", num, more, size, offset); - LOG_DBG("LWM2M CTX->offset= %d\n", ctx->offset); + LOG_DBG("CoAP BLOCK1: %"PRIu32"/%d/%d offset:%"PRIu32 + " LWM2M CTX->offset=%"PRIu32"\n", + num, more, size, offset, ctx->offset); LOG_DBG("Last TLV ID:%d final:%d\n", last_tlv_id, lwm2m_object_is_final_incoming(ctx)); if(offset > 0) { @@ -1562,7 +1563,8 @@ lwm2m_handler_callback(coap_message_t *request, coap_message_t *response, coap_set_header_content_format(response, context.content_type); if(offset != NULL) { - LOG_DBG("Setting new offset: oo %d, no: %d\n", *offset, context.offset); + LOG_DBG("Setting new offset: oo %"PRIu32 + ", no: %"PRIu32"\n", *offset, context.offset); if(context.writer_flags & WRITER_HAS_MORE) { *offset = context.offset; } else { diff --git a/os/services/lwm2m/lwm2m-firmware.c b/os/services/lwm2m/lwm2m-firmware.c index ba03eb3d3..e89c3dab4 100644 --- a/os/services/lwm2m/lwm2m-firmware.c +++ b/os/services/lwm2m/lwm2m-firmware.c @@ -39,6 +39,7 @@ #include "lwm2m-engine.h" #include "lwm2m-firmware.h" #include "coap.h" +#include #include /* Log configuration */ @@ -110,15 +111,16 @@ lwm2m_callback(lwm2m_object_instance_t *object, if(LOG_DBG_ENABLED) { if(coap_get_header_block1(ctx->request, &num, &more, &size, &offset)) { - LOG_DBG("CoAP BLOCK1: %d/%d/%d offset:%d\n", num, more, size, offset); - LOG_DBG("LWM2M CTX->offset= %d\n", ctx->offset); + LOG_DBG("CoAP BLOCK1: %"PRIu32"/%u/%u offset:%"PRIu32 + " LWM2M CTX->offset=%"PRIu32"\n", + num, more, size, offset, ctx->offset); } } switch(ctx->resource_id) { case UPDATE_PACKAGE: /* The firmware is written */ - LOG_DBG("Firmware received: %d %d fin:%d\n", ctx->offset, + LOG_DBG("Firmware received: %"PRIu32" %d fin:%d\n", ctx->offset, (int)ctx->inbuf->size, lwm2m_object_is_final_incoming(ctx)); if(lwm2m_object_is_final_incoming(ctx)) { state = STATE_DOWNLOADED; @@ -128,7 +130,7 @@ lwm2m_callback(lwm2m_object_instance_t *object, return LWM2M_STATUS_OK; case UPDATE_PACKAGE_URI: /* The firmware URI is written */ - LOG_DBG("Firmware URI received: %d %d fin:%d\n", ctx->offset, + LOG_DBG("Firmware URI received: %"PRIu32" %d fin:%d\n", ctx->offset, (int)ctx->inbuf->size, lwm2m_object_is_final_incoming(ctx)); if(LOG_DBG_ENABLED) { int i; diff --git a/os/services/lwm2m/lwm2m-security.c b/os/services/lwm2m/lwm2m-security.c index 1a3507877..cea41f244 100644 --- a/os/services/lwm2m/lwm2m-security.c +++ b/os/services/lwm2m/lwm2m-security.c @@ -44,6 +44,7 @@ #include #include +#include #include "lwm2m-object.h" #include "lwm2m-engine.h" #include "lwm2m-server.h" @@ -100,7 +101,7 @@ create_instance(uint16_t instance_id, lwm2m_status_t *status) sizeof(resources) / sizeof(lwm2m_resource_id_t); list_add(instances_list, &instances[i].instance); - LOG_DBG("Create new security instance\n"); + LOG_DBG("Create new security instance %u\n", instance_id); return &instances[i].instance; } } @@ -194,7 +195,7 @@ lwm2m_callback(lwm2m_object_instance_t *object, { int32_t v2; value = lwm2m_object_read_int(ctx, ctx->inbuf->buffer, ctx->inbuf->size, &v2); - LOG_DBG("Writing security MODE value: %d len: %d\n", v2, + LOG_DBG("Writing security MODE value: %"PRId32" len: %d\n", v2, (int)ctx->inbuf->size); security->security_mode = v2; } From 18cd711050824c239ba985b1cd01e8a007747c71 Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Thu, 7 Dec 2017 22:56:53 +0100 Subject: [PATCH 29/51] fixed issue with bootstrap and write of security and server object --- os/services/lwm2m/lwm2m-engine.c | 76 ++++++++++++++++++++------------ os/services/lwm2m/lwm2m-object.h | 1 + 2 files changed, 50 insertions(+), 27 deletions(-) diff --git a/os/services/lwm2m/lwm2m-engine.c b/os/services/lwm2m/lwm2m-engine.c index fccce3a4c..897675ec0 100644 --- a/os/services/lwm2m/lwm2m-engine.c +++ b/os/services/lwm2m/lwm2m-engine.c @@ -88,6 +88,7 @@ #define RSC_ID(x) ((uint16_t)(x & 0xffff)) #define RSC_READABLE(x) ((x & LWM2M_RESOURCE_READ) > 0) #define RSC_WRITABLE(x) ((x & LWM2M_RESOURCE_WRITE) > 0) +#define RSC_UNSPECIFIED(x) ((x & LWM2M_RESOURCE_OP_MASK) == 0) /* invalid instance ID - ffff object ID */ #define NO_INSTANCE 0xffffffff @@ -121,6 +122,15 @@ static lwm2m_object_instance_t * next_object_instance(const lwm2m_context_t *context, lwm2m_object_t *object, lwm2m_object_instance_t *last); +struct { + uint16_t object_id; + uint16_t instance_id; + uint16_t token_len; + uint8_t token[8]; /* max 8 bytes in COAP? */ + /* in the future also a timeout */ +} created; + + COAP_HANDLER(lwm2m_handler, lwm2m_handler_callback); LIST(object_list); LIST(generic_object_list); @@ -923,7 +933,7 @@ create_instance(lwm2m_context_t *context, lwm2m_object_t *object) static lwm2m_object_instance_t * get_or_create_instance(lwm2m_context_t *ctx, lwm2m_object_t *object, - uint8_t *created) + uint16_t *c) { lwm2m_object_instance_t *instance; @@ -931,35 +941,57 @@ get_or_create_instance(lwm2m_context_t *ctx, lwm2m_object_t *object, LOG_DBG("Instance: %u/%u/%u = %p\n", ctx->object_id, ctx->object_instance_id, ctx->resource_id, instance); /* by default we assume that the instance is not created... so we set flag to zero */ - if(created != NULL) { - *created = 0; + if(c != NULL) { + *c = LWM2M_OBJECT_INSTANCE_NONE; } if(instance == NULL) { instance = create_instance(ctx, object); if(instance != NULL) { - /* set created flag to one */ - if(created != NULL) { - *created = 1; + if(c != NULL) { + *c = instance->instance_id; } + created.instance_id = instance->instance_id; + created.object_id = instance->object_id; + created.token_len = created.token_len; + memcpy(&created.token, ctx->request->token, created.token_len); } } return instance; } /*---------------------------------------------------------------------------*/ static int -check_write(lwm2m_object_instance_t *instance, int rid) +check_write(lwm2m_context_t *ctx, lwm2m_object_instance_t *instance, int rid) { int i; if(instance->resource_ids != NULL && instance->resource_count > 0) { int count = instance->resource_count; for(i = 0; i < count; i++) { - if(RSC_ID(instance->resource_ids[i]) == rid && - RSC_WRITABLE(instance->resource_ids[i])) { - /* yes - writable */ - return 1; + if(RSC_ID(instance->resource_ids[i]) == rid) { + if(RSC_WRITABLE(instance->resource_ids[i])) { + /* yes - writable */ + return 1; + } + if(RSC_UNSPECIFIED(instance->resource_ids[i]) && + created.instance_id == instance->instance_id && + created.object_id == instance->object_id && + memcmp(&created.token, ctx->request->token, + created.token_len) == 0) { + /* yes - writeable at create - never otherwise - sec / srv */ + return 1; + } + break; } } } + /* Resource did not exist... - Ignore to avoid problems. */ + if(created.instance_id == instance->instance_id && + created.object_id == instance->object_id && + memcmp(&created.token, ctx->request->token, + created.token_len) == 0) { + LOG_DBG("Ignoring resource %u/%u/%d in newly created instance\n", + created.object_id, created.instance_id, rid); + return 1; + } return 0; } /*---------------------------------------------------------------------------*/ @@ -968,7 +1000,7 @@ process_tlv_write(lwm2m_context_t *ctx, lwm2m_object_t *object, int rid, uint8_t *data, int len) { lwm2m_object_instance_t *instance; - uint8_t created = 0; + uint16_t created = LWM2M_OBJECT_INSTANCE_NONE; ctx->inbuf->buffer = data; ctx->inbuf->pos = 0; ctx->inbuf->size = len; @@ -978,7 +1010,7 @@ process_tlv_write(lwm2m_context_t *ctx, lwm2m_object_t *object, ctx->object_instance_id, ctx->resource_id); instance = get_or_create_instance(ctx, object, &created); if(instance != NULL && instance->callback != NULL) { - if(created || check_write(instance, rid)) { + if(check_write(ctx, instance, rid)) { return instance->callback(instance, ctx); } else { return LWM2M_STATUS_OPERATION_NOT_ALLOWED; @@ -1001,6 +1033,8 @@ perform_multi_resource_write_op(lwm2m_object_t *object, uint8_t *inbuf; int inpos; size_t insize; + int i; + uint16_t created = LWM2M_OBJECT_INSTANCE_NONE; olv = ctx->level; inbuf = ctx->inbuf->buffer; @@ -1011,8 +1045,6 @@ perform_multi_resource_write_op(lwm2m_object_t *object, struct json_data json; while(lwm2m_json_next_token(ctx, &json)) { - int i; - uint8_t created = 0; LOG_DBG("JSON: '"); for(i = 0; i < json.name_len; i++) { LOG_DBG_("%c", json.name[i]); @@ -1022,6 +1054,7 @@ perform_multi_resource_write_op(lwm2m_object_t *object, LOG_DBG_("%c", json.value[i]); } LOG_DBG_("'\n"); + if(json.name[0] == 'n') { i = parse_path((const char *) json.value, json.value_len, &oid, &iid, &rid); if(i > 0) { @@ -1053,7 +1086,7 @@ perform_multi_resource_write_op(lwm2m_object_t *object, if(mode == MODE_READY) { /* allow write if just created - otherwise not */ - if(!created && !check_write(instance, ctx->resource_id)) { + if(!check_write(ctx, instance, ctx->resource_id)) { return LWM2M_STATUS_OPERATION_NOT_ALLOWED; } if(instance->callback(instance, ctx) != LWM2M_STATUS_OK) { @@ -1425,17 +1458,6 @@ lwm2m_handler_callback(coap_message_t *request, coap_message_t *response, } instance = get_instance_by_context(&context, &object); - if(instance == NULL - && object != NULL - && coap_get_method_type(request) == METHOD_PUT - && context.level == 2) { - /* ALLOW generic instance if CREATE / WRITE*/ - instance = create_instance(&context, object); - if(instance == NULL) { - LOG_WARN("failed to create instance %u/%u\n", - context.object_id, context.object_instance_id); - } - } /* * Check if we found either instance or object. Instance means we found an diff --git a/os/services/lwm2m/lwm2m-object.h b/os/services/lwm2m/lwm2m-object.h index d466a9e70..858f99c7b 100644 --- a/os/services/lwm2m/lwm2m-object.h +++ b/os/services/lwm2m/lwm2m-object.h @@ -58,6 +58,7 @@ #define LWM2M_RESOURCE_READ 0x10000 #define LWM2M_RESOURCE_WRITE 0x20000 #define LWM2M_RESOURCE_EXECUTE 0x40000 +#define LWM2M_RESOURCE_OP_MASK 0x70000 /* The resource id type of lwm2m objects - 16 bits for the ID - the rest is flags */ From 43466683ffefb88684a7cf8b97a1a616d477ecf1 Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Thu, 7 Dec 2017 23:18:27 +0100 Subject: [PATCH 30/51] fixed issues with the RD client --- os/services/lwm2m/lwm2m-rd-client.c | 46 +++++++++++++++++++---------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/os/services/lwm2m/lwm2m-rd-client.c b/os/services/lwm2m/lwm2m-rd-client.c index 556fd8cc4..f242b017b 100644 --- a/os/services/lwm2m/lwm2m-rd-client.c +++ b/os/services/lwm2m/lwm2m-rd-client.c @@ -71,6 +71,8 @@ #define LWM2M_DEFAULT_CLIENT_LIFETIME 600 /* sec */ #endif +#define MAX_RD_UPDATE_WAIT 5000 + #define REMOTE_PORT UIP_HTONS(COAP_DEFAULT_PORT) #define BS_REMOTE_PORT UIP_HTONS(5685) @@ -107,6 +109,7 @@ static uint8_t rd_state = 0; static uint8_t rd_flags = FLAG_RD_DATA_UPDATE_ON_DIRTY; static uint64_t wait_until_network_check = 0; static uint64_t last_update; +static uint64_t last_rd_progress = 0; static char query_data[64]; /* allocate some data for queries and updates */ static uint8_t rd_data[128]; /* allocate some data for the RD */ @@ -438,10 +441,8 @@ registration_callback(coap_request_state_t *state) } /* TODO Application callback? */ rd_state = INIT; - } else if(REGISTRATION_SENT == rd_state) { /* this can handle double invocations */ - /* Failure! */ - LOG_DBG_("Registration failed! Retry?\n"); - rd_state = DO_REGISTRATION; + /* remember last progress time */ + last_rd_progress = coap_timer_uptime(); } else { LOG_DBG_("Ignore\n"); } @@ -459,6 +460,7 @@ update_callback(coap_request_state_t *state) /* If we get a continue - we need to call the rd generator one more time */ if(CONTINUE_2_31 == state->response->code) { /* We assume that size never change?! */ + LOG_DBG_("Continue\n"); coap_get_header_block1(state->response, &rd_block1, NULL, NULL, NULL); coap_timer_set_callback(&block1_timer, block1_rd_callback); coap_timer_set(&block1_timer, 1); /* delay 1 ms */ @@ -468,19 +470,14 @@ update_callback(coap_request_state_t *state) last_update = coap_timer_uptime(); rd_state = REGISTRATION_DONE; rd_flags &= ~FLAG_RD_DATA_UPDATE_TRIGGERED; - return; + } else { + /* Possible error response codes are 4.00 Bad request & 4.04 Not Found */ + LOG_DBG_("Failed with code %d. Retrying registration\n", + state->response->code); + rd_state = DO_REGISTRATION; } - /* Possible error response codes are 4.00 Bad request & 4.04 Not Found */ - LOG_DBG_("Failed with code %d. Retrying registration\n", state->response->code); - rd_state = DO_REGISTRATION; - } else if(REGISTRATION_SENT == rd_state) { /* this can handle the current double invocation */ - /* Failure! */ - LOG_DBG("Registration failed! Retry?"); - rd_state = DO_REGISTRATION; - } else if(UPDATE_SENT == rd_state) { - /* Update failed */ - LOG_DBG("Update failed! Retry?"); - rd_state = DO_REGISTRATION; + /* remember last progress */ + last_rd_progress = coap_timer_uptime(); } else { LOG_DBG("Ignore\n"); } @@ -505,6 +502,13 @@ deregister_callback(coap_request_state_t *state) } } /*---------------------------------------------------------------------------*/ +static void +recover_from_rd_delay(void) +{ + /* This can be improved in the future... */ + rd_state = INIT; +} +/*---------------------------------------------------------------------------*/ /* CoAP timer callback */ static void periodic_process(coap_timer_t *timer) @@ -654,11 +658,16 @@ periodic_process(coap_timer_t *timer) coap_send_request(&rd_request_state, &session_info.server_ep, request, registration_callback); + last_rd_progress = coap_timer_uptime(); rd_state = REGISTRATION_SENT; } break; case REGISTRATION_SENT: /* just wait until the callback kicks us to the next state... */ + if(last_rd_progress + MAX_RD_UPDATE_WAIT < coap_timer_uptime()) { + /* Timeout on the update - something is wrong? */ + recover_from_rd_delay(); + } break; case REGISTRATION_DONE: /* All is done! */ @@ -672,12 +681,17 @@ periodic_process(coap_timer_t *timer) prepare_update(request, rd_flags & FLAG_RD_DATA_UPDATE_TRIGGERED); coap_send_request(&rd_request_state, &session_info.server_ep, request, update_callback); + last_rd_progress = coap_timer_uptime(); rd_state = UPDATE_SENT; } break; case UPDATE_SENT: /* just wait until the callback kicks us to the next state... */ + if(last_rd_progress + MAX_RD_UPDATE_WAIT < coap_timer_uptime()) { + /* Timeout on the update - something is wrong? */ + recover_from_rd_delay(); + } break; case DEREGISTER: LOG_INFO("DEREGISTER %s\n", session_info.assigned_ep); From c9cafb826d34e8f534b9c370aed992ee28e87dd1 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Fri, 8 Dec 2017 00:23:31 +0100 Subject: [PATCH 31/51] LWM2M: fixed token comparison to use token length --- os/services/lwm2m/lwm2m-engine.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/os/services/lwm2m/lwm2m-engine.c b/os/services/lwm2m/lwm2m-engine.c index 897675ec0..1d7b8bff7 100644 --- a/os/services/lwm2m/lwm2m-engine.c +++ b/os/services/lwm2m/lwm2m-engine.c @@ -52,6 +52,7 @@ #include "lwm2m-tlv-reader.h" #include "lwm2m-tlv-writer.h" #include "lib/list.h" +#include "sys/cc.h" #include #include #include @@ -121,12 +122,11 @@ static coap_handler_status_t lwm2m_handler_callback(coap_message_t *request, static lwm2m_object_instance_t * next_object_instance(const lwm2m_context_t *context, lwm2m_object_t *object, lwm2m_object_instance_t *last); - -struct { +static struct { uint16_t object_id; uint16_t instance_id; uint16_t token_len; - uint8_t token[8]; /* max 8 bytes in COAP? */ + uint8_t token[COAP_TOKEN_LEN]; /* in the future also a timeout */ } created; @@ -952,7 +952,7 @@ get_or_create_instance(lwm2m_context_t *ctx, lwm2m_object_t *object, } created.instance_id = instance->instance_id; created.object_id = instance->object_id; - created.token_len = created.token_len; + created.token_len = MIN(COAP_TOKEN_LEN, ctx->request->token_len); memcpy(&created.token, ctx->request->token, created.token_len); } } @@ -974,6 +974,7 @@ check_write(lwm2m_context_t *ctx, lwm2m_object_instance_t *instance, int rid) if(RSC_UNSPECIFIED(instance->resource_ids[i]) && created.instance_id == instance->instance_id && created.object_id == instance->object_id && + created.token_len == ctx->request->token_len && memcmp(&created.token, ctx->request->token, created.token_len) == 0) { /* yes - writeable at create - never otherwise - sec / srv */ @@ -986,6 +987,7 @@ check_write(lwm2m_context_t *ctx, lwm2m_object_instance_t *instance, int rid) /* Resource did not exist... - Ignore to avoid problems. */ if(created.instance_id == instance->instance_id && created.object_id == instance->object_id && + created.token_len == ctx->request->token_len && memcmp(&created.token, ctx->request->token, created.token_len) == 0) { LOG_DBG("Ignoring resource %u/%u/%d in newly created instance\n", From 5051b18ac98280a8f5958d08209880698ca786ee Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Fri, 8 Dec 2017 13:20:34 +0100 Subject: [PATCH 32/51] LWM2M: changed to 30 sec RD client registration --- os/services/lwm2m/lwm2m-rd-client.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/os/services/lwm2m/lwm2m-rd-client.c b/os/services/lwm2m/lwm2m-rd-client.c index f242b017b..12928001e 100644 --- a/os/services/lwm2m/lwm2m-rd-client.c +++ b/os/services/lwm2m/lwm2m-rd-client.c @@ -68,7 +68,7 @@ #define LOG_LEVEL LOG_LEVEL_LWM2M #ifndef LWM2M_DEFAULT_CLIENT_LIFETIME -#define LWM2M_DEFAULT_CLIENT_LIFETIME 600 /* sec */ +#define LWM2M_DEFAULT_CLIENT_LIFETIME 30 /* sec */ #endif #define MAX_RD_UPDATE_WAIT 5000 From ca827938ee82ed82ce0540a0a7fdeadfd3e2cb12 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Fri, 8 Dec 2017 13:24:16 +0100 Subject: [PATCH 33/51] Updated LWM2M example to use the logging module --- .../lwm2m/standalone/generic-object-test.c | 29 ++++++++----------- examples/lwm2m/standalone/posix-coap-timer.c | 21 ++++++-------- 2 files changed, 21 insertions(+), 29 deletions(-) diff --git a/examples/lwm2m/standalone/generic-object-test.c b/examples/lwm2m/standalone/generic-object-test.c index 493238607..2c394a249 100644 --- a/examples/lwm2m/standalone/generic-object-test.c +++ b/examples/lwm2m/standalone/generic-object-test.c @@ -48,25 +48,20 @@ #include #include +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "gen-obj-test" +#define LOG_LEVEL LOG_LEVEL_COAP + static lwm2m_object_t generic_object; #define MAX_SIZE 512 #define NUMBER_OF_INSTANCES 50 -#define DEBUG 0 - -#if DEBUG -#define PRINTF(...) printf(__VA_ARGS__) -#else -#define PRINTF(...) - -#endif - -static const lwm2m_resource_id_t resources[] = - { - RO(10000), - RO(11000), - }; +static const lwm2m_resource_id_t resources[] = { + RO(10000), + RO(11000), +}; /*---------------------------------------------------------------------------*/ static int read_data(uint8_t *buffer, int instance_id, int start, int len) @@ -87,8 +82,8 @@ opaque_callback(lwm2m_object_instance_t *object, lwm2m_context_t *ctx, int num_to_write) { int len; - PRINTF("opaque-stream callback num_to_write: %d off: %d outlen: %d\n", - num_to_write, ctx->offset, ctx->outbuf->len); + LOG_DBG("opaque-stream callback num_to_write: %d off: %d outlen: %d\n", + num_to_write, ctx->offset, ctx->outbuf->len); len = read_data(&ctx->outbuf->buffer[ctx->outbuf->len], ctx->object_instance_id, @@ -124,7 +119,7 @@ lwm2m_callback(lwm2m_object_instance_t *object, } break; case 11000: - PRINTF("Preparing object write\n"); + LOG_DBG("Preparing object write\n"); lwm2m_object_write_opaque_stream(ctx, MAX_SIZE, opaque_callback); break; default: diff --git a/examples/lwm2m/standalone/posix-coap-timer.c b/examples/lwm2m/standalone/posix-coap-timer.c index 29a0ecca6..3d39eebd5 100644 --- a/examples/lwm2m/standalone/posix-coap-timer.c +++ b/examples/lwm2m/standalone/posix-coap-timer.c @@ -38,13 +38,10 @@ #include "coap-timer.h" #include -#define DEBUG 1 -#if DEBUG -#include -#define PRINTF(...) printf(__VA_ARGS__) -#else -#define PRINTF(...) -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "posix-timer" +#define LOG_LEVEL LOG_LEVEL_WARN /* The maximal time allowed to move forward between updates */ #define MAX_TIME_CHANGE_MSEC 360000UL @@ -59,7 +56,7 @@ uptime(void) uint64_t t; if(gettimeofday(&tv, NULL)) { - PRINTF("*** failed to retrieve system time\n"); + LOG_WARN("*** failed to retrieve system time\n"); return last_msec; } @@ -70,13 +67,13 @@ uptime(void) /* No update first time */ } else if(t < last_msec) { /* System time has moved backwards */ - PRINTF("*** system time has moved backwards %lu msec\n", - (unsigned long)(last_msec - t)); + LOG_WARN("*** system time has moved backwards %lu msec\n", + (unsigned long)(last_msec - t)); } else if(t - last_msec > MAX_TIME_CHANGE_MSEC) { /* Too large jump forward in system time */ - PRINTF("*** system time has moved forward %lu msec\n", - (unsigned long)(t - last_msec)); + LOG_WARN("*** system time has moved forward %lu msec\n", + (unsigned long)(t - last_msec)); uptime_msec += 1000UL; } else { uptime_msec += t - last_msec; From 11b005c7a489dc0721220f39ac1eb9eb2db1ecfc Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Fri, 8 Dec 2017 15:57:40 +0100 Subject: [PATCH 34/51] Updated tinydtls submodule to address some Doxygen issues --- os/net/security/tinydtls | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/os/net/security/tinydtls b/os/net/security/tinydtls index 55fbfa86a..3852a923f 160000 --- a/os/net/security/tinydtls +++ b/os/net/security/tinydtls @@ -1 +1 @@ -Subproject commit 55fbfa86a2c6586501e36631c6d7f1cd7a83f0bc +Subproject commit 3852a923f396365fe69d69a540ba9085bb2d070d From 5dfaa5267b481e344765186c39db16247d146fe4 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Fri, 8 Dec 2017 17:44:18 +0100 Subject: [PATCH 35/51] Moved the LWM2M standalone example to external repository --- examples/lwm2m/standalone/.gitignore | 3 - examples/lwm2m/standalone/Hex2DTLS.java | 141 ---- examples/lwm2m/standalone/Hex2UDP.java | 139 ---- examples/lwm2m/standalone/Makefile | 61 -- examples/lwm2m/standalone/Makefile.contiki | 57 -- examples/lwm2m/standalone/README.md | 77 --- examples/lwm2m/standalone/coap-hex/coap-hex.c | 446 ------------ examples/lwm2m/standalone/coap-hex/coap-hex.h | 49 -- .../lwm2m/standalone/coap-ipv4/coap-ipv4.c | 648 ------------------ .../lwm2m/standalone/coap-ipv4/coap-ipv4.h | 51 -- examples/lwm2m/standalone/coap-log-conf.h | 115 ---- examples/lwm2m/standalone/contiki.h | 67 -- .../lwm2m/standalone/generic-object-test.c | 188 ----- examples/lwm2m/standalone/ipso-control-test.c | 86 --- examples/lwm2m/standalone/ipso-sensor-temp.c | 105 --- examples/lwm2m/standalone/lwm2m-example.c | 201 ------ examples/lwm2m/standalone/posix-coap-timer.c | 103 --- examples/lwm2m/standalone/posix-main.c | 213 ------ examples/lwm2m/standalone/posix-main.h | 55 -- .../tinydtls-support/dtls-support-conf.h | 57 -- .../tinydtls-support/dtls-support.c | 303 -------- 21 files changed, 3165 deletions(-) delete mode 100644 examples/lwm2m/standalone/.gitignore delete mode 100644 examples/lwm2m/standalone/Hex2DTLS.java delete mode 100644 examples/lwm2m/standalone/Hex2UDP.java delete mode 100644 examples/lwm2m/standalone/Makefile delete mode 100644 examples/lwm2m/standalone/Makefile.contiki delete mode 100644 examples/lwm2m/standalone/README.md delete mode 100644 examples/lwm2m/standalone/coap-hex/coap-hex.c delete mode 100644 examples/lwm2m/standalone/coap-hex/coap-hex.h delete mode 100644 examples/lwm2m/standalone/coap-ipv4/coap-ipv4.c delete mode 100644 examples/lwm2m/standalone/coap-ipv4/coap-ipv4.h delete mode 100644 examples/lwm2m/standalone/coap-log-conf.h delete mode 100644 examples/lwm2m/standalone/contiki.h delete mode 100644 examples/lwm2m/standalone/generic-object-test.c delete mode 100644 examples/lwm2m/standalone/ipso-control-test.c delete mode 100644 examples/lwm2m/standalone/ipso-sensor-temp.c delete mode 100644 examples/lwm2m/standalone/lwm2m-example.c delete mode 100644 examples/lwm2m/standalone/posix-coap-timer.c delete mode 100644 examples/lwm2m/standalone/posix-main.c delete mode 100644 examples/lwm2m/standalone/posix-main.h delete mode 100644 examples/lwm2m/standalone/tinydtls-support/dtls-support-conf.h delete mode 100644 examples/lwm2m/standalone/tinydtls-support/dtls-support.c diff --git a/examples/lwm2m/standalone/.gitignore b/examples/lwm2m/standalone/.gitignore deleted file mode 100644 index 131f2183a..000000000 --- a/examples/lwm2m/standalone/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -*.o -/lwm2m-src -/lwm2m-example diff --git a/examples/lwm2m/standalone/Hex2DTLS.java b/examples/lwm2m/standalone/Hex2DTLS.java deleted file mode 100644 index 8bb381100..000000000 --- a/examples/lwm2m/standalone/Hex2DTLS.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (c) 2016, SICS, Swedish ICT AB. - * 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. - */ - -/** - * \file - * A Java IPv4 transport for CoAP + LWM2M - * Converts hex input to DTLS/UDP packets and incoming packets to - * hex out. - * - * Note: This needs the eclipse scandium DTLS implementation to work. - * The example use PSK and the keys according to the code. This needs - * to be configured in Leshan for it to accept the device. - * \author - * Joakim Eriksson - * Niclas Finne - */ -import javax.xml.bind.DatatypeConverter; -import java.net.DatagramSocket; -import java.net.DatagramPacket; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.io.IOException; -import java.util.Arrays; -import java.io.BufferedReader; -import java.io.InputStreamReader; -import java.io.InputStream; -import java.io.PrintStream; - -import org.eclipse.californium.scandium.dtls.pskstore.StaticPskStore; -import org.eclipse.californium.scandium.config.DtlsConnectorConfig; -import org.eclipse.californium.scandium.DTLSConnector; -import org.eclipse.californium.elements.RawData; -import org.eclipse.californium.elements.RawDataChannel; - - -public class Hex2DTLS { - - DTLSConnector dtlsConnector; - InetAddress address; - int port; - - Hex2DTLS(String host, int port) { - try { - DtlsConnectorConfig.Builder builder = new DtlsConnectorConfig.Builder(new InetSocketAddress(0)); - builder.setPskStore(new StaticPskStore("Client_Identity", "secretPSK".getBytes())); - builder.setClientOnly(); - dtlsConnector = new DTLSConnector(builder.build(), null); - dtlsConnector.setRawDataReceiver(new RawDataChannel() { - public void receiveData(final RawData raw) { - receive(raw.getBytes()); - } - }); - dtlsConnector.start(); - - this.address = InetAddress.getByName(host); - this.port = port; - } catch(Exception e) { - e.printStackTrace(); - } - } - - public void send(byte[] data) throws IOException { - RawData rawData = new RawData(data, address, port); - dtlsConnector.send(rawData); - } - - /* Override this to make something more sensible with the data */ - public void receive(byte[] data) { - String s = DatatypeConverter.printHexBinary(data); - System.out.println("COAPHEX:" + s); - } - - /* Loop on std in to get lines of hex to send */ - public static void main(String[] args) throws IOException { - InputStream in = System.in; - final PrintStream out; - System.err.println("Connecting to " + args[0]); - if(args.length > 1) { - Runtime rt = Runtime.getRuntime(); - Process pr = rt.exec(args[1]); - System.err.println("Started " + args[1]); - in = pr.getInputStream(); - out = new PrintStream(pr.getOutputStream()); - } else { - out = System.out; - } - - /* Create a Hex2DTLS that print on this out stream . CoAPs Port*/ - Hex2DTLS udpc = new Hex2DTLS(args[0], 5684) { - public void receive(byte[] data) { - String s = DatatypeConverter.printHexBinary(data); - out.println("COAPHEX:" + s); - out.flush(); - System.err.println("IN: " + s); - } - }; - - BufferedReader buffer = - new BufferedReader(new InputStreamReader(in)); - - /* The read loop */ - while(true) { - String line = buffer.readLine(); - if(line == null) { - /* Connection closed */ - System.err.println("*** stdin closed"); - System.exit(0); - } else if (line.startsWith("COAPHEX:")) { - byte[] data = DatatypeConverter.parseHexBinary(line.substring(8)); - udpc.send(data); - } - System.err.println("OUT:" + line); - } - } -} diff --git a/examples/lwm2m/standalone/Hex2UDP.java b/examples/lwm2m/standalone/Hex2UDP.java deleted file mode 100644 index d084d7d24..000000000 --- a/examples/lwm2m/standalone/Hex2UDP.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (c) 2016, SICS, Swedish ICT AB. - * 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. - */ - -/** - * \file - * A Java IPv4 transport for CoAP + LWM2M - * Converts hex input to UDP packets and incoming packets to hex out. - * \author - * Joakim Eriksson - * Niclas Finne - */ -import javax.xml.bind.DatatypeConverter; -import java.net.DatagramSocket; -import java.net.DatagramPacket; -import java.net.InetAddress; -import java.io.IOException; -import java.util.Arrays; -import java.io.BufferedReader; -import java.io.InputStreamReader; -import java.io.InputStream; -import java.io.PrintStream; - -public class Hex2UDP implements Runnable { - - DatagramSocket serverSocket; - InetAddress address; - int port; - - Hex2UDP(String host, int port) { - try { - serverSocket = new DatagramSocket(); - this.address = InetAddress.getByName(host); - this.port = port; - new Thread(this).start(); - } catch(Exception e) { - /* Do good stuff here... */ - e.printStackTrace(); - } - } - - public void run() { - byte[] receiveData = new byte[1024]; - /* The receive loop */ - while(true) { - DatagramPacket receivePacket = - new DatagramPacket(receiveData, receiveData.length); - try { - /* Receive a packet */ - serverSocket.receive(receivePacket); - } catch (IOException e) { - e.printStackTrace(); - } - byte[] data2 = Arrays.copyOf(receivePacket.getData(), - receivePacket.getLength()); - receive(data2); - } - } - - public void send(byte[] data) throws IOException { - DatagramPacket sendPacket = - new DatagramPacket(data, data.length, address, port); - serverSocket.send(sendPacket); - } - - /* Override this to make something more sensible with the data */ - public void receive(byte[] data) { - String s = DatatypeConverter.printHexBinary(data); - System.out.println("COAPHEX:" + s); - } - - /* Loop on std in to get lines of hex to send */ - public static void main(String[] args) throws IOException { - InputStream in = System.in; - final PrintStream out; - System.err.println("Connecting to " + args[0]); - if(args.length > 2) { - Runtime rt = Runtime.getRuntime(); - Process pr = rt.exec(args[2]); - System.err.println("Started " + args[2]); - in = pr.getInputStream(); - out = new PrintStream(pr.getOutputStream()); - } else { - out = System.out; - } - - /* Create a Hex2UDP that print on this out stream */ - Hex2UDP udpc = new Hex2UDP(args[0], Integer.parseInt(args[1])) { - public void receive(byte[] data) { - String s = DatatypeConverter.printHexBinary(data); - out.println("COAPHEX:" + s); - out.flush(); - System.err.println("IN: " + s); - } - }; - - BufferedReader buffer = - new BufferedReader(new InputStreamReader(in)); - - /* The read loop */ - while(true) { - String line = buffer.readLine(); - if(line == null) { - /* Connection closed */ - System.err.println("*** stdin closed"); - System.exit(0); - } else if (line.startsWith("COAPHEX:")) { - byte[] data = DatatypeConverter.parseHexBinary(line.substring(8)); - udpc.send(data); - } - System.err.println("OUT:" + line); - } - } -} diff --git a/examples/lwm2m/standalone/Makefile b/examples/lwm2m/standalone/Makefile deleted file mode 100644 index c25819b38..000000000 --- a/examples/lwm2m/standalone/Makefile +++ /dev/null @@ -1,61 +0,0 @@ -PROJECT = lwm2m-example - -all: $(PROJECT) - -TARGETCDIR = lwm2m-src -COREDIRS = sys lib -SOURCEDIRS = . -SOURCE_FILES = posix-main.c posix-coap-timer.c ipso-sensor-temp.c \ - ipso-control-test.c generic-object-test.c -APPSDIRS = coap lwm2m ipso-objects - -ifneq ($(MAKE_WITH_DTLS),) - CFLAGS += -DWITH_DTLS=1 - TINYDTLS_DIRS = aes ecc sha2 - APPSDIRS += tinydtls ${addprefix tinydtls/,$(TINYDTLS_DIRS)} - SOURCE_FILES += dtls-support.c - SOURCEDIRS += tinydtls-support -endif - -TARGETCDIRS += ${addprefix $(TARGETCDIR)/,$(COREDIRS) $(APPSDIRS)} -SOURCEDIRS += ${addprefix $(TARGETCDIR)/,. $(APPSDIRS)} - -CFLAGS += -Wall -Werror -CFLAGS += ${addprefix -I,$(SOURCEDIRS)} - -TRANSPORT ?= ipv4 -ifeq ($(TRANSPORT),ipv4) - TRANSPORTDIR = coap-ipv4 - CFLAGS += -DWITH_COAP_IPV4=1 -DCOAP_TRANSPORT_CONF_H=\"coap-ipv4.h\" -else ifeq ($(TRANSPORT),hex) - TRANSPORTDIR = coap-hex - CFLAGS += -DWITH_COAP_HEX=1 -DCOAP_TRANSPORT_CONF_H=\"coap-hex.h\" -else - ${error Unknown CoAP transport: $(TRANSPORT)} -endif - -SOURCEDIRS += $(TRANSPORTDIR) -SOURCE_FILES += ${notdir ${wildcard $(TRANSPORTDIR)/*.c}} - -vpath %.c $(SOURCEDIRS) - --include Makefile.contiki - -ifndef OBJECT_FILES - SOURCE_FILES += ${wildcard ${addsuffix /*.c,$(TARGETCDIRS)} } - OBJECT_FILES = $(SOURCE_FILES:.c=.o) -endif - -$(PROJECT): $(PROJECT).c $(OBJECT_FILES) - $(CC) $(CFLAGS) -o $@ $(PROJECT).c $(OBJECT_FILES) - -lib: liblwm2m.a - -clean:: - @-rm -f $(OBJECT_FILES) *.o liblwm2m.a $(PROJECT) - -liblwm2m.a: $(OBJECT_FILES) - $(AR) rvs $@ $(OBJECT_FILES) - -%.o: %.c - $(CC) $(CFLAGS) -c $< -o $@ diff --git a/examples/lwm2m/standalone/Makefile.contiki b/examples/lwm2m/standalone/Makefile.contiki deleted file mode 100644 index 807bb1b82..000000000 --- a/examples/lwm2m/standalone/Makefile.contiki +++ /dev/null @@ -1,57 +0,0 @@ -CONTIKI = ../../.. -CP=cp -MKDIR=mkdir - -DTLS_PATH := $(CONTIKI)/os/net/security -CORE_FILES = sys/cc.h sys/cc-gcc.h lib/list.c lib/memb.c -COAP_FILES = ${addprefix coap/,${filter-out coap-blocking-api.% coap-uip.% coap-timer-default.%,${notdir ${wildcard $(CONTIKI)/os/net/app-layer/coap/coap*}}}} -LWM2M_FILES = ${addprefix lwm2m/,${filter-out ,${notdir ${wildcard $(CONTIKI)/os/services/lwm2m/lwm2m-*}}}} -IPSO_FILES = ${addprefix ipso-objects/,${filter-out ipso-leds-control.c ipso-objects.% ipso-temperature.% ipso-light-control.% ipso-button.c,${notdir ${wildcard $(CONTIKI)/os/services/ipso-objects/ipso-*}}}} -TARGET_FILES += ${addprefix $(TARGETCDIR)/,$(CORE_FILES) $(CORE_FILES:.c=.h) \ - $(COAP_FILES) $(LWM2M_FILES) $(IPSO_FILES)} - -ifeq ($(MAKE_WITH_DTLS),1) - ifeq (${wildcard $(DTLS_PATH)/tinydtls/Makefile},) - ${error Could not find the tinyDTLS submodule. Please run "git submodule update --init" and try again} - endif - - DTLS_FILES = ${subst $(DTLS_PATH)/,,${wildcard ${addprefix $(DTLS_PATH)/tinydtls/,*.[ch] ${addsuffix /*.[ch],$(TINYDTLS_DIRS)}}}} - TARGET_FILES += ${addprefix $(TARGETCDIR)/,$(DTLS_FILES)} -endif - -SOURCE_FILES += ${filter %.c,$(TARGET_FILES)} -OBJECT_FILES = $(SOURCE_FILES:.c=.o) - -$(TARGETCDIR): - @$(MKDIR) $@ - -$(TARGETCDIRS): $(TARGETCDIR) - @$(MKDIR) $@ - -$(TARGETCDIR)/sys/%: $(CONTIKI)/os/sys/% | $(TARGETCDIRS) - @$(CP) -av $^ $@ - -$(TARGETCDIR)/lib/%: $(CONTIKI)/os/lib/% | $(TARGETCDIRS) - @$(CP) -av $^ $@ - -$(TARGETCDIR)/coap/%: $(CONTIKI)/os/net/app-layer/coap/% | $(TARGETCDIRS) - @$(CP) -av $^ $@ - -$(TARGETCDIR)/lwm2m/%: $(CONTIKI)/os/services/lwm2m/% | $(TARGETCDIRS) - @$(CP) -av $^ $@ - -$(TARGETCDIR)/ipso-objects/%: $(CONTIKI)/os/services/ipso-objects/% | $(TARGETCDIRS) - @$(CP) -av $^ $@ - -$(TARGETCDIR)/tinydtls/%.c: $(DTLS_PATH)/tinydtls/%.c | $(TARGETCDIRS) - @$(CP) -av $^ $@ - -$(TARGETCDIR)/tinydtls/%.h: $(DTLS_PATH)/tinydtls/%.h | $(TARGETCDIRS) - @$(CP) -av $^ $@ - -$(OBJECT_FILES): $(TARGET_FILES) - -copy: $(TARGET_FILES) - -clean:: - @-rm -rf $(TARGETCDIR) diff --git a/examples/lwm2m/standalone/README.md b/examples/lwm2m/standalone/README.md deleted file mode 100644 index b762d1595..000000000 --- a/examples/lwm2m/standalone/README.md +++ /dev/null @@ -1,77 +0,0 @@ -LWM2M Standalone Example -==================================== - -This is an example of how to make use of the OMA LWM2M and CoAP -implementation from Contiki-NG in a native application. - -The Makefile will copy necessary files from Contiki-NG to the subfolder -```lwm2m-src``` and then compile the example ```lwm2m-example``` -as a native application. By copying only the needed source files, -the example can be used outside the Contiki-NG source tree. - -### Running the LWM2M example - -```bash -cd contiki/examples/lwm2m/standalone -make -./lwm2m-example -``` - -The example application will start a CoAP server listening on localhost port -5683 with some example LWM2M objects. By default, the example application will -also register itself with the Leshan server at leshan.eclipse.org. To specify -a different LWM2M server: -`./lwm2m-example coap:// `. - -For example to connect to a locally running LWM2M server: - -```bash -./lwm2m-example coap://127.0.0.1/ example-endpoint-name -``` - -### Running the LWM2M example with DTLS - -The example currently only supports PSK and the default credentials can be -changed in the file `lwm2m-example.c`. - -```c -#define PSK_DEFAULT_IDENTITY "Client_identity" -#define PSK_DEFAULT_KEY "secretPSK" -``` - -To compile with DTLS support and connect to a local LWM2M server with matching -credentials configured: - -```bash -cd contiki/examples/lwm2m/standalone -make clean -make MAKE_WITH_DTLS=1 -./lwm2m-example coaps://127.0.0.1 -``` - -### Moving the example outside Contiki-NG - -```bash -cd contiki/examples/lwm2m/standalone -make copy -``` - -Copy the example directory contents to a directory outside Contiki-NG. -Remove the Makefile ```Makefile.contiki``` and the remaining Makefile -will compile the example independent of the Contiki-NG source tree. - - -### Running the LWM2M examle with HEX transport - -The Hex Transport can be tested together with DTLS using: - -```bash -make clean -make TRANSPORT=hex MAKE_WITH_DTLS=1 -javac Hex2UDP.java -java Hex2UDP leshan.eclipse.org 5684 ./lwm2m-example -``` - -Note that you need to configure the Leshan server with the correct key and ID. - -(without DTLS it should be 5683 for CoAP). diff --git a/examples/lwm2m/standalone/coap-hex/coap-hex.c b/examples/lwm2m/standalone/coap-hex/coap-hex.c deleted file mode 100644 index d663d7e24..000000000 --- a/examples/lwm2m/standalone/coap-hex/coap-hex.c +++ /dev/null @@ -1,446 +0,0 @@ -/* - * Copyright (c) 2016, SICS, Swedish ICT AB. - * 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. - */ - -/** - * \file - * A HEX text transport for CoAP - * \author - * Niclas Finne - * Joakim Eriksson - */ - -#include "coap.h" -#include "coap-endpoint.h" -#include "coap-engine.h" -#include -#include -#include - -/* Log configuration */ -#include "coap-log.h" -#define LOG_MODULE "coap-hex" -#define LOG_LEVEL LOG_LEVEL_COAP - -#ifdef WITH_DTLS -#include "tinydtls.h" -#include "dtls.h" -#include "dtls_debug.h" -#endif /* WITH_DTLS */ - -#define BUFSIZE 1280 - -typedef union { - uint32_t u32[(BUFSIZE + 3) / 4]; - uint8_t u8[BUFSIZE]; -} coap_buf_t; - -static coap_endpoint_t last_source; -static coap_buf_t coap_aligned_buf; -static uint16_t coap_buf_len; - -#ifdef WITH_DTLS -#define PSK_DEFAULT_IDENTITY "Client_identity" -#define PSK_DEFAULT_KEY "secretPSK" - -static dtls_handler_t cb; -static dtls_context_t *dtls_context = NULL; - -/* The PSK information for DTLS */ -#define PSK_ID_MAXLEN 256 -#define PSK_MAXLEN 256 -static unsigned char psk_id[PSK_ID_MAXLEN]; -static size_t psk_id_length = 0; -static unsigned char psk_key[PSK_MAXLEN]; -static size_t psk_key_length = 0; -#endif /* WITH_DTLS */ - -/*---------------------------------------------------------------------------*/ -static const coap_endpoint_t * -coap_src_endpoint(void) -{ - return &last_source; -} -/*---------------------------------------------------------------------------*/ -void -coap_endpoint_copy(coap_endpoint_t *destination, const coap_endpoint_t *from) -{ - memcpy(destination, from, sizeof(coap_endpoint_t)); -} -/*---------------------------------------------------------------------------*/ -int -coap_endpoint_cmp(const coap_endpoint_t *e1, const coap_endpoint_t *e2) -{ - return e1->addr == e2->addr; -} -/*---------------------------------------------------------------------------*/ -void -coap_endpoint_log(const coap_endpoint_t *ep) -{ - LOG_OUTPUT("%u", ep->addr); -} -/*---------------------------------------------------------------------------*/ -void -coap_endpoint_print(const coap_endpoint_t *ep) -{ - printf("%u", ep->addr); -} -/*---------------------------------------------------------------------------*/ -int -coap_endpoint_snprint(char *buf, size_t size, const coap_endpoint_t *ep) -{ - int n; - if(size == 0) { - return 0; - } - n = snprintf(buf, size - 1, "%u", ep->addr); - if(n >= size - 1) { - buf[size - 1] = '\0'; - } - return n; -} -/*---------------------------------------------------------------------------*/ -int -coap_endpoint_parse(const char *text, size_t size, coap_endpoint_t *ep) -{ - /* Hex based CoAP has no addresses, just writes data to standard out */ - ep->addr = last_source.addr; -#ifdef WITH_DTLS - ep->secure = 1; -#endif /* WITH_DTLS */ - return 1; -} -/*---------------------------------------------------------------------------*/ -uint8_t * -coap_databuf(void) -{ - return coap_aligned_buf.u8; -} -/*---------------------------------------------------------------------------*/ -uint16_t -coap_datalen() -{ - return coap_buf_len; -} -/*---------------------------------------------------------------------------*/ -static int -hextod(char c) -{ - if(c >= '0' && c <= '9') { - return c - '0'; - } - if(c >= 'a' && c <= 'f') { - return c - 'a' + 10; - } - if(c >= 'A' && c <= 'F') { - return c - 'A' + 10; - } - return -1; -} -/*---------------------------------------------------------------------------*/ -static void -stdin_callback(const char *line) -{ - uint8_t *buf; - int i, len, llen, v1, v2; - - if(strncmp("COAPHEX:", line, 8) != 0) { - /* Not a CoAP message */ - return; - } - - line += 8; - llen = strlen(line); - if((llen & 1) != 0) { - /* Odd number of characters - not hex */ - fprintf(stderr, "ERROR: %s\n", line); - return; - } - - buf = coap_databuf(); - for(i = 0, len = 0; i < llen; i += 2, len++) { - v1 = hextod(line[i]); - v2 = hextod(line[i + 1]); - if(v1 < 0 || v2 < 0) { - /* Not hex */ - fprintf(stderr, "ERROR: %s\n", line); - return; - } - buf[len] = (uint8_t)(((v1 << 4) | v2) & 0xff); - } - - LOG_INFO("RECV from "); - LOG_INFO_COAP_EP(&last_source); - LOG_INFO_(" %u bytes\n", len); - coap_buf_len = len; - - if(LOG_DBG_ENABLED) { - int i; - uint8_t *data; - data = coap_databuf(); - LOG_DBG("Received: "); - for(i = 0; i < len; i++) { - LOG_DBG_("%02x", data[i]); - } - LOG_DBG_("\n"); - } - -#ifdef WITH_DTLS - /* DTLS receive??? */ - last_source.secure = 1; - dtls_handle_message(dtls_context, (coap_endpoint_t *) coap_src_endpoint(), coap_databuf(), coap_datalen()); -#else - coap_receive(coap_src_endpoint(), coap_databuf(), coap_datalen()); -#endif /* WITH_DTLS */ -} -/*---------------------------------------------------------------------------*/ -void -coap_transport_init(void) -{ - select_set_stdin_callback(stdin_callback); - - LOG_INFO("CoAP listening on standard in\n"); - -#ifdef WITH_DTLS - /* create new contet with app-data - no real app-data... */ - dtls_context = dtls_new_context(&last_source); - if(!dtls_context) { - LOG_ERR("DTLS: cannot create context\n"); - exit(-1); - } - -#ifdef DTLS_PSK - psk_id_length = strlen(PSK_DEFAULT_IDENTITY); - psk_key_length = strlen(PSK_DEFAULT_KEY); - memcpy(psk_id, PSK_DEFAULT_IDENTITY, psk_id_length); - memcpy(psk_key, PSK_DEFAULT_KEY, psk_key_length); -#endif /* DTLS_PSK */ - LOG_DBG("Setting DTLS handler\n"); - dtls_set_handler(dtls_context, &cb); -#endif /* WITH_DTLS */ - -} -/*---------------------------------------------------------------------------*/ -int -coap_sendto(const coap_endpoint_t *ep, const uint8_t *data, uint16_t len) -{ - if(!coap_endpoint_is_connected(ep)) { - LOG_WARN("CoAP endpoint not connected\n"); - return -1; - } - -#ifdef WITH_DTLS - if(coap_endpoint_is_secure(ep)) { - return dtls_write(dtls_context, (session_t *)ep, (uint8_t *)data, len); - } -#endif /* WITH_DTLS */ - - int i; - printf("COAPHEX:"); - for(i = 0; i < len; i++) { - printf("%02x", data[i]); - } - printf("\n"); - - return len; -} -/*---------------------------------------------------------------------------*/ -int -coap_endpoint_connect(coap_endpoint_t *ep) -{ - if(ep->secure == 0) { - return 1; - } -#ifdef WITH_DTLS - LOG_DBG("DTLS EP:"); - LOG_DBG_COAP_EP(ep); - LOG_DBG_(" len:%d\n", ep->size); - - /* setup all address info here... should be done to connect */ - - dtls_connect(dtls_context, ep); -#endif /* WITH_DTLS */ - return 1; -} -/*---------------------------------------------------------------------------*/ -void -coap_endpoint_disconnect(coap_endpoint_t *ep) -{ -#ifdef WITH_DTLS - dtls_close(dtls_context, ep); -#endif /* WITH_DTLS */ -} -/*---------------------------------------------------------------------------*/ -int -coap_endpoint_is_secure(const coap_endpoint_t *ep) -{ - return ep->secure; -} -/*---------------------------------------------------------------------------*/ -int -coap_endpoint_is_connected(const coap_endpoint_t *ep) -{ - if(ep->secure) { -#ifdef WITH_DTLS - dtls_peer_t *peer; - peer = dtls_get_peer(dtls_context, ep); - if(peer != NULL) { - /* only if handshake is done! */ - LOG_DBG("peer state for "); - LOG_DBG_COAP_EP(ep); - LOG_DBG_(" is %d %d\n", peer->state, dtls_peer_is_connected(peer)); - return dtls_peer_is_connected(peer); - } else { - LOG_DBG("Did not find peer "); - LOG_DBG_COAP_EP(ep); - LOG_DBG_("\n"); - } -#endif /* WITH_DTLS */ - return 0; - } - /* Assume that the UDP socket is already up... */ - return 1; -} - -/* DTLS */ -#ifdef WITH_DTLS - -/* This is input coming from the DTLS code - e.g. de-crypted input from - the other side - peer */ -static int -input_from_peer(struct dtls_context_t *ctx, - session_t *session, uint8_t *data, size_t len) -{ - size_t i; - dtls_peer_t *peer; - - printf("received data:"); - for(i = 0; i < len; i++) { - printf("%c", data[i]); - } - printf("\nHex:"); - for(i = 0; i < len; i++) { - printf("%02x", data[i]); - } - printf("\n"); - - /* Send this into coap-input */ - memmove(coap_databuf(), data, len); - coap_buf_len = len; - - peer = dtls_get_peer(ctx, session); - /* If we have a peer then ensure that the endpoint is tagged as secure */ - if(peer) { - session->secure = 1; - } - - coap_receive(session, coap_databuf(), coap_datalen()); - - return 0; -} - -/* This is output from the DTLS code to be sent to peer (encrypted) */ -static int -output_to_peer(struct dtls_context_t *ctx, - session_t *session, uint8_t *data, size_t len) -{ - int fd = *(int *)dtls_get_app_data(ctx); - printf("output_to_peer len:%d %d (s-size: %d)\n", (int)len, fd, - session->size); - - - int i; - printf("COAPHEX:"); - for(i = 0; i < len; i++) { - printf("%02x", data[i]); - } - printf("\n"); - - return len; -} - - -/* This function is the "key store" for tinyDTLS. It is called to - * retrieve a key for the given identity within this particular - * session. */ -static int -get_psk_info(struct dtls_context_t *ctx, - const session_t *session, - dtls_credentials_type_t type, - const unsigned char *id, size_t id_len, - unsigned char *result, size_t result_length) -{ - LOG_DBG("---===>>> Getting the Key or ID <<<===---\n"); - switch(type) { - case DTLS_PSK_IDENTITY: - if(id_len) { - dtls_debug("got psk_identity_hint: '%.*s'\n", id_len, id); - } - - if(result_length < psk_id_length) { - dtls_warn("cannot set psk_identity -- buffer too small\n"); - return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); - } - - memcpy(result, psk_id, psk_id_length); - return psk_id_length; - case DTLS_PSK_KEY: - if(id_len != psk_id_length || memcmp(psk_id, id, id_len) != 0) { - dtls_warn("PSK for unknown id requested, exiting\n"); - return dtls_alert_fatal_create(DTLS_ALERT_ILLEGAL_PARAMETER); - } else if(result_length < psk_key_length) { - dtls_warn("cannot set psk -- buffer too small\n"); - return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); - } - - memcpy(result, psk_key, psk_key_length); - return psk_key_length; - default: - dtls_warn("unsupported request type: %d\n", type); - } - - return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); -} - - -static dtls_handler_t cb = { - .write = output_to_peer, - .read = input_from_peer, - .event = NULL, -#ifdef DTLS_PSK - .get_psk_info = get_psk_info, -#endif /* DTLS_PSK */ -#ifdef DTLS_ECC - /* .get_ecdsa_key = get_ecdsa_key, */ - /* .verify_ecdsa_key = verify_ecdsa_key */ -#endif /* DTLS_ECC */ -}; - -#endif /* WITH_DTLS */ - -/*---------------------------------------------------------------------------*/ diff --git a/examples/lwm2m/standalone/coap-hex/coap-hex.h b/examples/lwm2m/standalone/coap-hex/coap-hex.h deleted file mode 100644 index 5da72f5b7..000000000 --- a/examples/lwm2m/standalone/coap-hex/coap-hex.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2016, SICS, Swedish ICT AB. - * 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. - */ - -/** - * \file - * A HEX text transport for CoAP - * \author - * Niclas Finne - * Joakim Eriksson - */ - -#ifndef COAP_HEX_H_ -#define COAP_HEX_H_ - -#define COAP_ENDPOINT_CUSTOM 1 - -typedef struct { - int addr; /* if we want to switch on something... */ - unsigned int size; - int secure; -} coap_endpoint_t; - -#endif /* COAP_HEX_H_ */ diff --git a/examples/lwm2m/standalone/coap-ipv4/coap-ipv4.c b/examples/lwm2m/standalone/coap-ipv4/coap-ipv4.c deleted file mode 100644 index b8b5c464c..000000000 --- a/examples/lwm2m/standalone/coap-ipv4/coap-ipv4.c +++ /dev/null @@ -1,648 +0,0 @@ -/* - * Copyright (c) 2016, SICS, Swedish ICT AB. - * 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. - */ - -/** - * \file - * A native IPv4 transport for CoAP - * \author - * Niclas Finne - * Joakim Eriksson - */ - -#include "coap.h" -#include "coap-endpoint.h" -#include "coap-engine.h" -#include "coap-keystore.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Log configuration */ -#include "coap-log.h" -#define LOG_MODULE "coap-ipv4" -#define LOG_LEVEL LOG_LEVEL_COAP - -#ifdef WITH_DTLS -#include "tinydtls.h" -#include "dtls.h" -#include "dtls_debug.h" -#endif /* WITH_DTLS */ - -#define BUFSIZE 1280 - -typedef union { - uint32_t u32[(BUFSIZE + 3) / 4]; - uint8_t u8[BUFSIZE]; -} coap_buf_t; - -static int coap_ipv4_fd = -1; - -static coap_endpoint_t last_source; -static coap_buf_t coap_aligned_buf; -static uint16_t coap_buf_len; - -#ifdef WITH_DTLS -static int dtls_ipv4_fd = -1; -static dtls_handler_t cb; -static dtls_context_t *dtls_context = NULL; - -static const coap_keystore_t *dtls_keystore = NULL; -#endif /* WITH_DTLS */ - -/*---------------------------------------------------------------------------*/ -static const coap_endpoint_t * -coap_src_endpoint(void) -{ - return &last_source; -} -/*---------------------------------------------------------------------------*/ -int -coap_endpoint_is_secure(const coap_endpoint_t *ep) -{ - return ep->secure; -} -/*---------------------------------------------------------------------------*/ -int -coap_endpoint_is_connected(const coap_endpoint_t *ep) -{ - if(ep->secure) { -#ifdef WITH_DTLS - dtls_peer_t *peer; - peer = dtls_get_peer(dtls_context, ep); - if(peer != NULL) { - /* only if handshake is done! */ - LOG_DBG("DTLS peer state for "); - LOG_DBG_COAP_EP(ep); - LOG_DBG_(" is %d %d\n", peer->state, dtls_peer_is_connected(peer)); - return dtls_peer_is_connected(peer); - } else { - LOG_DBG("DTLS did not find peer "); - LOG_DBG_COAP_EP(ep); - LOG_DBG_("\n"); - } -#endif /* WITH_DTLS */ - return 0; - } - /* Assume that the UDP socket is already up... */ - return 1; -} -/*---------------------------------------------------------------------------*/ -int -coap_endpoint_connect(coap_endpoint_t *ep) -{ - if(ep->secure == 0) { - return 1; - } - -#ifdef WITH_DTLS - LOG_DBG("DTLS connect to "); - LOG_DBG_COAP_EP(ep); - LOG_DBG_(" len:%d\n", ep->size); - - /* setup all address info here... should be done to connect */ - if(dtls_context) { - dtls_connect(dtls_context, ep); - return 1; - } -#endif /* WITH_DTLS */ - - return 0; -} -/*---------------------------------------------------------------------------*/ -void -coap_endpoint_disconnect(coap_endpoint_t *ep) -{ -#ifdef WITH_DTLS - if(ep && ep->secure && dtls_context) { - dtls_close(dtls_context, ep); - } -#endif /* WITH_DTLS */ -} -/*---------------------------------------------------------------------------*/ -void -coap_endpoint_copy(coap_endpoint_t *destination, const coap_endpoint_t *from) -{ - memcpy(destination, from, sizeof(coap_endpoint_t)); -} -/*---------------------------------------------------------------------------*/ -int -coap_endpoint_cmp(const coap_endpoint_t *e1, const coap_endpoint_t *e2) -{ - /* need to compare only relevant parts of sockaddr */ - switch(e1->addr.sin_family) { - case AF_INET: - return e1->addr.sin_port == e2->addr.sin_port && - e1->secure == e2->secure && - memcmp(&e1->addr.sin_addr, &e2->addr.sin_addr, - sizeof(struct in_addr)) == 0; - default: - return 0; - } -} -/*---------------------------------------------------------------------------*/ -void -coap_endpoint_log(const coap_endpoint_t *ep) -{ - const char *address; - address = inet_ntoa(ep->addr.sin_addr); - if(address != NULL) { - LOG_OUTPUT("coap%s://%s:%u", ep->secure ? "s" : "", - address, ntohs(ep->addr.sin_port)); - } else { - LOG_OUTPUT("<#N/A>"); - } -} -/*---------------------------------------------------------------------------*/ -void -coap_endpoint_print(const coap_endpoint_t *ep) -{ - const char *address; - address = inet_ntoa(ep->addr.sin_addr); - if(address != NULL) { - printf("coap%s://%s:%u", ep->secure ? "s" : "", - address, ntohs(ep->addr.sin_port)); - } else { - printf("<#N/A>"); - } -} -/*---------------------------------------------------------------------------*/ -int -coap_endpoint_snprint(char *buf, size_t size, const coap_endpoint_t *ep) -{ - const char *address; - int n; - if(size == 0) { - return 0; - } - address = inet_ntoa(ep->addr.sin_addr); - if(address != NULL) { - n = snprintf(buf, size - 1, - "coap%s://%s:%u", ep->secure ? "s" : "", - address, ntohs(ep->addr.sin_port)); - } else { - n = snprintf(buf, size - 1, "<#N/A>"); - } - if(n >= size - 1) { - buf[size - 1] = '\0'; - } - return n; -} -/*---------------------------------------------------------------------------*/ -int -coap_endpoint_parse(const char *text, size_t size, coap_endpoint_t *ep) -{ - /* text = format coap://host:port/... we assume */ - /* will not work for know - on the TODO */ - /* set server and port */ - char host[32]; - uint16_t port; - int hlen = 0; - int secure; - int offset = 0; - int i; - LOG_DBG("parsing endpoint %.*s => ", (int)size, text); - if(strncmp("coap://", text, 7) == 0) { - secure = 0; - offset = 7; - } else if(strncmp("coaps://", text, 8) == 0) { - secure = 1; - offset = 8; - LOG_DBG_("secure "); - } else { - secure = 0; - } - - for(i = offset; i < size && text[i] != ':' && text[i] != '/' && - hlen < sizeof(host) - 1; i++) { - host[hlen++] = text[i]; - } - host[hlen] = 0; - - port = secure == 0 ? COAP_DEFAULT_PORT : COAP_DEFAULT_SECURE_PORT; - if(text[i] == ':') { - /* Parse IPv4 endpoint port */ - port = atoi(&text[i + 1]); - } - - LOG_DBG_("endpoint at %s:%u\n", host, port); - - ep->addr.sin_family = AF_INET; - ep->addr.sin_port = htons(port); - ep->size = sizeof(ep->addr); - ep->secure = secure; - if(inet_aton(host, &ep->addr.sin_addr) == 0) { - /* Failed to parse the address */ - LOG_WARN("Failed to parse endpoint host '%s'\n", host); - return 0; - } - return 1; -} -/*---------------------------------------------------------------------------*/ -uint8_t * -coap_databuf(void) -{ - return coap_aligned_buf.u8; -} -/*---------------------------------------------------------------------------*/ -uint16_t -coap_datalen() -{ - return coap_buf_len; -} -/*---------------------------------------------------------------------------*/ -static int -read_packet_to_coapbuf(int fd, int is_secure) -{ - int len; - - memset(&last_source, 0, sizeof(last_source)); - last_source.size = sizeof(last_source.addr); - len = recvfrom(fd, coap_databuf(), BUFSIZE, 0, - (struct sockaddr *)&last_source.addr, &last_source.size); - if(len == -1) { - if(errno == EAGAIN) { - return 0; - } - err(1, "CoAP-IPv4: recv"); - return 0; - } - - last_source.secure = is_secure; - - LOG_INFO("RECV from "); - LOG_INFO_COAP_EP(&last_source); - LOG_INFO_(" %u bytes\n", len); - coap_buf_len = len; - -#if 0 - if((rand() & 0xffff) < 0x1000) { - printf("*********---- PACKET LOSS ----********\n"); - return 0; - } -#endif - - return 1; -} -/*---------------------------------------------------------------------------*/ -static int -coap_ipv4_set_fd(fd_set *rset, fd_set *wset) -{ - if(coap_ipv4_fd >= 0) { - FD_SET(coap_ipv4_fd, rset); - return 1; - } - return 0; -} -/*---------------------------------------------------------------------------*/ -static void -coap_ipv4_handle_fd(fd_set *rset, fd_set *wset) -{ - - if(coap_ipv4_fd >= 0 && FD_ISSET(coap_ipv4_fd, rset)) { - if(read_packet_to_coapbuf(coap_ipv4_fd, 0)) { -#if LOG_DBG_ENABLED - int i; - uint8_t *data; - data = coap_databuf(); - LOG_DBG("Received: "); - for(i = 0; i < coap_buf_len; i++) { - LOG_DBG_("%02x", data[i]); - } - LOG_DBG_("\n"); -#endif /* LOG_DBG_ENABLED */ - coap_receive(coap_src_endpoint(), coap_databuf(), coap_datalen()); - } - } -} -/*---------------------------------------------------------------------------*/ -static const struct select_callback udp_callback = { - coap_ipv4_set_fd, coap_ipv4_handle_fd -}; -/*---------------------------------------------------------------------------*/ -#ifdef WITH_DTLS -static int -dtls_ipv4_set_fd(fd_set *rset, fd_set *wset) -{ - if(dtls_ipv4_fd >= 0 && dtls_context) { - FD_SET(dtls_ipv4_fd, rset); - return 1; - } - return 0; -} -#endif /* WITH_DTLS */ -/*---------------------------------------------------------------------------*/ -#ifdef WITH_DTLS -static void -dtls_ipv4_handle_fd(fd_set *rset, fd_set *wset) -{ - if(dtls_ipv4_fd >= 0 && FD_ISSET(dtls_ipv4_fd, rset)) { - if(read_packet_to_coapbuf(dtls_ipv4_fd, 1) && dtls_context) { - /* DTLS receive */ - dtls_handle_message(dtls_context, &last_source, - coap_databuf(), coap_datalen()); - } - } -} -#endif /* WITH_DTLS */ -/*---------------------------------------------------------------------------*/ -#ifdef WITH_DTLS -static const struct select_callback dtls_callback = { - dtls_ipv4_set_fd, dtls_ipv4_handle_fd -}; -#endif /* WITH_DTLS */ -/*---------------------------------------------------------------------------*/ -void -coap_transport_init(void) -{ - static struct sockaddr_in server; - - coap_ipv4_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if(coap_ipv4_fd == -1) { - fprintf(stderr, "Could not create CoAP UDP socket\n"); - exit(1); - return; - } - - memset((void *)&server, 0, sizeof(server)); - - server.sin_family = AF_INET; - server.sin_port = htons(COAP_SERVER_PORT); - server.sin_addr.s_addr = htonl(INADDR_ANY); - - if(bind(coap_ipv4_fd, (struct sockaddr *)&server, sizeof(server)) == -1) { - fprintf(stderr, "Could not bind CoAP UDP port to %u\n", COAP_SERVER_PORT); - exit(1); - } - - LOG_INFO("CoAP server listening on port %u\n", COAP_SERVER_PORT); - select_set_callback(coap_ipv4_fd, &udp_callback); - -#ifdef WITH_DTLS - dtls_init(); - dtls_set_log_level(8); - - dtls_ipv4_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if(dtls_ipv4_fd == -1) { - fprintf(stderr, "Could not create CoAP DTLS UDP socket\n"); - exit(1); - return; - } - - memset((void *)&server, 0, sizeof(server)); - server.sin_family = AF_INET; - server.sin_port = htons(COAP_DEFAULT_SECURE_PORT); - server.sin_addr.s_addr = htonl(INADDR_ANY); - - if(bind(dtls_ipv4_fd, (struct sockaddr *)&server, sizeof(server)) == -1) { - fprintf(stderr, "Could not bind CoAP DTLS UDP port to %u\n", - COAP_DEFAULT_SECURE_PORT); - exit(1); - } - - LOG_INFO("CoAP DTLS server listening on port %u\n", COAP_DEFAULT_SECURE_PORT); - select_set_callback(dtls_ipv4_fd, &dtls_callback); - - /* create new contet with app-data */ - dtls_context = dtls_new_context(&dtls_ipv4_fd); - if(!dtls_context) { - fprintf(stderr, "DTLS: cannot create context\n"); - exit(-1); - } - - dtls_set_handler(dtls_context, &cb); -#endif /* WITH_DTLS */ -} -/*---------------------------------------------------------------------------*/ -int -coap_sendto(const coap_endpoint_t *ep, const uint8_t *data, uint16_t len) -{ - int ret; - - if(!coap_endpoint_is_connected(ep)) { - LOG_WARN("endpoint "); - LOG_WARN_COAP_EP(ep); - LOG_WARN_(" not connected - dropping packet\n"); - return -1; - } - -#ifdef WITH_DTLS - if(coap_endpoint_is_secure(ep)) { - if(dtls_context) { - ret = dtls_write(dtls_context, (session_t *)ep, (uint8_t *)data, len); - LOG_DBG("SENT DTLS to "); - LOG_DBG_COAP_EP(ep); - if(ret < 0) { - LOG_DBG_(" - error %d\n", ret); - } else { - LOG_DBG_(" %d/%u bytes\n", ret, len); - } - return ret; - } - LOG_WARN("no DTLS context\n"); - return -1; - } -#endif /* WITH_DTLS */ - - if(coap_ipv4_fd >= 0) { - ret = sendto(coap_ipv4_fd, data, len, 0, (struct sockaddr *)&ep->addr, - ep->size); - LOG_INFO("SENT to "); - LOG_INFO_COAP_EP(ep); - if(ret < 0) { - LOG_INFO_(" - error %d: %s\n", ret, strerror(errno)); - } else { - LOG_INFO_(" %d/%u bytes\n", ret, len); - - if(LOG_DBG_ENABLED) { - int i; - LOG_DBG("Sent: "); - for(i = 0; i < len; i++) { - LOG_DBG_("%02x", data[i]); - } - LOG_DBG_("\n"); - } - } - return ret; - } - - LOG_DBG("failed to send - no socket\n"); - return -1; -} -/*---------------------------------------------------------------------------*/ -/* DTLS */ -#ifdef WITH_DTLS - -/* This is input coming from the DTLS code - e.g. de-crypted input from - the other side - peer */ -static int -input_from_peer(struct dtls_context_t *ctx, - session_t *session, uint8_t *data, size_t len) -{ -#if LOG_DBG_ENABLED - size_t i; - - LOG_DBG("DTLS received data: "); - for(i = 0; i < len; i++) { - LOG_DBG_("%c", data[i]); - } - LOG_DBG_("\n"); - LOG_DBG("Hex: "); - for(i = 0; i < len; i++) { - LOG_DBG_("%02x", data[i]); - } - LOG_DBG_("\n"); -#endif /* LOG_DBG_ENABLED */ - - /* Send this into coap-input */ - memmove(coap_databuf(), data, len); - coap_buf_len = len; - - /* Ensure that the endpoint is tagged as secure */ - session->secure = 1; - - coap_receive(session, coap_databuf(), coap_datalen()); - - return 0; -} - -/* This is output from the DTLS code to be sent to peer (encrypted) */ -static int -output_to_peer(struct dtls_context_t *ctx, - session_t *session, uint8_t *data, size_t len) -{ - int fd = *(int *)dtls_get_app_data(ctx); - LOG_DBG("DTLS output_to_peer len:%d %d (s-size: %d)\n", (int)len, fd, - session->size); - return sendto(fd, data, len, MSG_DONTWAIT, - (struct sockaddr *)&session->addr, session->size); -} - -/* This defines the key-store set API since we hookup DTLS here */ -void -coap_set_keystore(const coap_keystore_t *keystore) -{ - dtls_keystore = keystore; -} - -/* This function is the "key store" for tinyDTLS. It is called to - * retrieve a key for the given identity within this particular - * session. */ -static int -get_psk_info(struct dtls_context_t *ctx, - const session_t *session, - dtls_credentials_type_t type, - const unsigned char *id, size_t id_len, - unsigned char *result, size_t result_length) -{ - const coap_keystore_t *keystore; - coap_keystore_psk_entry_t ks; - - keystore = dtls_keystore; - if(keystore == NULL) { - LOG_DBG("--- No key store available ---\n"); - return 0; - } - - memset(&ks, 0, sizeof(ks)); - LOG_DBG("---===>>> Getting the Key or ID <<<===---\n"); - switch(type) { - case DTLS_PSK_IDENTITY: - if(id && id_len) { - ks.identity_hint = id; - ks.identity_hint_len = id_len; - dtls_debug("got psk_identity_hint: '%.*s'\n", id_len, id); - } - - if(keystore->coap_get_psk_info) { - /* we know that session is a coap endpoint */ - keystore->coap_get_psk_info((coap_endpoint_t *)session, &ks); - } - if(ks.identity == NULL || ks.identity_len == 0) { - LOG_DBG("no psk_identity found\n"); - return 0; - } - - if(result_length < ks.identity_len) { - LOG_DBG("cannot return psk_identity -- buffer too small\n"); - return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); - } - memcpy(result, ks.identity, ks.identity_len); - LOG_DBG("psk_identity with %u bytes found\n", ks.identity_len); - return ks.identity_len; - - case DTLS_PSK_KEY: - if(keystore->coap_get_psk_info) { - ks.identity = id; - ks.identity_len = id_len; - /* we know that session is a coap endpoint */ - keystore->coap_get_psk_info((coap_endpoint_t *)session, &ks); - } - if(ks.key == NULL || ks.key_len == 0) { - LOG_DBG("PSK for unknown id requested, exiting\n"); - return dtls_alert_fatal_create(DTLS_ALERT_ILLEGAL_PARAMETER); - } - - if(result_length < ks.key_len) { - LOG_DBG("cannot return psk -- buffer too small\n"); - return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); - } - memcpy(result, ks.key, ks.key_len); - LOG_DBG("psk with %u bytes found\n", ks.key_len); - return ks.key_len; - - default: - dtls_warn("unsupported request type: %d\n", type); - } - - return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); -} - -static dtls_handler_t cb = { - .write = output_to_peer, - .read = input_from_peer, - .event = NULL, -#ifdef DTLS_PSK - .get_psk_info = get_psk_info, -#endif /* DTLS_PSK */ -#ifdef DTLS_ECC - /* .get_ecdsa_key = get_ecdsa_key, */ - /* .verify_ecdsa_key = verify_ecdsa_key */ -#endif /* DTLS_ECC */ -}; - -#endif /* WITH_DTLS */ - -/*---------------------------------------------------------------------------*/ diff --git a/examples/lwm2m/standalone/coap-ipv4/coap-ipv4.h b/examples/lwm2m/standalone/coap-ipv4/coap-ipv4.h deleted file mode 100644 index 8af2e5fc6..000000000 --- a/examples/lwm2m/standalone/coap-ipv4/coap-ipv4.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2016, SICS, Swedish ICT AB. - * 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. - */ - -/** - * \file - * A native IPv4 transport for CoAP - * \author - * Niclas Finne - * Joakim Eriksson - */ - -#ifndef COAP_IPV4_H_ -#define COAP_IPV4_H_ - -#include - -#define COAP_ENDPOINT_CUSTOM 1 - -typedef struct { - struct sockaddr_in addr; - unsigned int size; - int secure; -} coap_endpoint_t; - -#endif /* COAP_IPV4_H_ */ diff --git a/examples/lwm2m/standalone/coap-log-conf.h b/examples/lwm2m/standalone/coap-log-conf.h deleted file mode 100644 index aaedb2ebe..000000000 --- a/examples/lwm2m/standalone/coap-log-conf.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (c) 2017, RISE SICS. - * 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 copyright holder 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 COPYRIGHT HOLDER 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 - * COPYRIGHT HOLDER 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. - */ - -/** - * \file - * Standalone CoAP log configuration - * \author - * Niclas Finne - * Joakim Eriksson - */ - -#ifndef COAP_LOG_CONF_H_ -#define COAP_LOG_CONF_H_ - -#include "contiki.h" -#include - -/* The different log levels available */ -#define LOG_LEVEL_NONE 0 /* No log */ -#define LOG_LEVEL_ERR 1 /* Errors */ -#define LOG_LEVEL_WARN 2 /* Warnings */ -#define LOG_LEVEL_INFO 3 /* Basic info */ -#define LOG_LEVEL_DBG 4 /* Detailed debug */ - -#ifndef LOG_LEVEL_COAP -#define LOG_LEVEL_COAP LOG_LEVEL_DBG -#endif /* LOG_LEVEL_COAP */ - -#ifndef LOG_LEVEL_LWM2M -#define LOG_LEVEL_LWM2M LOG_LEVEL_DBG -#endif /* LOG_LEVEL_LWM2M */ - -#ifndef LOG_WITH_LOC -#define LOG_WITH_LOC 0 -#endif /* LOG_WITH_LOC */ - -#ifndef LOG_WITH_MODULE_PREFIX -#define LOG_WITH_MODULE_PREFIX 1 -#endif /* LOG_WITH_MODULE_PREFIX */ - -/* Custom output function -- default is printf */ -#ifdef LOG_CONF_OUTPUT -#define LOG_OUTPUT(...) LOG_CONF_OUTPUT(__VA_ARGS__) -#else /* LOG_CONF_OUTPUT */ -#define LOG_OUTPUT(...) printf(__VA_ARGS__) -#endif /* LOG_CONF_OUTPUT */ - -/* Custom line prefix output function -- default is LOG_OUTPUT */ -#ifdef LOG_CONF_OUTPUT_PREFIX -#define LOG_OUTPUT_PREFIX(level, levelstr, module) LOG_CONF_OUTPUT_PREFIX(level, levelstr, module) -#else /* LOG_CONF_OUTPUT_PREFIX */ -#define LOG_OUTPUT_PREFIX(level, levelstr, module) LOG_OUTPUT("[%-4s: %-10s] ", levelstr, module) -#endif /* LOG_CONF_OUTPUT_PREFIX */ - -/* Main log function */ - -#define LOG(newline, level, levelstr, ...) do { \ - if(level <= (LOG_LEVEL)) { \ - if(newline) { \ - if(LOG_WITH_MODULE_PREFIX) { \ - LOG_OUTPUT_PREFIX(level, levelstr, LOG_MODULE); \ - } \ - if(LOG_WITH_LOC) { \ - LOG_OUTPUT("[%s: %d] ", __FILE__, __LINE__); \ - } \ - } \ - LOG_OUTPUT(__VA_ARGS__); \ - } \ - } while (0) - -/* More compact versions of LOG macros */ -#define LOG_ERR(...) LOG(1, LOG_LEVEL_ERR, "ERR", __VA_ARGS__) -#define LOG_WARN(...) LOG(1, LOG_LEVEL_WARN, "WARN", __VA_ARGS__) -#define LOG_INFO(...) LOG(1, LOG_LEVEL_INFO, "INFO", __VA_ARGS__) -#define LOG_DBG(...) LOG(1, LOG_LEVEL_DBG, "DBG", __VA_ARGS__) - -#define LOG_ERR_(...) LOG(0, LOG_LEVEL_ERR, "ERR", __VA_ARGS__) -#define LOG_WARN_(...) LOG(0, LOG_LEVEL_WARN, "WARN", __VA_ARGS__) -#define LOG_INFO_(...) LOG(0, LOG_LEVEL_INFO, "INFO", __VA_ARGS__) -#define LOG_DBG_(...) LOG(0, LOG_LEVEL_DBG, "DBG", __VA_ARGS__) - -/* For testing log level */ -#define LOG_ERR_ENABLED ((LOG_LEVEL) >= (LOG_LEVEL_ERR)) -#define LOG_WARN_ENABLED ((LOG_LEVEL) >= (LOG_LEVEL_WARN)) -#define LOG_INFO_ENABLED ((LOG_LEVEL) >= (LOG_LEVEL_INFO)) -#define LOG_DBG_ENABLED ((LOG_LEVEL) >= (LOG_LEVEL_DBG)) - -#endif /* COAP_LOG_CONF_H_ */ diff --git a/examples/lwm2m/standalone/contiki.h b/examples/lwm2m/standalone/contiki.h deleted file mode 100644 index e626cc816..000000000 --- a/examples/lwm2m/standalone/contiki.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2016, SICS, Swedish ICT AB. - * 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. - */ - -/** - * \file - * Configuration for Contiki library - * \author - * Niclas Finne - * Joakim Eriksson - */ - -#ifndef CONTIKI_H_ -#define CONTIKI_H_ - -#include - -#include "posix-main.h" - -#define COAP_LOG_CONF_PATH "coap-log-conf.h" - -#define COAP_TIMER_CONF_DRIVER coap_timer_native_driver - -#define LWM2M_ENGINE_CLIENT_ENDPOINT_NAME "lwm2m-ex" -#define LWM2M_DEVICE_MANUFACTURER "RISE SICS" -#define LWM2M_DEVICE_TYPE "lwm2m-example" -#define LWM2M_DEVICE_MODEL_NUMBER "000" -#define LWM2M_DEVICE_SERIAL_NO "1" -#define LWM2M_DEVICE_FIRMWARE_VERSION "0.1" - -/* Use LWM2M as DTLS keystore */ -#define COAP_DTLS_KEYSTORE_CONF_WITH_LWM2M 1 - -#ifdef COAP_TRANSPORT_CONF_H -#include COAP_TRANSPORT_CONF_H -#endif - -#ifndef COAP_MAX_CHUNK_SIZE -#define COAP_MAX_CHUNK_SIZE 256 -#endif /* COAP_MAX_CHUNK_SIZE */ - -#endif /* CONTIKI_H_ */ diff --git a/examples/lwm2m/standalone/generic-object-test.c b/examples/lwm2m/standalone/generic-object-test.c deleted file mode 100644 index 2c394a249..000000000 --- a/examples/lwm2m/standalone/generic-object-test.c +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright (c) 2017, RISE SICS AB - * 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 copyright holder 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 COPYRIGHT HOLDER 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 - * COPYRIGHT HOLDER 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. - */ - -/** - * \addtogroup lwm2m-objects - * @{ - */ - -/** - * \file - * Implementation of OMA LWM2M / Generic Object Example - * \author - * Joakim Eriksson - * Niclas Finne - */ - -#include -#include "lwm2m-object.h" -#include "lwm2m-engine.h" -#include "coap-engine.h" -#include -#include - -/* Log configuration */ -#include "coap-log.h" -#define LOG_MODULE "gen-obj-test" -#define LOG_LEVEL LOG_LEVEL_COAP - -static lwm2m_object_t generic_object; - -#define MAX_SIZE 512 -#define NUMBER_OF_INSTANCES 50 - -static const lwm2m_resource_id_t resources[] = { - RO(10000), - RO(11000), -}; - -/*---------------------------------------------------------------------------*/ -static int read_data(uint8_t *buffer, int instance_id, int start, int len) -{ - int i; - int start_index; - start_index = instance_id; - /* Write len bytes into the buffer from the start-offset */ - for(i = 0; i < len; i++) { - buffer[i] = '0' + ((start_index + i) & 0x3f); - if(i + start >= MAX_SIZE) return i; - } - return i; -} - -static lwm2m_status_t -opaque_callback(lwm2m_object_instance_t *object, - lwm2m_context_t *ctx, int num_to_write) -{ - int len; - LOG_DBG("opaque-stream callback num_to_write: %d off: %d outlen: %d\n", - num_to_write, ctx->offset, ctx->outbuf->len); - - len = read_data(&ctx->outbuf->buffer[ctx->outbuf->len], - ctx->object_instance_id, - ctx->offset, num_to_write); - - ctx->outbuf->len += len; - - /* Do we need to write more */ - if(ctx->offset + len < MAX_SIZE) { - ctx->writer_flags |= WRITER_HAS_MORE; - } - return LWM2M_STATUS_OK; -} - -/*---------------------------------------------------------------------------*/ -static lwm2m_status_t -lwm2m_callback(lwm2m_object_instance_t *object, - lwm2m_context_t *ctx) -{ - - if(ctx->level <= 2) { - return LWM2M_STATUS_ERROR; - } - - /* Only support for read at the moment */ - if(ctx->operation == LWM2M_OP_READ) { - switch(ctx->resource_id) { - case 10000: - { - char str[30]; - snprintf(str, 30, "hello-%d", (int)ctx->object_instance_id); - lwm2m_object_write_string(ctx, str, strlen(str)); - } - break; - case 11000: - LOG_DBG("Preparing object write\n"); - lwm2m_object_write_opaque_stream(ctx, MAX_SIZE, opaque_callback); - break; - default: - return LWM2M_STATUS_NOT_FOUND; - } - } - return LWM2M_STATUS_OK; -} -/*---------------------------------------------------------------------------*/ -static void -setup_instance(lwm2m_object_instance_t *instance, uint16_t instance_id) -{ - instance->object_id = generic_object.impl->object_id; - instance->instance_id = instance_id; - instance->callback = lwm2m_callback; - instance->resource_ids = resources; - instance->resource_count = sizeof(resources) / sizeof(lwm2m_resource_id_t); -} -/*---------------------------------------------------------------------------*/ -static lwm2m_object_instance_t * -get_by_id(uint16_t instance_id, lwm2m_status_t *status) -{ - lwm2m_object_instance_t *instance = NULL; - if(status != NULL) { - *status = LWM2M_STATUS_OK; - } - if(instance_id < NUMBER_OF_INSTANCES) { - instance = lwm2m_engine_get_instance_buffer(); - if(instance == NULL) { - return NULL; - } - - /* We are fine - update instance variable */ - setup_instance(instance, instance_id); - } - return instance; -} -/*---------------------------------------------------------------------------*/ -static lwm2m_object_instance_t * -get_first(lwm2m_status_t *status) -{ - return get_by_id(0, status); -} -/*---------------------------------------------------------------------------*/ -static lwm2m_object_instance_t * -get_next(lwm2m_object_instance_t *instance, lwm2m_status_t *status) -{ - return get_by_id(instance->instance_id + 1, status); -} -/*---------------------------------------------------------------------------*/ -static lwm2m_object_impl_t generic_object_impl = { - .object_id = 4712, - .get_first = get_first, - .get_next = get_next, - .get_by_id = get_by_id -}; - -/*---------------------------------------------------------------------------*/ -void -lwm2m_generic_object_test_init(void) -{ - generic_object.impl = &generic_object_impl; - - lwm2m_engine_add_generic_object(&generic_object); -} -/*---------------------------------------------------------------------------*/ diff --git a/examples/lwm2m/standalone/ipso-control-test.c b/examples/lwm2m/standalone/ipso-control-test.c deleted file mode 100644 index 394659e74..000000000 --- a/examples/lwm2m/standalone/ipso-control-test.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2016, SICS Swedish ICT AB - * 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 copyright holder 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 COPYRIGHT HOLDER 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 - * COPYRIGHT HOLDER 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. - */ - -/** - * \addtogroup ipso-objects - * @{ - */ - -/** - * \file - * Implementation of OMA LWM2M / IPSO Generic Control - * \author - * Joakim Eriksson - * Niclas Finne - */ - -#include "lwm2m-object.h" -#include "lwm2m-engine.h" -#include "coap-engine.h" -#include "ipso-control-template.h" -#include -#include -#include - -static lwm2m_status_t set_value(ipso_control_t *control, uint8_t value); -static lwm2m_status_t set_light_value(ipso_control_t *control, uint8_t value); - -/* Name, Object ID, Instance ID, set_value callback */ -IPSO_CONTROL(test_control, 3306, 0, set_value); - -IPSO_CONTROL(light_control, 3311, 0, set_light_value); - -/*---------------------------------------------------------------------------*/ -static lwm2m_status_t -set_value(ipso_control_t *control, uint8_t value) -{ - /* do something with the value! */ - printf("Value set to: %u before: %u\n", value, - ipso_control_get_value(control)); - return LWM2M_STATUS_OK; -} -/*---------------------------------------------------------------------------*/ -static lwm2m_status_t -set_light_value(ipso_control_t *control, uint8_t value) -{ - /* do something with the value! */ - printf("Light value set to: %u before: %u\n", value, - ipso_control_get_value(control)); - return LWM2M_STATUS_OK; -} -/*---------------------------------------------------------------------------*/ -void -ipso_control_test_init(void) -{ - ipso_control_add(&test_control); - ipso_control_add(&light_control); -} -/*---------------------------------------------------------------------------*/ -/** @} */ diff --git a/examples/lwm2m/standalone/ipso-sensor-temp.c b/examples/lwm2m/standalone/ipso-sensor-temp.c deleted file mode 100644 index 6cbd0784e..000000000 --- a/examples/lwm2m/standalone/ipso-sensor-temp.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2016, SICS Swedish ICT AB - * 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 copyright holder 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 COPYRIGHT HOLDER 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 - * COPYRIGHT HOLDER 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. - */ - -/** - * \addtogroup ipso-objects - * @{ - */ - -/** - * \file - * Implementation of OMA LWM2M / IPSO Generic Sensor - * \author - * Joakim Eriksson - * Niclas Finne - */ - -#include "lwm2m-object.h" -#include "lwm2m-engine.h" -#include "coap-engine.h" -#include "ipso-sensor-template.h" -#include -#include - -static uint32_t temp = 19000; -static uint32_t hum = 30000; - -static lwm2m_status_t get_temp_value(const ipso_sensor_t *sensor, int32_t *value); -static lwm2m_status_t get_hum_value(const ipso_sensor_t *sensor, int32_t *value); - -IPSO_SENSOR(temp_sensor, 3303, get_temp_value, - .max_range = 120000, /* milli celcius */ - .min_range = -30000, /* milli celcius */ - .unit = "Cel", - .update_interval = 10 - ); - -IPSO_SENSOR(temp_sensor2, 3303, get_temp_value, - .max_range = 120000, /* milli celcius */ - .min_range = -30000, /* milli celcius */ - .unit = "Cel", - .update_interval = 10 - ); - -/*---------------------------------------------------------------------------*/ - -IPSO_SENSOR(hum_sensor, 3304, get_hum_value, - .instance_id = 12, - .max_range = 100000, /* milli */ - .min_range = 0, /* milli */ - .unit = "%", - .update_interval = 10 - ); - -/*---------------------------------------------------------------------------*/ - -static lwm2m_status_t -get_temp_value(const ipso_sensor_t *sensor, int32_t *value) -{ - *value = temp++; - return LWM2M_STATUS_OK; -} -/*---------------------------------------------------------------------------*/ -static lwm2m_status_t -get_hum_value(const ipso_sensor_t *sensor, int32_t *value) -{ - *value = hum++; - return LWM2M_STATUS_OK; -} -/*---------------------------------------------------------------------------*/ -void -ipso_sensor_temp_init(void) -{ - ipso_sensor_add(&temp_sensor); - ipso_sensor_add(&temp_sensor2); - ipso_sensor_add(&hum_sensor); -} -/*---------------------------------------------------------------------------*/ -/** @} */ diff --git a/examples/lwm2m/standalone/lwm2m-example.c b/examples/lwm2m/standalone/lwm2m-example.c deleted file mode 100644 index 772a524d1..000000000 --- a/examples/lwm2m/standalone/lwm2m-example.c +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright (c) 2016, SICS, Swedish ICT AB. - * 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. - */ - -/** - * \file - * An OMA LWM2M standalone example to demonstrate how to use - * the Contiki OMA LWM2M library from a native application. - * \author - * Niclas Finne - * Joakim Eriksson - */ - -#include "lwm2m-engine.h" -#include "lwm2m-rd-client.h" -#include "lwm2m-firmware.h" -#include "lwm2m-server.h" -#include "lwm2m-security.h" -#include "lwm2m-device.h" -#include "coap.h" -#include "coap-timer.h" -#include -#include -#include -#include - -#define PSK_DEFAULT_IDENTITY "Client_identity" -#define PSK_DEFAULT_KEY "secretPSK" - -#define WITH_TEST_NOTIFICATION 1 - -void ipso_sensor_temp_init(void); -void ipso_control_test_init(void); -void ipso_blockwise_test_init(void); -void lwm2m_generic_object_test_init(void); - -/* set this above zero to get auto deregister */ -static int deregister = -1; - -/*---------------------------------------------------------------------------*/ -#if WITH_TEST_NOTIFICATION -static void -callback(coap_timer_t *timer) -{ - /* Automatic notification on device timer for test!*/ - lwm2m_notify_observers("3/0/13"); - coap_timer_reset(timer, 10000); - if(deregister > 0) { - deregister--; - if(deregister == 0) { - printf("Deregistering.\n"); - lwm2m_rd_client_deregister(); - } - } -} -#endif /* WITH_TEST_NOTIFICATION */ -/*---------------------------------------------------------------------------*/ -static void -session_callback(struct lwm2m_session_info *si, int state) -{ - printf("Got Session Callback!!! %d\n", state); -} -/*---------------------------------------------------------------------------*/ -#ifndef LWM2M_DEFAULT_RD_SERVER -/* Default to leshan.eclipse.org */ -#ifdef WITH_DTLS -#define LWM2M_DEFAULT_RD_SERVER "coaps://5.39.83.206" -#else -#define LWM2M_DEFAULT_RD_SERVER "coap://5.39.83.206" -#endif -#endif /* LWM2M_DEFAULT_RD_SERVER */ -/*---------------------------------------------------------------------------*/ -void -start_application(int argc, char *argv[]) -{ - const char *default_server = LWM2M_DEFAULT_RD_SERVER; - coap_endpoint_t server_ep; - int has_server_ep = 0; - char *name = "abcde"; - - if(argc > 1) { - default_server = argv[1]; - } - if(argc > 2) { - name = argv[2]; - } - - if(default_server != NULL && *default_server != '\0') { - if(coap_endpoint_parse(default_server, strlen(default_server), &server_ep) == 0) { - fprintf(stderr, "failed to parse the server address '%s'\n", default_server); - exit(1); - } - has_server_ep = 1; - } - - /* Example using network timer */ -#if WITH_TEST_NOTIFICATION - { - static coap_timer_t nt; - coap_timer_set_callback(&nt, callback); - coap_timer_set(&nt, 10000); - } -#endif /* WITH_TEST_NOTIFICATION */ - - /* Initialize the OMA LWM2M engine */ - lwm2m_engine_init(); - - ipso_sensor_temp_init(); - ipso_control_test_init(); - ipso_blockwise_test_init(); - lwm2m_generic_object_test_init(); - - /* Register default LWM2M objects */ - - lwm2m_device_init(); - lwm2m_firmware_init(); - lwm2m_security_init(); - lwm2m_server_init(); - - if(has_server_ep) { - /* start RD client */ - printf("Starting RD client to register at "); - coap_endpoint_print(&server_ep); - printf("\n"); - -#ifdef WITH_DTLS -#if COAP_DTLS_KEYSTORE_CONF_WITH_LWM2M -#if defined(PSK_DEFAULT_IDENTITY) && defined(PSK_DEFAULT_KEY) - { - lwm2m_security_server_t *server; - /* Register new server with instance id, server id, lifetime in seconds */ - if(!lwm2m_server_add(0, 1, 600)) { - printf("failed to add server object\n"); - } - - server = lwm2m_security_add_server(0, 1, - (uint8_t *)default_server, - strlen(default_server)); - if(server == NULL) { - printf("failed to add security object\n"); - } else { - if(lwm2m_security_set_server_psk(server, - (uint8_t *)PSK_DEFAULT_IDENTITY, - strlen(PSK_DEFAULT_IDENTITY), - (uint8_t *)PSK_DEFAULT_KEY, - strlen(PSK_DEFAULT_KEY))) { - printf("registered security object for endpoint %s\n", - default_server); - } else { - printf("failed to register security object\n"); - } - } - } -#endif /* defined(PSK_DEFAULT_IDENTITY) && defined(PSK_DEFAULT_KEY) */ -#endif /* COAP_DTLS_KEYSTORE_CONF_WITH_LWM2M */ -#endif /* WITH_DTLS */ - -#define BOOTSTRAP 0 -#if BOOTSTRAP - lwm2m_rd_client_register_with_bootstrap_server(&server_ep); - lwm2m_rd_client_use_bootstrap_server(1); -#else /* BOOTSTRAP */ - lwm2m_rd_client_register_with_server(&server_ep); -#endif /* BOOTSTRAP */ - lwm2m_rd_client_use_registration_server(1); - - lwm2m_rd_client_init(name); - - lwm2m_rd_client_set_session_callback(session_callback); - - } else { - fprintf(stderr, "No registration server specified.\n"); - } - printf("COAP MAX PACKET: %d (BLOCK:%d)\n", COAP_MAX_PACKET_SIZE, COAP_MAX_BLOCK_SIZE); -} -/*---------------------------------------------------------------------------*/ diff --git a/examples/lwm2m/standalone/posix-coap-timer.c b/examples/lwm2m/standalone/posix-coap-timer.c deleted file mode 100644 index 3d39eebd5..000000000 --- a/examples/lwm2m/standalone/posix-coap-timer.c +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (c) 2016, SICS, Swedish ICT AB. - * 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. - */ - -/** - * \file - * Example posix implementation of CoAP timer driver. - * \author - * Niclas Finne - * Joakim Eriksson - */ - -#include "coap-timer.h" -#include - -/* Log configuration */ -#include "coap-log.h" -#define LOG_MODULE "posix-timer" -#define LOG_LEVEL LOG_LEVEL_WARN - -/* The maximal time allowed to move forward between updates */ -#define MAX_TIME_CHANGE_MSEC 360000UL - -static uint64_t uptime_msec = 0; -static uint64_t last_msec; -/*---------------------------------------------------------------------------*/ -static uint64_t -uptime(void) -{ - struct timeval tv; - uint64_t t; - - if(gettimeofday(&tv, NULL)) { - LOG_WARN("*** failed to retrieve system time\n"); - return last_msec; - } - - t = tv.tv_sec * (uint64_t)1000; - t += tv.tv_usec / (uint64_t)1000; - - if(last_msec == 0) { - /* No update first time */ - } else if(t < last_msec) { - /* System time has moved backwards */ - LOG_WARN("*** system time has moved backwards %lu msec\n", - (unsigned long)(last_msec - t)); - - } else if(t - last_msec > MAX_TIME_CHANGE_MSEC) { - /* Too large jump forward in system time */ - LOG_WARN("*** system time has moved forward %lu msec\n", - (unsigned long)(t - last_msec)); - uptime_msec += 1000UL; - } else { - uptime_msec += t - last_msec; - } - - last_msec = t; - - return uptime_msec; -} -/*---------------------------------------------------------------------------*/ -static void -init(void) -{ - uptime(); -} -/*---------------------------------------------------------------------------*/ -static void -update(void) -{ -} -/*---------------------------------------------------------------------------*/ -const coap_timer_driver_t coap_timer_native_driver = { - .init = init, - .uptime = uptime, - .update = update, -}; -/*---------------------------------------------------------------------------*/ diff --git a/examples/lwm2m/standalone/posix-main.c b/examples/lwm2m/standalone/posix-main.c deleted file mode 100644 index a077eb101..000000000 --- a/examples/lwm2m/standalone/posix-main.c +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright (c) 2016, SICS, Swedish ICT AB. - * 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. - */ - -/** - * \file - * Simple posix main loop with support functions. - * \author - * Niclas Finne - * Joakim Eriksson - */ - -#include "lwm2m-engine.h" -#include "lwm2m-rd-client.h" -#include "coap-timer.h" -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef SELECT_CONF_MAX -#define SELECT_MAX SELECT_CONF_MAX -#else -#define SELECT_MAX 8 -#endif - -static const struct select_callback *select_callback[SELECT_MAX]; -static int select_max = 0; -static int is_stdin_open = 1; -static void (* stdin_callback)(const char *line); -static char stdin_buffer[2048]; -static uint16_t stdin_count; -/*---------------------------------------------------------------------------*/ -int -select_set_callback(int fd, const struct select_callback *callback) -{ - int i; - if(fd >= 0 && fd < SELECT_MAX) { - /* Check that the callback functions are set */ - if(callback != NULL && - (callback->set_fd == NULL || callback->handle_fd == NULL)) { - callback = NULL; - } - - select_callback[fd] = callback; - - /* Update fd max */ - if(callback != NULL) { - if(fd > select_max) { - select_max = fd; - } - } else { - select_max = 0; - for(i = SELECT_MAX - 1; i > 0; i--) { - if(select_callback[i] != NULL) { - select_max = i; - break; - } - } - } - return 1; - } - fprintf(stderr, "*** failed to set callback for fd %d\n", fd); - return 0; -} -/*---------------------------------------------------------------------------*/ -void -select_set_stdin_callback(void (* line_read)(const char *line)) -{ - stdin_callback = line_read; -} -/*---------------------------------------------------------------------------*/ -static int -stdin_set_fd(fd_set *rset, fd_set *wset) -{ - if(is_stdin_open) { - FD_SET(STDIN_FILENO, rset); - } - return 1; -} -/*---------------------------------------------------------------------------*/ -static void -stdin_handle_fd(fd_set *rset, fd_set *wset) -{ - ssize_t ret; - char c; - if(is_stdin_open && FD_ISSET(STDIN_FILENO, rset)) { - ret = read(STDIN_FILENO, &c, 1); - if(ret > 0) { - if(c == '\r') { - /* Ignore CR */ - } else if(c == '\n' || stdin_count >= sizeof(stdin_buffer) - 1) { - stdin_buffer[stdin_count] = 0; - if(stdin_count > 0 && stdin_callback != NULL) { - stdin_callback(stdin_buffer); - } else { - fprintf(stderr, "STDIN: %s\n", stdin_buffer); - } - stdin_count = 0; - } else { - stdin_buffer[stdin_count++] = (char)c; - } - } else if(ret == 0) { - /* Standard in closed */ - is_stdin_open = 0; - fprintf(stderr, "*** stdin closed\n"); - stdin_count = 0; - if(stdin_callback) { - stdin_buffer[0] = 0; - stdin_callback(stdin_buffer); - } - } else if(errno != EAGAIN) { - err(1, "stdin: read"); - } - } -} -/*---------------------------------------------------------------------------*/ -const static struct select_callback stdin_fd = { - stdin_set_fd, stdin_handle_fd -}; -/*---------------------------------------------------------------------------*/ -int -main(int argc, char *argv[]) -{ - uint64_t next_time; - fd_set fdr, fdw; - int maxfd, retval, i; - struct timeval tv; - - /* Make standard output unbuffered. */ - setvbuf(stdout, (char *)NULL, _IONBF, 0); - - select_set_callback(STDIN_FILENO, &stdin_fd); - - /* Start the application */ - start_application(argc, argv); - - while(1) { - tv.tv_sec = 0; - tv.tv_usec = 250; - - next_time = coap_timer_time_to_next_expiration(); - if(next_time > 0) { - tv.tv_sec = next_time / 1000; - tv.tv_usec = (next_time % 1000) * 1000; - if(tv.tv_usec == 0 && tv.tv_sec == 0) { - /* - * CoAP timer time resolution is milliseconds. Avoid millisecond - * busy loops. - */ - tv.tv_usec = 250; - } - } - - FD_ZERO(&fdr); - FD_ZERO(&fdw); - maxfd = 0; - for(i = 0; i <= select_max; i++) { - if(select_callback[i] != NULL && select_callback[i]->set_fd(&fdr, &fdw)) { - maxfd = i; - } - } - - retval = select(maxfd + 1, &fdr, &fdw, NULL, &tv); - if(retval < 0) { - if(errno != EINTR) { - perror("select"); - } - } else if(retval > 0) { - /* timeout => retval == 0 */ - for(i = 0; i <= maxfd; i++) { - if(select_callback[i] != NULL) { - select_callback[i]->handle_fd(&fdr, &fdw); - } - } - } - - /* Process network timers */ - for(retval = 0; retval < 5 && coap_timer_run(); retval++); - } - - return 0; -} -/*---------------------------------------------------------------------------*/ diff --git a/examples/lwm2m/standalone/posix-main.h b/examples/lwm2m/standalone/posix-main.h deleted file mode 100644 index c220cd9f9..000000000 --- a/examples/lwm2m/standalone/posix-main.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2016, SICS, Swedish ICT AB. - * 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. - */ - -/** - * \file - * Simple posix main loop with support functions. - * \author - * Niclas Finne - * Joakim Eriksson - */ - -#ifndef POSIX_MAIN_H_ -#define POSIX_MAIN_H_ - -#include -#include - -typedef struct select_callback { - int (* set_fd)(fd_set *fdr, fd_set *fdw); - void (* handle_fd)(fd_set *fdr, fd_set *fdw); -} select_callback_t; - -int select_set_callback(int fd, const select_callback_t *callback); - -void select_set_stdin_callback(void (* line_read)(const char *text)); - -void start_application(int argc, char *argv[]); - -#endif /* POSIX_MAIN_H_ */ diff --git a/examples/lwm2m/standalone/tinydtls-support/dtls-support-conf.h b/examples/lwm2m/standalone/tinydtls-support/dtls-support-conf.h deleted file mode 100644 index 25e55b31d..000000000 --- a/examples/lwm2m/standalone/tinydtls-support/dtls-support-conf.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2017, SICS, Swedish ICT AB. - * 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. - */ - -/** - * \file - * tinyDTLS support for LWM2M standalone - * \author - * Niclas Finne - * Joakim Eriksson - */ - -#ifndef DTLS_SUPPORT_CONF_H_ -#define DTLS_SUPPORT_CONF_H_ - -#include "coap-endpoint.h" - -#include "coap-timer.h" - -typedef coap_endpoint_t session_t; - -typedef struct { - coap_timer_t retransmit_timer; -} dtls_support_context_state_t; - -#define DTLS_SUPPORT_CONF_CONTEXT_STATE dtls_support_context_state_t - -#define DTLS_TICKS_PER_SECOND 1000 - -typedef uint64_t dtls_tick_t; - -#endif /* DTLS_SUPPORT_CONF_H_ */ diff --git a/examples/lwm2m/standalone/tinydtls-support/dtls-support.c b/examples/lwm2m/standalone/tinydtls-support/dtls-support.c deleted file mode 100644 index 35d04d2a0..000000000 --- a/examples/lwm2m/standalone/tinydtls-support/dtls-support.c +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Copyright (c) 2017, SICS, Swedish ICT AB. - * 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. - */ - -/** - * \file - * Posix support for TinyDTLS - * \author - * Niclas Finne - * Joakim Eriksson - */ - -#include "tinydtls.h" -#include "coap-timer.h" -#include - -#include -#include -#include -#include -#include -#include - -#define DEBUG DEBUG_NONE -#include "dtls_debug.h" - -#if DEBUG -#define PRINTEP(ep) coap_endpoint_print(ep) -#else /* DEBUG */ -#define PRINTEP(ep) -#endif /* DEBUG */ - -extern char *loglevels[]; -/*---------------------------------------------------------------------------*/ -static inline size_t -print_timestamp(char *s, size_t len) -{ -#ifdef HAVE_TIME_H - time_t t; - struct tm *tmp; - t = time(NULL); - tmp = localtime(&t); - return strftime(s, len, "%b %d %H:%M:%S", tmp); -#else /* alternative implementation: just print the timestamp */ - uint64_t t; - t = coap_timer_uptime(); - return snprintf(s, len, "%u.%03u", - (unsigned int)(t / 1000), - (unsigned int)(t % 1000)); -#endif /* HAVE_TIME_H */ -} -/*---------------------------------------------------------------------------*/ -#include -static pthread_mutex_t cipher_context_mutex = PTHREAD_MUTEX_INITIALIZER; -static dtls_cipher_context_t cipher_context; -#define LOCK(P) pthread_mutex_lock(P) -#define UNLOCK(P) pthread_mutex_unlock(P) -/*---------------------------------------------------------------------------*/ -dtls_cipher_context_t * -dtls_cipher_context_acquire(void) -{ - LOCK(&cipher_context_mutex); - return &cipher_context; -} -/*---------------------------------------------------------------------------*/ -void -dtls_cipher_context_release(dtls_cipher_context_t *c) -{ - /* just one single context for now */ - UNLOCK(&cipher_context_mutex); -} -/*---------------------------------------------------------------------------*/ -dtls_context_t * -dtls_context_acquire(void) -{ - return (dtls_context_t *)malloc(sizeof(dtls_context_t)); -} -/*---------------------------------------------------------------------------*/ -void -dtls_context_release(dtls_context_t *context) -{ - free(context); -} -/*---------------------------------------------------------------------------*/ -#ifndef NDEBUG -size_t -dsrv_print_addr(const session_t *addr, char *buf, size_t len) -{ - return 0; -} -#endif /* NDEBUG */ -/*---------------------------------------------------------------------------*/ -#ifdef HAVE_VPRINTF -void -dsrv_log(log_t level, char *format, ...) -{ - static char timebuf[32]; - va_list ap; - FILE *log_fd; - - if(dtls_get_log_level() < level) { - return; - } - - log_fd = level <= DTLS_LOG_CRIT ? stderr : stdout; - - if(print_timestamp(timebuf, sizeof(timebuf))) { - fprintf(log_fd, "%s ", timebuf); - } - - if(level <= DTLS_LOG_DEBUG) { - fprintf(log_fd, "%s ", loglevels[level]); - } - - va_start(ap, format); - vfprintf(log_fd, format, ap); - va_end(ap); - fflush(log_fd); -} -#endif /* HAVE_VPRINTF */ -/*---------------------------------------------------------------------------*/ -void -dtls_dsrv_hexdump_log(log_t level, const char *name, - const unsigned char *buf, size_t length, int extend) -{ - static char timebuf[32]; - FILE *log_fd; - int n = 0; - - if(dtls_get_log_level() < level) { - return; - } - - log_fd = level <= DTLS_LOG_CRIT ? stderr : stdout; - - if(print_timestamp(timebuf, sizeof(timebuf))) { - fprintf(log_fd, "%s ", timebuf); - } - - if(level <= DTLS_LOG_DEBUG) { - fprintf(log_fd, "%s ", loglevels[level]); - } - - if(extend) { - fprintf(log_fd, "%s: (%zu bytes):\n", name, length); - - while(length--) { - if(n % 16 == 0) { - fprintf(log_fd, "%08X ", n); - } - - fprintf(log_fd, "%02X ", *buf++); - - n++; - if(n % 8 == 0) { - if(n % 16 == 0) { - fprintf(log_fd, "\n"); - } else { - fprintf(log_fd, " "); - } - } - } - } else { - fprintf(log_fd, "%s: (%zu bytes): ", name, length); - while(length--) { - fprintf(log_fd, "%02X", *buf++); - } - } - fprintf(log_fd, "\n"); - - fflush(log_fd); -} -/*---------------------------------------------------------------------------*/ -/* --------- time support ----------- */ -void -dtls_ticks(dtls_tick_t *t) -{ - *t = coap_timer_uptime(); -} -/*---------------------------------------------------------------------------*/ -int -dtls_fill_random(uint8_t *buf, size_t len) -{ - FILE *urandom = fopen("/dev/urandom", "r"); - - if(!urandom) { - dtls_emerg("cannot initialize PRNG\n"); - return 0; - } - - if(fread(buf, 1, len, urandom) != len) { - dtls_emerg("cannot initialize PRNG\n"); - fclose(urandom); - return 0; - } - - fclose(urandom); - - return 1; -} -/*---------------------------------------------------------------------------*/ -/* message retransmission */ -/*---------------------------------------------------------------------------*/ -static void -dtls_retransmit_callback(coap_timer_t *timer) -{ - dtls_context_t *ctx; - uint64_t now; - uint64_t next; - - ctx = coap_timer_get_user_data(timer); - now = coap_timer_uptime(); - /* Just one retransmission per timer scheduling */ - dtls_check_retransmit(ctx, &next, 0); - - /* need to set timer to some value even if no nextpdu is available */ - if(next != 0) { - coap_timer_set(timer, next <= now ? 1 : next - now); - } -} -/*---------------------------------------------------------------------------*/ -void -dtls_set_retransmit_timer(dtls_context_t *ctx, unsigned int timeout) -{ - coap_timer_set_callback(&ctx->support.retransmit_timer, - dtls_retransmit_callback); - coap_timer_set_user_data(&ctx->support.retransmit_timer, ctx); - coap_timer_set(&ctx->support.retransmit_timer, timeout); -} -/*---------------------------------------------------------------------------*/ -/* Implementation of session functions */ -void -dtls_session_init(session_t *session) -{ - memset(session, 0, sizeof(session_t)); -} -/*---------------------------------------------------------------------------*/ -int -dtls_session_equals(const session_t *a, const session_t *b) -{ - coap_endpoint_t *e1 = (coap_endpoint_t *)a; - coap_endpoint_t *e2 = (coap_endpoint_t *)b; - - PRINTF(" **** EP:"); - PRINTEP(e1); - PRINTF(" =?= "); - PRINTEP(e2); - PRINTF(" => %d\n", coap_endpoint_cmp(e1, e2)); - - return coap_endpoint_cmp(e1, e2); -} -/*---------------------------------------------------------------------------*/ -void * -dtls_session_get_address(const session_t *a) -{ - /* improve this to only contain the addressing info */ - return (void *)a; -} -/*---------------------------------------------------------------------------*/ -int -dtls_session_get_address_size(const session_t *a) -{ - /* improve this to only contain the addressing info */ - return sizeof(session_t); -} -/*---------------------------------------------------------------------------*/ -void -dtls_session_print(const session_t *a) -{ - coap_endpoint_print((const coap_endpoint_t *)a); -} -/*---------------------------------------------------------------------------*/ -/* The init */ -void -dtls_support_init(void) -{ -} -/*---------------------------------------------------------------------------*/ From 11da00db3efb3d15b747f39c2d0f66876fe60ec4 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Fri, 8 Dec 2017 17:47:27 +0100 Subject: [PATCH 36/51] Added LWM2M standalone example as submodule for regression tests --- .gitmodules | 3 +++ tests/18-coap-lwm2m/example-lwm2m-standalone | 1 + 2 files changed, 4 insertions(+) create mode 160000 tests/18-coap-lwm2m/example-lwm2m-standalone diff --git a/.gitmodules b/.gitmodules index a20bff843..36eb3cd95 100644 --- a/.gitmodules +++ b/.gitmodules @@ -16,3 +16,6 @@ [submodule "os/net/security/tinydtls"] path = os/net/security/tinydtls url = https://github.com/contiki-ng/tinydtls.git +[submodule "tests/18-coap-lwm2m/example-lwm2m-standalone"] + path = tests/18-coap-lwm2m/example-lwm2m-standalone + url = https://github.com/contiki-ng/example-lwm2m-standalone.git diff --git a/tests/18-coap-lwm2m/example-lwm2m-standalone b/tests/18-coap-lwm2m/example-lwm2m-standalone new file mode 160000 index 000000000..9d3157a47 --- /dev/null +++ b/tests/18-coap-lwm2m/example-lwm2m-standalone @@ -0,0 +1 @@ +Subproject commit 9d3157a47e7741857c3702d3e5d0939c2e2aef92 From e37dd179d1b1978cf96c45c8323c28735f383746 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Tue, 12 Dec 2017 00:39:39 +0100 Subject: [PATCH 37/51] CoAP: added missing UIP_LLH_LEN in buffer size check as described by Laurent Deru in #242. --- os/net/app-layer/coap/coap-uip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/os/net/app-layer/coap/coap-uip.c b/os/net/app-layer/coap/coap-uip.c index f6f80fe46..094cf794d 100644 --- a/os/net/app-layer/coap/coap-uip.c +++ b/os/net/app-layer/coap/coap-uip.c @@ -63,7 +63,7 @@ #endif /* WITH_DTLS */ /* sanity check for configured values */ -#if COAP_MAX_PACKET_SIZE > (UIP_BUFSIZE - UIP_IPH_LEN - UIP_UDPH_LEN) +#if COAP_MAX_PACKET_SIZE > (UIP_BUFSIZE - UIP_LLH_LEN - UIP_IPH_LEN - UIP_UDPH_LEN) #error "UIP_CONF_BUFFER_SIZE too small for COAP_MAX_CHUNK_SIZE" #endif From 7bbbbbab9af2da769483f1d6db4aea974e8dfa15 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Tue, 19 Dec 2017 17:05:36 +0100 Subject: [PATCH 38/51] Excluded the optional tinyDTLS module from Doxygen --- tools/doxygen/Doxyfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/doxygen/Doxyfile b/tools/doxygen/Doxyfile index 8073a8239..2c2bf5e4a 100644 --- a/tools/doxygen/Doxyfile +++ b/tools/doxygen/Doxyfile @@ -809,7 +809,8 @@ EXCLUDE_SYMLINKS = NO EXCLUDE_PATTERNS = */cpu/cc26xx-cc13xx/lib/* \ */cpu/cc26xx-cc13xx/rf-core/api/* \ - */platform/stm32nucleo-spirit1/stm32cube-lib/* + */platform/stm32nucleo-spirit1/stm32cube-lib/* \ + */os/net/security/tinydtls/* # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the From 2d31c06a1ef4f4f1cfc2ead99e569da79f6ba3a9 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Tue, 19 Dec 2017 17:53:53 +0100 Subject: [PATCH 39/51] CoAP: renamed OPTION_MAP_SIZE to COAP_OPTION_MAP_SIZE for consistency --- os/net/app-layer/coap/coap.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/os/net/app-layer/coap/coap.h b/os/net/app-layer/coap/coap.h index 9a93c7525..5aa7631f3 100644 --- a/os/net/app-layer/coap/coap.h +++ b/os/net/app-layer/coap/coap.h @@ -69,7 +69,7 @@ #endif /* COAP_MAX_BLOCK_SIZE */ /* bitmap for set options */ -#define OPTION_MAP_SIZE (sizeof(uint8_t) * 8) +#define COAP_OPTION_MAP_SIZE (sizeof(uint8_t) * 8) /* parsed message struct */ typedef struct { @@ -83,7 +83,7 @@ typedef struct { uint8_t token_len; uint8_t token[COAP_TOKEN_LEN]; - uint8_t options[COAP_OPTION_SIZE1 / OPTION_MAP_SIZE + 1]; /* bitmap to check if option is set */ + uint8_t options[COAP_OPTION_SIZE1 / COAP_OPTION_MAP_SIZE + 1]; /* bitmap to check if option is set */ uint16_t content_format; /* parse options once and store; allows setting options in random order */ uint32_t max_age; @@ -132,7 +132,7 @@ coap_set_option(coap_message_t *message, unsigned int opt) if(opt > COAP_OPTION_SIZE1) { return 0; } - message->options[opt / OPTION_MAP_SIZE] |= 1 << (opt % OPTION_MAP_SIZE); + message->options[opt / COAP_OPTION_MAP_SIZE] |= 1 << (opt % COAP_OPTION_MAP_SIZE); return 1; } @@ -140,7 +140,7 @@ static inline int coap_is_option(const coap_message_t *message, unsigned int opt) { return (opt <= COAP_OPTION_SIZE1) && - (message->options[opt / OPTION_MAP_SIZE] & (1 << (opt % OPTION_MAP_SIZE))) != 0; + (message->options[opt / COAP_OPTION_MAP_SIZE] & (1 << (opt % COAP_OPTION_MAP_SIZE))) != 0; } /* option format serialization */ From 811a62d8db860299eae14354480f048b8889c6c4 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Tue, 19 Dec 2017 18:12:14 +0100 Subject: [PATCH 40/51] lwm2m: made LWM2M security object URI and key size configurable + fixed typo --- os/services/lwm2m/lwm2m-security.c | 12 ++++++------ os/services/lwm2m/lwm2m-security.h | 21 +++++++++++++++------ 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/os/services/lwm2m/lwm2m-security.c b/os/services/lwm2m/lwm2m-security.c index cea41f244..a8b0801dc 100644 --- a/os/services/lwm2m/lwm2m-security.c +++ b/os/services/lwm2m/lwm2m-security.c @@ -178,7 +178,7 @@ lwm2m_callback(lwm2m_object_instance_t *object, switch(ctx->resource_id) { case LWM2M_SECURITY_SERVER_URI_ID: LOG_DBG("Writing security URI value: len: %d\n", (int)ctx->inbuf->size); - value = lwm2m_object_read_string(ctx, ctx->inbuf->buffer, ctx->inbuf->size, security->server_uri, URI_SIZE); + value = lwm2m_object_read_string(ctx, ctx->inbuf->buffer, ctx->inbuf->size, security->server_uri, LWM2M_SECURITY_URI_SIZE); /* This is string... */ security->server_uri_len = ctx->last_value_len; break; @@ -201,7 +201,7 @@ lwm2m_callback(lwm2m_object_instance_t *object, } break; case LWM2M_SECURITY_CLIENT_PKI_ID: - value = lwm2m_object_read_string(ctx, ctx->inbuf->buffer, ctx->inbuf->size, security->public_key, KEY_SIZE); + value = lwm2m_object_read_string(ctx, ctx->inbuf->buffer, ctx->inbuf->size, security->public_key, LWM2M_SECURITY_KEY_SIZE); security->public_key_len = ctx->last_value_len; LOG_DBG("Writing client PKI: len: %d '", (int)ctx->last_value_len); @@ -210,7 +210,7 @@ lwm2m_callback(lwm2m_object_instance_t *object, LOG_DBG_("'\n"); break; case LWM2M_SECURITY_KEY_ID: - value = lwm2m_object_read_string(ctx, ctx->inbuf->buffer, ctx->inbuf->size, security->secret_key, URI_SIZE); + value = lwm2m_object_read_string(ctx, ctx->inbuf->buffer, ctx->inbuf->size, security->secret_key, LWM2M_SECURITY_KEY_SIZE); security->secret_key_len = ctx->last_value_len; LOG_DBG("Writing secret key: len: %d '", (int)ctx->last_value_len); @@ -255,7 +255,7 @@ lwm2m_security_add_server(uint16_t instance_id, lwm2m_security_server_t *server; int i; - if(server_uri_len > URI_SIZE) { + if(server_uri_len > LWM2M_SECURITY_URI_SIZE) { LOG_WARN("too long server URI: %u\n", server_uri_len); return NULL; } @@ -312,11 +312,11 @@ lwm2m_security_set_server_psk(lwm2m_security_server_t *server, if(server == NULL || identity == NULL || key == NULL) { return 0; } - if(identity_len > KEY_SIZE) { + if(identity_len > LWM2M_SECURITY_KEY_SIZE) { LOG_WARN("too large identity: %u\n", identity_len); return 0; } - if(key_len > KEY_SIZE) { + if(key_len > LWM2M_SECURITY_KEY_SIZE) { LOG_WARN("too large identity: %u\n", key_len); return 0; } diff --git a/os/services/lwm2m/lwm2m-security.h b/os/services/lwm2m/lwm2m-security.h index 3120388b7..941fafde3 100644 --- a/os/services/lwm2m/lwm2m-security.h +++ b/os/services/lwm2m/lwm2m-security.h @@ -36,21 +36,30 @@ #ifndef LWM2M_SECURITY_H #define LWM2M_SECURITY_H -#define URI_SIZE 64 -#define KEY_SIZE 32 +#ifdef LWM2M_SECURITY_CONF_URI_SIZE +#define LWM2M_SECURITY_URI_SIZE LWM2M_SECURITY_CONF_URI_SIZE +#else /* LWM2M_SECURITY_CONF_URI_SIZE */ +#define LWM2M_SECURITY_URI_SIZE 64 +#endif /* LWM2M_SECURITY_CONF_URI_SIZE */ + +#ifdef LWM2M_SECURITY_CONF_KEY_SIZE +#define LWM2M_SECURITY_KEY_SIZE LWM2M_SECURITY_CONF_KEY_SIZE +#else /* LWM2M_SECURITY_CONF_KEY_SIZE */ +#define LWM2M_SECURITY_KEY_SIZE 32 +#endif /* LWM2M_SECURITY_CONF_KEY_SIZE */ typedef struct { lwm2m_object_instance_t instance; uint16_t server_id; uint8_t bootstrap; uint8_t security_mode; - uint8_t server_uri[URI_SIZE]; + uint8_t server_uri[LWM2M_SECURITY_URI_SIZE]; uint8_t server_uri_len; - uint8_t public_key[KEY_SIZE]; + uint8_t public_key[LWM2M_SECURITY_KEY_SIZE]; uint8_t public_key_len; - uint8_t secret_key[KEY_SIZE]; + uint8_t secret_key[LWM2M_SECURITY_KEY_SIZE]; uint8_t secret_key_len; - uint8_t server_public_key[KEY_SIZE]; + uint8_t server_public_key[LWM2M_SECURITY_KEY_SIZE]; uint8_t server_public_key_len; } lwm2m_security_server_t; From ee65ba289ec53cbaebd3d819aa064508d3c48347 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Thu, 21 Dec 2017 18:54:28 +0100 Subject: [PATCH 41/51] lwm2m: moved LWM2M object resource IDs to each object header file. Added Doxygen groups in CoAP and LWM2M. --- os/net/app-layer/coap/coap-block1.c | 9 +- os/net/app-layer/coap/coap-block1.h | 6 ++ os/net/app-layer/coap/coap-blocking-api.c | 6 ++ os/net/app-layer/coap/coap-blocking-api.h | 6 ++ os/net/app-layer/coap/coap-callback-api.c | 6 ++ os/net/app-layer/coap/coap-callback-api.h | 6 ++ os/net/app-layer/coap/coap-conf.h | 6 ++ os/net/app-layer/coap/coap-constants.h | 6 ++ os/net/app-layer/coap/coap-endpoint.h | 79 ++++++++++++++- os/net/app-layer/coap/coap-engine.c | 6 ++ os/net/app-layer/coap/coap-engine.h | 6 ++ os/net/app-layer/coap/coap-keystore-simple.c | 6 ++ os/net/app-layer/coap/coap-keystore-simple.h | 16 ++- os/net/app-layer/coap/coap-keystore.h | 39 +++++++- os/net/app-layer/coap/coap-log.c | 6 ++ os/net/app-layer/coap/coap-log.h | 11 +++ os/net/app-layer/coap/coap-observe-client.c | 6 ++ os/net/app-layer/coap/coap-observe-client.h | 6 ++ os/net/app-layer/coap/coap-observe.c | 6 ++ os/net/app-layer/coap/coap-observe.h | 6 ++ .../app-layer/coap/coap-res-well-known-core.c | 6 ++ os/net/app-layer/coap/coap-separate.c | 6 ++ os/net/app-layer/coap/coap-separate.h | 6 ++ os/net/app-layer/coap/coap-timer-default.c | 12 +++ os/net/app-layer/coap/coap-timer.c | 11 ++- os/net/app-layer/coap/coap-timer.h | 97 ++++++++++++++++--- os/net/app-layer/coap/coap-transactions.c | 6 ++ os/net/app-layer/coap/coap-transactions.h | 6 ++ os/net/app-layer/coap/coap-transport.h | 42 +++++++- os/net/app-layer/coap/coap-uip.c | 24 +++-- os/net/app-layer/coap/coap.h | 12 ++- .../coap/tinydtls-support/dtls-support-conf.h | 38 ++++++++ os/services/ipso-objects/ipso-objects.c | 2 +- os/services/ipso-objects/ipso-objects.h | 3 +- os/services/lwm2m/lwm2m-device.c | 2 +- os/services/lwm2m/lwm2m-device.h | 18 +++- os/services/lwm2m/lwm2m-engine.c | 26 ++--- os/services/lwm2m/lwm2m-engine.h | 2 +- os/services/lwm2m/lwm2m-json.c | 2 +- os/services/lwm2m/lwm2m-json.h | 2 +- os/services/lwm2m/lwm2m-object.h | 48 +-------- os/services/lwm2m/lwm2m-plain-text.c | 4 +- os/services/lwm2m/lwm2m-plain-text.h | 2 +- os/services/lwm2m/lwm2m-rd-client.c | 4 +- os/services/lwm2m/lwm2m-rd-client.h | 19 +++- os/services/lwm2m/lwm2m-security.c | 4 +- os/services/lwm2m/lwm2m-security.h | 17 ++++ os/services/lwm2m/lwm2m-server.c | 4 +- os/services/lwm2m/lwm2m-server.h | 5 + os/services/lwm2m/lwm2m-tlv-reader.c | 4 +- os/services/lwm2m/lwm2m-tlv-reader.h | 4 +- os/services/lwm2m/lwm2m-tlv-writer.c | 4 +- os/services/lwm2m/lwm2m-tlv-writer.h | 4 +- os/services/lwm2m/lwm2m-tlv.c | 4 +- os/services/lwm2m/lwm2m-tlv.h | 4 +- 55 files changed, 567 insertions(+), 131 deletions(-) diff --git a/os/net/app-layer/coap/coap-block1.c b/os/net/app-layer/coap/coap-block1.c index d39e3d730..e08a321d1 100644 --- a/os/net/app-layer/coap/coap-block1.c +++ b/os/net/app-layer/coap/coap-block1.c @@ -36,6 +36,11 @@ * Lars Schmertmann */ +/** + * \addtogroup coap + * @{ + */ + #include #include @@ -47,7 +52,7 @@ #define LOG_MODULE "coap-block1" #define LOG_LEVEL LOG_LEVEL_COAP -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /** * \brief Block 1 support within a coap-ressource @@ -111,3 +116,5 @@ coap_block1_handler(coap_message_t *request, coap_message_t *response, return 0; } +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/net/app-layer/coap/coap-block1.h b/os/net/app-layer/coap/coap-block1.h index 2d61eaf36..50638ef66 100644 --- a/os/net/app-layer/coap/coap-block1.h +++ b/os/net/app-layer/coap/coap-block1.h @@ -36,6 +36,11 @@ * Lars Schmertmann */ +/** + * \addtogroup coap + * @{ + */ + #ifndef COAP_BLOCK1_H_ #define COAP_BLOCK1_H_ @@ -47,3 +52,4 @@ int coap_block1_handler(coap_message_t *request, coap_message_t *response, uint8_t *target, size_t *len, size_t max_len); #endif /* COAP_BLOCK1_H_ */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-blocking-api.c b/os/net/app-layer/coap/coap-blocking-api.c index c8e8a1c6c..0d2c5dc58 100644 --- a/os/net/app-layer/coap/coap-blocking-api.c +++ b/os/net/app-layer/coap/coap-blocking-api.c @@ -36,6 +36,11 @@ * Matthias Kovatsch */ +/** + * \addtogroup coap + * @{ + */ + #include "coap-engine.h" #include "coap-blocking-api.h" #include "sys/cc.h" @@ -128,3 +133,4 @@ PT_THREAD(coap_blocking_request PT_END(&state->pt); } /*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/net/app-layer/coap/coap-blocking-api.h b/os/net/app-layer/coap/coap-blocking-api.h index 4a8fba6f0..d9a916c04 100644 --- a/os/net/app-layer/coap/coap-blocking-api.h +++ b/os/net/app-layer/coap/coap-blocking-api.h @@ -29,6 +29,11 @@ * This file is part of the Contiki operating system. */ +/** + * \addtogroup coap + * @{ + */ + #ifndef COAP_BLOCKING_API_H_ #define COAP_BLOCKING_API_H_ @@ -65,3 +70,4 @@ PT_THREAD(coap_blocking_request } #endif /* COAP_BLOCKING_API_H_ */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-callback-api.c b/os/net/app-layer/coap/coap-callback-api.c index a83806727..fe3cac6c0 100644 --- a/os/net/app-layer/coap/coap-callback-api.c +++ b/os/net/app-layer/coap/coap-callback-api.c @@ -37,6 +37,10 @@ * Joakim Eriksson, joakime@sics.se */ +/** + * \addtogroup coap + * @{ + */ #include "coap-engine.h" #include "coap-callback-api.h" @@ -151,3 +155,5 @@ coap_send_request(coap_request_state_t *state, coap_endpoint_t *endpoint, progress_request(state); } +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/net/app-layer/coap/coap-callback-api.h b/os/net/app-layer/coap/coap-callback-api.h index 612157587..6de7ab587 100644 --- a/os/net/app-layer/coap/coap-callback-api.h +++ b/os/net/app-layer/coap/coap-callback-api.h @@ -37,6 +37,11 @@ * Joakim Eriksson, joakime@sics.se */ +/** + * \addtogroup coap + * @{ + */ + #ifndef COAP_CALLBACK_API_H_ #define COAP_CALLBACK_API_H_ @@ -65,3 +70,4 @@ void coap_send_request(coap_request_state_t *state, coap_endpoint_t *endpoint, void (*callback)(coap_request_state_t *state)); #endif /* COAP_CALLBACK_API_H_ */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-conf.h b/os/net/app-layer/coap/coap-conf.h index 17f140243..911017ed8 100644 --- a/os/net/app-layer/coap/coap-conf.h +++ b/os/net/app-layer/coap/coap-conf.h @@ -36,6 +36,11 @@ * Matthias Kovatsch */ +/** + * \addtogroup coap + * @{ + */ + #ifndef COAP_CONF_H_ #define COAP_CONF_H_ @@ -99,3 +104,4 @@ #endif /* COAP_OBSERVE_REFRESH_INTERVAL */ #endif /* COAP_CONF_H_ */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-constants.h b/os/net/app-layer/coap/coap-constants.h index 574da4759..f73a5b950 100644 --- a/os/net/app-layer/coap/coap-constants.h +++ b/os/net/app-layer/coap/coap-constants.h @@ -36,6 +36,11 @@ * Matthias Kovatsch */ +/** + * \addtogroup coap + * @{ + */ + #ifndef COAP_CONSTANTS_H_ #define COAP_CONSTANTS_H_ @@ -184,3 +189,4 @@ typedef enum { } coap_resource_flags_t; #endif /* COAP_CONSTANTS_H_ */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-endpoint.h b/os/net/app-layer/coap/coap-endpoint.h index 705b10fa2..1174a774b 100644 --- a/os/net/app-layer/coap/coap-endpoint.h +++ b/os/net/app-layer/coap/coap-endpoint.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, SICS, Swedish ICT AB. + * Copyright (c) 2016-2018, SICS, Swedish ICT AB. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -35,6 +35,11 @@ * Joakim Eriksson */ +/** + * \addtogroup coap-transport + * @{ + */ + #ifndef COAP_ENDPOINT_H_ #define COAP_ENDPOINT_H_ @@ -51,24 +56,92 @@ typedef struct { } coap_endpoint_t; #endif /* COAP_ENDPOINT_CUSTOM */ -void coap_endpoint_copy(coap_endpoint_t *destination, - const coap_endpoint_t *from); +/** + * \brief Copy a CoAP endpoint from one memory area to another. + * + * \param dest A pointer to a CoAP endpoint to copy to. + * \param src A pointer to a CoAP endpoint to copy from. + */ +void coap_endpoint_copy(coap_endpoint_t *dest, const coap_endpoint_t *src); +/** + * \brief Compare two CoAP endpoints. + * + * \param dest A pointer to the first CoAP endpoint. + * \param src A pointer to the second CoAP endpoint. + * \return Non-zero if the endpoints are identical and zero otherwise. + */ int coap_endpoint_cmp(const coap_endpoint_t *e1, const coap_endpoint_t *e2); +/** + * \brief Print a CoAP endpoint via the logging module. + * + * \param ep A pointer to the CoAP endpoint to log. + */ void coap_endpoint_log(const coap_endpoint_t *ep); + +/** + * \brief Print a CoAP endpoint. + * + * \param ep A pointer to the CoAP endpoint to print. + */ void coap_endpoint_print(const coap_endpoint_t *ep); + +/** + * \brief Print a CoAP endpoint to a string. The output is always + * null-terminated unless size is zero. + * + * \param str The string to write to. + * \param size The max number of characters to write. + * \param ep A pointer to the CoAP endpoint to print. + * \return Returns the number of characters needed for the output + * excluding the ending null-terminator or negative if an + * error occurred. + */ int coap_endpoint_snprint(char *str, size_t size, const coap_endpoint_t *ep); +/** + * \brief Parse a CoAP endpoint. + * + * \param text The string to parse. + * \param size The max number of characters in the string. + * \param ep A pointer to the CoAP endpoint to write to. + * \return Returns non-zero if the endpoint was successfully parsed and + * zero otherwise. + */ int coap_endpoint_parse(const char *text, size_t size, coap_endpoint_t *ep); +/** + * \brief Check if a CoAP endpoint is secure (encrypted). + * + * \param ep A pointer to a CoAP endpoint. + * \return Returns non-zero if the endpoint is secure and zero otherwise. + */ int coap_endpoint_is_secure(const coap_endpoint_t *ep); +/** + * \brief Check if a CoAP endpoint is connected. + * + * \param ep A pointer to a CoAP endpoint. + * \return Returns non-zero if the endpoint is connected and zero otherwise. + */ int coap_endpoint_is_connected(const coap_endpoint_t *ep); +/** + * \brief Request a connection to a CoAP endpoint. + * + * \param ep A pointer to a CoAP endpoint. + * \return Returns zero if an error occured and non-zero otherwise. + */ int coap_endpoint_connect(coap_endpoint_t *ep); +/** + * \brief Request that any connection to a CoAP endpoint is discontinued. + * + * \param ep A pointer to a CoAP endpoint. + */ void coap_endpoint_disconnect(coap_endpoint_t *ep); #endif /* COAP_ENDPOINT_H_ */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-engine.c b/os/net/app-layer/coap/coap-engine.c index 25d48671e..1327cb3e6 100644 --- a/os/net/app-layer/coap/coap-engine.c +++ b/os/net/app-layer/coap/coap-engine.c @@ -36,6 +36,11 @@ * Matthias Kovatsch */ +/** + * \addtogroup coap + * @{ + */ + #include "coap-engine.h" #include "sys/cc.h" #include "lib/list.h" @@ -506,3 +511,4 @@ process_callback(coap_timer_t *t) } } /*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/net/app-layer/coap/coap-engine.h b/os/net/app-layer/coap/coap-engine.h index 48cd4cb63..140ed0211 100644 --- a/os/net/app-layer/coap/coap-engine.h +++ b/os/net/app-layer/coap/coap-engine.h @@ -36,6 +36,11 @@ * Matthias Kovatsch */ +/** + * \addtogroup coap + * @{ + */ + #ifndef COAP_ENGINE_H_ #define COAP_ENGINE_H_ @@ -170,3 +175,4 @@ coap_resource_t *coap_get_next_resource(coap_resource_t *resource); #include "coap-transport.h" #endif /* COAP_ENGINE_H_ */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-keystore-simple.c b/os/net/app-layer/coap/coap-keystore-simple.c index e195f1b33..1eb8737e9 100644 --- a/os/net/app-layer/coap/coap-keystore-simple.c +++ b/os/net/app-layer/coap/coap-keystore-simple.c @@ -36,6 +36,11 @@ * Joakim Eriksson */ +/** + * \addtogroup coap-keystore + * @{ + */ + #include "coap-endpoint.h" #include "coap-keystore.h" #include @@ -89,3 +94,4 @@ coap_keystore_simple_init(void) #endif /* WITH_DTLS */ } /*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/net/app-layer/coap/coap-keystore-simple.h b/os/net/app-layer/coap/coap-keystore-simple.h index 6e76927e5..2252002d4 100644 --- a/os/net/app-layer/coap/coap-keystore-simple.h +++ b/os/net/app-layer/coap/coap-keystore-simple.h @@ -36,17 +36,27 @@ * Joakim Eriksson */ +/** + * \addtogroup coap-keystore + * @{ + */ + #ifndef COAP_KEYSTORE_SIMPLE_H_ #define COAP_KEYSTORE_SIMPLE_H_ -/* - * Registers a simple CoAP DTLS keystore with fixed PSK credentials. +/** + * \brief Registers a simple CoAP DTLS keystore with fixed pre-shared key + * credentials. * - * The credentials can be configured in project-conf.h + * The credentials can be configured in project-conf.h as shown in the + * following example: * + * ~~~~~~~~~~~~~~~{.c} * #define COAP_DTLS_PSK_DEFAULT_IDENTITY "user" * #define COAP_DTLS_PSK_DEFAULT_KEY "password" + * ~~~~~~~~~~~~~~~ */ void coap_keystore_simple_init(void); #endif /* COAP_KEYSTORE_SIMPLE_H_ */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-keystore.h b/os/net/app-layer/coap/coap-keystore.h index ecf45315c..6a3763d5a 100644 --- a/os/net/app-layer/coap/coap-keystore.h +++ b/os/net/app-layer/coap/coap-keystore.h @@ -29,12 +29,33 @@ * */ +/** + * \file + * API for CoAP keystore + * \author + * Niclas Finne + * Joakim Eriksson + */ + +/** + * \addtogroup coap + * @{ + * + * \defgroup coap-keystore CoAP keystore API + * @{ + * + * The CoAP keystore API defines a common interface for retrieving + * authorization information for CoAP/DTLS. + */ + #ifndef COAP_KEYSTORE_H_ #define COAP_KEYSTORE_H_ #include "coap-endpoint.h" -/* Pre-shared key info */ +/** + * The structure of a CoAP pre-shared key info. + */ typedef struct { const uint8_t *identity_hint; uint16_t identity_hint_len; @@ -44,12 +65,24 @@ typedef struct { uint16_t key_len; } coap_keystore_psk_entry_t; -/* the function for getting the data from a keystore */ -typedef struct coap_keystore { +/** + * The structure of a CoAP keystore. + * + * The keystore implementation provides a function callback for each type of + * authorization supported. The API currently only specifies a function + * callback for pre-shared keys. + */ +typedef struct { int (* coap_get_psk_info)(const coap_endpoint_t *address_info, coap_keystore_psk_entry_t *info); } coap_keystore_t; +/** + * \brief Set the CoAP keystore to use by CoAP. + * \param keystore A pointer to a CoAP keystore. + */ void coap_set_keystore(const coap_keystore_t *keystore); #endif /* COAP_KEYSTORE_H_ */ +/** @} */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-log.c b/os/net/app-layer/coap/coap-log.c index 083c9aaf4..36f3bc016 100644 --- a/os/net/app-layer/coap/coap-log.c +++ b/os/net/app-layer/coap/coap-log.c @@ -36,6 +36,11 @@ * Joakim Eriksson */ +/** + * \addtogroup coap + * @{ + */ + #include "coap-log.h" /*---------------------------------------------------------------------------*/ void @@ -52,3 +57,4 @@ coap_log_string(const char *text, size_t len) } } /*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/net/app-layer/coap/coap-log.h b/os/net/app-layer/coap/coap-log.h index 79457bbe4..2e6a0a359 100644 --- a/os/net/app-layer/coap/coap-log.h +++ b/os/net/app-layer/coap/coap-log.h @@ -36,6 +36,11 @@ * Joakim Eriksson */ +/** + * \addtogroup coap + * @{ + */ + #ifndef COAP_LOG_H_ #define COAP_LOG_H_ @@ -73,6 +78,12 @@ #define LOG_INFO_COAP_STRING(text, len) LOG_COAP_STRING(LOG_LEVEL_INFO, text, len) #define LOG_DBG_COAP_STRING(text, len) LOG_COAP_STRING(LOG_LEVEL_DBG, text, len) +/** + * \brief Logs a CoAP string that has a length but might not be 0-terminated. + * \param text The CoAP string + * \param len The number of characters in the CoAP string + */ void coap_log_string(const char *text, size_t len); #endif /* COAP_LOG_H_ */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-observe-client.c b/os/net/app-layer/coap/coap-observe-client.c index f264663eb..af1e89f14 100644 --- a/os/net/app-layer/coap/coap-observe-client.c +++ b/os/net/app-layer/coap/coap-observe-client.c @@ -37,6 +37,11 @@ * Daniele Alessandrelli */ +/** + * \addtogroup coap + * @{ + */ + #include "coap.h" #include "coap-observe-client.h" #include "sys/cc.h" @@ -311,3 +316,4 @@ coap_obs_request_registration(const coap_endpoint_t *endpoint, char *uri, return obs; } #endif /* COAP_OBSERVE_CLIENT */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-observe-client.h b/os/net/app-layer/coap/coap-observe-client.h index 5c1a9a816..79625caff 100644 --- a/os/net/app-layer/coap/coap-observe-client.h +++ b/os/net/app-layer/coap/coap-observe-client.h @@ -37,6 +37,11 @@ * Daniele Alessandrelli */ +/** + * \addtogroup coap + * @{ + */ + #ifndef COAP_OBSERVING_CLIENT_H_ #define COAP_OBSERVING_CLIENT_H_ @@ -118,3 +123,4 @@ coap_observee_t *coap_obs_request_registration(const coap_endpoint_t *endpoint, uint8_t coap_generate_token(uint8_t **token_ptr); #endif /* COAP_OBSERVING_CLIENT_H_ */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-observe.c b/os/net/app-layer/coap/coap-observe.c index ae3fe843f..ac336fbd8 100644 --- a/os/net/app-layer/coap/coap-observe.c +++ b/os/net/app-layer/coap/coap-observe.c @@ -36,6 +36,11 @@ * Matthias Kovatsch */ +/** + * \addtogroup coap + * @{ + */ + #include #include #include "coap-observe.h" @@ -335,3 +340,4 @@ coap_observe_handler(coap_resource_t *resource, coap_message_t *coap_req, } } /*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/net/app-layer/coap/coap-observe.h b/os/net/app-layer/coap/coap-observe.h index 5a78237cb..c276522c5 100644 --- a/os/net/app-layer/coap/coap-observe.h +++ b/os/net/app-layer/coap/coap-observe.h @@ -36,6 +36,11 @@ * Matthias Kovatsch */ +/** + * \addtogroup coap + * @{ + */ + #ifndef COAP_OBSERVE_H_ #define COAP_OBSERVE_H_ @@ -76,3 +81,4 @@ void coap_observe_handler(coap_resource_t *resource, coap_message_t *request, coap_message_t *response); #endif /* COAP_OBSERVE_H_ */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-res-well-known-core.c b/os/net/app-layer/coap/coap-res-well-known-core.c index 752cfa90e..2893925c9 100644 --- a/os/net/app-layer/coap/coap-res-well-known-core.c +++ b/os/net/app-layer/coap/coap-res-well-known-core.c @@ -36,6 +36,11 @@ * Matthias Kovatsch */ +/** + * \addtogroup coap + * @{ + */ + #include "coap-engine.h" #include #include @@ -205,3 +210,4 @@ well_known_core_get_handler(coap_message_t *request, coap_message_t *response, RESOURCE(res_well_known_core, "ct=40", well_known_core_get_handler, NULL, NULL, NULL); /*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/net/app-layer/coap/coap-separate.c b/os/net/app-layer/coap/coap-separate.c index 15f20eefa..318a4e53d 100644 --- a/os/net/app-layer/coap/coap-separate.c +++ b/os/net/app-layer/coap/coap-separate.c @@ -36,6 +36,11 @@ * Matthias Kovatsch */ +/** + * \addtogroup coap + * @{ + */ + #include "coap.h" #include "coap-separate.h" #include "coap-transactions.h" @@ -144,3 +149,4 @@ coap_separate_resume(coap_message_t *response, coap_separate_t *separate_store, } } /*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/net/app-layer/coap/coap-separate.h b/os/net/app-layer/coap/coap-separate.h index 2f815188a..97cbdbf92 100644 --- a/os/net/app-layer/coap/coap-separate.h +++ b/os/net/app-layer/coap/coap-separate.h @@ -36,6 +36,11 @@ * Matthias Kovatsch */ +/** + * \addtogroup coap + * @{ + */ + #ifndef COAP_SEPARATE_H_ #define COAP_SEPARATE_H_ @@ -69,3 +74,4 @@ void coap_separate_resume(coap_message_t *response, uint8_t code); #endif /* COAP_SEPARATE_H_ */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-timer-default.c b/os/net/app-layer/coap/coap-timer-default.c index f0323dfee..ad1b30d28 100644 --- a/os/net/app-layer/coap/coap-timer-default.c +++ b/os/net/app-layer/coap/coap-timer-default.c @@ -35,6 +35,16 @@ * Joakim Eriksson */ +/** + * \addtogroup coap-timer + * @{ + * + * \defgroup coap-timer-default CoAP timer for Contiki-NG + * @{ + * + * This is an implementation of CoAP timer for Contiki-NG. + */ + #include "coap-timer.h" #include "sys/clock.h" #include "sys/etimer.h" @@ -126,3 +136,5 @@ const coap_timer_driver_t coap_timer_default_driver = { .update = update, }; /*---------------------------------------------------------------------------*/ +/** @} */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-timer.c b/os/net/app-layer/coap/coap-timer.c index 30583d33b..06a65c7f6 100644 --- a/os/net/app-layer/coap/coap-timer.c +++ b/os/net/app-layer/coap/coap-timer.c @@ -35,18 +35,20 @@ * Joakim Eriksson */ +/** + * \addtogroup coap-timer + * @{ + */ + #include "coap-timer.h" #include "lib/list.h" +#include "sys/cc.h" /* Log configuration */ #include "coap-log.h" #define LOG_MODULE "coap-timer" #define LOG_LEVEL LOG_LEVEL_NONE -#ifndef NULL -#define NULL 0 -#endif - LIST(timer_list); static uint8_t is_initialized; /*---------------------------------------------------------------------------*/ @@ -183,3 +185,4 @@ coap_timer_init(void) } } /*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/net/app-layer/coap/coap-timer.h b/os/net/app-layer/coap/coap-timer.h index a0aec4b16..0461232ba 100644 --- a/os/net/app-layer/coap/coap-timer.h +++ b/os/net/app-layer/coap/coap-timer.h @@ -35,6 +35,16 @@ * Joakim Eriksson */ +/** + * \addtogroup coap + * @{ + * + * \defgroup coap-timer CoAP timer API + * @{ + * + * The CoAP timer API defines a common interface for CoAP timer and time functionality. + */ + #ifndef COAP_TIMER_H_ #define COAP_TIMER_H_ @@ -65,8 +75,9 @@ typedef struct { extern const coap_timer_driver_t COAP_TIMER_DRIVER; -/* - * milliseconds since boot +/** + * \brief Get the time since boot in milliseconds. + * \return The number of milliseconds since boot. */ static inline uint64_t coap_timer_uptime(void) @@ -74,8 +85,9 @@ coap_timer_uptime(void) return COAP_TIMER_DRIVER.uptime(); } -/* - * seconds since boot +/** + * \brief Get the time since boot in seconds. + * \return The number of seconds since boot. */ static inline uint32_t coap_timer_seconds(void) @@ -83,57 +95,116 @@ coap_timer_seconds(void) return (uint32_t)(COAP_TIMER_DRIVER.uptime() / 1000); } +/** + * \brief Set a callback function to be called when a CoAP timer expires. + * + * \param timer A pointer to a CoAP timer. + * \param callback A callback function. + */ static inline void coap_timer_set_callback(coap_timer_t *timer, void (* callback)(coap_timer_t *)) { timer->callback = callback; } +/** + * \brief Get user data that has been attached to a CoAP timer. + * + * \param timer A pointer to a CoAP timer. + * \return An opaque pointer to user data or NULL if no user data is + * attached to the timer. + */ static inline void * coap_timer_get_user_data(coap_timer_t *timer) { return timer->user_data; } +/** + * \brief Attach user data to a CoAP timer. + * + * \param timer A pointer to a CoAP timer. + * \param data An opaque pointer to user data. + */ static inline void coap_timer_set_user_data(coap_timer_t *timer, void *data) { timer->user_data = data; } +/** + * \brief Check if a CoAP timer has expired. + * + * \param timer A pointer to a CoAP timer. + * \return Non-zero if the timer has expired, zero otherwise. + */ static inline int coap_timer_expired(const coap_timer_t *timer) { return timer->expiration_time <= coap_timer_uptime(); } +/** + * \brief Stop a pending CoAP timer. + * + * After this function has been called, the timer will be expired + * and will not call the callback function. + * + * \param timer A pointer to a CoAP timer. + */ void coap_timer_stop(coap_timer_t *timer); +/** + * \brief Set a CoAP timer to expire after the specified time. + * + * \param timer A pointer to a CoAP timer. + * \param time The time until the timer expires. + */ void coap_timer_set(coap_timer_t *timer, uint64_t time); /** - * Set the CoAP timer to expire the specified time after the previous - * expiration time. If the new expiration time has already passed, the - * timer will expire as soon as possible. + * \brief Reset a CoAP timer to expire a specified time after the + * last expiration time. * - * If the timer has not yet expired when this function is called, the - * time until the timer expires will be extended by the specified time. + * This function sets the CoAP timer to expire the specified time + * after the previous expiration time. If the new expiration time + * has already passed, the timer will expire as soon as possible. + * + * If the timer has not yet expired when this function is called, + * the time until the timer expires will be extended by the + * specified time. + * + * \param timer A pointer to a CoAP timer. + * \param time The time after previous expiration the timer expires. */ void coap_timer_reset(coap_timer_t *timer, uint64_t time); /** - * Returns the time until next timer expires or 0 if there already - * exists expired timers that have not yet been processed. - * Returns a time in the future if there are no timers pending. + * Get the time until next CoAP timer expires or 0 if there already exists + * expired timers that have not yet been processed. This function is normally + * never called by application code. + * + * Returns the time to next CoAP timer expires or 0 if unprocessed expired + * timers exists. Returns a time in the future if there are no timers pending. */ uint64_t coap_timer_time_to_next_expiration(void); /** - * Must be called periodically to process any expired CoAP timers. + * This function must be called periodically by the CoAP timer driver to + * process any expired CoAP timers. This function is normally never called by + * application code. + * * Returns non-zero if it needs to run again to process more timers. */ int coap_timer_run(void); +/** + * This function initializes the CoAP timer library. It is automatically + * called at first use of a CoAP timer. This function is normally never called + * by application code. + */ void coap_timer_init(void); #endif /* COAP_TIMER_H_ */ +/** @} */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-transactions.c b/os/net/app-layer/coap/coap-transactions.c index b10d5a31a..652737b94 100644 --- a/os/net/app-layer/coap/coap-transactions.c +++ b/os/net/app-layer/coap/coap-transactions.c @@ -36,6 +36,11 @@ * Matthias Kovatsch */ +/** + * \addtogroup coap + * @{ + */ + #include "coap-transactions.h" #include "coap-observe.h" #include "coap-timer.h" @@ -163,3 +168,4 @@ coap_get_transaction_by_mid(uint16_t mid) return NULL; } /*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/net/app-layer/coap/coap-transactions.h b/os/net/app-layer/coap/coap-transactions.h index 497c5fc35..65334b4eb 100644 --- a/os/net/app-layer/coap/coap-transactions.h +++ b/os/net/app-layer/coap/coap-transactions.h @@ -36,6 +36,11 @@ * Matthias Kovatsch */ +/** + * \addtogroup coap + * @{ + */ + #ifndef COAP_TRANSACTIONS_H_ #define COAP_TRANSACTIONS_H_ @@ -75,3 +80,4 @@ void coap_clear_transaction(coap_transaction_t *t); coap_transaction_t *coap_get_transaction_by_mid(uint16_t mid); #endif /* COAP_TRANSACTIONS_H_ */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-transport.h b/os/net/app-layer/coap/coap-transport.h index 71d0ffae1..3de6f71dc 100644 --- a/os/net/app-layer/coap/coap-transport.h +++ b/os/net/app-layer/coap/coap-transport.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, SICS, Swedish ICT AB. + * Copyright (c) 2016-2018, SICS, Swedish ICT AB. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -35,16 +35,50 @@ * Joakim Eriksson */ +/** + * \addtogroup coap + * @{ + * + * \defgroup coap-transport CoAP transport API + * @{ + * + * The CoAP transport API defines a common interface for sending/receiving + * CoAP messages. + */ + #ifndef COAP_TRANSPORT_H_ #define COAP_TRANSPORT_H_ #include "coap-endpoint.h" -void coap_transport_init(void); +/** + * \brief Returns a common data buffer that can be used when + * generating CoAP messages for transmission. The buffer + * size is at least COAP_MAX_PACKET_SIZE bytes. + * + * In Contiki-NG, this corresponds to the uIP buffer. + * + * \return A pointer to a data buffer where a CoAP message can be stored. + */ +uint8_t *coap_databuf(void); +/** + * \brief Send a message to the specified CoAP endpoint + * \param ep A pointer to a CoAP endpoint + * \param data A pointer to data to send + * \param len The size of the data to send + * \return The number of bytes sent or negative if an error occurred. + */ int coap_sendto(const coap_endpoint_t *ep, const uint8_t *data, uint16_t len); -uint8_t *coap_databuf(void); -uint16_t coap_datalen(void); +/** + * \brief Initialize the CoAP transport. + * + * This function initializes the CoAP transport implementation and + * should only be called by the CoAP engine. + */ +void coap_transport_init(void); #endif /* COAP_TRANSPORT_H_ */ +/** @} */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-uip.c b/os/net/app-layer/coap/coap-uip.c index 094cf794d..dd78f5d3b 100644 --- a/os/net/app-layer/coap/coap-uip.c +++ b/os/net/app-layer/coap/coap-uip.c @@ -35,6 +35,17 @@ * Joakim Eriksson */ +/** + * \addtogroup coap-transport + * @{ + * + * \defgroup coap-uip CoAP transport implementation for uIP + * @{ + * + * This is an implementation of CoAP transport and CoAP endpoint over uIP + * with DTLS support. + */ + #include "contiki.h" #include "net/ipv6/uip-udp-packet.h" #include "net/ipv6/uiplib.h" @@ -272,7 +283,8 @@ coap_endpoint_is_connected(const coap_endpoint_t *ep) /* only if handshake is done! */ LOG_DBG("DTLS peer state for "); LOG_DBG_COAP_EP(ep); - LOG_DBG_(" is %d %d\n", peer->state, dtls_peer_is_connected(peer)); + LOG_DBG_(" is %d (%sconnected)\n", peer->state, + dtls_peer_is_connected(peer) ? "" : "not "); return dtls_peer_is_connected(peer); } else { LOG_DBG("DTLS did not find peer "); @@ -328,12 +340,6 @@ coap_databuf(void) return uip_appdata; } /*---------------------------------------------------------------------------*/ -uint16_t -coap_datalen() -{ - return uip_datalen(); -} -/*---------------------------------------------------------------------------*/ void coap_transport_init(void) { @@ -503,7 +509,7 @@ output_to_peer(struct dtls_context_t *ctx, struct uip_udp_conn *udp_connection = dtls_get_app_data(ctx); LOG_DBG("output_to DTLS peer ["); LOG_DBG_6ADDR(&session->ipaddr); - LOG_DBG_("]:%u %d bytes\n", session->port, (int)len); + LOG_DBG_("]:%u %d bytes\n", uip_ntohs(session->port), (int)len); uip_udp_packet_sendto(udp_connection, data, len, &session->ipaddr, session->port); return len; @@ -605,3 +611,5 @@ static dtls_handler_t cb = { #endif /* WITH_DTLS */ /*---------------------------------------------------------------------------*/ +/** @} */ +/** @} */ diff --git a/os/net/app-layer/coap/coap.h b/os/net/app-layer/coap/coap.h index 5aa7631f3..8d9aed61c 100644 --- a/os/net/app-layer/coap/coap.h +++ b/os/net/app-layer/coap/coap.h @@ -31,19 +31,21 @@ /** * \file - * An implementation of the Constrained Application Protocol (RFC). + * An implementation of the Constrained Application Protocol (RFC 7252). * \author * Matthias Kovatsch */ /** - * \defgroup coap CoAP + * \addtogroup apps * @{ * - * The Constrained Application Protocol - RFC 7252 + * \defgroup coap An implementation of CoAP + * @{ + * + * This is an implementation of the Constrained Application Protocol */ - #ifndef COAP_H_ #define COAP_H_ @@ -298,5 +300,5 @@ int coap_get_payload(coap_message_t *message, const uint8_t **payload); int coap_set_payload(coap_message_t *message, const void *payload, size_t length); #endif /* COAP_H_ */ - +/** @} */ /** @} */ diff --git a/os/net/app-layer/coap/tinydtls-support/dtls-support-conf.h b/os/net/app-layer/coap/tinydtls-support/dtls-support-conf.h index b1dbacd7d..0e655ec2e 100644 --- a/os/net/app-layer/coap/tinydtls-support/dtls-support-conf.h +++ b/os/net/app-layer/coap/tinydtls-support/dtls-support-conf.h @@ -1,3 +1,41 @@ +/* + * Copyright (c) 2017, RISE SICS AB. + * 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 copyright holder 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 COPYRIGHT HOLDER 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 + * COPYRIGHT HOLDER 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. + */ + +/** + * \file + * DTLS support for CoAP + * \author + * Niclas Finne + * Joakim Eriksson + */ + #ifndef DTLS_SUPPORT_CONF_H_ #define DTLS_SUPPORT_CONF_H_ diff --git a/os/services/ipso-objects/ipso-objects.c b/os/services/ipso-objects/ipso-objects.c index 1e8243f94..b1138ca09 100644 --- a/os/services/ipso-objects/ipso-objects.c +++ b/os/services/ipso-objects/ipso-objects.c @@ -29,7 +29,7 @@ */ /** - * \addtogroup oma-lwm2m + * \addtogroup ipso-objects * @{ */ diff --git a/os/services/ipso-objects/ipso-objects.h b/os/services/ipso-objects/ipso-objects.h index 6b8f5c2a6..92bdfd8de 100644 --- a/os/services/ipso-objects/ipso-objects.h +++ b/os/services/ipso-objects/ipso-objects.h @@ -37,8 +37,7 @@ * \defgroup ipso-objects An implementation of IPSO Objects * @{ * - * This application is an implementation of IPSO Objects for - * OMA Lightweight M2M. + * This is an implementation of IPSO Objects for OMA LWM2M. */ /** diff --git a/os/services/lwm2m/lwm2m-device.c b/os/services/lwm2m/lwm2m-device.c index 460e9426e..9e91b37fd 100644 --- a/os/services/lwm2m/lwm2m-device.c +++ b/os/services/lwm2m/lwm2m-device.c @@ -29,7 +29,7 @@ */ /** - * \addtogroup oma-lwm2m + * \addtogroup lwm2m * @{ */ diff --git a/os/services/lwm2m/lwm2m-device.h b/os/services/lwm2m/lwm2m-device.h index 2800038c8..d7389153c 100644 --- a/os/services/lwm2m/lwm2m-device.h +++ b/os/services/lwm2m/lwm2m-device.h @@ -29,7 +29,7 @@ */ /** - * \addtogroup oma-lwm2m + * \addtogroup lwm2m * @{ */ @@ -46,6 +46,22 @@ #include "contiki.h" +#define LWM2M_DEVICE_MANUFACTURER_ID 0 +#define LWM2M_DEVICE_MODEL_NUMBER_ID 1 +#define LWM2M_DEVICE_SERIAL_NUMBER_ID 2 +#define LWM2M_DEVICE_FIRMWARE_VERSION_ID 3 +#define LWM2M_DEVICE_REBOOT_ID 4 +#define LWM2M_DEVICE_FACTORY_DEFAULT_ID 5 +#define LWM2M_DEVICE_AVAILABLE_POWER_SOURCES 6 +/* These do have multiple instances */ +#define LWM2M_DEVICE_POWER_SOURCE_VOLTAGE 7 +#define LWM2M_DEVICE_POWER_SOURCE_CURRENT 8 +#define LWM2M_DEVICE_BATTERY_LEVEL 9 + +#define LWM2M_DEVICE_ERROR_CODE 11 +#define LWM2M_DEVICE_TIME_ID 13 +#define LWM2M_DEVICE_TYPE_ID 17 + #ifndef LWM2M_DEVICE_MODEL_NUMBER #ifdef BOARD_STRING #define LWM2M_DEVICE_MODEL_NUMBER BOARD_STRING diff --git a/os/services/lwm2m/lwm2m-engine.c b/os/services/lwm2m/lwm2m-engine.c index 1d7b8bff7..a36b4f7b1 100644 --- a/os/services/lwm2m/lwm2m-engine.c +++ b/os/services/lwm2m/lwm2m-engine.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Yanzi Networks AB. + * Copyright (c) 2015-2018, Yanzi Networks AB. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,7 +29,7 @@ */ /** - * \addtogroup oma-lwm2m + * \addtogroup lwm2m * @{ */ @@ -554,13 +554,13 @@ lwm2m_engine_init(void) #endif } /*---------------------------------------------------------------------------*/ -/** - * @brief Set the writer pointer to the proper writer based on the Accept: header +/* + * 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 + * 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 + * 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) @@ -590,11 +590,11 @@ lwm2m_engine_select_writer(lwm2m_context_t *context, unsigned int accept) return accept; } /*---------------------------------------------------------------------------*/ -/** - * @brief Set the reader pointer to the proper reader based on the Content-format: header +/* + * 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 + * 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) @@ -1368,7 +1368,7 @@ lwm2m_handler_callback(coap_message_t *request, coap_message_t *response, if(offset != NULL) { context.offset = *offset; } - context.inbuf->size = coap_get_payload(request, (const uint8_t **) &context.inbuf->buffer); + context.inbuf->size = coap_get_payload(request, (const uint8_t **)&context.inbuf->buffer); context.inbuf->pos = 0; /* Maybe this should be part of CoAP itself - this seems not to be working @@ -1431,7 +1431,7 @@ lwm2m_handler_callback(coap_message_t *request, coap_message_t *response, } } - /** + /* * 1 => Object only * 2 => Object and Instance * 3 => Object and Instance and Resource diff --git a/os/services/lwm2m/lwm2m-engine.h b/os/services/lwm2m/lwm2m-engine.h index a819540ce..62a667e99 100644 --- a/os/services/lwm2m/lwm2m-engine.h +++ b/os/services/lwm2m/lwm2m-engine.h @@ -29,7 +29,7 @@ */ /** - * \addtogroup oma-lwm2m + * \addtogroup lwm2m * @{ */ diff --git a/os/services/lwm2m/lwm2m-json.c b/os/services/lwm2m/lwm2m-json.c index 2d623388c..ac02bab20 100644 --- a/os/services/lwm2m/lwm2m-json.c +++ b/os/services/lwm2m/lwm2m-json.c @@ -29,7 +29,7 @@ */ /** - * \addtogroup oma-lwm2m + * \addtogroup lwm2m * @{ */ diff --git a/os/services/lwm2m/lwm2m-json.h b/os/services/lwm2m/lwm2m-json.h index 0fd9a1a82..8267d0246 100644 --- a/os/services/lwm2m/lwm2m-json.h +++ b/os/services/lwm2m/lwm2m-json.h @@ -29,7 +29,7 @@ */ /** - * \addtogroup oma-lwm2m + * \addtogroup lwm2m * @{ */ diff --git a/os/services/lwm2m/lwm2m-object.h b/os/services/lwm2m/lwm2m-object.h index 858f99c7b..c6c582a35 100644 --- a/os/services/lwm2m/lwm2m-object.h +++ b/os/services/lwm2m/lwm2m-object.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Yanzi Networks AB. + * Copyright (c) 2015-2018, Yanzi Networks AB. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,15 +34,15 @@ */ /** - * \defgroup oma-lwm2m An implementation of OMA LWM2M + * \defgroup lwm2m An implementation of LWM2M * @{ * - * This application is an implementation of OMA Lightweight M2M. + * This is an implementation of OMA Lightweight M2M (LWM2M). */ /** * \file - * Header file for the Contiki OMA LWM2M object API + * Header file for the LWM2M object API * \author * Joakim Eriksson * Niclas Finne @@ -70,7 +70,6 @@ typedef uint32_t lwm2m_resource_id_t; #define RW(x) (x | LWM2M_RESOURCE_READ | LWM2M_RESOURCE_WRITE) #define EX(x) (x | LWM2M_RESOURCE_EXECUTE) - #define LWM2M_OBJECT_SECURITY_ID 0 #define LWM2M_OBJECT_SERVER_ID 1 #define LWM2M_OBJECT_ACCESS_CONTROL_ID 2 @@ -80,45 +79,6 @@ typedef uint32_t lwm2m_resource_id_t; #define LWM2M_OBJECT_LOCATION_ID 6 #define LWM2M_OBJECT_CONNECTIVITY_STATISTICS_ID 7 -#define LWM2M_SECURITY_SERVER_URI_ID 0 -#define LWM2M_SECURITY_BOOTSTRAP_SERVER_ID 1 -#define LWM2M_SECURITY_MODE_ID 2 -#define LWM2M_SECURITY_CLIENT_PKI_ID 3 -#define LWM2M_SECURITY_SERVER_PKI_ID 4 -#define LWM2M_SECURITY_KEY_ID 5 -#define LWM2M_SECURITY_SHORT_SERVER_ID 10 - -#define LWM2M_SERVER_SHORT_SERVER_ID 0 -#define LWM2M_SERVER_LIFETIME_ID 1 -#define LWM2M_SERVER_BINDING_ID 7 -#define LWM2M_SERVER_REG_UPDATE_TRIGGER_ID 8 - -#define LWM2M_DEVICE_MANUFACTURER_ID 0 -#define LWM2M_DEVICE_MODEL_NUMBER_ID 1 -#define LWM2M_DEVICE_SERIAL_NUMBER_ID 2 -#define LWM2M_DEVICE_FIRMWARE_VERSION_ID 3 -#define LWM2M_DEVICE_REBOOT_ID 4 -#define LWM2M_DEVICE_FACTORY_DEFAULT_ID 5 -#define LWM2M_DEVICE_AVAILABLE_POWER_SOURCES 6 -/* These do have multiple instances */ -#define LWM2M_DEVICE_POWER_SOURCE_VOLTAGE 7 -#define LWM2M_DEVICE_POWER_SOURCE_CURRENT 8 -#define LWM2M_DEVICE_BATTERY_LEVEL 9 - -#define LWM2M_DEVICE_ERROR_CODE 11 -#define LWM2M_DEVICE_TIME_ID 13 -#define LWM2M_DEVICE_TYPE_ID 17 - - -/* Pre-shared key mode */ -#define LWM2M_SECURITY_MODE_PSK 0 -/* Raw Public Key mode */ -#define LWM2M_SECURITY_MODE_RPK 1 -/* Certificate mode */ -#define LWM2M_SECURITY_MODE_CERTIFICATE 2 -/* NoSec mode */ -#define LWM2M_SECURITY_MODE_NOSEC 3 - typedef enum { LWM2M_OP_NONE, LWM2M_OP_READ, diff --git a/os/services/lwm2m/lwm2m-plain-text.c b/os/services/lwm2m/lwm2m-plain-text.c index 4799fcaa6..bbd293aa0 100644 --- a/os/services/lwm2m/lwm2m-plain-text.c +++ b/os/services/lwm2m/lwm2m-plain-text.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Yanzi Networks AB. + * Copyright (c) 2015-2018, Yanzi Networks AB. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,7 +29,7 @@ */ /** - * \addtogroup oma-lwm2m + * \addtogroup lwm2m * @{ */ diff --git a/os/services/lwm2m/lwm2m-plain-text.h b/os/services/lwm2m/lwm2m-plain-text.h index bf12a118c..7922a8ce8 100644 --- a/os/services/lwm2m/lwm2m-plain-text.h +++ b/os/services/lwm2m/lwm2m-plain-text.h @@ -29,7 +29,7 @@ */ /** - * \addtogroup oma-lwm2m + * \addtogroup lwm2m * @{ */ diff --git a/os/services/lwm2m/lwm2m-rd-client.c b/os/services/lwm2m/lwm2m-rd-client.c index 12928001e..0f904ee4d 100644 --- a/os/services/lwm2m/lwm2m-rd-client.c +++ b/os/services/lwm2m/lwm2m-rd-client.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Yanzi Networks AB. + * Copyright (c) 2015-2018, Yanzi Networks AB. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,7 +29,7 @@ */ /** - * \addtogroup oma-lwm2m + * \addtogroup lwm2m * @{ */ diff --git a/os/services/lwm2m/lwm2m-rd-client.h b/os/services/lwm2m/lwm2m-rd-client.h index 0707728f9..7fba7e0ae 100644 --- a/os/services/lwm2m/lwm2m-rd-client.h +++ b/os/services/lwm2m/lwm2m-rd-client.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, SICS Swedish ICT AB. + * Copyright (c) 2016-2018, SICS Swedish ICT AB. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,6 +28,20 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + * \addtogroup lwm2m + * @{ + */ + +/** + * \file + * Header file for the Contiki OMA LWM2M Registration and Bootstrap + * Client. + * \author + * Joakim Eriksson + * Niclas Finne + */ + #ifndef LWM2M_RD_CLIENT_H_ #define LWM2M_RD_CLIENT_H_ @@ -61,7 +75,9 @@ void lwm2m_rd_client_init(const char *ep); void lwm2m_rd_client_set_session_callback(session_callback_t cb); +#ifndef LWM2M_RD_CLIENT_ASSIGNED_ENDPOINT_MAX_LEN #define LWM2M_RD_CLIENT_ASSIGNED_ENDPOINT_MAX_LEN 15 +#endif /* LWM2M_RD_CLIENT_ASSIGNED_ENDPOINT_MAX_LEN */ /*---------------------------------------------------------------------------*/ /*- Server session-*Currently single session only*---------------------------*/ @@ -83,3 +99,4 @@ struct lwm2m_session_info { }; #endif /* LWM2M_RD_CLIENT_H_ */ +/** @} */ diff --git a/os/services/lwm2m/lwm2m-security.c b/os/services/lwm2m/lwm2m-security.c index a8b0801dc..d1b29a319 100644 --- a/os/services/lwm2m/lwm2m-security.c +++ b/os/services/lwm2m/lwm2m-security.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Yanzi Networks AB. + * Copyright (c) 2015-2018, Yanzi Networks AB. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,7 +29,7 @@ */ /** - * \addtogroup oma-lwm2m + * \addtogroup lwm2m * @{ * */ diff --git a/os/services/lwm2m/lwm2m-security.h b/os/services/lwm2m/lwm2m-security.h index 941fafde3..9fb3df78f 100644 --- a/os/services/lwm2m/lwm2m-security.h +++ b/os/services/lwm2m/lwm2m-security.h @@ -36,6 +36,23 @@ #ifndef LWM2M_SECURITY_H #define LWM2M_SECURITY_H +#define LWM2M_SECURITY_SERVER_URI_ID 0 +#define LWM2M_SECURITY_BOOTSTRAP_SERVER_ID 1 +#define LWM2M_SECURITY_MODE_ID 2 +#define LWM2M_SECURITY_CLIENT_PKI_ID 3 +#define LWM2M_SECURITY_SERVER_PKI_ID 4 +#define LWM2M_SECURITY_KEY_ID 5 +#define LWM2M_SECURITY_SHORT_SERVER_ID 10 + +/* Pre-shared key mode */ +#define LWM2M_SECURITY_MODE_PSK 0 +/* Raw Public Key mode */ +#define LWM2M_SECURITY_MODE_RPK 1 +/* Certificate mode */ +#define LWM2M_SECURITY_MODE_CERTIFICATE 2 +/* NoSec mode */ +#define LWM2M_SECURITY_MODE_NOSEC 3 + #ifdef LWM2M_SECURITY_CONF_URI_SIZE #define LWM2M_SECURITY_URI_SIZE LWM2M_SECURITY_CONF_URI_SIZE #else /* LWM2M_SECURITY_CONF_URI_SIZE */ diff --git a/os/services/lwm2m/lwm2m-server.c b/os/services/lwm2m/lwm2m-server.c index 0378221c6..67b2c45ba 100644 --- a/os/services/lwm2m/lwm2m-server.c +++ b/os/services/lwm2m/lwm2m-server.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Yanzi Networks AB. + * Copyright (c) 2015-2018, Yanzi Networks AB. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,7 +29,7 @@ */ /** - * \addtogroup oma-lwm2m + * \addtogroup lwm2m * @{ * */ diff --git a/os/services/lwm2m/lwm2m-server.h b/os/services/lwm2m/lwm2m-server.h index 92968d138..733b0889d 100644 --- a/os/services/lwm2m/lwm2m-server.h +++ b/os/services/lwm2m/lwm2m-server.h @@ -38,6 +38,11 @@ #include "contiki.h" +#define LWM2M_SERVER_SHORT_SERVER_ID 0 +#define LWM2M_SERVER_LIFETIME_ID 1 +#define LWM2M_SERVER_BINDING_ID 7 +#define LWM2M_SERVER_REG_UPDATE_TRIGGER_ID 8 + #ifdef LWM2M_SERVER_CONF_MAX_COUNT #define LWM2M_SERVER_MAX_COUNT LWM2M_SERVER_CONF_MAX_COUNT #else diff --git a/os/services/lwm2m/lwm2m-tlv-reader.c b/os/services/lwm2m/lwm2m-tlv-reader.c index f1d41d945..cbeed6bd2 100644 --- a/os/services/lwm2m/lwm2m-tlv-reader.c +++ b/os/services/lwm2m/lwm2m-tlv-reader.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Yanzi Networks AB. + * Copyright (c) 2015-2018, Yanzi Networks AB. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,7 +29,7 @@ */ /** - * \addtogroup oma-lwm2m + * \addtogroup lwm2m * @{ * */ diff --git a/os/services/lwm2m/lwm2m-tlv-reader.h b/os/services/lwm2m/lwm2m-tlv-reader.h index 5fe610511..15db7024d 100644 --- a/os/services/lwm2m/lwm2m-tlv-reader.h +++ b/os/services/lwm2m/lwm2m-tlv-reader.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Yanzi Networks AB. + * Copyright (c) 2015-2018, Yanzi Networks AB. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,7 +28,7 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -/** \addtogroup oma-lwm2m +/** \addtogroup lwm2m * @{ */ /** diff --git a/os/services/lwm2m/lwm2m-tlv-writer.c b/os/services/lwm2m/lwm2m-tlv-writer.c index 5d69fe733..6df16447e 100644 --- a/os/services/lwm2m/lwm2m-tlv-writer.c +++ b/os/services/lwm2m/lwm2m-tlv-writer.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Yanzi Networks AB. + * Copyright (c) 2015-2018, Yanzi Networks AB. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,7 +29,7 @@ */ /** - * \addtogroup oma-lwm2m + * \addtogroup lwm2m * @{ * */ diff --git a/os/services/lwm2m/lwm2m-tlv-writer.h b/os/services/lwm2m/lwm2m-tlv-writer.h index 94f3e61bc..681ccf280 100644 --- a/os/services/lwm2m/lwm2m-tlv-writer.h +++ b/os/services/lwm2m/lwm2m-tlv-writer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Yanzi Networks AB. + * Copyright (c) 2015-2018, Yanzi Networks AB. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,7 +28,7 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -/** \addtogroup oma-lwm2m +/** \addtogroup lwm2m * @{ */ /** diff --git a/os/services/lwm2m/lwm2m-tlv.c b/os/services/lwm2m/lwm2m-tlv.c index 37b1afc61..eb9941784 100644 --- a/os/services/lwm2m/lwm2m-tlv.c +++ b/os/services/lwm2m/lwm2m-tlv.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Yanzi Networks AB. + * Copyright (c) 2015-2018, Yanzi Networks AB. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,7 +29,7 @@ */ /** - * \addtogroup oma-lwm2m + * \addtogroup lwm2m * @{ * */ diff --git a/os/services/lwm2m/lwm2m-tlv.h b/os/services/lwm2m/lwm2m-tlv.h index 0cfef25ad..2766263fa 100644 --- a/os/services/lwm2m/lwm2m-tlv.h +++ b/os/services/lwm2m/lwm2m-tlv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Yanzi Networks AB. + * Copyright (c) 2015-2018, Yanzi Networks AB. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,7 +28,7 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -/** \addtogroup oma-lwm2m +/** \addtogroup lwm2m * @{ */ /** From 5ad09ecabb99d1f7a8a4d91d49418e6620a046f4 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Thu, 21 Dec 2017 18:54:28 +0100 Subject: [PATCH 42/51] lwm2m: added regression test for LWM2M standalone. --- .../18-coap-lwm2m/07-lwm2m-standalone-test.sh | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100755 tests/18-coap-lwm2m/07-lwm2m-standalone-test.sh diff --git a/tests/18-coap-lwm2m/07-lwm2m-standalone-test.sh b/tests/18-coap-lwm2m/07-lwm2m-standalone-test.sh new file mode 100755 index 000000000..5516eeb46 --- /dev/null +++ b/tests/18-coap-lwm2m/07-lwm2m-standalone-test.sh @@ -0,0 +1,58 @@ +#!/bin/bash + +# Contiki directory +CONTIKI=$1 +# Test basename +BASENAME=07-lwm2m-standalone-test + +git clone https://github.com/contiki-ng/example-lwm2m-standalone.git +# Building standalone posix example +make -C example-lwm2m-standalone/lwm2m > make.log 2> make.err + +echo "Downloading leshan" +wget -nc https://joakimeriksson.github.io/resources/leshan-server-demo-1.0.0-SNAPSHOT-jar-with-dependencies.jar +echo "Starting leshan server" +java -jar leshan-server-demo-1.0.0-SNAPSHOT-jar-with-dependencies.jar -lp 5686 -slp 5687 >leshan.log 2>leshan.err & +LESHID=$! + +echo "Starting lwm2m standalone example" +example-lwm2m-standalone/lwm2m/lwm2m-example coap://127.0.0.1:5686 > node.log 2> node.err & + +CPID=$! + +sleep 50 + +echo "Closing native node" +sleep 1 +pgrep ipso | sudo xargs kill -9 + +echo "Closing leshan" +sleep 1 +pgrep java | sudo xargs kill -9 + + +if grep -q 'OK' leshan.err ; then + cp leshan.err $BASENAME.testlog; + printf "%-32s TEST OK\n" "$BASENAME" | tee $BASENAME.testlog; +else + echo "==== make.log ====" ; cat make.log; + echo "==== make.err ====" ; cat make.err; + echo "==== node.log ====" ; cat node.log; + echo "==== node.err ====" ; cat node.err; + echo "==== leshan.log ====" ; cat leshan.log; + echo "==== leshan.err ====" ; cat leshan.err; + echo "==== $BASENAME.log ====" ; cat $BASENAME.log; + + printf "%-32s TEST FAIL\n" "$BASENAME" | tee $BASENAME.testlog; +fi + +rm make.log +rm make.err +rm node.log +rm node.err +rm leshan.log +rm leshan.err + +# We do not want Make to stop -> Return 0 +# The Makefile will check if a log contains FAIL at the end +exit 0 From 3c52d6727c7beaafdd1533669e17cf2e09127b45 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Fri, 12 Jan 2018 16:08:42 +0100 Subject: [PATCH 43/51] The CoAP example no longer fits in the limited ROM in Tmote Sky. Added a compile warning and documented the limitation in the README. --- examples/coap/Makefile | 1 + examples/coap/README.md | 68 +------ examples/coap/coap-example-client.c | 26 +-- examples/coap/coap-example-server.c | 17 +- examples/coap/in6addr.patch | 10 - examples/coap/project-conf.h | 7 +- examples/coap/server-client-native.csc | 231 ------------------------ examples/coap/server-client-observe.csc | 203 --------------------- examples/coap/server-client.csc | 231 ------------------------ examples/coap/server-only.csc | 193 -------------------- examples/coap/sky/module-macros.h | 47 +++++ 11 files changed, 73 insertions(+), 961 deletions(-) delete mode 100644 examples/coap/in6addr.patch delete mode 100644 examples/coap/server-client-native.csc delete mode 100644 examples/coap/server-client-observe.csc delete mode 100644 examples/coap/server-client.csc delete mode 100644 examples/coap/server-only.csc create mode 100644 examples/coap/sky/module-macros.h diff --git a/examples/coap/Makefile b/examples/coap/Makefile index cb27da2ab..e2c6e4a5d 100644 --- a/examples/coap/Makefile +++ b/examples/coap/Makefile @@ -9,6 +9,7 @@ ifeq ($(TARGET),native) MODULES_REL += ./resources-plugtest endif MODULES_REL += ./resources +MODULES_REL += $(TARGET) # Include the CoAP implementation MODULES += os/net/app-layer/coap diff --git a/examples/coap/README.md b/examples/coap/README.md index 6ba2f6071..67ba38f26 100644 --- a/examples/coap/README.md +++ b/examples/coap/README.md @@ -16,76 +16,14 @@ EXAMPLE FILES PRELIMINARIES ------------- -- Make sure rpl-border-router has the same network stack and fits into mote memory. -- Alternatively, you can use the native rpl-border-router together with the slip-radio. -- For convenience, define the Cooja addresses in /etc/hosts - fd00::0212:7401:0001:0101 cooja1 - fd00::0212:7402:0002:0202 cooja2 - ... - Get the Copper (Cu) CoAP user-agent from [https://addons.mozilla.org/en-US/firefox/addon/copper-270430](https://addons.mozilla.org/en-US/firefox/addon/copper-270430) -- Optional: Save your target as default target - make TARGET=sky savetarget - -COOJA HOWTO ------------ - -###Server only: - - make TARGET=cooja server-only.csc - -Open new terminal - - make connect-router-cooja - -- Start Copper and discover resources at coap://cooja2:5683/ -- Choose "Click button on Sky 2" from the context menu of mote 2 (server) after - requesting /test/separate -- Do the same when observing /test/event - -###With client: - - make TARGET=cooja server-client.csc - -Open new terminal - - make connect-router-cooja - -- Wait until red LED toggles on mote 2 (server) -- Choose "Click button on Sky 3" from the context menu of mote 3 (client) and - watch serial output TMOTE SKY HOWTO --------------- -###Server: - -1. Connect two Tmote Skys (check with $ make TARGET=sky sky-motelist) - - make TARGET=sky coap-example-server.upload MOTE=2 - make TARGET=sky login MOTE=2 - -2. Press reset button, get address, abort with Ctrl+C: - Line: "Tentative link-local IPv6 address fe80:0000:0000:0000:____:____:____:____" - - cd ../rpl-border-router/ - make TARGET=sky border-router.upload MOTE=1 - make connect-router - - For a BR tty other than USB0: - - make connect-router-port PORT=X - -3. Start Copper and discover resources at: - - coap://[fd00::____:____:____:____]:5683/ - -### Add a client: - -1. Change the hard-coded server address in coap-example-client.c to fd00::____:____:____:____ -2. Connect a third Tmote Sky - - make TARGET=sky coap-example-client.upload MOTE=3 +The CoAP example no longer fits in the limited ROM of the Tmote Sky. +Please use a platform with larger ROM instead. NATIVE HOWTO ------------ @@ -132,7 +70,7 @@ in coap-example-server.c. In general, coap supports: - Separate Responses (no rest_set_pre_handler() required anymore, note coap_separate_accept(), _reject(), and _resume()) - Resource Discovery -- Observing Resources (see EVENT_ and PRERIODIC_RESOURCE, note +- Observing Resources (see EVENT_ and PERIODIC_RESOURCE, note COAP_MAX_OBSERVERS) TODOs diff --git a/examples/coap/coap-example-client.c b/examples/coap/coap-example-client.c index ca203c210..8f685d458 100644 --- a/examples/coap/coap-example-client.c +++ b/examples/coap/coap-example-client.c @@ -45,24 +45,19 @@ #include "coap-blocking-api.h" #include "dev/button-sensor.h" -#define DEBUG DEBUG_NONE -#include "net/ipv6/uip-debug.h" +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "client" +#define LOG_LEVEL LOG_LEVEL_COAP /* FIXME: This server address is hard-coded for Cooja and link-local for unconnected border router. */ -#define SERVER_NODE(ipaddr) uip_ip6addr(ipaddr, 0xfe80, 0, 0, 0, 0x0212, 0x7402, 0x0002, 0x0202) /* cooja2 */ -/* #define SERVER_NODE(ipaddr) uip_ip6addr(ipaddr, 0xbbbb, 0, 0, 0, 0, 0, 0, 0x1) */ - #define SERVER_EP "coap://[fe80::212:7402:0002:0202]" -#define LOCAL_PORT UIP_HTONS(COAP_DEFAULT_PORT + 1) -#define REMOTE_PORT UIP_HTONS(COAP_DEFAULT_PORT) - #define TOGGLE_INTERVAL 10 PROCESS(er_example_client, "Erbium Example Client"); AUTOSTART_PROCESSES(&er_example_client); -uip_ipaddr_t server_ipaddr; static struct etimer et; /* Example URIs that can be queried. */ @@ -91,10 +86,7 @@ PROCESS_THREAD(er_example_client, ev, data) static coap_message_t request[1]; /* This way the packet can be treated as pointer as usual. */ - /* SERVER_NODE(&server_ipaddr); */ - - coap_endpoint_parse(SERVER_EP, strlen(SERVER_EP), - &server_ep); + coap_endpoint_parse(SERVER_EP, strlen(SERVER_EP), &server_ep); /* receives all CoAP messages */ coap_engine_init(); @@ -120,8 +112,8 @@ PROCESS_THREAD(er_example_client, ev, data) coap_set_payload(request, (uint8_t *)msg, sizeof(msg) - 1); - coap_endpoint_print(&server_ep); - PRINTF(" : %u\n", UIP_HTONS(REMOTE_PORT)); + LOG_INFO_COAP_EP(&server_ep); + LOG_INFO_("\n"); COAP_BLOCKING_REQUEST(&server_ep, request, client_chunk_handler); @@ -139,8 +131,8 @@ PROCESS_THREAD(er_example_client, ev, data) printf("--Requesting %s--\n", service_urls[uri_switch]); - PRINT6ADDR(&server_ipaddr); - PRINTF(" : %u\n", UIP_HTONS(REMOTE_PORT)); + LOG_INFO_COAP_EP(&server_ep); + LOG_INFO_("\n"); COAP_BLOCKING_REQUEST(&server_ep, request, client_chunk_handler); diff --git a/examples/coap/coap-example-server.c b/examples/coap/coap-example-server.c index 968afb548..3cbcbc746 100644 --- a/examples/coap/coap-example-server.c +++ b/examples/coap/coap-example-server.c @@ -40,7 +40,6 @@ #include #include #include "contiki.h" -#include "contiki-net.h" #include "coap-engine.h" #if PLATFORM_HAS_BUTTON @@ -127,13 +126,15 @@ PROCESS_THREAD(er_example_server, ev, data) * All static variables are the same for each URI path. */ coap_activate_resource(&res_hello, "test/hello"); -/* coap_activate_resource(&res_mirror, "debug/mirror"); */ -/* coap_activate_resource(&res_chunks, "test/chunks"); */ -/* coap_activate_resource(&res_separate, "test/separate"); */ - coap_activate_resource(&res_push, "test/push"); -/* coap_activate_resource(&res_event, "sensors/button"); */ -/* coap_activate_resource(&res_sub, "test/sub"); */ -/* coap_activate_resource(&res_b1_sep_b2, "test/b1sepb2"); */ + coap_activate_resource(&res_mirror, "debug/mirror"); + coap_activate_resource(&res_chunks, "test/chunks"); + coap_activate_resource(&res_separate, "test/separate"); + coap_activate_resource(&res_push, "test/push"); +#if PLATFORM_HAS_BUTTON + coap_activate_resource(&res_event, "sensors/button"); +#endif /* PLATFORM_HAS_BUTTON */ + coap_activate_resource(&res_sub, "test/sub"); + coap_activate_resource(&res_b1_sep_b2, "test/b1sepb2"); #if PLATFORM_HAS_LEDS /* coap_activate_resource(&res_leds, "actuators/leds"); */ coap_activate_resource(&res_toggle, "actuators/toggle"); diff --git a/examples/coap/in6addr.patch b/examples/coap/in6addr.patch deleted file mode 100644 index 92ca106cf..000000000 --- a/examples/coap/in6addr.patch +++ /dev/null @@ -1,10 +0,0 @@ -21,23c21 -< #ifdef __INSIDE_CYGWIN__ -< uint32_t __s6_addr32[4]; -< #endif ---- -> u_int __s6_addr32[4]; -36d33 -< #ifdef __INSIDE_CYGWIN__ -39d35 -< #endif diff --git a/examples/coap/project-conf.h b/examples/coap/project-conf.h index 6f7d132e0..115d6fbb0 100644 --- a/examples/coap/project-conf.h +++ b/examples/coap/project-conf.h @@ -53,7 +53,9 @@ /* #define COAP_MAX_HEADER_SIZE 70 */ /* Multiplies with chunk size, be aware of memory constraints. */ +#ifndef COAP_MAX_OPEN_TRANSACTIONS #define COAP_MAX_OPEN_TRANSACTIONS 4 +#endif /* COAP_MAX_OPEN_TRANSACTIONS */ /* Must be <= open transactions, default is COAP_MAX_OPEN_TRANSACTIONS-1. */ /* #define COAP_MAX_OBSERVERS 2 */ @@ -62,10 +64,9 @@ #define COAP_LINK_FORMAT_FILTERING 0 #define COAP_PROXY_OPTION_PROCESSING 0 -/* Turn off DAO-ACK to make code smaller */ -#define RPL_CONF_WITH_DAO_ACK 0 - /* Enable client-side support for COAP observe */ +#ifndef COAP_OBSERVE_CLIENT #define COAP_OBSERVE_CLIENT 1 +#endif /* COAP_OBSERVE_CLIENT */ #endif /* PROJECT_ERBIUM_CONF_H_ */ diff --git a/examples/coap/server-client-native.csc b/examples/coap/server-client-native.csc deleted file mode 100644 index cec9ca8a7..000000000 --- a/examples/coap/server-client-native.csc +++ /dev/null @@ -1,231 +0,0 @@ - - - [APPS_DIR]/mrm - [APPS_DIR]/mspsim - [APPS_DIR]/avrora - [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view - [APPS_DIR]/powertracker - - REST with RPL router - 1.0 - 123456 - 1000000 - - org.contikios.cooja.radiomediums.UDGM - 50.0 - 50.0 - 1.0 - 1.0 - - - 40000 - - - org.contikios.cooja.mspmote.SkyMoteType - slipradio - Sky SLIP radio - [CONTIKI_DIR]/examples/ipv6/slip-radio/slip-radio.c - make slip-radio.sky TARGET=sky - [CONTIKI_DIR]/examples/ipv6/slip-radio/slip-radio.sky - org.contikios.cooja.interfaces.Position - org.contikios.cooja.interfaces.RimeAddress - org.contikios.cooja.interfaces.IPAddress - org.contikios.cooja.interfaces.Mote2MoteRelations - org.contikios.cooja.interfaces.MoteAttributes - org.contikios.cooja.mspmote.interfaces.MspClock - org.contikios.cooja.mspmote.interfaces.MspMoteID - org.contikios.cooja.mspmote.interfaces.SkyButton - org.contikios.cooja.mspmote.interfaces.SkyFlash - org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem - org.contikios.cooja.mspmote.interfaces.Msp802154Radio - org.contikios.cooja.mspmote.interfaces.MspSerial - org.contikios.cooja.mspmote.interfaces.SkyLED - org.contikios.cooja.mspmote.interfaces.MspDebugOutput - org.contikios.cooja.mspmote.interfaces.SkyTemperature - - - org.contikios.cooja.mspmote.SkyMoteType - server - Erbium Server - [CONTIKI_DIR]/examples/coap/coap-example-server.c - make coap-example-server.sky TARGET=sky - [CONTIKI_DIR]/examples/coap/coap-example-server.sky - org.contikios.cooja.interfaces.Position - org.contikios.cooja.interfaces.RimeAddress - org.contikios.cooja.interfaces.IPAddress - org.contikios.cooja.interfaces.Mote2MoteRelations - org.contikios.cooja.interfaces.MoteAttributes - org.contikios.cooja.mspmote.interfaces.MspClock - org.contikios.cooja.mspmote.interfaces.MspMoteID - org.contikios.cooja.mspmote.interfaces.SkyButton - org.contikios.cooja.mspmote.interfaces.SkyFlash - org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem - org.contikios.cooja.mspmote.interfaces.Msp802154Radio - org.contikios.cooja.mspmote.interfaces.MspSerial - org.contikios.cooja.mspmote.interfaces.SkyLED - org.contikios.cooja.mspmote.interfaces.MspDebugOutput - org.contikios.cooja.mspmote.interfaces.SkyTemperature - - - org.contikios.cooja.mspmote.SkyMoteType - client - Erbium Client - [CONTIKI_DIR]/examples/coap/coap-example-client.c - make coap-example-client.sky TARGET=sky - [CONTIKI_DIR]/examples/coap/coap-example-client.sky - org.contikios.cooja.interfaces.Position - org.contikios.cooja.interfaces.RimeAddress - org.contikios.cooja.interfaces.IPAddress - org.contikios.cooja.interfaces.Mote2MoteRelations - org.contikios.cooja.interfaces.MoteAttributes - org.contikios.cooja.mspmote.interfaces.MspClock - org.contikios.cooja.mspmote.interfaces.MspMoteID - org.contikios.cooja.mspmote.interfaces.SkyButton - org.contikios.cooja.mspmote.interfaces.SkyFlash - org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem - org.contikios.cooja.mspmote.interfaces.Msp802154Radio - org.contikios.cooja.mspmote.interfaces.MspSerial - org.contikios.cooja.mspmote.interfaces.SkyLED - org.contikios.cooja.mspmote.interfaces.MspDebugOutput - org.contikios.cooja.mspmote.interfaces.SkyTemperature - - - - - org.contikios.cooja.interfaces.Position - 30.303994886410642 - 17.22128424003353 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 1 - - slipradio - - - - - org.contikios.cooja.interfaces.Position - 46.57186415376375 - 37.25589203828498 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 2 - - server - - - - - org.contikios.cooja.interfaces.Position - 18.194682268367348 - 50.210548118402656 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 3 - - client - - - - org.contikios.cooja.plugins.SimControl - 259 - 0 - 179 - 1 - 2 - - - org.contikios.cooja.plugins.Visualizer - - org.contikios.cooja.plugins.skins.IDVisualizerSkin - org.contikios.cooja.plugins.skins.UDGMVisualizerSkin - org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin - org.contikios.cooja.plugins.skins.AttributeVisualizerSkin - org.contikios.cooja.plugins.skins.LEDVisualizerSkin - org.contikios.cooja.plugins.skins.AddressVisualizerSkin - 2.255467003316979 0.0 0.0 2.255467003316979 59.30641698643764 -13.478401994502008 - - 300 - 2 - 178 - 262 - 1 - - - org.contikios.cooja.plugins.LogListener - - - - - - 762 - 4 - 491 - 2 - 182 - - - org.contikios.cooja.plugins.RadioLogger - - 150 - - false - false - - - 451 - -1 - 305 - 73 - 140 - true - - - org.contikios.cooja.plugins.TimeLine - - 0 - 1 - 2 - - - - - 25.49079397896416 - - 1624 - 5 - 252 - 6 - 712 - - - org.contikios.cooja.plugins.MoteInterfaceViewer - 1 - - Serial port - 0,0 - - 853 - 3 - 491 - 765 - 182 - - - org.contikios.cooja.serialsocket.SerialSocketServer - 0 - 422 - 1 - 82 - 606 - 51 - - - diff --git a/examples/coap/server-client-observe.csc b/examples/coap/server-client-observe.csc deleted file mode 100644 index a7c9cca8b..000000000 --- a/examples/coap/server-client-observe.csc +++ /dev/null @@ -1,203 +0,0 @@ - - - [APPS_DIR]/mrm - [APPS_DIR]/mspsim - [APPS_DIR]/avrora - [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view - [APPS_DIR]/powertracker - - REST with RPL router - 1.0 - 123456 - 1000000 - - org.contikios.cooja.radiomediums.UDGM - 50.0 - 50.0 - 1.0 - 1.0 - - - 40000 - - - org.contikios.cooja.mspmote.SkyMoteType - rplroot - Sky RPL Root - [CONTIKI_DIR]/examples/rpl-border-router/border-router.c - make border-router.sky TARGET=sky - [CONTIKI_DIR]/examples/rpl-border-router/border-router.sky - org.contikios.cooja.interfaces.Position - org.contikios.cooja.interfaces.RimeAddress - org.contikios.cooja.interfaces.IPAddress - org.contikios.cooja.interfaces.Mote2MoteRelations - org.contikios.cooja.interfaces.MoteAttributes - org.contikios.cooja.mspmote.interfaces.MspClock - org.contikios.cooja.mspmote.interfaces.MspMoteID - org.contikios.cooja.mspmote.interfaces.SkyButton - org.contikios.cooja.mspmote.interfaces.SkyFlash - org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem - org.contikios.cooja.mspmote.interfaces.Msp802154Radio - org.contikios.cooja.mspmote.interfaces.MspSerial - org.contikios.cooja.mspmote.interfaces.SkyLED - org.contikios.cooja.mspmote.interfaces.MspDebugOutput - org.contikios.cooja.mspmote.interfaces.SkyTemperature - - - org.contikios.cooja.mspmote.SkyMoteType - server - Erbium Server - [CONTIKI_DIR]/examples/coap/coap-example-server.c - make coap-example-server.sky TARGET=sky - [CONTIKI_DIR]/examples/coap/coap-example-server.sky - org.contikios.cooja.interfaces.Position - org.contikios.cooja.interfaces.RimeAddress - org.contikios.cooja.interfaces.IPAddress - org.contikios.cooja.interfaces.Mote2MoteRelations - org.contikios.cooja.interfaces.MoteAttributes - org.contikios.cooja.mspmote.interfaces.MspClock - org.contikios.cooja.mspmote.interfaces.MspMoteID - org.contikios.cooja.mspmote.interfaces.SkyButton - org.contikios.cooja.mspmote.interfaces.SkyFlash - org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem - org.contikios.cooja.mspmote.interfaces.Msp802154Radio - org.contikios.cooja.mspmote.interfaces.MspSerial - org.contikios.cooja.mspmote.interfaces.SkyLED - org.contikios.cooja.mspmote.interfaces.MspDebugOutput - org.contikios.cooja.mspmote.interfaces.SkyTemperature - - - org.contikios.cooja.mspmote.SkyMoteType - client - Erbium Client - [CONTIKI_DIR]/examples/coap/coap-example-observe-client.c - make coap-example-observe-client.sky TARGET=sky - [CONTIKI_DIR]/examples/coap/coap-example-observe-client.sky - org.contikios.cooja.interfaces.Position - org.contikios.cooja.interfaces.RimeAddress - org.contikios.cooja.interfaces.IPAddress - org.contikios.cooja.interfaces.Mote2MoteRelations - org.contikios.cooja.interfaces.MoteAttributes - org.contikios.cooja.mspmote.interfaces.MspClock - org.contikios.cooja.mspmote.interfaces.MspMoteID - org.contikios.cooja.mspmote.interfaces.SkyButton - org.contikios.cooja.mspmote.interfaces.SkyFlash - org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem - org.contikios.cooja.mspmote.interfaces.Msp802154Radio - org.contikios.cooja.mspmote.interfaces.MspSerial - org.contikios.cooja.mspmote.interfaces.SkyLED - org.contikios.cooja.mspmote.interfaces.MspDebugOutput - org.contikios.cooja.mspmote.interfaces.SkyTemperature - - - - - org.contikios.cooja.interfaces.Position - 33.260163187353555 - 30.643217359962595 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 1 - - rplroot - - - - - org.contikios.cooja.interfaces.Position - 54.537149936813485 - 51.51086225537906 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 2 - - server - - - - - org.contikios.cooja.interfaces.Position - 77.97942851220571 - 67.86182390447284 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 3 - - client - - - - org.contikios.cooja.plugins.SimControl - 259 - 3 - 179 - 2 - 1 - - - org.contikios.cooja.plugins.Visualizer - - org.contikios.cooja.plugins.skins.IDVisualizerSkin - org.contikios.cooja.plugins.skins.UDGMVisualizerSkin - org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin - org.contikios.cooja.plugins.skins.AttributeVisualizerSkin - org.contikios.cooja.plugins.skins.LEDVisualizerSkin - org.contikios.cooja.plugins.skins.AddressVisualizerSkin - 2.092412892721766 0.0 0.0 2.092412892721766 34.70057915472623 -45.606066372444175 - - 300 - 4 - 178 - 261 - 1 - - - org.contikios.cooja.plugins.LogListener - - - - - - 762 - 0 - 491 - 2 - 182 - - - org.contikios.cooja.plugins.RadioLogger - - 167 - - false - false - - - 560 - 1 - 492 - 764 - 181 - - - org.contikios.cooja.serialsocket.SerialSocketServer - 0 - - 60001 - true - - 362 - 2 - 116 - 561 - 1 - - - diff --git a/examples/coap/server-client.csc b/examples/coap/server-client.csc deleted file mode 100644 index a649d048a..000000000 --- a/examples/coap/server-client.csc +++ /dev/null @@ -1,231 +0,0 @@ - - - [APPS_DIR]/mrm - [APPS_DIR]/mspsim - [APPS_DIR]/avrora - [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view - [APPS_DIR]/powertracker - - REST with RPL router - 1.0 - 123456 - 1000000 - - org.contikios.cooja.radiomediums.UDGM - 50.0 - 50.0 - 1.0 - 1.0 - - - 40000 - - - org.contikios.cooja.mspmote.SkyMoteType - rplroot - Sky RPL Root - [CONTIKI_DIR]/examples/rpl-border-router/border-router.c - make border-router.sky TARGET=sky - [CONTIKI_DIR]/examples/rpl-border-router/border-router.sky - org.contikios.cooja.interfaces.Position - org.contikios.cooja.interfaces.RimeAddress - org.contikios.cooja.interfaces.IPAddress - org.contikios.cooja.interfaces.Mote2MoteRelations - org.contikios.cooja.interfaces.MoteAttributes - org.contikios.cooja.mspmote.interfaces.MspClock - org.contikios.cooja.mspmote.interfaces.MspMoteID - org.contikios.cooja.mspmote.interfaces.SkyButton - org.contikios.cooja.mspmote.interfaces.SkyFlash - org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem - org.contikios.cooja.mspmote.interfaces.Msp802154Radio - org.contikios.cooja.mspmote.interfaces.MspSerial - org.contikios.cooja.mspmote.interfaces.SkyLED - org.contikios.cooja.mspmote.interfaces.MspDebugOutput - org.contikios.cooja.mspmote.interfaces.SkyTemperature - - - org.contikios.cooja.mspmote.SkyMoteType - server - Erbium Server - [CONTIKI_DIR]/examples/coap/coap-example-server.c - make coap-example-server.sky TARGET=sky - [CONTIKI_DIR]/examples/coap/coap-example-server.sky - org.contikios.cooja.interfaces.Position - org.contikios.cooja.interfaces.RimeAddress - org.contikios.cooja.interfaces.IPAddress - org.contikios.cooja.interfaces.Mote2MoteRelations - org.contikios.cooja.interfaces.MoteAttributes - org.contikios.cooja.mspmote.interfaces.MspClock - org.contikios.cooja.mspmote.interfaces.MspMoteID - org.contikios.cooja.mspmote.interfaces.SkyButton - org.contikios.cooja.mspmote.interfaces.SkyFlash - org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem - org.contikios.cooja.mspmote.interfaces.Msp802154Radio - org.contikios.cooja.mspmote.interfaces.MspSerial - org.contikios.cooja.mspmote.interfaces.SkyLED - org.contikios.cooja.mspmote.interfaces.MspDebugOutput - org.contikios.cooja.mspmote.interfaces.SkyTemperature - - - org.contikios.cooja.mspmote.SkyMoteType - client - Erbium Client - [CONTIKI_DIR]/examples/coap/coap-example-client.c - make coap-example-client.sky TARGET=sky - [CONTIKI_DIR]/examples/coap/coap-example-client.sky - org.contikios.cooja.interfaces.Position - org.contikios.cooja.interfaces.RimeAddress - org.contikios.cooja.interfaces.IPAddress - org.contikios.cooja.interfaces.Mote2MoteRelations - org.contikios.cooja.interfaces.MoteAttributes - org.contikios.cooja.mspmote.interfaces.MspClock - org.contikios.cooja.mspmote.interfaces.MspMoteID - org.contikios.cooja.mspmote.interfaces.SkyButton - org.contikios.cooja.mspmote.interfaces.SkyFlash - org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem - org.contikios.cooja.mspmote.interfaces.Msp802154Radio - org.contikios.cooja.mspmote.interfaces.MspSerial - org.contikios.cooja.mspmote.interfaces.SkyLED - org.contikios.cooja.mspmote.interfaces.MspDebugOutput - org.contikios.cooja.mspmote.interfaces.SkyTemperature - - - - - org.contikios.cooja.interfaces.Position - 33.260163187353555 - 30.643217359962595 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 1 - - rplroot - - - - - org.contikios.cooja.interfaces.Position - 46.57186415376375 - 40.35946215910942 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 2 - - server - - - - - org.contikios.cooja.interfaces.Position - 18.638049428485125 - 47.55034515769599 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 3 - - client - - - - org.contikios.cooja.plugins.SimControl - 259 - 0 - 179 - 2 - 1 - - - org.contikios.cooja.plugins.Visualizer - - org.contikios.cooja.plugins.skins.IDVisualizerSkin - org.contikios.cooja.plugins.skins.UDGMVisualizerSkin - org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin - org.contikios.cooja.plugins.skins.AttributeVisualizerSkin - org.contikios.cooja.plugins.skins.LEDVisualizerSkin - org.contikios.cooja.plugins.skins.AddressVisualizerSkin - 3.61568947862321 0.0 0.0 3.61568947862321 15.610600779367 -85.92728269158351 - - 300 - 2 - 178 - 261 - 1 - - - org.contikios.cooja.plugins.LogListener - - - - - - 762 - 3 - 491 - 2 - 182 - - - org.contikios.cooja.plugins.RadioLogger - - 150 - - false - false - - - 451 - -1 - 305 - 73 - 140 - true - - - org.contikios.cooja.serialsocket.SerialSocketServer - 0 - 422 - 4 - 74 - 578 - 18 - - - org.contikios.cooja.plugins.TimeLine - - 0 - 1 - 2 - - - - - 25.49079397896416 - - 1624 - 5 - 252 - 6 - 712 - - - org.contikios.cooja.plugins.MoteInterfaceViewer - 2 - - Serial port - 0,0 - - 853 - 1 - 491 - 765 - 182 - - - diff --git a/examples/coap/server-only.csc b/examples/coap/server-only.csc deleted file mode 100644 index 715deae1c..000000000 --- a/examples/coap/server-only.csc +++ /dev/null @@ -1,193 +0,0 @@ - - - [APPS_DIR]/mrm - [APPS_DIR]/mspsim - [APPS_DIR]/avrora - [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view - [APPS_DIR]/powertracker - - REST with RPL router - 1.0 - 123456 - 1000000 - - org.contikios.cooja.radiomediums.UDGM - 50.0 - 50.0 - 1.0 - 1.0 - - - 40000 - - - org.contikios.cooja.mspmote.SkyMoteType - rplroot - Sky RPL Root - [CONTIKI_DIR]/examples/rpl-border-router/border-router.c - make border-router.sky TARGET=sky - [CONTIKI_DIR]/examples/rpl-border-router/border-router.sky - org.contikios.cooja.interfaces.Position - org.contikios.cooja.interfaces.RimeAddress - org.contikios.cooja.interfaces.IPAddress - org.contikios.cooja.interfaces.Mote2MoteRelations - org.contikios.cooja.interfaces.MoteAttributes - org.contikios.cooja.mspmote.interfaces.MspClock - org.contikios.cooja.mspmote.interfaces.MspMoteID - org.contikios.cooja.mspmote.interfaces.SkyButton - org.contikios.cooja.mspmote.interfaces.SkyFlash - org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem - org.contikios.cooja.mspmote.interfaces.Msp802154Radio - org.contikios.cooja.mspmote.interfaces.MspSerial - org.contikios.cooja.mspmote.interfaces.SkyLED - org.contikios.cooja.mspmote.interfaces.MspDebugOutput - org.contikios.cooja.mspmote.interfaces.SkyTemperature - - - org.contikios.cooja.mspmote.SkyMoteType - server - Erbium Server - [CONTIKI_DIR]/examples/coap/coap-example-server.c - make coap-example-server.sky TARGET=sky - [CONTIKI_DIR]/examples/coap/coap-example-server.sky - org.contikios.cooja.interfaces.Position - org.contikios.cooja.interfaces.RimeAddress - org.contikios.cooja.interfaces.IPAddress - org.contikios.cooja.interfaces.Mote2MoteRelations - org.contikios.cooja.interfaces.MoteAttributes - org.contikios.cooja.mspmote.interfaces.MspClock - org.contikios.cooja.mspmote.interfaces.MspMoteID - org.contikios.cooja.mspmote.interfaces.SkyButton - org.contikios.cooja.mspmote.interfaces.SkyFlash - org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem - org.contikios.cooja.mspmote.interfaces.Msp802154Radio - org.contikios.cooja.mspmote.interfaces.MspSerial - org.contikios.cooja.mspmote.interfaces.SkyLED - org.contikios.cooja.mspmote.interfaces.MspDebugOutput - org.contikios.cooja.mspmote.interfaces.SkyTemperature - - - - - org.contikios.cooja.interfaces.Position - 33.260163187353555 - 30.643217359962595 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 1 - - rplroot - - - - - org.contikios.cooja.interfaces.Position - 35.100895239785295 - 39.70574552287428 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 2 - - server - - - - org.contikios.cooja.plugins.SimControl - 259 - 0 - 179 - 2 - 1 - - - org.contikios.cooja.plugins.Visualizer - - org.contikios.cooja.plugins.skins.IDVisualizerSkin - org.contikios.cooja.plugins.skins.UDGMVisualizerSkin - org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin - org.contikios.cooja.plugins.skins.AttributeVisualizerSkin - org.contikios.cooja.plugins.skins.LEDVisualizerSkin - org.contikios.cooja.plugins.skins.AddressVisualizerSkin - 7.9849281638410705 0.0 0.0 7.9849281638410705 -133.27812697619663 -225.04752569190535 - - 300 - 1 - 175 - 262 - 2 - - - org.contikios.cooja.plugins.LogListener - - - - - - 560 - 3 - 326 - 1 - 293 - - - org.contikios.cooja.plugins.RadioLogger - - 150 - - false - false - - - 451 - -1 - 305 - 73 - 140 - true - - - org.contikios.cooja.serialsocket.SerialSocketServer - 0 - 422 - 4 - 74 - 39 - 199 - - - org.contikios.cooja.plugins.TimeLine - - 0 - 1 - - - - - 25.49079397896416 - - 1624 - 5 - 252 - 4 - 622 - - - org.contikios.cooja.plugins.MoteInterfaceViewer - 1 - - Serial port - 0,0 - - 702 - 2 - 646 - 564 - 2 - - - diff --git a/examples/coap/sky/module-macros.h b/examples/coap/sky/module-macros.h new file mode 100644 index 000000000..3fcb04015 --- /dev/null +++ b/examples/coap/sky/module-macros.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2018, RISE SICS AB. + * 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 copyright holder 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 COPYRIGHT HOLDER 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 + * COPYRIGHT HOLDER 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. + */ + +#error The CoAP example no longer fits the limited ROM in the Tmote Sky. \ + Please select another platform with more ROM to compile the CoAP example. + +/*---------------------------------------------------------------------------*/ +#define COAP_OBSERVE_CLIENT 0 + +#define COAP_MAX_CHUNK_SIZE 48 + +/* Turn off DAO-ACK and probing to make code smaller */ +#define RPL_CONF_WITH_DAO_ACK 0 + +#define LOG_CONF_LEVEL_MAIN 0 + +#define DCOSYNCH_CONF_ENABLED 0 + +#define PROCESS_CONF_NUMEVENTS 8 +/*---------------------------------------------------------------------------*/ From e746b024f0cc40ecd4625cf0b3ff557730a23e94 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Fri, 12 Jan 2018 18:57:14 +0100 Subject: [PATCH 44/51] CoAP: fixed typo in Doxygen comment --- os/net/app-layer/coap/coap-endpoint.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/os/net/app-layer/coap/coap-endpoint.h b/os/net/app-layer/coap/coap-endpoint.h index 1174a774b..969791241 100644 --- a/os/net/app-layer/coap/coap-endpoint.h +++ b/os/net/app-layer/coap/coap-endpoint.h @@ -67,8 +67,8 @@ void coap_endpoint_copy(coap_endpoint_t *dest, const coap_endpoint_t *src); /** * \brief Compare two CoAP endpoints. * - * \param dest A pointer to the first CoAP endpoint. - * \param src A pointer to the second CoAP endpoint. + * \param e1 A pointer to the first CoAP endpoint. + * \param e2 A pointer to the second CoAP endpoint. * \return Non-zero if the endpoints are identical and zero otherwise. */ int coap_endpoint_cmp(const coap_endpoint_t *e1, const coap_endpoint_t *e2); From 8a44da0814783bbc53fd50fc3c4a54ebbeeb9f6f Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Wed, 17 Jan 2018 20:00:18 +0100 Subject: [PATCH 45/51] Updated tinydtls submodule --- os/net/security/tinydtls | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/os/net/security/tinydtls b/os/net/security/tinydtls index 3852a923f..fc8d33cb7 160000 --- a/os/net/security/tinydtls +++ b/os/net/security/tinydtls @@ -1 +1 @@ -Subproject commit 3852a923f396365fe69d69a540ba9085bb2d070d +Subproject commit fc8d33cb790bfec64acc595e9ab8ba25a2d27b5a From b4d69603bea572629adc2a77438a050ee81d7f68 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Wed, 17 Jan 2018 20:01:07 +0100 Subject: [PATCH 46/51] Updated LWM2M standalone example submodule --- tests/18-coap-lwm2m/example-lwm2m-standalone | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/18-coap-lwm2m/example-lwm2m-standalone b/tests/18-coap-lwm2m/example-lwm2m-standalone index 9d3157a47..7ab51eaaa 160000 --- a/tests/18-coap-lwm2m/example-lwm2m-standalone +++ b/tests/18-coap-lwm2m/example-lwm2m-standalone @@ -1 +1 @@ -Subproject commit 9d3157a47e7741857c3702d3e5d0939c2e2aef92 +Subproject commit 7ab51eaaa309c123fbd318c6ad3338cce1e48e48 From 6562b78c6ca745c91ad4a8ff0b972b0a6b0a5333 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Wed, 17 Jan 2018 20:02:40 +0100 Subject: [PATCH 47/51] Updated DTLS support for new logging system --- os/net/app-layer/coap/coap-uip.c | 2 - .../coap/tinydtls-support/dtls-support-conf.h | 7 +- .../coap/tinydtls-support/dtls-support.c | 104 +++--------------- 3 files changed, 20 insertions(+), 93 deletions(-) diff --git a/os/net/app-layer/coap/coap-uip.c b/os/net/app-layer/coap/coap-uip.c index dd78f5d3b..c86136efe 100644 --- a/os/net/app-layer/coap/coap-uip.c +++ b/os/net/app-layer/coap/coap-uip.c @@ -70,7 +70,6 @@ #ifdef WITH_DTLS #include "tinydtls.h" #include "dtls.h" -#include "dtls_debug.h" #endif /* WITH_DTLS */ /* sanity check for configured values */ @@ -346,7 +345,6 @@ coap_transport_init(void) process_start(&coap_engine, NULL); #ifdef WITH_DTLS dtls_init(); - dtls_set_log_level(8); #if COAP_DTLS_KEYSTORE_CONF_WITH_SIMPLE coap_keystore_simple_init(); diff --git a/os/net/app-layer/coap/tinydtls-support/dtls-support-conf.h b/os/net/app-layer/coap/tinydtls-support/dtls-support-conf.h index 0e655ec2e..9265583e5 100644 --- a/os/net/app-layer/coap/tinydtls-support/dtls-support-conf.h +++ b/os/net/app-layer/coap/tinydtls-support/dtls-support-conf.h @@ -39,7 +39,10 @@ #ifndef DTLS_SUPPORT_CONF_H_ #define DTLS_SUPPORT_CONF_H_ -#undef HAVE_VPRINTF +/* Use same log level as CoAP as default */ +#define LOG_LEVEL_DTLS LOG_LEVEL_COAP + +#define DTLS_LOG_CONF_PATH "coap-log.h" #include "coap-endpoint.h" @@ -58,8 +61,6 @@ typedef struct { typedef clock_time_t dtls_tick_t; -#define WITH_CONTIKI 1 - #define HAVE_ASSERT_H 1 #endif /* DTLS_SUPPORT_CONF_H_ */ diff --git a/os/net/app-layer/coap/tinydtls-support/dtls-support.c b/os/net/app-layer/coap/tinydtls-support/dtls-support.c index 17dceddc9..ad960b718 100644 --- a/os/net/app-layer/coap/tinydtls-support/dtls-support.c +++ b/os/net/app-layer/coap/tinydtls-support/dtls-support.c @@ -41,8 +41,11 @@ #include #include -#define DEBUG DEBUG_FULLY -#include "dtls_debug.h" +/* Log configuration */ +#define LOG_MODULE "dtls-support" +#define LOG_LEVEL LOG_LEVEL_DTLS +#include "dtls-log.h" +#include "coap-log.h" static dtls_context_t the_dtls_context; static dtls_cipher_context_t cipher_context; @@ -55,7 +58,7 @@ dtls_context_acquire(void) return NULL; } lock_context = 1; - PRINTF("DS: Allocated context\n"); + LOG_DBG("Allocated context\n"); return &the_dtls_context; } /*---------------------------------------------------------------------------*/ @@ -140,13 +143,13 @@ dtls_session_equals(const session_t *a, const session_t *b) coap_endpoint_t *e1 = (coap_endpoint_t *)a; coap_endpoint_t *e2 = (coap_endpoint_t *)b; -#if DEBUG - printf(" **** EP:"); - coap_endpoint_print(e1); - printf(" =?= "); - coap_endpoint_print(e2); - printf(" => %d\n", coap_endpoint_cmp(e1, e2)); -#endif /* DEBUG */ + if(LOG_DBG_ENABLED) { + LOG_DBG(" **** EP:"); + LOG_DBG_COAP_EP(e1); + LOG_DBG_(" =?= "); + LOG_DBG_COAP_EP(e2); + LOG_DBG_(" => %d\n", coap_endpoint_cmp(e1, e2)); + } return coap_endpoint_cmp(e1, e2); } @@ -170,90 +173,15 @@ dtls_session_print(const session_t *a) coap_endpoint_print((const coap_endpoint_t *)a); } /*---------------------------------------------------------------------------*/ -size_t -dsrv_print_addr(const session_t *addr, char *buf, size_t len) -{ - if(len > 1) { - /* TODO print endpoint */ - buf[0] = '['; - buf[1] = ']'; - return 2; - } - return 0; -} -/*---------------------------------------------------------------------------*/ -extern char *loglevels[]; -static inline size_t -print_timestamp(log_t level) -{ - dtls_tick_t now; - dtls_ticks(&now); - if(level <= DTLS_LOG_DEBUG) { - printf("%s ", loglevels[level]); - } - return printf("%5lu ", (unsigned long)now); -} -/*---------------------------------------------------------------------------*/ -#ifdef HAVE_VPRINTF void -dsrv_log(log_t level, char *format, ...) +dtls_session_log(const session_t *a) { - va_list ap; - - if(dtls_get_log_level() < level) { - return; - } - - print_timestamp(level); - - va_start(ap, format); - vprintf(format, ap); - va_end(ap); -} - -#endif /* HAVE_VPRINTF */ -/*---------------------------------------------------------------------------*/ -void -dtls_dsrv_hexdump_log(log_t level, const char *name, const unsigned char *buf, size_t length, int extend) -{ - int n = 0; - - if(dtls_get_log_level() < level) { - return; - } - - print_timestamp(level); - - if(extend) { - printf("%s: (%zu bytes):\n", name, length); - - while(length--) { - if(n % 16 == 0) { - printf("%08X ", n); - } - printf("%02X ", *buf++); - - n++; - if(n % 8 == 0) { - if(n % 16 == 0) { - printf("\n"); - } else { - printf(" "); - } - } - } - } else { - printf("%s: (%zu bytes): ", name, length); - while(length--) { - printf("%02X", *buf++); - } - } - printf("\n"); + coap_endpoint_log((const coap_endpoint_t *)a); } /*---------------------------------------------------------------------------*/ void dtls_support_init(void) { - dtls_info("dtls_support_init.\n"); + LOG_INFO("init\n"); } /*---------------------------------------------------------------------------*/ From 833da8df76948e2d1d5973f5f63c7b62b8fc4817 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Wed, 17 Jan 2018 20:03:28 +0100 Subject: [PATCH 48/51] Added compile information about license when including tinyDTLS in build --- os/net/app-layer/coap/Makefile.coap | 1 + 1 file changed, 1 insertion(+) diff --git a/os/net/app-layer/coap/Makefile.coap b/os/net/app-layer/coap/Makefile.coap index ddf195221..b3e319119 100644 --- a/os/net/app-layer/coap/Makefile.coap +++ b/os/net/app-layer/coap/Makefile.coap @@ -29,4 +29,5 @@ ifeq ($(MAKE_WITH_DTLS),1) ${error Unsupported CoAP DTLS keystore: $(MAKE_COAP_DTLS_KEYSTORE)} endif + ${info Building with tinyDTLS - see $(CONTIKI)/$(TINYDTLS_PATH)/LICENSE} endif From a18aaa4e261b918f609af1e65fdd2de380d9e58f Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Fri, 19 Jan 2018 06:49:24 +0100 Subject: [PATCH 49/51] Show compile information about tinyDTLS license only once. --- os/net/app-layer/coap/Makefile.coap | 2 -- .../app-layer/coap/tinydtls-support/Makefile.tinydtls-support | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) create mode 100644 os/net/app-layer/coap/tinydtls-support/Makefile.tinydtls-support diff --git a/os/net/app-layer/coap/Makefile.coap b/os/net/app-layer/coap/Makefile.coap index b3e319119..4afecf78a 100644 --- a/os/net/app-layer/coap/Makefile.coap +++ b/os/net/app-layer/coap/Makefile.coap @@ -28,6 +28,4 @@ ifeq ($(MAKE_WITH_DTLS),1) else ${error Unsupported CoAP DTLS keystore: $(MAKE_COAP_DTLS_KEYSTORE)} endif - - ${info Building with tinyDTLS - see $(CONTIKI)/$(TINYDTLS_PATH)/LICENSE} endif diff --git a/os/net/app-layer/coap/tinydtls-support/Makefile.tinydtls-support b/os/net/app-layer/coap/tinydtls-support/Makefile.tinydtls-support new file mode 100644 index 000000000..ac8a5aff4 --- /dev/null +++ b/os/net/app-layer/coap/tinydtls-support/Makefile.tinydtls-support @@ -0,0 +1 @@ +${info Building with tinyDTLS - see $(CONTIKI)/$(TINYDTLS_PATH)/LICENSE} From d3613ba10fa7549fd57fee22ff0dbb669e08cf2e Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Fri, 19 Jan 2018 13:26:47 +0100 Subject: [PATCH 50/51] Updated tinyDTLS submodule to remove some debug output --- os/net/security/tinydtls | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/os/net/security/tinydtls b/os/net/security/tinydtls index fc8d33cb7..5da931eeb 160000 --- a/os/net/security/tinydtls +++ b/os/net/security/tinydtls @@ -1 +1 @@ -Subproject commit fc8d33cb790bfec64acc595e9ab8ba25a2d27b5a +Subproject commit 5da931eeb78d1cd4a1e0068a91de9b78bd3f66de From 06e15563c0ee2675e3210e294040b7c5b8ca25ed Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Fri, 19 Jan 2018 14:41:29 +0100 Subject: [PATCH 51/51] Added compile-test of CoAP/LWM2M with DTLS --- tests/01-compile-base/Makefile | 2 ++ tests/03-compile-arm-ports-02/Makefile | 1 + 2 files changed, 3 insertions(+) diff --git a/tests/01-compile-base/Makefile b/tests/01-compile-base/Makefile index 78efc6411..748837c50 100644 --- a/tests/01-compile-base/Makefile +++ b/tests/01-compile-base/Makefile @@ -12,6 +12,8 @@ libs/energest/native \ libs/energest/sky \ libs/data-structures/native \ libs/data-structures/sky \ +ipso-objects/native \ +ipso-objects/native:MAKE_WITH_DTLS=1 \ rpl-udp/sky \ rpl-border-router/native \ rpl-border-router/sky \ diff --git a/tests/03-compile-arm-ports-02/Makefile b/tests/03-compile-arm-ports-02/Makefile index 25345e14c..4c6cb6d01 100644 --- a/tests/03-compile-arm-ports-02/Makefile +++ b/tests/03-compile-arm-ports-02/Makefile @@ -10,6 +10,7 @@ platform-specific/cc2538-common/pka/zoul \ platform-specific/zoul/orion/ip64-router/zoul:BOARD=orion \ coap/zoul \ ipso-objects/zoul \ +ipso-objects/zoul:MAKE_WITH_DTLS=1 \ hello-world/zoul \ sensniff/zoul \ sensniff/zoul:ZOUL_CONF_SUB_GHZ_SNIFFER=1 \