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