Imported LWM2M standalone example from lwm2m-contiki at https://github.com/sics-iot/lwm2m-contiki

This commit is contained in:
Niclas Finne 2017-10-25 03:12:54 +02:00
parent 83446e3f58
commit e7edd147a9
20 changed files with 2989 additions and 0 deletions

3
examples/lwm2m/standalone/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
*.o
oma-lwm2m-src
lwm2m-example

View File

@ -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 <joakime@sics.se>
* Niclas Finne <nfi@sics.se>
*/
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);
}
}
}

View File

@ -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 <joakime@sics.se>
* Niclas Finne <nfi@sics.se>
*/
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);
}
}
}

View File

@ -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 $@

View File

@ -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)

View File

@ -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)

View File

@ -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 <nfi@sics.se>
* Joakim Eriksson <joakime@sics.se>
*/
#include "coap.h"
#include "coap-endpoint.h"
#include "coap-engine.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#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 */
/*---------------------------------------------------------------------------*/

View File

@ -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 <nfi@sics.se>
* Joakim Eriksson <joakime@sics.se>
*/
#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_ */

View File

@ -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 <nfi@sics.se>
* Joakim Eriksson <joakime@sics.se>
*/
#include "coap.h"
#include "coap-endpoint.h"
#include "coap-engine.h"
#include "coap-keystore.h"
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <err.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#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 */
/*---------------------------------------------------------------------------*/

View File

@ -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 <nfi@sics.se>
* Joakim Eriksson <joakime@sics.se>
*/
#ifndef COAP_IPV4_H_
#define COAP_IPV4_H_
#include <netinet/in.h>
#define COAP_ENDPOINT_CUSTOM 1
typedef struct {
struct sockaddr_in addr;
unsigned int size;
int secure;
} coap_endpoint_t;
#endif /* COAP_IPV4_H_ */

View File

@ -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 <nfi@sics.se>
* Joakim Eriksson <joakime@sics.se>
*/
#ifndef CONTIKI_H_
#define CONTIKI_H_
#include <stdint.h>
#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_ */

View File

@ -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 <joakime@sics.se>
* Niclas Finne <nfi@sics.se>
*/
#include <stdint.h>
#include "lwm2m-object.h"
#include "lwm2m-engine.h"
#include "coap-engine.h"
#include <string.h>
#include <stdio.h>
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);
}
/*---------------------------------------------------------------------------*/

View File

@ -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 <joakime@sics.se>
* Niclas Finne <nfi@sics.se>
*/
#include <stdint.h>
#include "lwm2m-object.h"
#include "lwm2m-engine.h"
#include "coap-engine.h"
#include "ipso-sensor-template.h"
#include "ipso-control-template.h"
#include <stdio.h>
#include <string.h>
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);
}
/*---------------------------------------------------------------------------*/
/** @} */

View File

@ -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 <joakime@sics.se>
* Niclas Finne <nfi@sics.se>
*/
#include <stdint.h>
#include "lwm2m-object.h"
#include "lwm2m-engine.h"
#include "coap-engine.h"
#include "ipso-sensor-template.h"
#include <string.h>
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);
}
/*---------------------------------------------------------------------------*/
/** @} */

View File

@ -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 <nfi@sics.se>
* Joakim Eriksson <joakime@sics.se>
*/
#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 <inttypes.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#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);
}
/*---------------------------------------------------------------------------*/

View File

@ -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 <nfi@sics.se>
* Joakim Eriksson <joakime@sics.se>
*/
#include "coap-timer.h"
#include <sys/time.h>
#define DEBUG 1
#if DEBUG
#include <stdio.h>
#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,
};
/*---------------------------------------------------------------------------*/

View File

@ -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 <nfi@sics.se>
* Joakim Eriksson <joakime@sics.se>
*/
#include "lwm2m-engine.h"
#include "lwm2m-rd-client.h"
#include "coap-timer.h"
#include <unistd.h>
#include <sys/select.h>
#include <errno.h>
#include <err.h>
#include <stdio.h>
#include <inttypes.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#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;
}
/*---------------------------------------------------------------------------*/

View File

@ -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 <nfi@sics.se>
* Joakim Eriksson <joakime@sics.se>
*/
#ifndef POSIX_MAIN_H_
#define POSIX_MAIN_H_
#include <inttypes.h>
#include <sys/select.h>
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_ */

View File

@ -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 <nfi@sics.se>
* Joakim Eriksson <joakime@sics.se>
*/
#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_ */

View File

@ -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 <nfi@sics.se>
* Joakim Eriksson <joakime@sics.se>
*/
#include "tinydtls.h"
#include "coap-timer.h"
#include <stdlib.h>
#include <sys/time.h>
#include <arpa/inet.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#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 <pthread.h>
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)
{
}
/*---------------------------------------------------------------------------*/