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
This commit is contained in:
parent
6fe4026686
commit
4a82bda543
4
examples/lwm2m/standalone/.gitignore
vendored
4
examples/lwm2m/standalone/.gitignore
vendored
@ -1,3 +1,3 @@
|
||||
*.o
|
||||
oma-lwm2m-src
|
||||
lwm2m-example
|
||||
/lwm2m-src
|
||||
/lwm2m-example
|
||||
|
@ -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 \
|
||||
|
@ -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
|
||||
|
@ -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://<server host address> <endpoint name>`.
|
||||
|
||||
|
||||
### 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).
|
||||
|
@ -51,6 +51,7 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#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:
|
||||
|
@ -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_ */
|
||||
|
@ -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 {
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "coap-timer.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <stdarg.h>
|
||||
|
Loading…
Reference in New Issue
Block a user