From 108284670c19981855fa0c0c9dd30303012d6373 Mon Sep 17 00:00:00 2001
From: Hauke Petersen <hauke.petersen@fu-berlin.de>
Date: Mon, 24 Jul 2017 17:42:26 +0200
Subject: [PATCH] net: added RD client for simplified registration

---
 Makefile.dep                                  | 13 +++-
 makefiles/pseudomodules.inc.mk                |  1 +
 sys/Makefile                                  |  3 +
 sys/auto_init/auto_init.c                     |  5 ++
 sys/include/net/rdcli_common.h                | 13 ++++
 sys/include/net/rdcli_config.h                | 35 +++++++++++
 sys/include/net/rdcli_simple.h                | 47 +++++++++++++++
 .../rdcli_common/rdcli_common.c               | 30 ++++++++++
 .../application_layer/rdcli_simple/Makefile   |  7 +++
 .../rdcli_simple/rdcli_simple.c               | 60 +++++++++++++++++++
 .../rdcli_simple/rdcli_simple_standalone.c    | 54 +++++++++++++++++
 11 files changed, 267 insertions(+), 1 deletion(-)
 create mode 100644 sys/include/net/rdcli_simple.h
 create mode 100644 sys/net/application_layer/rdcli_simple/Makefile
 create mode 100644 sys/net/application_layer/rdcli_simple/rdcli_simple.c
 create mode 100644 sys/net/application_layer/rdcli_simple/rdcli_simple_standalone.c

diff --git a/Makefile.dep b/Makefile.dep
index 6a93d54740..3c9a0a1a0d 100644
--- a/Makefile.dep
+++ b/Makefile.dep
@@ -708,9 +708,20 @@ ifneq (,$(filter skald,$(USEMODULE)))
   USEMODULE += random
 endif
 
+ifneq (,$(filter rdcli_simple_standalone,$(USEMODULE)))
+  USEMODULE += rdcli_simple
+  USEMODULE += xtimer
+endif
+
+ifneq (,$(filter rdcli_simple,$(USEMODULE)))
+  USEMODULE += rdcli_common
+  USEMODULE += fmt
+endif
+
 ifneq (,$(filter rdcli_common,$(USEMODULE)))
-  USEMODULE += luid
   USEMODULE += fmt
+  USEMODULE += gcoap
+  USEMODULE += luid
 endif
 
 # always select gpio (until explicit dependencies are sorted out)
diff --git a/makefiles/pseudomodules.inc.mk b/makefiles/pseudomodules.inc.mk
index 15b562684e..ebb54ee0a9 100644
--- a/makefiles/pseudomodules.inc.mk
+++ b/makefiles/pseudomodules.inc.mk
@@ -64,6 +64,7 @@ PSEUDOMODULES += pktqueue
 PSEUDOMODULES += printf_float
 PSEUDOMODULES += prng
 PSEUDOMODULES += prng_%
+PSEUDOMODULES += rdcli_simple_standalone
 PSEUDOMODULES += saul_adc
 PSEUDOMODULES += saul_default
 PSEUDOMODULES += saul_gpio
diff --git a/sys/Makefile b/sys/Makefile
index 3c48acd69d..f08ec774ae 100644
--- a/sys/Makefile
+++ b/sys/Makefile
@@ -130,6 +130,9 @@ endif
 ifneq (,$(filter rdcli_common,$(USEMODULE)))
   DIRS += net/application_layer/rdcli_common
 endif
+ifneq (,$(filter rdcli_simple,$(USEMODULE)))
+    DIRS += net/application_layer/rdcli_simple
+endif
 
 DIRS += $(dir $(wildcard $(addsuffix /Makefile, $(USEMODULE))))
 
diff --git a/sys/auto_init/auto_init.c b/sys/auto_init/auto_init.c
index 4896751c26..6cdaded5b3 100644
--- a/sys/auto_init/auto_init.c
+++ b/sys/auto_init/auto_init.c
@@ -164,6 +164,11 @@ void auto_init(void)
     extern void rdcli_common_init(void);
     rdcli_common_init();
 #endif
+#ifdef MODULE_RDCLI_SIMPLE_STANDALONE
+    DEBUG("Auto init rdcli_simple module\n");
+    extern void rdcli_simple_run(void);
+    rdcli_simple_run();
+#endif
 
 /* initialize network devices */
 #ifdef MODULE_AUTO_INIT_GNRC_NETIF
diff --git a/sys/include/net/rdcli_common.h b/sys/include/net/rdcli_common.h
index 005928b219..2077b3b312 100644
--- a/sys/include/net/rdcli_common.h
+++ b/sys/include/net/rdcli_common.h
@@ -46,6 +46,19 @@ static inline const char *rdcli_common_get_ep(void)
     return (const char *)rdcli_ep;
 }
 
+/**
+ * @brief   Add selected query string options to a gcoap request
+ *
+ * This function adds:
+ *  - `ep` -> as extracted by rdcli_commont_get_ep()
+ *  - [optional] `lt` -> if defined by RDCLI_LT
+ *  - [optional] 'd'  -> if defined by RDCLI_D
+ *
+ *  @return  0 on success
+ *  @return  <0 on error
+ */
+int rdcli_common_add_qstring(coap_pkt_t *pkt);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/sys/include/net/rdcli_config.h b/sys/include/net/rdcli_config.h
index 906d37fc66..1acd5d7578 100644
--- a/sys/include/net/rdcli_config.h
+++ b/sys/include/net/rdcli_config.h
@@ -26,6 +26,27 @@
 extern "C" {
 #endif
 
+/**
+ * @brief   Default lifetime in seconds (the default is 1 day)
+ */
+#ifndef RDCLI_LT
+#define RDCLI_LT                (86400UL)
+#endif
+
+/**
+ * @brief   Delay until the RD client starts to try registering (in seconds)
+ */
+#ifndef RDCLI_STARTUP_DELAY
+#define RDCLI_STARTUP_DELAY     (3U)
+#endif
+
+/**
+ * @brief   Default client update interval (default is half the lifetime)
+ */
+#ifndef RDCLI_UPDATE_INTERVAL
+#define RDCLI_UPDATE_INTERVAL   (RDCLI_LT / 2)
+#endif
+
 /**
  * @name    Endpoint ID definition
  *
@@ -52,6 +73,20 @@ extern "C" {
 #endif
 /** @} */
 
+/**
+ * @brief   Default IPv6 address to use when looking for RDs
+ */
+#ifndef RDCLI_SERVER_ADDR
+#define RDCLI_SERVER_ADDR       IPV6_ADDR_ALL_NODES_LINK_LOCAL
+#endif
+
+/**
+ * @brief   Default Port to use when looking for RDs
+ */
+#ifndef RDCLI_SERVER_PORT
+#define RDCLI_SERVER_PORT       COAP_PORT
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/sys/include/net/rdcli_simple.h b/sys/include/net/rdcli_simple.h
new file mode 100644
index 0000000000..1e5d08ffc4
--- /dev/null
+++ b/sys/include/net/rdcli_simple.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2017 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ */
+
+/**
+ * @defgroup    net_rdcli_simple Simple CoRE Resource Directory Registration
+ * @ingroup     net_rdcli
+ * @brief       CoAP-based CoRE Resource Directory client supporting the simple
+ *              registration only
+ * @{
+ *
+ * @file
+ * @brief       Interface for a simple CoRE RD registration
+ *
+ * @author      Hauke Petersen <hauke.petersen@fu-berlin.de>
+ */
+
+#ifndef NET_RDCLI_SIMPLE_H
+#define NET_RDCLI_SIMPLE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief   Initiate the node registration by sending an empty CoAP POST message
+ *          to the RD server's /.well-known/core resource
+ */
+int rdcli_simple_register(void);
+
+/**
+ * @brief   Spawn a new thread that registers the node and updates the
+ *          registration with all responding RDs using the simple registration
+ *          process
+ */
+void rdcli_simple_run(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NET_RDCLI_SIMPLE_H */
+/** @} */
diff --git a/sys/net/application_layer/rdcli_common/rdcli_common.c b/sys/net/application_layer/rdcli_common/rdcli_common.c
index d8298930c4..d3c2d24ccd 100644
--- a/sys/net/application_layer/rdcli_common/rdcli_common.c
+++ b/sys/net/application_layer/rdcli_common/rdcli_common.c
@@ -21,6 +21,7 @@
 #include "fmt.h"
 #include "luid.h"
 
+#include "net/gcoap.h"
 #include "net/rdcli_common.h"
 
 #define ENABLE_DEBUG (0)
@@ -58,3 +59,32 @@ void rdcli_common_init(void)
 
     rdcli_ep[pos] = '\0';
 }
+
+int rdcli_common_add_qstring(coap_pkt_t *pkt)
+{
+    /* extend the url with some query string options */
+    int res = gcoap_add_qstring(pkt, "ep", rdcli_ep);
+    if (res < 0) {
+        return res;
+    }
+
+    /* [optional] set the lifetime parameter */
+#if RDCLI_LT
+    char lt[11];
+    lt[fmt_u32_dec(lt, RDCLI_LT)] = '\0';
+    res = gcoap_add_qstring(pkt, "lt", lt);
+    if (res < 0) {
+        return res;
+    }
+#endif
+
+    /* [optional] set the domain parameter */
+#ifdef RDCLI_D
+    res = gcoap_add_qstring(pkt, "d", RDCLI_D);
+    if (res < 0) {
+        return res;
+    }
+#endif
+
+    return 0;
+}
diff --git a/sys/net/application_layer/rdcli_simple/Makefile b/sys/net/application_layer/rdcli_simple/Makefile
new file mode 100644
index 0000000000..997bf2fc80
--- /dev/null
+++ b/sys/net/application_layer/rdcli_simple/Makefile
@@ -0,0 +1,7 @@
+SRC = rdcli_simple.c
+
+ifneq (,$(filter rdcli_simple_standalone,$(USEMODULE)))
+  SRC += rdcli_simple_standalone.c
+endif
+
+include $(RIOTBASE)/Makefile.base
diff --git a/sys/net/application_layer/rdcli_simple/rdcli_simple.c b/sys/net/application_layer/rdcli_simple/rdcli_simple.c
new file mode 100644
index 0000000000..cb86eeef83
--- /dev/null
+++ b/sys/net/application_layer/rdcli_simple/rdcli_simple.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2017 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ */
+
+/**
+ * @ingroup     net_rdcli_simple
+ * @{
+ *
+ * @file
+ * @brief       Simplified CoAP resource directory client implementation
+ *
+ * @author      Hauke Petersen <hauke.petersen@fu-berlin.de>
+ *
+ * @}
+ */
+
+#include <string.h>
+
+#include "fmt.h"
+#include "net/gcoap.h"
+#include "net/rdcli_config.h"
+#include "net/rdcli_common.h"
+#include "net/rdcli_simple.h"
+
+#define BUFSIZE             (128U)
+
+static coap_pkt_t pkt;
+static uint8_t buf[BUFSIZE];
+
+/* allocate an UDP endpoint to the RD server */
+static const sock_udp_ep_t remote = {
+    .family    = AF_INET6,
+    .netif     = SOCK_ADDR_ANY_NETIF,
+    .addr      = RDCLI_SERVER_ADDR ,
+    .port      = RDCLI_SERVER_PORT
+};
+
+int rdcli_simple_register(void)
+{
+    /* build the initial CON packet */
+    int res = gcoap_req_init(&pkt, buf, sizeof(buf), COAP_METHOD_POST,
+                             "/.well-known/core");
+    if (res < 0) {
+        return res;
+    }
+    /* make packet confirmable */
+    coap_hdr_set_type(pkt.hdr, COAP_TYPE_CON);
+    /* add Uri-Query options */
+    res = rdcli_common_add_qstring(&pkt);
+    if (res < 0) {
+        return res;
+    }
+    /* finish, we don't have any payload */
+    ssize_t len = gcoap_finish(&pkt, 0, COAP_FORMAT_LINK);
+    return (int)gcoap_req_send2(buf, len, &remote, NULL);
+}
diff --git a/sys/net/application_layer/rdcli_simple/rdcli_simple_standalone.c b/sys/net/application_layer/rdcli_simple/rdcli_simple_standalone.c
new file mode 100644
index 0000000000..868250ff19
--- /dev/null
+++ b/sys/net/application_layer/rdcli_simple/rdcli_simple_standalone.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2017 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ */
+
+/**
+ * @ingroup     net_rdcli_simple
+ * @{
+ *
+ * @file
+ * @brief       Standalone extension for the simple RD registration client
+ *
+ * @author      Hauke Petersen <hauke.petersen@fu-berlin.de>
+ *
+ * @}
+ */
+
+#include "log.h"
+#include "thread.h"
+#include "xtimer.h"
+#include "net/rdcli_config.h"
+#include "net/rdcli_simple.h"
+
+#define STACKSIZE           (THREAD_STACKSIZE_DEFAULT)
+#define PRIO                (THREAD_PRIORITY_MAIN - 1)
+#define TNAME               "rdcli_simple"
+
+static char _stack[STACKSIZE];
+
+static void *reg_runner(void *arg)
+{
+    (void)arg;
+
+    /* wait some seconds to give the address configuration some time to settle */
+    xtimer_sleep(RDCLI_STARTUP_DELAY);
+
+    while (1) {
+        int res = rdcli_simple_register();
+        if (res < 0) {
+            LOG_ERROR("[rdcli_simple] error: unable to trigger registration\n");
+        }
+        xtimer_sleep(RDCLI_UPDATE_INTERVAL);
+    }
+
+    return NULL;    /* should never be reached */
+}
+
+void rdcli_simple_run(void)
+{
+    thread_create(_stack, sizeof(_stack), PRIO, 0, reg_runner, NULL, TNAME);
+}
-- 
GitLab