Imported LWM2M standalone example from lwm2m-contiki at https://github.com/sics-iot/lwm2m-contiki
This commit is contained in:
parent
83446e3f58
commit
e7edd147a9
3
examples/lwm2m/standalone/.gitignore
vendored
Normal file
3
examples/lwm2m/standalone/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
*.o
|
||||
oma-lwm2m-src
|
||||
lwm2m-example
|
141
examples/lwm2m/standalone/Hex2DTLS.java
Normal file
141
examples/lwm2m/standalone/Hex2DTLS.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
139
examples/lwm2m/standalone/Hex2UDP.java
Normal file
139
examples/lwm2m/standalone/Hex2UDP.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
61
examples/lwm2m/standalone/Makefile
Normal file
61
examples/lwm2m/standalone/Makefile
Normal 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 $@
|
53
examples/lwm2m/standalone/Makefile.contiki
Normal file
53
examples/lwm2m/standalone/Makefile.contiki
Normal 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)
|
68
examples/lwm2m/standalone/README.md
Normal file
68
examples/lwm2m/standalone/README.md
Normal 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)
|
427
examples/lwm2m/standalone/coap-hex/coap-hex.c
Normal file
427
examples/lwm2m/standalone/coap-hex/coap-hex.c
Normal 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 */
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
51
examples/lwm2m/standalone/coap-hex/coap-hex.h
Normal file
51
examples/lwm2m/standalone/coap-hex/coap-hex.h
Normal 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_ */
|
597
examples/lwm2m/standalone/coap-ipv4/coap-ipv4.c
Normal file
597
examples/lwm2m/standalone/coap-ipv4/coap-ipv4.c
Normal 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 */
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
51
examples/lwm2m/standalone/coap-ipv4/coap-ipv4.h
Normal file
51
examples/lwm2m/standalone/coap-ipv4/coap-ipv4.h
Normal 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_ */
|
60
examples/lwm2m/standalone/contiki.h
Normal file
60
examples/lwm2m/standalone/contiki.h
Normal 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_ */
|
193
examples/lwm2m/standalone/generic-object-test.c
Normal file
193
examples/lwm2m/standalone/generic-object-test.c
Normal 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);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
93
examples/lwm2m/standalone/ipso-control-test.c
Normal file
93
examples/lwm2m/standalone/ipso-control-test.c
Normal 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);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @} */
|
119
examples/lwm2m/standalone/ipso-sensor-temp.c
Normal file
119
examples/lwm2m/standalone/ipso-sensor-temp.c
Normal 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);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @} */
|
200
examples/lwm2m/standalone/lwm2m-example.c
Normal file
200
examples/lwm2m/standalone/lwm2m-example.c
Normal 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);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
106
examples/lwm2m/standalone/posix-coap-timer.c
Normal file
106
examples/lwm2m/standalone/posix-coap-timer.c
Normal 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,
|
||||
};
|
||||
/*---------------------------------------------------------------------------*/
|
213
examples/lwm2m/standalone/posix-main.c
Normal file
213
examples/lwm2m/standalone/posix-main.c
Normal 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;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
55
examples/lwm2m/standalone/posix-main.h
Normal file
55
examples/lwm2m/standalone/posix-main.h
Normal 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_ */
|
@ -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_ */
|
302
examples/lwm2m/standalone/tinydtls-support/dtls-support.c
Normal file
302
examples/lwm2m/standalone/tinydtls-support/dtls-support.c
Normal 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)
|
||||
{
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
Loading…
Reference in New Issue
Block a user